tests/sixtracklib/opencl: fix various typos (mostly related to NS handling in OpenCL kernels) not detected earlier

#ifndef TESTS_SIXTRACKLIB_OPENCL_TEST_PARTICLES_KERNEL_OPENCL_CL__
#define TESTS_SIXTRACKLIB_OPENCL_TEST_PARTICLES_KERNEL_OPENCL_CL__

#if !defined( SIXTRL_NO_INCLUDES )
    #include "sixtracklib/_impl/definitions.h"
    #include "sixtracklib/common/impl/buffer_defines.h"
    #include "sixtracklib/common/impl/managed_buffer_minimal.h"
    #include "sixtracklib/common/impl/managed_buffer_remap.h"
    #include "sixtracklib/common/particles.h"
#endif /* !defined( SIXTRL_NO_INCLUDES ) */

#pragma OPENCL_EXTENSION cl_khr_int32_extended_atomics

__kernel void NS(Particles_copy_buffer_opencl)(
    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT in_buffer_begin,
    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT out_buffer_begin,
    SIXTRL_DATAPTR_DEC int* SIXTRL_RESTRICT ptr_success_flag )
{
    typedef NS(buffer_size_t) buf_size_t;
    typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*       obj_iter_t;
    typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* obj_const_iter_t;

    typedef SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles) const* ptr_const_particles_t;
    typedef SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)*       ptr_particles_t;

    int success_flag = ( int )0u;
    buf_size_t const slot_size = ( buf_size_t )8u;

    if( ( !NS(ManagedBuffer_needs_remapping)(  in_buffer_begin,  slot_size ) ) ) &&
        ( !NS(ManagedBuffer_needs_remapping)( out_buffer_begin,  slot_size ) ) ) &&
        (  NS(ManagedBuffer_get_num_objects)( out_buffer_begin, slot_size ) ==
           NS(ManagedBuffer_get_num_objects)(  in_buffer_begin, slot_size ) ) )
    {
        obj_const_iter_t in_obj_it  = NS(ManagedBuffer_get_const_objects_index_begin)(
            in_buffer_begin, slot_size );

        obj_const_iter_t in_obj_end = NS(ManagedBuffer_get_const_objects_index_end)(
            in_buffer_begin, slot_size );

        obj_iter_t out_obj_it = NS(ManagedBuffer_get_objects_index_begin)(
            out_buffer_begin, slot_size );

        buf_size_t obj_begin_index = ( buf_size_t )0u;

        size_t const global_id = get_global_id( 0 );

        for( ; in_obj_it != in_obj_end ; ++in_obj_it, ++out_obj_it )
        {
            ptr_const_particles_t in_particles = ( ptr_const_particles_t )(
                uintptr_t )NS(Object_get_begin_addr)( in_obj_it );

            ptr_particles_t out_particles = ( ptr_particles_t )(
                uintptr_t )NS(Object_get_begin_addr)( out_obj_it );

            buf_size_t const nn =
                NS(Particles_get_num_of_particles)( in_particles );

            buf_size_t const obj_end_index = obj_begin_index + nn;

            if( nn == NS(Particles_get_num_of_particles)( out_particles ) )
            {
                if( ( global_id >= obj_begin_index ) &&
                    ( global_id <  obj_end_index ) )
                {
                    buf_size_t const particle_id = global_id - obj_begin_index;

                    if( particle_id < nn )
                    {
                        NS(Particles_copy_single)( out_particles, particle_id,
                            in_particles, particle_id );
                    }
                    else
                    {
                        success_flag |= -1;
                    }

                    break;
                }
            }
            else
            {
                success_flag |= -2;
            }
        }
    }
    else
    {
        if( NS(ManagedBuffer_needs_remapping)(  in_buffer_begin, slot_size ) ) )
        {
            success_flag |= -4;
        }

        if( NS(ManagedBuffer_needs_remapping)( out_buffer_begin, slot_size ) ) )
        {
            success_flag |= -8;
        }

        if(  NS(ManagedBuffer_get_num_objects)( out_buffer_begin, slot_size ) !=
             NS(ManagedBuffer_get_num_objects)(  in_buffer_begin, slot_size ) )
        {
            success_flag |= -16;
        }
    }

    if( ( success_flag != 0 ) && ( ptr_success_flag != SIXTRL_NULLPTR ) )
    {
        atomic_or( ptr_success_flag, success_flag );
    }

    return;
}

#endif /* TESTS_SIXTRACKLIB_OPENCL_TEST_PARTICLES_KERNEL_OPENCL_CL__ */

/* end: tests/sixtracklib/opencl/test_particles_kernel.cl */

#ifndef TESTS_SIXTRACKLIB_OPENCL_TEST_PARTICLES_KERNEL_OPENCL_CL__
#define TESTS_SIXTRACKLIB_OPENCL_TEST_PARTICLES_KERNEL_OPENCL_CL__

#if !defined( SIXTRL_NO_INCLUDES )
    #include "sixtracklib/_impl/definitions.h"
    #include "sixtracklib/common/impl/buffer_defines.h"
    #include "sixtracklib/common/impl/managed_buffer_minimal.h"
    #include "sixtracklib/common/impl/managed_buffer_remap.h"
    #include "sixtracklib/common/particles.h"
#endif /* !defined( SIXTRL_NO_INCLUDES ) */

#pragma OPENCL_EXTENSION cl_khr_int32_extended_atomics

__kernel void NS(Particles_copy_buffer_opencl)(
    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT in_buffer_begin,
    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT out_buffer_begin,
    SIXTRL_DATAPTR_DEC int* SIXTRL_RESTRICT ptr_success_flag )
{
    typedef NS(buffer_size_t) buf_size_t;
    typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*       obj_iter_t;
    typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* obj_const_iter_t;

    typedef SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles) const* ptr_const_particles_t;
    typedef SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)*       ptr_particles_t;

    int success_flag = ( int )0u;
    buf_size_t const slot_size = ( buf_size_t )8u;

    if( ( !NS(ManagedBuffer_needs_remapping(  in_buffer_begin,  slot_size ) ) ) &&
        ( !NS(ManagedBuffer_needs_remapping( out_buffer_begin,  slot_size ) ) ) &&
        (  NS(ManagedBuffer_get_num_objects)( out_buffer_begin, slot_size ) ==
           NS(ManagedBuffer_get_num_objects)(  in_buffer_begin, slot_size ) ) )
    {
        obj_const_iter_t in_obj_it  = NS(ManagedBuffer_get_const_objects_index_begin)(
            in_buffer_begin, slot_size );

        obj_const_iter_t in_obj_end = NS(ManagedBuffer_get_const_objects_index_end)(
            in_buffer_begin, slot_size );

        obj_iter_t out_obj_it = NS(ManagedBuffer_get_objects_index_begin)(
            out_buffer_begin, slot_size );

        buf_size_t obj_begin_index = ( buf_size_t )0u;

        size_t const global_id = get_global_id( 0 );

        for( ; in_obj_it != in_obj_end ; ++in_obj_it, ++out_obj_it )
        {
            ptr_const_particles_t in_particles = ( ptr_const_particles_t )(
                uintptr_t )NS(Object_get_begin_addr)( in_obj_it );

            ptr_particles_t out_particles = ( ptr_particles_t )(
                uintptr_t )NS(Object_get_begin_addr)( out_obj_it );

            buf_size_t const nn =
                NS(Particles_get_num_of_particles)( in_particles );

            buf_size_t const obj_end_index = obj_begin_index + nn;

            if( nn == NS(Particles_get_num_of_particles)( out_particles ) )
            {
                if( ( global_id >= obj_begin_index ) &&
                    ( global_id <  obj_end_index ) )
                {
                    buf_size_t const particle_id = global_id - obj_begin_index;

                    if( particle_id < nn )
                    {
                        NS(Particles_copy_single)( out_particles, particle_id,
                            in_particles, particle_id );
                    }
                    else
                    {
                        success_flag |= -1;
                    }

                    break;
                }
            }
            else
            {
                success_flag |= -2;
            }
        }
    }
    else
    {
        if( NS(ManagedBuffer_needs_remapping(  in_buffer_begin, slot_size ) ) )
        {
            success_flag |= -4;
        }

        if( NS(ManagedBuffer_needs_remapping( out_buffer_begin, slot_size ) ) )
        {
            success_flag |= -8;
        }

        if(  NS(ManagedBuffer_get_num_objects)( out_buffer_begin, slot_size ) !=
             NS(ManagedBuffer_get_num_objects)(  in_buffer_begin, slot_size ) )
        {
            success_flag |= -16;
        }
    }

    if( ( success_flag != 0 ) && ( ptr_success_flag != SIXTRL_NULLPTR ) )
    {
        atomic_or( ptr_success_flag, success_flag );
    }

    return;
}

#endif /* TESTS_SIXTRACKLIB_OPENCL_TEST_PARTICLES_KERNEL_OPENCL_CL__ */

/* end: tests/sixtracklib/opencl/test_particles_kernel.cl */


fix pooling cl

fix pooling cl

/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/

#define _FLOAT float
#define _FLOAT2 float2
#define _FLOAT4 float4
#define _FLOAT8 float8
#define _INT_MASK_GLOBAL uchar
#define _INT_MASK_LOCAL uchar

#ifndef FLT_MAX
#define FLT_MAX 3.402823466e+38F /* max value */
#endif

#define UNUSED __attribute__((__unused__))

#define MLO_POOLING_OP_AVE 0
#define MLO_POOLING_OP_MAX 1
#define MLO_POOLING_OP_STC 2

#define MLO_POOLING_GROUP_SZ2 1

#ifndef MLO_POOLING_OP_ID
#define MLO_POOLING_OP_ID 0
#endif
// max
#if MLO_POOLING_OP_ID == MLO_POOLING_OP_MAX
#define MLO_POOLING_OP(A, B) fmax(A, B);
#elif MLO_POOLING_OP_ID == MLO_POOLING_OP_AVE
#define MLO_POOLING_OP(A, B) (A + B);
#endif

/*********************************************************************************

**********************************************************************************/

#define MLO_BOT_DATA_SZ0 \
    (MLO_POOLING_N_HORIZ_OUT_PIX * MLO_POOLING_STRIDE0 + MLO_POOLING_KERNEL_SZ0 - 1)
#define MLO_BOT_DATA_SZ1 \
    (MLO_POOLING_N_VERT_OUT_PIX * MLO_POOLING_STRIDE1 + MLO_POOLING_KERNEL_SZ1 - 1)

__attribute__((reqd_work_group_size(MLO_POOLING_GROUP_SZ0,
                                    MLO_POOLING_GROUP_SZ1,
                                    MLO_POOLING_GROUP_SZ2))) __kernel void
mloPoolingG(const __global _FLOAT* bot,
            __global _FLOAT* top,
#if !defined(MLO_POOLING_DO_BACKWARD) || MLO_POOLING_OP_ID != MLO_POOLING_OP_MAX
            UNUSED
#endif
                __global _INT_MASK_GLOBAL* mask)
{

    uint x       = get_group_id(0) * MLO_POOLING_GROUP_SZ0 * MLO_POOLING_N_HORIZ_OUT_PIX;
    uint y       = get_group_id(1) * MLO_POOLING_GROUP_SZ1 * MLO_POOLING_N_VERT_OUT_PIX;
    uint lcl_id0 = get_local_id(0);
    uint lcl_id1 = get_local_id(1);
    //		int lcl_id = (lcl_id1 << MLO_POOLING_GROUP_LG2SZ0) + lcl_id0;
    uint ob      = get_global_id(2); // output * batch_sz
    uint b       = ob / MLO_POOLING_N_OUTPUTS;
    uint o       = ob - b * MLO_POOLING_N_OUTPUTS;
    uint bot_x   = (x + lcl_id0 * MLO_POOLING_N_HORIZ_OUT_PIX) * MLO_POOLING_STRIDE0;
    uint bot_y   = (y + lcl_id1 * MLO_POOLING_N_VERT_OUT_PIX) * MLO_POOLING_STRIDE1;
    uint bot_off = b * MLO_POOLING_BOT_BATCH_STRIDE + o * MLO_POOLING_BOT_CHANNEL_STRIDE;

    _FLOAT bot_data[MLO_BOT_DATA_SZ1][MLO_BOT_DATA_SZ0];
    _FLOAT res[MLO_POOLING_N_VERT_OUT_PIX][MLO_POOLING_N_HORIZ_OUT_PIX];
#if defined(MLO_POOLING_DO_BACKWARD) && MLO_POOLING_OP_ID == MLO_POOLING_OP_MAX
    _INT_MASK_LOCAL mask_private[MLO_POOLING_N_VERT_OUT_PIX][MLO_POOLING_N_HORIZ_OUT_PIX];
#endif
    for(int k = 0; k < MLO_POOLING_N_VERT_OUT_PIX; k++)
    {
        for(int l = 0; l < MLO_POOLING_N_HORIZ_OUT_PIX; l++)
        {
#if MLO_POOLING_OP_ID == MLO_POOLING_OP_MAX
            res[k][l] = -FLT_MAX;
#elif MLO_POOLING_OP_ID == MLO_POOLING_OP_AVE
            res[k][l]         = 0;
#endif
        }
    }

    for(uint j = 0; j < MLO_BOT_DATA_SZ1; ++j)
    {
        int run_y = (int)bot_y + j - MLO_POOLING_PAD1;

        for(uint i = 0; i < MLO_BOT_DATA_SZ0; ++i)
        {
            int run_x        = (int)bot_x + i - MLO_POOLING_PAD0;
            uint bot_gbl_off = bot_off + (uint)run_y * MLO_POOLING_BOT_STRIDE + (uint)run_x;
            bool vis         = ((run_y >= 0 && run_y < MLO_POOLING_BOT_HEIGHT) &&
                        (run_x >= 0 && run_x < MLO_POOLING_BOT_WIDTH))
                           ? true
                           : false;
            bot_data[j][i] = (vis) ? bot[bot_gbl_off] : 0;
        }
    }

    for(uint k = 0; k < MLO_POOLING_N_VERT_OUT_PIX; k++)
    {
#if MLO_POOLING_OP_ID == MLO_POOLING_OP_AVE
        uint y_dst  = y + lcl_id1 * MLO_POOLING_N_VERT_OUT_PIX + k;
        uint hstart = y_dst * MLO_POOLING_STRIDE1 - MLO_POOLING_PAD1;
        uint hend   = min((uint)(hstart + MLO_POOLING_KERNEL_SZ1),
                        (uint)(MLO_POOLING_BOT_HEIGHT + MLO_POOLING_PAD1));
#endif
        for(uint l = 0; l < MLO_POOLING_N_HORIZ_OUT_PIX; l++)
        {

#if MLO_POOLING_OP_ID == MLO_POOLING_OP_AVE
            uint x_dst  = x + lcl_id0 * MLO_POOLING_N_HORIZ_OUT_PIX + l;
            uint wstart = x_dst * MLO_POOLING_STRIDE0 - MLO_POOLING_PAD0;
            uint wend   = min((uint)(wstart + MLO_POOLING_KERNEL_SZ0),
                            (uint)(MLO_POOLING_BOT_WIDTH + MLO_POOLING_PAD0));
            uint pool_size = (hend - hstart) * (wend - wstart);
#endif
#if defined(MLO_POOLING_DO_BACKWARD) && MLO_POOLING_OP_ID == MLO_POOLING_OP_MAX
            mask_private[k][l] = 0xFF;
#endif

            for(uint j = 0; j < MLO_POOLING_KERNEL_SZ1; j++)
            {
                for(uint i = 0; i < MLO_POOLING_KERNEL_SZ0; i++)
                {

                    _FLOAT bot_val =
                        bot_data[j + k * MLO_POOLING_STRIDE1][i + l * MLO_POOLING_STRIDE0];
#if 0
						if (y_dst == 0 && x_dst == 6)
						{

							printf("k: %d %f %f\n",
								lcl_off + (k * MLO_POOLING_STRIDE1+j)*MLO_POOLING_LCL_DATA_WIDTH + (l * MLO_POOLING_STRIDE0+i),
								res[k][l],
								bot_val
								);
						}
#endif
#if defined(MLO_POOLING_DO_BACKWARD) && MLO_POOLING_OP_ID == MLO_POOLING_OP_MAX
                    if(bot_val > res[k][l])
                    {
                        res[k][l]          = bot_val;
                        mask_private[k][l] = i + MLO_POOLING_KERNEL_SZ0 * j;
                    }
#else
                    res[k][l] = MLO_POOLING_OP(res[k][l], bot_val);
#endif
                }
            }

#if MLO_POOLING_OP_ID == MLO_POOLING_OP_AVE
            res[k][l] *= (_FLOAT)1.f / (_FLOAT)pool_size;
#endif
        }
    }

    uint top_y   = (y + lcl_id1 * MLO_POOLING_N_VERT_OUT_PIX);
    uint top_x   = (x + lcl_id0 * MLO_POOLING_N_HORIZ_OUT_PIX);
    uint top_off = b * MLO_POOLING_TOP_BATCH_STRIDE + o * MLO_POOLING_TOP_CHANNEL_STRIDE +
                   top_y * MLO_POOLING_TOP_STRIDE + top_x;
    for(uint k = 0; k < MLO_POOLING_N_VERT_OUT_PIX; k++)
    {
        for(uint l = 0; l < MLO_POOLING_N_HORIZ_OUT_PIX; l++)
        {
            if(top_y + k < MLO_POOLING_TOP_HEIGHT && top_x + l < MLO_POOLING_TOP_WIDTH)
            {
                top[top_off + k * MLO_POOLING_TOP_STRIDE + l] = res[k][l];
#if defined(MLO_POOLING_DO_BACKWARD) && MLO_POOLING_OP_ID == MLO_POOLING_OP_MAX
                mask[top_off + k * MLO_POOLING_TOP_STRIDE + l] = mask_private[k][l];
#endif
            }
        }
    }
}

/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/

#define _FLOAT float
#define _FLOAT2 float2
#define _FLOAT4 float4
#define _FLOAT8 float8
#define _INT_MASK_GLOBAL uchar
#define _INT_MASK_LOCAL uchar

#ifndef FLT_MAX
#define FLT_MAX 3.402823466e+38F /* max value */
#endif

#define UNUSED __attribute__((__unused__))

#define MLO_POOLING_OP_AVE 0
#define MLO_POOLING_OP_MAX 1
#define MLO_POOLING_OP_STC 2

#define MLO_POOLING_GROUP_SZ2 1

#ifndef MLO_POOLING_OP_ID
#define MLO_POOLING_OP_ID 0
#endif
// max
#if MLO_POOLING_OP_ID == MLO_POOLING_OP_MAX
#define MLO_POOLING_OP(A, B) fmax(A, B);
#elif MLO_POOLING_OP_ID == MLO_POOLING_OP_AVE
#define MLO_POOLING_OP(A, B) (A + B);
#endif

/*********************************************************************************

**********************************************************************************/

#define MLO_BOT_DATA_SZ0 \
    (MLO_POOLING_N_HORIZ_OUT_PIX * MLO_POOLING_STRIDE0 + MLO_POOLING_KERNEL_SZ0 - 1)
#define MLO_BOT_DATA_SZ1 \
    (MLO_POOLING_N_VERT_OUT_PIX * MLO_POOLING_STRIDE1 + MLO_POOLING_KERNEL_SZ1 - 1)

__attribute__((reqd_work_group_size(MLO_POOLING_GROUP_SZ0,
                                    MLO_POOLING_GROUP_SZ1,
                                    MLO_POOLING_GROUP_SZ2))) __kernel void
mloPoolingG(const __global _FLOAT* bot,
            __global _FLOAT* top,
#if !defined(MLO_POOLING_DO_BACKWARD) || MLO_POOLING_OP_ID != MLO_POOLING_OP_MAX
            UNUSED
#endif
                __global _INT_MASK_GLOBAL* mask)
{

    uint x       = get_group_id(0) * MLO_POOLING_GROUP_SZ0 * MLO_POOLING_N_HORIZ_OUT_PIX;
    uint y       = get_group_id(1) * MLO_POOLING_GROUP_SZ1 * MLO_POOLING_N_VERT_OUT_PIX;
    uint lcl_id0 = get_local_id(0);
    uint lcl_id1 = get_local_id(1);
    //		int lcl_id = (lcl_id1 << MLO_POOLING_GROUP_LG2SZ0) + lcl_id0;
    uint ob      = get_global_id(2); // output * batch_sz
    uint b       = ob / MLO_POOLING_N_OUTPUTS;
    uint o       = ob - b * MLO_POOLING_N_OUTPUTS;
    uint bot_x   = (x + lcl_id0 * MLO_POOLING_N_HORIZ_OUT_PIX) * MLO_POOLING_STRIDE0;
    uint bot_y   = (y + lcl_id1 * MLO_POOLING_N_VERT_OUT_PIX) * MLO_POOLING_STRIDE1;
    uint bot_off = b * MLO_POOLING_BOT_BATCH_STRIDE + o * MLO_POOLING_BOT_CHANNEL_STRIDE;

    _FLOAT bot_data[MLO_BOT_DATA_SZ1][MLO_BOT_DATA_SZ0];
    _FLOAT res[MLO_POOLING_N_VERT_OUT_PIX][MLO_POOLING_N_HORIZ_OUT_PIX];
#if defined(MLO_POOLING_DO_BACKWARD) && MLO_POOLING_OP_ID == MLO_POOLING_OP_MAX
    _INT_MASK_LOCAL mask_private[MLO_POOLING_N_VERT_OUT_PIX][MLO_POOLING_N_HORIZ_OUT_PIX];
#endif
    for(int k = 0; k < MLO_POOLING_N_VERT_OUT_PIX; k++)
    {
        for(int l = 0; l < MLO_POOLING_N_HORIZ_OUT_PIX; l++)
        {
#if MLO_POOLING_OP_ID == MLO_POOLING_OP_MAX
            res[k][l] = -FLT_MAX;
#elif MLO_POOLING_OP_ID == MLO_POOLING_OP_AVE
            res[k][l]         = 0;
#endif
        }
    }

    for(uint j = 0; j < MLO_BOT_DATA_SZ1; ++j)
    {
        int run_y = (int)bot_y + j - MLO_POOLING_PAD1;

        for(uint i = 0; i < MLO_BOT_DATA_SZ0; ++i)
        {
            int run_x        = (int)bot_x + i - MLO_POOLING_PAD0;
            uint bot_gbl_off = bot_off + (uint)run_y * MLO_POOLING_BOT_STRIDE + (uint)run_x;
            bool vis         = ((run_y >= 0 && run_y < MLO_POOLING_BOT_HEIGHT) &&
                        (run_x >= 0 && run_x < MLO_POOLING_BOT_WIDTH))
                           ? true
                           : false;
            bot_data[j][i] = (vis) ? bot[bot_gbl_off] : 0;
        }
    }

    for(uint k = 0; k < MLO_POOLING_N_VERT_OUT_PIX; k++)
    {
#if MLO_POOLING_OP_ID == MLO_POOLING_OP_AVE
        uint y_dst  = y + lcl_id1 * MLO_POOLING_N_VERT_OUT_PIX + k;
        uint hstart = y_dst * MLO_POOLING_STRIDE1 - MLO_POOLING_PAD1;
        uint hend = min(hstart + MLO_POOLING_KERNEL_SZ1, MLO_POOLING_BOT_HEIGHT + MLO_POOLING_PAD1);
#endif
        for(uint l = 0; l < MLO_POOLING_N_HORIZ_OUT_PIX; l++)
        {

#if MLO_POOLING_OP_ID == MLO_POOLING_OP_AVE
            uint x_dst  = x + lcl_id0 * MLO_POOLING_N_HORIZ_OUT_PIX + l;
            uint wstart = x_dst * MLO_POOLING_STRIDE0 - MLO_POOLING_PAD0;
            uint wend =
                min(wstart + MLO_POOLING_KERNEL_SZ0, MLO_POOLING_BOT_WIDTH + MLO_POOLING_PAD0);
            uint pool_size = (hend - hstart) * (wend - wstart);
#endif
#if defined(MLO_POOLING_DO_BACKWARD) && MLO_POOLING_OP_ID == MLO_POOLING_OP_MAX
            mask_private[k][l] = 0xFF;
#endif

            for(uint j = 0; j < MLO_POOLING_KERNEL_SZ1; j++)
            {
                for(uint i = 0; i < MLO_POOLING_KERNEL_SZ0; i++)
                {

                    _FLOAT bot_val =
                        bot_data[j + k * MLO_POOLING_STRIDE1][i + l * MLO_POOLING_STRIDE0];
#if 0
						if (y_dst == 0 && x_dst == 6)
						{

							printf("k: %d %f %f\n",
								lcl_off + (k * MLO_POOLING_STRIDE1+j)*MLO_POOLING_LCL_DATA_WIDTH + (l * MLO_POOLING_STRIDE0+i),
								res[k][l],
								bot_val
								);
						}
#endif
#if defined(MLO_POOLING_DO_BACKWARD) && MLO_POOLING_OP_ID == MLO_POOLING_OP_MAX
                    if(bot_val > res[k][l])
                    {
                        res[k][l]          = bot_val;
                        mask_private[k][l] = i + MLO_POOLING_KERNEL_SZ0 * j;
                    }
#else
                    res[k][l] = MLO_POOLING_OP(res[k][l], bot_val);
#endif
                }
            }

#if MLO_POOLING_OP_ID == MLO_POOLING_OP_AVE
            res[k][l] *= (_FLOAT)1.f / (_FLOAT)pool_size;
#endif
        }
    }

    uint top_y   = (y + lcl_id1 * MLO_POOLING_N_VERT_OUT_PIX);
    uint top_x   = (x + lcl_id0 * MLO_POOLING_N_HORIZ_OUT_PIX);
    uint top_off = b * MLO_POOLING_TOP_BATCH_STRIDE + o * MLO_POOLING_TOP_CHANNEL_STRIDE +
                   top_y * MLO_POOLING_TOP_STRIDE + top_x;
    for(uint k = 0; k < MLO_POOLING_N_VERT_OUT_PIX; k++)
    {
        for(uint l = 0; l < MLO_POOLING_N_HORIZ_OUT_PIX; l++)
        {
            if(top_y + k < MLO_POOLING_TOP_HEIGHT && top_x + l < MLO_POOLING_TOP_WIDTH)
            {
                top[top_off + k * MLO_POOLING_TOP_STRIDE + l] = res[k][l];
#if defined(MLO_POOLING_DO_BACKWARD) && MLO_POOLING_OP_ID == MLO_POOLING_OP_MAX
                mask[top_off + k * MLO_POOLING_TOP_STRIDE + l] = mask_private[k][l];
#endif
            }
        }
    }
}


Fix kernel by comments

Fix kernel by comments

//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// @Authors
//    Niko Li, newlife20080214@gmail.com
//    Rock Li, Rock.li@amd.com
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors as is and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//

#if lcn == 1
    #if dcn == 4
        #define LUT_OP(num)\
            int idx = *(__global const int *)(srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx & 0xff];\
            dst[1] = lut_l[(idx >> 8) & 0xff];\
            dst[2] = lut_l[(idx >> 16) & 0xff];\
            dst[3] = lut_l[(idx >> 24) & 0xff];
    #elif dcn == 3
        #define LUT_OP(num)\
            uchar3 idx = vload3(0, srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx.x];\
            dst[1] = lut_l[idx.y];\
            dst[2] = lut_l[idx.z];
    #elif dcn == 2
        #define LUT_OP(num)\
            __global const uchar2 * idx = (__global const uchar2 *)(srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx->x];\
            dst[1] = lut_l[idx->y];
    #elif dcn == 1
        #define LUT_OP(num)\
            uchar idx = (srcptr + mad24(num, src_step, src_index))[0];\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx];
    #else
        #define LUT_OP(num)\
            src = (__global const srcT *)(srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            for (int cn = 0; cn < dcn; ++cn)\
                dst[cn] = lut_l[src[cn]];
    #endif
#else
    #if dcn == 4
        #define LUT_OP(num)\
            __global const uchar4 *src_pixel = (__global const uchar4 *)(srcptr + mad24(num, src_step, src_index));\
            int4 idx = convert_int4(src_pixel[0]) * lcn + (int4)(0, 1, 2, 3);\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx.x];\
            dst[1] = lut_l[idx.y];\
            dst[2] = lut_l[idx.z];\
            dst[3] = lut_l[idx.w];
    #elif dcn == 3
        #define LUT_OP(num)\
            uchar3 src_pixel = vload3(0, srcptr + mad24(num, src_step, src_index));\
            int3 idx = convert_int3(src_pixel) * lcn + (int3)(0, 1, 2);\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx.x];\
            dst[1] = lut_l[idx.y];\
            dst[2] = lut_l[idx.z];
    #elif dcn == 2
        #define LUT_OP(num)\
            __global const uchar2 *src_pixel = (__global const uchar2 *)(srcptr + mad24(num, src_step, src_index));\
            int2 idx = convert_int2(src_pixel[0]) * lcn + (int2)(0, 1);\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx.x];\
            dst[1] = lut_l[idx.y];
    #elif dcn == 1 //error case (1 < lcn) ==> lcn == scn == dcn
        #define LUT_OP(num)\
            uchar idx = (srcptr + mad24(num, src_step, src_index))[0];\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx];
    #else
        #define LUT_OP(num)\
            src = (__global const srcT *)(srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            for (int cn = 0; cn < dcn; ++cn)\
                dst[cn] = lut_l[mad24(src[cn], lcn, cn)];
    #endif
#endif

#define LOCAL_LUT_INIT\
    {\
        __global const dstT * lut = (__global const dstT *)(lutptr + lut_offset);\
        int init = mad24((int)get_local_id(1), (int)get_local_size(0), (int)get_local_id(0));\
        int step = get_local_size(0) * get_local_size(1);\
        for (int i = init; i < 256 * lcn; i += step)\
        {\
            lut_l[i] = lut[i];\
        }\
        barrier(CLK_LOCAL_MEM_FENCE);\
    }

__kernel void LUT(__global const uchar * srcptr, int src_step, int src_offset,
                  __global const uchar * lutptr, int lut_step, int lut_offset,
                  __global uchar * dstptr, int dst_step, int dst_offset, int rows, int cols)
{
    __local dstT lut_l[256 * lcn];
    LOCAL_LUT_INIT;

    int x = get_global_id(0);
    int y = 4 * get_global_id(1);

    if (x < cols && y < rows)
    {
        int src_index = mad24(y, src_step, mad24(x, (int)sizeof(srcT) * dcn, src_offset));
        int dst_index = mad24(y, dst_step, mad24(x, (int)sizeof(dstT) * dcn, dst_offset));
        __global const srcT * src; __global dstT * dst;
        int tmp_idx;
        LUT_OP(0);
        if (y < rows - 1)
        {
            LUT_OP(1);
            if (y < rows - 2)
            {
                LUT_OP(2);
                if (y < rows - 3)
                {
                    LUT_OP(3);
                }
            }
        }

    }
}

//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// @Authors
//    Niko Li, newlife20080214@gmail.com
//    Rock Li, Rock.li@amd.com
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors as is and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//

#if lcn == 1
    #if dcn == 4
        #define LUT_OP(num)\
            __global const uchar4 *idx = (__global const uchar4 *)(srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx->x];\
            dst[1] = lut_l[idx->y];\
            dst[2] = lut_l[idx->z];\
            dst[3] = lut_l[idx->w];
    #elif dcn == 3
        #define LUT_OP(num)\
            uchar3 idx = vload3(0, srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx.x];\
            dst[1] = lut_l[idx.y];\
            dst[2] = lut_l[idx.z];
    #elif dcn == 2
        #define LUT_OP(num)\
            __global const uchar2 * idx = (__global const uchar2 *)(srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx->x];\
            dst[1] = lut_l[idx->y];
    #elif dcn == 1
        #define LUT_OP(num)\
            uchar idx = (srcptr + mad24(num, src_step, src_index))[0];\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx];
    #else
        #define LUT_OP(num)\
            src = (__global const srcT *)(srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            for (int cn = 0; cn < dcn; ++cn)\
                dst[cn] = lut_l[src[cn]];
    #endif
#else
    #if dcn == 4
        #define LUT_OP(num)\
            __global const uchar4 *src_pixel = (__global const uchar4 *)(srcptr + mad24(num, src_step, src_index));\
            int4 idx = convert_int4(src_pixel[0]) * lcn + (int4)(0, 1, 2, 3);\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx.x];\
            dst[1] = lut_l[idx.y];\
            dst[2] = lut_l[idx.z];\
            dst[3] = lut_l[idx.w];
    #elif dcn == 3
        #define LUT_OP(num)\
            uchar3 src_pixel = vload3(0, srcptr + mad24(num, src_step, src_index));\
            int3 idx = convert_int3(src_pixel) * lcn + (int3)(0, 1, 2);\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx.x];\
            dst[1] = lut_l[idx.y];\
            dst[2] = lut_l[idx.z];
    #elif dcn == 2
        #define LUT_OP(num)\
            __global const uchar2 *src_pixel = (__global const uchar2 *)(srcptr + mad24(num, src_step, src_index));\
            int2 idx = convert_int2(src_pixel[0]) * lcn + (int2)(0, 1);\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx.x];\
            dst[1] = lut_l[idx.y];
    #elif dcn == 1 //error case (1 < lcn) ==> lcn == scn == dcn
        #define LUT_OP(num)\
            uchar idx = (srcptr + mad24(num, src_step, src_index))[0];\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            dst[0] = lut_l[idx];
    #else
        #define LUT_OP(num)\
            src = (__global const srcT *)(srcptr + mad24(num, src_step, src_index));\
            dst = (__global dstT *)(dstptr + mad24(num, dst_step, dst_index));\
            for (int cn = 0; cn < dcn; ++cn)\
                dst[cn] = lut_l[mad24(src[cn], lcn, cn)];
    #endif
#endif

#define LOCAL_LUT_INIT\
    {\
        __global const dstT * lut = (__global const dstT *)(lutptr + lut_offset);\
        int init = mad24((int)get_local_id(1), (int)get_local_size(0), (int)get_local_id(0));\
        int step = get_local_size(0) * get_local_size(1);\
        for (int i = init; i < 256 * lcn; i += step)\
        {\
            lut_l[i] = lut[i];\
        }\
        barrier(CLK_LOCAL_MEM_FENCE);\
    }

__kernel void LUT(__global const uchar * srcptr, int src_step, int src_offset,
                  __global const uchar * lutptr, int lut_step, int lut_offset,
                  __global uchar * dstptr, int dst_step, int dst_offset, int rows, int cols)
{
    __local dstT lut_l[256 * lcn];
    LOCAL_LUT_INIT;

    int x = get_global_id(0);
    int y = 4 * get_global_id(1);

    if (x < cols && y < rows)
    {
        int src_index = mad24(y, src_step, mad24(x, (int)sizeof(srcT) * dcn, src_offset));
        int dst_index = mad24(y, dst_step, mad24(x, (int)sizeof(dstT) * dcn, dst_offset));
        __global const srcT * src; __global dstT * dst;
        int tmp_idx;
        LUT_OP(0);
        if (y < rows - 1)
        {
            LUT_OP(1);
            if (y < rows - 2)
            {
                LUT_OP(2);
                if (y < rows - 3)
                {
                    LUT_OP(3);
                }
            }
        }

    }
}


clean up

clean up

/*  Copyright 2014 Aaron Boxer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */

#include "ocl_platform.cl"

/*

BPC Scan Pattern

Xx4 stripes

The stripes are scanned from top to bottom, and the columns within a
stripe are scanned from left to right.

*/

#define CODEBLOCKY_QUARTER 8

#define BOUNDARY 1
#define BOUNDARY_X2 2

#define CODEBLOCKY_X4 128

#define STATE_BUFFER_SIZE 1156
#define STATE_BOTTOM_BOUNDARY_OFFSET 1124

#define STATE_BUFFER_STRIDE 34
#define STATE_BUFFER_STRIDE_X4 136

#define LEFT_TOP -35
#define TOP  -34
#define RIGHT_TOP -33

#define LEFT   -1
#define RIGHT   1

#define LEFT_BOTTOM  33
#define BOTTOM  34
#define RIGHT_BOTTOM  35

// bit positions (0 based indices)
#define INPUT_SIGN_BITPOS  15

#define NBH_BITPOS         0x2
#define RLC_BITPOS         0x4
#define PIXEL_START_BITPOS 0xA
#define PIXEL_END_BITPOS   0x18
#define SIGN_BITPOS        0x19

#define SIGMA_NEW			 0x1		  //0
#define SIGMA_OLD			 0x10		  //1
#define NBH					 0x20		  //2
#define RLC					 0x80		  //4
#define RLC_D_POSITION		 0x380        //6-9
#define PIXEL				 0x7FFF0000   //10-24
#define SIGN				 0x2000000    //25

#define INPUT_TO_SIGN_SHIFT 10

CONSTANT sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE  | CLK_FILTER_NEAREST;

#define BIT(pix) (((pix)>>(bp))&1)

void KERNEL run(read_only image2d_t R,
						 read_only image2d_t G,
						 read_only image2d_t B,
						 read_only image2d_t A , const unsigned int  width, const unsigned int height) {

	// state buffer
	LOCAL int state[STATE_BUFFER_SIZE];

	///////////////////////////////////////////////////////////////////////////////////////////////////////
	//0. read data into LDS
	int2 posIn = (int2)(getGlobalId(0),  (getGlobalId(1)&7)*CODEBLOCKY + getLocalId(1) );
	LOCAL int* statePtr = state + BOUNDARY + getLocalId(0);
	for (int i = 0; i < 4; ++i) {
		int pixel = read_imagei(R, sampler, posIn).x;
		*statePtr = (abs(pixel) << PIXEL_START_BITPOS) | ((pixel << INPUT_TO_SIGN_SHIFT) & SIGN);
		posIn.y++;
		statePtr += STATE_BUFFER_STRIDE;

	}
	localMemoryFence();

	///////////////////////////////////////////////////////////////////////////////////
	//1. Calculate MSB

	LOCAL int msbScratch[CODEBLOCKX]; // between one and 32 - zero value indicates that this code block is identically zero

	int maxSigBit;
	if (getLocalId(1) == 0) {
		int maxVal = 0;
		state[getLocalId(0)] = 0;   //top boundary
		LOCAL int* statePtr = state + (BOUNDARY + getLocalId(0));
		for (int i = 0; i < CODEBLOCKY; ++i) {
			maxVal = max(maxVal, (*statePtr >> PIXEL_START_BITPOS)&0x7FFF);
			statePtr += STATE_BUFFER_STRIDE;
		}
		state[ getLocalId(0) + STATE_BOTTOM_BOUNDARY_OFFSET] = 0;		//bottom boundary

		//initialize full left and right boundary columns
		if (getLocalId(0) == 0 || getLocalId(0) == CODEBLOCKX-1) {
			int delta = -1 + (getLocalId(0)/(CODEBLOCKX-1))*2; // -1 or +1
			statePtr = state + BOUNDARY + getLocalId(0) + delta;
			 for (int i = 0; i < CODEBLOCKY+ BOUNDARY_X2; ++i) {
				 *statePtr = 0;
				 statePtr += STATE_BUFFER_STRIDE;
			 }
		}

		// calculate column-msb
		maxSigBit = 31 - clz(maxVal);
		msbScratch[getLocalId(0)] =maxSigBit;
	}
	localMemoryFence();

	if (getLocalId(1) == 0) {
		//calculate global msb
		if (getLocalId(0) == 0) {
			int4 mx = (int4)(maxSigBit);

			LOCAL int* scratchPtr = msbScratch;
			for(int i=0; i < CODEBLOCKX; i+=4) {
				mx = max(mx,(int4)(msbScratch[i],msbScratch[i+1],msbScratch[i+2],msbScratch[i+3]));
			}
			maxSigBit = mx.x;
			maxSigBit = max(maxSigBit, mx.y);
			maxSigBit = max(maxSigBit, mx.z);
			maxSigBit = max(maxSigBit, mx.w);
			msbScratch[0] = maxSigBit;
		}
	}
	localMemoryFence();

	if (msbScratch[0] == -1)
		return;

	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// 2. CUP on MSB

	//Algorithm 13 Clean-up pass on the MSB
	//1: set sigmanew := bit value
	//2: set rlcNbh :=  SUM(sigmanew) of preceding column and upper position
	//3: if rlcNbh = 0 and y-dimension of current position is a multiple of 4
	//then
	//4: execute RLC operation
	//5: end if
	//6: if rlcNbh = 1 then
	//7: execute ZC operation
	//8: end if
	//9: if sigmanew = 1 then
	//10: execute SC operation
	//11: end if

	int bp = msbScratch[0] + PIXEL_START_BITPOS;

	// sigma_new
	statePtr = state + (BOUNDARY + getLocalId(0)) + (BOUNDARY + getLocalId(1))*STATE_BUFFER_STRIDE_X4;
	for (int i = 0; i < 4; ++i) {
		int current = *statePtr;
		*statePtr |= BIT(current);	 // set sigma_new
		statePtr += STATE_BUFFER_STRIDE;

	}
	localMemoryFence();

	// rlcNbh
	statePtr = state + (BOUNDARY + getLocalId(0)) + (BOUNDARY + getLocalId(1))*STATE_BUFFER_STRIDE_X4;
	int top = statePtr[TOP];
	int leftTop = statePtr[LEFT_TOP];
	int left = statePtr[LEFT];
	int leftBottom = statePtr[LEFT_BOTTOM];

	for (int i = 0; i < 4; ++i) {
		int nbh = BIT(top) + BIT(leftTop) + BIT(left) + BIT(leftBottom);
		nbh = ((nbh | (~nbh + 1)) >> 27) * NBH;  // NBH if non-zero, otherwise zero
		*statePtr |= nbh;	 // set nbh
		statePtr += STATE_BUFFER_STRIDE;
		top = left;
		left = leftBottom;
		top = statePtr[TOP];
		leftBottom = statePtr[LEFT_BOTTOM];

	}
	localMemoryFence();

/*

	// run CUP coding on MSB
	statePtr = state + BOUNDARY + getLocalId(0);
	int y = 0;
    current = statePtr[0];
	int currentPlusOne = statePtr[STATE_BUFFER_STRIDE];
	for (int i = BOUNDARY; i < CODEBLOCKY+BOUNDARY; ++i) {
		 if (!(y&3) ) {
			//RLC

			// get information about both SIGMA_NEW and SIGMA_OLD from
			// left and right neighbours and current bit,
			// and use this to update the current RLC bit
#ifdef POO

			statePtr[0] |= (( left & SIGMA_NEW ) ||
								(left & SIGMA_OLD ) ||
								  ( current & SIGMA_NEW ) ||
								   ( current & SIGMA_OLD ) ||
								    ( right   & SIGMA_NEW ) ||
								      ( right   & SIGMA_OLD )) << RLC_BITPOS ;

			localMemoryFence();

			// get information about bit value from the left neighbour and update current RLC bit
			statePtr[0] |= BIT (statePtr[LEFT]) << RLC_BITPOS;

			localMemoryFence();

			// get the information from RLC bits of successors
			atomic_or(statePtr + (y&0xfffffffc - y)*STATE_BUFFER_STRIDE, *statePtr & RLC );

			localMemoryFence();

			int nbh = 0;
#endif
		 } else {
			//ZC

		 }
		 if (BIT(current)) {
			//SC

		 }
		 statePtr += STATE_BUFFER_STRIDE;
		 y++;

	}
	localMemoryFence();
#endif
*/
}

/*  Copyright 2014 Aaron Boxer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */

#include "ocl_platform.cl"

/*

BPC Scan Pattern

Xx4 stripes

The stripes are scanned from top to bottom, and the columns within a
stripe are scanned from left to right.

*/

#define CODEBLOCKY_QUARTER 8

#define BOUNDARY 1
#define BOUNDARY_X2 2

#define CODEBLOCKY_X4 128

#define STATE_BUFFER_SIZE 1156
#define STATE_BOUNDARY_OFFSET 1124

#define STATE_BUFFER_STRIDE 34
#define STATE_BUFFER_STRIDE_X4 136

#define LEFT_TOP -35
#define TOP  -34
#define RIGHT_TOP -33

#define LEFT   -1
#define RIGHT   1

#define LEFT_BOTTOM  33
#define BOTTOM  34
#define RIGHT_BOTTOM  35

// bit numbers (0 based indices)
#define INPUT_SIGN_BITPOS  15

#define NBH_BITPOS         0x2
#define RLC_BITPOS         0x4
#define PIXEL_START_BITPOS 0xA
#define PIXEL_END_BITPOS   0x18
#define SIGN_BITPOS        0x19

#define SIGMA_NEW			 0x1		  //0
#define SIGMA_OLD			 0x10		  //1
#define NBH					 0x20		  //2
#define RLC					 0x80		  //4
#define RLC_D_POSITION		 0x380        //6-9
#define PIXEL				 0x7FFF0000   //10-24
#define SIGN				 0x2000000    //25

#define INPUT_TO_SIGN_SHIFT 10

#define AMD

CONSTANT sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE  | CLK_FILTER_NEAREST;

#define BIT(pix) (((pix)>>(bp))&1)

void KERNEL run(read_only image2d_t R,
						 read_only image2d_t G,
						 read_only image2d_t B,
						 read_only image2d_t A , const unsigned int  width, const unsigned int height) {

	// state buffer
	LOCAL int state[STATE_BUFFER_SIZE];

	///////////////////////////////////////////////////////////////////////////////////////////////////////
	//0. read data into LDS
	int2 posIn = (int2)(getGlobalId(0),  (getGlobalId(1)&7)*CODEBLOCKY + getLocalId(1) );
	LOCAL int* statePtr = state + BOUNDARY + getLocalId(0);
	for (int i = 0; i < 4; ++i) {
		int pixel = read_imagei(R, sampler, posIn).x;
		*statePtr = (abs(pixel) << PIXEL_START_BITPOS) | ((pixel << INPUT_TO_SIGN_SHIFT) & SIGN);
		posIn.y++;
		statePtr += STATE_BUFFER_STRIDE;

	}
	localMemoryFence();

	///////////////////////////////////////////////////////////////////////////////////
	//1. Calculate MSB
	// between one and 32 - zero value indicates that this code block is identically zero
	LOCAL int msbScratch[CODEBLOCKX];

	int maxSigBit;
	if (getLocalId(1) == 0) {
		int maxVal = 0;
		state[getLocalId(0)] = 0;   //boundary
		LOCAL int* statePtr = state + (BOUNDARY + getLocalId(0));
		for (int i = 0; i < CODEBLOCKY; ++i) {
			maxVal = max(maxVal, (*statePtr >> PIXEL_START_BITPOS)&0x7FFF);
			statePtr += STATE_BUFFER_STRIDE;
		}
		state[ getLocalId(0) + STATE_BOUNDARY_OFFSET] = 0;		//boundary

		//initialize full boundary columns
		if (getLocalId(0) == 0 || getLocalId(0) == CODEBLOCKX-1) {
			int delta = -1 + (getLocalId(0)/(CODEBLOCKX-1))*2; // -1 or +1
			statePtr = state + BOUNDARY + getLocalId(0) + delta;
			 for (int i = 0; i < CODEBLOCKY+ BOUNDARY_X2; ++i) {
				 *statePtr = 0;
				 statePtr += STATE_BUFFER_STRIDE;
			 }
		}

		// calculate column-msb
		maxSigBit = 31 - clz(maxVal);
		msbScratch[getLocalId(0)] =maxSigBit;
	}
	localMemoryFence();
	if (getLocalId(1) == 0) {
		//calculate global msb
		if (getLocalId(0) == 0) {
			int4 mx = (int4)(maxSigBit);

			LOCAL int* scratchPtr = msbScratch;
			for(int i=0; i < CODEBLOCKX; i+=4) {
				mx = max(mx,(int4)(msbScratch[i],msbScratch[i+1],msbScratch[i+2],msbScratch[i+3]));
			}
			maxSigBit = mx.x;
			maxSigBit = max(maxSigBit, mx.y);
			maxSigBit = max(maxSigBit, mx.z);
			maxSigBit = max(maxSigBit, mx.w);
			msbScratch[0] = maxSigBit;
		}
	}
	localMemoryFence();
	if (msbScratch[0] == -1)
		return;

	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// 2. CUP on MSB

	//Algorithm 13 Clean-up pass on the MSB
	//1: set sigmanew := bit value
	//2: set rlcNbh :=  SUM(sigmanew) of preceding column and upper position
	//3: if rlcNbh = 0 and y-dimension of current position is a multiple of 4
	//then
	//4: execute RLC operation
	//5: end if
	//6: if rlcNbh = 1 then
	//7: execute ZC operation
	//8: end if
	//9: if sigmanew = 1 then
	//10: execute SC operation
	//11: end if

	int bp = msbScratch[0] + PIXEL_START_BITPOS;

	// sigma_new
	statePtr = state + (BOUNDARY + getLocalId(0)) + (BOUNDARY + getLocalId(1))*STATE_BUFFER_STRIDE_X4;
	for (int i = 0; i < 4; ++i) {
		int current = *statePtr;
		*statePtr |= BIT(current);	 // set sigma_new
		statePtr += STATE_BUFFER_STRIDE;

	}
	localMemoryFence();

	// rlcNbh
	statePtr = state + (BOUNDARY + getLocalId(0)) + (BOUNDARY + getLocalId(1))*STATE_BUFFER_STRIDE_X4;
	int top = statePtr[TOP];
	int leftTop = statePtr[LEFT_TOP];
	int left = statePtr[LEFT];
	int leftBottom = statePtr[LEFT_BOTTOM];

	for (int i = 0; i < 4; ++i) {
		int nbh = BIT(top) + BIT(leftTop) + BIT(left) + BIT(leftBottom);
		nbh = ((nbh | (~nbh + 1)) >> 27) * NBH;  // NBH if non-zero, otherwise zero
		*statePtr |= nbh;	 // set nbh
		statePtr += STATE_BUFFER_STRIDE;
		top = left;
		left = leftBottom;
		top = statePtr[TOP];
		leftBottom = statePtr[LEFT_BOTTOM];

	}
	localMemoryFence();

/*

	// run CUP coding on MSB
	statePtr = state + BOUNDARY + getLocalId(0);
	int y = 0;
    current = statePtr[0];
	int currentPlusOne = statePtr[STATE_BUFFER_STRIDE];
	for (int i = BOUNDARY; i < CODEBLOCKY+BOUNDARY; ++i) {
		 if (!(y&3) ) {
			//RLC

			// get information about both SIGMA_NEW and SIGMA_OLD from
			// left and right neighbours and current bit,
			// and use this to update the current RLC bit
#ifdef POO

			statePtr[0] |= (( left & SIGMA_NEW ) ||
								(left & SIGMA_OLD ) ||
								  ( current & SIGMA_NEW ) ||
								   ( current & SIGMA_OLD ) ||
								    ( right   & SIGMA_NEW ) ||
								      ( right   & SIGMA_OLD )) << RLC_BITPOS ;

			localMemoryFence();

			// get information about bit value from the left neighbour and update current RLC bit
			statePtr[0] |= BIT (statePtr[LEFT]) << RLC_BITPOS;

			localMemoryFence();

			// get the information from RLC bits of successors
			atomic_or(statePtr + (y&0xfffffffc - y)*STATE_BUFFER_STRIDE, *statePtr & RLC );

			localMemoryFence();

			int nbh = 0;
#endif
		 } else {
			//ZC

		 }
		 if (BIT(current)) {
			//SC

		 }
		 statePtr += STATE_BUFFER_STRIDE;
		 y++;

	}
	localMemoryFence();
#endif
*/
}


Inline all the things

Inline all the things

#define EPSILON 0.00001

typedef struct PRNG {
    ulong m_seed[16];
    ulong m_p;
} PRNG;

typedef struct Camera {
    float3 m_pos;
    float3 m_dir;
    float3 m_world_up;
    float3 m_right;
    float3 m_up;
    float m_canvas_width;
    float m_canvas_height;
    float3 m_canvas_center_pos;
    float3 m_canvas_dir_x;
    float3 m_canvas_dir_y;
    float m_near_plane_dist;
    float m_far_plane_dist;
    int m_screen_width;
    int m_screen_height;
    float m_vertical_fov;
    float m_horizontal_fov;
} Camera;

typedef struct Material {
    float3 m_reflectance;
    float3 m_emittance;
} Material;

typedef struct Triangle {
    float3 m_v1;
    float3 m_v2;
    float3 m_v3;
    Material m_material;
    float3 m_normal;
    float3 m_centroid;
    float m_area;
} Triangle;

typedef struct FlatStructure {
    Triangle m_triangles[100];
    unsigned m_num_triangles;
} FlatStructure;

typedef struct Ray {
    float3 m_origin;
    float3 m_dir;
    float3 m_invdir;
} Ray;

typedef struct IntersectionInfo {
    bool m_has_intersected;
    float3 m_pos;
    float3 m_normal;
    Ray m_incoming_ray;
    Material m_material;
} IntersectionInfo;

typedef struct AABB {
    float3 m_min;
    float3 m_max;
} AABB;

// From http://xorshift.di.unimi.it/xorshift1024star.c
inline ulong xorshift1024star(__global PRNG *prng) {
    ulong s0 = prng->m_seed[prng->m_p];
    ulong s1 = prng->m_seed[prng->m_p = (prng->m_p + 1) & 15];
    s1 ^= s1 << 31; // a
    s1 ^= s1 >> 11; // b
    s0 ^= s0 >> 30; // c
    return (prng->m_seed[prng->m_p] = s0 ^ s1) * 1181783497276652981L;
}

inline float rand_range(__global PRNG *prng, const float min, const float max) {
    return min + ((float)xorshift1024star(prng)) / (float)(ULONG_MAX / (max - min));
}

inline bool AABB_is_null(const AABB *aabb) {
    bool min_null = length(aabb->m_min) == 0;
    bool max_null = length(aabb->m_max) == 0;
    return min_null && max_null;
}

inline float3 AABB_min(const AABB *aabb) {
    return aabb->m_min;
}

inline float3 AABB_max(const AABB *aabb) {
    return aabb->m_max;
}

inline float3 AABB_diagonal(const AABB *aabb) {
    return aabb->m_max - aabb->m_min;
}

inline float3 AABB_center(const AABB *aabb) {
    return aabb->m_min + (AABB_diagonal(aabb) * 0.5f);
}

// std_array<glm_vec3, 8> AABB_vertices(AABB &aabb) {
//     std_array<glm_vec3, 8> result;
//     result[0] = {aabb.m_min.x, aabb.m_min.y, aabb.m_min.z}; // lower left front
//     result[1] = {aabb.m_max.x, aabb.m_min.y, aabb.m_min.z}; // lower right front
//     result[2] = {aabb.m_min.x, aabb.m_max.y, aabb.m_min.z}; // upper left front
//     result[3] = {aabb.m_max.x, aabb.m_max.y, aabb.m_min.z}; // upper right front
//     result[4] = {aabb.m_min.x, aabb.m_min.y, aabb.m_max.z}; // lower left back
//     result[5] = {aabb.m_max.x, aabb.m_min.y, aabb.m_max.z}; // lower right back
//     result[6] = {aabb.m_min.x, aabb.m_max.y, aabb.m_max.z}; // upper left back
//     result[7] = {aabb.m_max.x, aabb.m_max.y, aabb.m_max.z}; // upper right back
//     return result;
// }

inline void AABB_extend(AABB *aabb, float3 point) {
    aabb->m_min = min(point, aabb->m_min);
    aabb->m_max = max(point, aabb->m_max);
}

inline bool AABB_overlaps(const AABB *first, const AABB *second) {
    return first->m_max.x > second->m_min.x && first->m_min.x < second->m_max.x &&
           first->m_max.y > second->m_min.y && first->m_min.y < second->m_max.y &&
           first->m_max.z > second->m_min.z && first->m_min.z < second->m_max.z;
}

inline void AABB_reset(AABB *aabb) {
    aabb->m_min = 0;
    aabb->m_max = 0;
}

inline float2 Camera_screenspace_to_camspace(__constant const Camera *camera, unsigned x, unsigned y) {
    float rel_x = -(x - camera->m_screen_width / 2.f) / camera->m_screen_width;
    float rel_y = -(y - camera->m_screen_height / 2.f) / camera->m_screen_height;
    return (float2)(rel_x, rel_y);
}

inline int2 Camera_camspace_to_screenspace(__constant const Camera *camera, int2 coords) {
    int screen_x = round(0.5f * (camera->m_screen_width - 2.f * camera->m_screen_width * coords.x));
    int screen_y =
        round(0.5f * (camera->m_screen_height - 2.f * camera->m_screen_height * coords.y));
    return (int2)(screen_x, screen_y);
}

inline float3 Camera_camspace_to_worldspace(__constant const Camera *camera, float2 rel_pos) {
    float3 worldspace = camera->m_canvas_center_pos + (rel_pos.x * camera->m_canvas_dir_x) +
                        (rel_pos.y * camera->m_canvas_dir_y);
    return worldspace;
}

// float2 Camera_worldspace_to_camspace(const Camera *camera, float3 world_pos_on_canvas) {
//     float3 canvas_center_to_point = world_pos_on_canvas - Camera_canvas_center_pos(camera);
//
//     // Manually calculate angle between the positive y-axis on the canvas and the world point
//     float3 ay = canvas_center_to_point;
//     float3 by = Camera_up(camera);
//     float3 cy = cross(ay, by);
//     float angle1y = atan(dot(ay, by), length(cy));
//
//     // Manually calculate angle between the positive x-axis on the canvas and the world point
//     float3 ax = canvas_center_to_point;
//     float3 bx = Camera_right(camera);
//     float3 cx = cross(ax, bx);
//     float angle1x = atan(length(cx), dot(ax, bx));
//
//     float angle2x = glm_pi<float>() - (glm_half_pi<float>() + angle1x);
//     float len = length(canvas_center_to_point);
//     float x = sin(angle2x) * len;
//     float y = sin(angle1y) * len;
//     float rel_x = -(2 * x) / Camera_canvas_width(camera);
//     float rel_y = -(2 * y) / Camera_canvas_height(camera);
//     return (float2)(rel_x, -rel_y);
// }

// glm_vec3 Camera_worldpoint_to_worldspace(const Camera *camera, glm_vec3 world_point) {
//     auto ray_to_cam = pos(camera) - world_point;
//     float dist = 0;
//     bool collided = glm_intersectRayPlane(world_point, glm_normalize(ray_to_cam),
//                                           canvas_center_pos(camera), dir(camera), dist);
//     if (collided) {
//         return world_point + glm_normalize(ray_to_cam) * dist;
//     } else {
//         return glm_vec3(0);
//     }
// }

// From
// http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-box-intersection
inline bool intersect_ray_aabb(const Ray *ray, const AABB *aabb) {
    float tmin, tmax, tymin, tymax, tzmin, tzmax;

    float3 bounds[2];
    bounds[0] = AABB_min(aabb);
    bounds[1] = AABB_max(aabb);

    char3 sign;
    sign.x = (ray->m_invdir.x < 0);
    sign.y = (ray->m_invdir.y < 0);
    sign.z = (ray->m_invdir.z < 0);

    tmin = (bounds[sign.x].x - ray->m_origin.x) * ray->m_invdir.x;
    tmax = (bounds[1 - sign.x].x - ray->m_origin.x) * ray->m_invdir.x;
    tymin = (bounds[sign.y].y - ray->m_origin.y) * ray->m_invdir.y;
    tymax = (bounds[1 - sign.y].y - ray->m_origin.y) * ray->m_invdir.y;

    if ((tmin > tymax) || (tymin > tmax))
        return false;
    if (tymin > tmin)
        tmin = tymin;
    if (tymax < tmax)
        tmax = tymax;

    tzmin = (bounds[sign.z].z - ray->m_origin.z) * ray->m_invdir.z;
    tzmax = (bounds[1 - sign.z].z - ray->m_origin.z) * ray->m_invdir.z;

    if ((tmin > tzmax) || (tzmin > tmax))
        return false;
    if (tzmin > tmin)
        tmin = tzmin;
    if (tzmax < tmax)
        tmax = tzmax;

    return true;
}

// Möller-Trumbore intersection algorithm
// (see https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm)
inline bool intersect_ray_triangle(const Ray *ray, __constant const Triangle *triangle, float *dist) {
    // Calculate edges of triangle from v0.
    float3 e0 = triangle->m_v2 - triangle->m_v1;
    float3 e1 = triangle->m_v3 - triangle->m_v1;

    // Calculate determinant to check whether the ray is in the newly calculated plane made up from
    // e0 and e1.
    float3 pvec = cross(ray->m_dir, e1);
    float det = dot(e0, pvec);

    // Check whether determinant is close to 0. If that is the case, the ray is in the same plane as
    // the triangle itself which means that they can't collide. This effectively disables backface
    // culling for which we would instead only check whether det < epsilon.
    if (det > -EPSILON && det < EPSILON)
        return false;

    float inv_det = 1.f / det;

    // Calculate distance from v1 to ray origin
    float3 tvec = ray->m_origin - triangle->m_v1;

    // Calculate u parameter and test bound
    float u = dot(tvec, pvec) * inv_det;

    // Check whether the intersection lies outside of the triangle
    if (u < 0.f || u > 1.f)
        return false;

    // Prepare to test v parameter
    float3 qvec = cross(tvec, e0);

    // Calculate v parameter and test bound
    float v = dot(ray->m_dir, qvec) * inv_det;

    // Check whether the intersection lies outside of the triangle
    if (v < 0.f || u + v > 1.f)
        return false;

    float t = dot(e1, qvec) * inv_det;

    if (t > EPSILON) {
        *dist = t - EPSILON;
        return true;
    }

    // If we end up here, there was no hit
    return false;
}

inline IntersectionInfo Scene_intersect(__constant FlatStructure *accel_struct, Ray *ray) {
    IntersectionInfo intersect_info;

    // Keep track of closest triangle
    float closest_dist = FLT_MAX;
    Triangle closest_triangle;
    // for (const auto &shape : FlatStructure::shapes(flatstruct)) {
    //     if (intersect_ray_aabb(ray, Shape::aabb(shape))) {
    //         for (auto &tri : Shape::triangles(shape)) {
    for (unsigned i = 0; i < accel_struct->m_num_triangles; i++) {
        float dist_to_intersect;
        __constant Triangle *tri = &(accel_struct->m_triangles[i]);
        bool intersected = intersect_ray_triangle(ray, tri, &dist_to_intersect);
        if (intersected) {
            // Find closest triangle
            if (dist_to_intersect < closest_dist) {
                closest_dist = dist_to_intersect;
                closest_triangle = *tri;

                intersect_info.m_has_intersected = true;
                intersect_info.m_pos = ray->m_origin + ray->m_dir * closest_dist;
                intersect_info.m_incoming_ray = *ray;
                intersect_info.m_normal = closest_triangle.m_normal;
                intersect_info.m_material = closest_triangle.m_material;
            }
        }
    }
    //     }
    // }

    return intersect_info;
}

__kernel void renderer_trace_pixel_color(__write_only __global float4 *output, const int width,
                                         const unsigned max_depth, __global PRNG *prng,
                                         __constant Camera *camera,
                                         __constant FlatStructure *flatstruct) {
    int x = get_global_id(0);
    int y = get_global_id(1);
    int index = y * width + x;

    float2 rel_pos = Camera_screenspace_to_camspace(camera, x, y);
    float3 world_pos = Camera_camspace_to_worldspace(camera, rel_pos);
    float3 ray_dir = normalize(world_pos - camera->m_pos);

    float3 ret_color = (float3)(0);
    Ray next_ray = {world_pos, ray_dir};
    float3 brdf = (float3)(1);
    for (unsigned depth = 0; depth < max_depth; depth++) {
        IntersectionInfo intersect_info = Scene_intersect(flatstruct, &next_ray);
        if (intersect_info.m_has_intersected) {
            // ret_color = intersect_info.m_material.m_reflectance;
            // break;

            // Get the local radiance only on first bounce
            float3 local_radiance;
            // if (depth == 0) {
            // auto ray = ray_pos - impact_pos;
            // float dist2 = glm_dot(ray, ray);
            // auto cos_area = glm_dot(-ray_dir, tri->m_normal) * tri->m_area;
            // auto solid_angle = cos_area / glm_max(dist2, 1e-6f);
            //
            // if (cos_area > 0.0)
            //     local_radiance = tri->m_emittance * solid_angle;
            //     local_radiance = intersect_info.m_material.m_emittance;
            // }

            local_radiance = intersect_info.m_material.m_emittance;

            // Emitter sample
            // TODO
            // glm_vec3 illumination;

            float3 normal =
                intersect_info.m_normal *
                -sign(dot(intersect_info.m_normal, intersect_info.m_incoming_ray.m_dir));

            // Find new random direction for diffuse reflection
            float u = 2.f * rand_range(prng, 0.f, 1.f);
            float v = 2.f * M_PI_F * rand_range(prng, 0.f, 1.f);
            float xx = sqrt(1 - u * u) * cos(v);
            float yy = sqrt(1 - u * u) * sin(v);
            float zz = u;
            float3 new_ray_dir = {xx, yy, zz};
            new_ray_dir = normalize(new_ray_dir);
            if (dot(new_ray_dir, normal) < 0) {
                new_ray_dir = -new_ray_dir;
            }

            float cos_theta = dot(new_ray_dir, normal);

            ret_color += brdf * local_radiance;
            brdf *= 2.f * intersect_info.m_material.m_reflectance * cos_theta;

            // Make a new ray
            Ray new_ray = {intersect_info.m_pos, new_ray_dir};
            next_ray = new_ray;

        } else {
            break;
        }
    }

    output[index] = (float4)(ret_color.x, ret_color.y, ret_color.z, 1.f);
    // output[index] = (float4)(rand_range(prng, 0.f, 1.f), rand_range(prng, 0.f, 1.f),
    //                          rand_range(prng, 0.f, 1.f), 1.f);
}

#define EPSILON 0.00001

typedef struct PRNG {
    ulong m_seed[16];
    ulong m_p;
} PRNG;

typedef struct Camera {
    float3 m_pos;
    float3 m_dir;
    float3 m_world_up;
    float3 m_right;
    float3 m_up;
    float m_canvas_width;
    float m_canvas_height;
    float3 m_canvas_center_pos;
    float3 m_canvas_dir_x;
    float3 m_canvas_dir_y;
    float m_near_plane_dist;
    float m_far_plane_dist;
    int m_screen_width;
    int m_screen_height;
    float m_vertical_fov;
    float m_horizontal_fov;
} Camera;

typedef struct Material {
    float3 m_reflectance;
    float3 m_emittance;
} Material;

typedef struct Triangle {
    float3 m_v1;
    float3 m_v2;
    float3 m_v3;
    Material m_material;
    float3 m_normal;
    float3 m_centroid;
    float m_area;
} Triangle;

typedef struct FlatStructure {
    Triangle m_triangles[100];
    unsigned m_num_triangles;
} FlatStructure;

typedef struct Ray {
    float3 m_origin;
    float3 m_dir;
    float3 m_invdir;
} Ray;

typedef struct IntersectionInfo {
    bool m_has_intersected;
    float3 m_pos;
    float3 m_normal;
    Ray m_incoming_ray;
    Material m_material;
} IntersectionInfo;

typedef struct AABB {
    float3 m_min;
    float3 m_max;
} AABB;

// From http://xorshift.di.unimi.it/xorshift1024star.c
ulong xorshift1024star(__global PRNG *prng) {
    ulong s0 = prng->m_seed[prng->m_p];
    ulong s1 = prng->m_seed[prng->m_p = (prng->m_p + 1) & 15];
    s1 ^= s1 << 31; // a
    s1 ^= s1 >> 11; // b
    s0 ^= s0 >> 30; // c
    return (prng->m_seed[prng->m_p] = s0 ^ s1) * 1181783497276652981L;
}

float rand_range(__global PRNG *prng, const float min, const float max) {
    return min + ((float)xorshift1024star(prng)) / (float)(ULONG_MAX / (max - min));
}

bool AABB_is_null(const AABB *aabb) {
    bool min_null = length(aabb->m_min) == 0;
    bool max_null = length(aabb->m_max) == 0;
    return min_null && max_null;
}

float3 AABB_min(const AABB *aabb) {
    return aabb->m_min;
}

float3 AABB_max(const AABB *aabb) {
    return aabb->m_max;
}

float3 AABB_diagonal(const AABB *aabb) {
    return aabb->m_max - aabb->m_min;
}

float3 AABB_center(const AABB *aabb) {
    return aabb->m_min + (AABB_diagonal(aabb) * 0.5f);
}

// std_array<glm_vec3, 8> AABB_vertices(AABB &aabb) {
//     std_array<glm_vec3, 8> result;
//     result[0] = {aabb.m_min.x, aabb.m_min.y, aabb.m_min.z}; // lower left front
//     result[1] = {aabb.m_max.x, aabb.m_min.y, aabb.m_min.z}; // lower right front
//     result[2] = {aabb.m_min.x, aabb.m_max.y, aabb.m_min.z}; // upper left front
//     result[3] = {aabb.m_max.x, aabb.m_max.y, aabb.m_min.z}; // upper right front
//     result[4] = {aabb.m_min.x, aabb.m_min.y, aabb.m_max.z}; // lower left back
//     result[5] = {aabb.m_max.x, aabb.m_min.y, aabb.m_max.z}; // lower right back
//     result[6] = {aabb.m_min.x, aabb.m_max.y, aabb.m_max.z}; // upper left back
//     result[7] = {aabb.m_max.x, aabb.m_max.y, aabb.m_max.z}; // upper right back
//     return result;
// }

void AABB_extend(AABB *aabb, float3 point) {
    aabb->m_min = min(point, aabb->m_min);
    aabb->m_max = max(point, aabb->m_max);
}

bool AABB_overlaps(const AABB *first, const AABB *second) {
    return first->m_max.x > second->m_min.x && first->m_min.x < second->m_max.x &&
           first->m_max.y > second->m_min.y && first->m_min.y < second->m_max.y &&
           first->m_max.z > second->m_min.z && first->m_min.z < second->m_max.z;
}

void AABB_reset(AABB *aabb) {
    aabb->m_min = 0;
    aabb->m_max = 0;
}

float2 Camera_screenspace_to_camspace(__constant const Camera *camera, unsigned x, unsigned y) {
    float rel_x = -(x - camera->m_screen_width / 2.f) / camera->m_screen_width;
    float rel_y = -(y - camera->m_screen_height / 2.f) / camera->m_screen_height;
    return (float2)(rel_x, rel_y);
}

int2 Camera_camspace_to_screenspace(__constant const Camera *camera, int2 coords) {
    int screen_x = round(0.5f * (camera->m_screen_width - 2.f * camera->m_screen_width * coords.x));
    int screen_y =
        round(0.5f * (camera->m_screen_height - 2.f * camera->m_screen_height * coords.y));
    return (int2)(screen_x, screen_y);
}

float3 Camera_camspace_to_worldspace(__constant const Camera *camera, float2 rel_pos) {
    float3 worldspace = camera->m_canvas_center_pos + (rel_pos.x * camera->m_canvas_dir_x) +
                        (rel_pos.y * camera->m_canvas_dir_y);
    return worldspace;
}

// float2 Camera_worldspace_to_camspace(const Camera *camera, float3 world_pos_on_canvas) {
//     float3 canvas_center_to_point = world_pos_on_canvas - Camera_canvas_center_pos(camera);
//
//     // Manually calculate angle between the positive y-axis on the canvas and the world point
//     float3 ay = canvas_center_to_point;
//     float3 by = Camera_up(camera);
//     float3 cy = cross(ay, by);
//     float angle1y = atan(dot(ay, by), length(cy));
//
//     // Manually calculate angle between the positive x-axis on the canvas and the world point
//     float3 ax = canvas_center_to_point;
//     float3 bx = Camera_right(camera);
//     float3 cx = cross(ax, bx);
//     float angle1x = atan(length(cx), dot(ax, bx));
//
//     float angle2x = glm_pi<float>() - (glm_half_pi<float>() + angle1x);
//     float len = length(canvas_center_to_point);
//     float x = sin(angle2x) * len;
//     float y = sin(angle1y) * len;
//     float rel_x = -(2 * x) / Camera_canvas_width(camera);
//     float rel_y = -(2 * y) / Camera_canvas_height(camera);
//     return (float2)(rel_x, -rel_y);
// }

// glm_vec3 Camera_worldpoint_to_worldspace(const Camera *camera, glm_vec3 world_point) {
//     auto ray_to_cam = pos(camera) - world_point;
//     float dist = 0;
//     bool collided = glm_intersectRayPlane(world_point, glm_normalize(ray_to_cam),
//                                           canvas_center_pos(camera), dir(camera), dist);
//     if (collided) {
//         return world_point + glm_normalize(ray_to_cam) * dist;
//     } else {
//         return glm_vec3(0);
//     }
// }

// From
// http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-box-intersection
bool intersect_ray_aabb(const Ray *ray, const AABB *aabb) {
    float tmin, tmax, tymin, tymax, tzmin, tzmax;

    float3 bounds[2];
    bounds[0] = AABB_min(aabb);
    bounds[1] = AABB_max(aabb);

    char3 sign;
    sign.x = (ray->m_invdir.x < 0);
    sign.y = (ray->m_invdir.y < 0);
    sign.z = (ray->m_invdir.z < 0);

    tmin = (bounds[sign.x].x - ray->m_origin.x) * ray->m_invdir.x;
    tmax = (bounds[1 - sign.x].x - ray->m_origin.x) * ray->m_invdir.x;
    tymin = (bounds[sign.y].y - ray->m_origin.y) * ray->m_invdir.y;
    tymax = (bounds[1 - sign.y].y - ray->m_origin.y) * ray->m_invdir.y;

    if ((tmin > tymax) || (tymin > tmax))
        return false;
    if (tymin > tmin)
        tmin = tymin;
    if (tymax < tmax)
        tmax = tymax;

    tzmin = (bounds[sign.z].z - ray->m_origin.z) * ray->m_invdir.z;
    tzmax = (bounds[1 - sign.z].z - ray->m_origin.z) * ray->m_invdir.z;

    if ((tmin > tzmax) || (tzmin > tmax))
        return false;
    if (tzmin > tmin)
        tmin = tzmin;
    if (tzmax < tmax)
        tmax = tzmax;

    return true;
}

// Möller-Trumbore intersection algorithm
// (see https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm)
bool intersect_ray_triangle(const Ray *ray, __constant const Triangle *triangle, float *dist) {
    // Calculate edges of triangle from v0.
    float3 e0 = triangle->m_v2 - triangle->m_v1;
    float3 e1 = triangle->m_v3 - triangle->m_v1;

    // Calculate determinant to check whether the ray is in the newly calculated plane made up from
    // e0 and e1.
    float3 pvec = cross(ray->m_dir, e1);
    float det = dot(e0, pvec);

    // Check whether determinant is close to 0. If that is the case, the ray is in the same plane as
    // the triangle itself which means that they can't collide. This effectively disables backface
    // culling for which we would instead only check whether det < epsilon.
    if (det > -EPSILON && det < EPSILON)
        return false;

    float inv_det = 1.f / det;

    // Calculate distance from v1 to ray origin
    float3 tvec = ray->m_origin - triangle->m_v1;

    // Calculate u parameter and test bound
    float u = dot(tvec, pvec) * inv_det;

    // Check whether the intersection lies outside of the triangle
    if (u < 0.f || u > 1.f)
        return false;

    // Prepare to test v parameter
    float3 qvec = cross(tvec, e0);

    // Calculate v parameter and test bound
    float v = dot(ray->m_dir, qvec) * inv_det;

    // Check whether the intersection lies outside of the triangle
    if (v < 0.f || u + v > 1.f)
        return false;

    float t = dot(e1, qvec) * inv_det;

    if (t > EPSILON) {
        *dist = t - EPSILON;
        return true;
    }

    // If we end up here, there was no hit
    return false;
}

IntersectionInfo Scene_intersect(__constant FlatStructure *accel_struct, Ray *ray) {
    IntersectionInfo intersect_info;

    // Keep track of closest triangle
    float closest_dist = FLT_MAX;
    Triangle closest_triangle;
    // for (const auto &shape : FlatStructure::shapes(flatstruct)) {
    //     if (intersect_ray_aabb(ray, Shape::aabb(shape))) {
    //         for (auto &tri : Shape::triangles(shape)) {
    for (unsigned i = 0; i < accel_struct->m_num_triangles; i++) {
        float dist_to_intersect;
        __constant Triangle *tri = &(accel_struct->m_triangles[i]);
        bool intersected = intersect_ray_triangle(ray, tri, &dist_to_intersect);
        if (intersected) {
            // Find closest triangle
            if (dist_to_intersect < closest_dist) {
                closest_dist = dist_to_intersect;
                closest_triangle = *tri;

                intersect_info.m_has_intersected = true;
                intersect_info.m_pos = ray->m_origin + ray->m_dir * closest_dist;
                intersect_info.m_incoming_ray = *ray;
                intersect_info.m_normal = closest_triangle.m_normal;
                intersect_info.m_material = closest_triangle.m_material;
            }
        }
    }
    //     }
    // }

    return intersect_info;
}

__kernel void renderer_trace_pixel_color(__write_only __global float4 *output, const int width,
                                         const unsigned max_depth, __global PRNG *prng,
                                         __constant Camera *camera,
                                         __constant FlatStructure *flatstruct) {
    int x = get_global_id(0);
    int y = get_global_id(1);
    int index = y * width + x;

    float2 rel_pos = Camera_screenspace_to_camspace(camera, x, y);
    float3 world_pos = Camera_camspace_to_worldspace(camera, rel_pos);
    float3 ray_dir = normalize(world_pos - camera->m_pos);

    float3 ret_color = (float3)(0);
    Ray next_ray = {world_pos, ray_dir};
    float3 brdf = (float3)(1);
    for (unsigned depth = 0; depth < max_depth; depth++) {
        IntersectionInfo intersect_info = Scene_intersect(flatstruct, &next_ray);
        if (intersect_info.m_has_intersected) {
            // Get the local radiance only on first bounce
            float3 local_radiance;
            // if (depth == 0) {
            // auto ray = ray_pos - impact_pos;
            // float dist2 = glm_dot(ray, ray);
            // auto cos_area = glm_dot(-ray_dir, tri->m_normal) * tri->m_area;
            // auto solid_angle = cos_area / glm_max(dist2, 1e-6f);
            //
            // if (cos_area > 0.0)
            //     local_radiance = tri->m_emittance * solid_angle;
            //     local_radiance = intersect_info.m_material.m_emittance;
            // }

            local_radiance = intersect_info.m_material.m_emittance;

            // Emitter sample
            // TODO
            // glm_vec3 illumination;

            float3 normal =
                intersect_info.m_normal *
                -sign(dot(intersect_info.m_normal, intersect_info.m_incoming_ray.m_dir));

            // Find new random direction for diffuse reflection
            float u = 2.f * rand_range(prng, 0.f, 1.f);
            float v = 2.f * M_PI_F * rand_range(prng, 0.f, 1.f);
            float xx = sqrt(1 - u * u) * cos(v);
            float yy = sqrt(1 - u * u) * sin(v);
            float zz = u;
            float3 new_ray_dir = {xx, yy, zz};
            new_ray_dir = normalize(new_ray_dir);
            if (dot(new_ray_dir, normal) < 0) {
                new_ray_dir = -new_ray_dir;
            }

            float cos_theta = dot(new_ray_dir, normal);

            ret_color += brdf * local_radiance;
            brdf *= 2.f * intersect_info.m_material.m_reflectance * cos_theta;

            // Make a new ray
            Ray new_ray = {intersect_info.m_pos, new_ray_dir};
            next_ray = new_ray;

        } else {
            break;
        }
    }

    output[index] = (float4)(ret_color.x, ret_color.y, ret_color.z, 1.f);
    // output[index] = (float4)(rand_range(prng, 0.f, 1.f), rand_range(prng, 0.f, 1.f),
    //                          rand_range(prng, 0.f, 1.f), 1.f);
}


Added CL_MEM_LOCAL definition.

Added CL_MEM_LOCAL definition.

git-svn-id: 602a26e73ae9f2a14e2bb95676f2e137fcc39919@3072 7c0444ca-5550-0410-9008-faecdbe78eb5

#include "LIF_params.h"
#include "cl_random.cl"

#ifndef __CL_PLATFORM_H

#  include <math.h>
#  define EXP expf
#  define CL_KERNEL
#  define CL_MEM_GLOBAL
#  define CL_MEM_LOCAL

#else  /* compiling with OpenCL */

#  define EXP exp
#  define CL_KERNEL     __kernel
#  define CL_MEM_GLOBAL __global
#  define CL_MEM_LOCAL  __local

#endif

//
// update the state of a retinal layer (spiking)
//
//    assume called with 1D kernel
//
CL_KERNEL
void LIF_update_state(
    const float time,
    const float dt,
    const LIF_params * params,

    const int nx,
    const int ny,
    const int nf,
    const int nb,

    CL_MEM_GLOBAL uint4 * rnd,
    CL_MEM_GLOBAL float * V,
    CL_MEM_GLOBAL float * Vth,
    CL_MEM_GLOBAL float * G_E,
    CL_MEM_GLOBAL float * G_I,
    CL_MEM_GLOBAL float * G_IB,
    CL_MEM_GLOBAL float * phiExc,
    CL_MEM_GLOBAL float * phiInh,
    CL_MEM_GLOBAL float * phiInhB,
    CL_MEM_GLOBAL float * activity)
{
   int k;
#ifndef __CL_PLATFORM_H
for (k = 0; k < nx*ny*nf; k++) {
#else
   k = get_global_id(0);
#endif

   int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // local param variables
   float tau, tauE, tauI, tauIB, Vrest, VthRest, Vexc, Vinh, VinhB, tauVth, deltaVth;

   float dt_sec;
   const float GMAX = 10.0;

   // local variables
   float l_activ;

   uint4 l_rnd = rnd[k];

   float l_V   = V[k];
   float l_Vth = Vth[k];

   float l_G_E  = G_E[k];
   float l_G_I  = G_I[k];
   float l_G_IB = G_IB[k];

   float l_phiExc  = phiExc[k];
   float l_phiInh  = phiInh[k];
   float l_phiInhB = phiInhB[k];

   // temporary arrays
   float tauInf, VmemInf;

   //
   // start of LIF2_update_exact_linear
   //

   // define local param variables
   //
   tau   = params->tau;
   tauE  = params->tauE;
   tauI  = params->tauI;
   tauIB = params->tauIB;

   Vrest = params->Vrest;
   Vexc  = params->Vexc;
   Vinh  = params->Vinh;
   VinhB = params->VinhB;

   tauVth   = params->tauVth;
   VthRest  = params->VthRest;
   deltaVth = params->deltaVth;

   // add noise
   //
   dt_sec = .001 * dt;   // convert to seconds

   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqE) {
      l_rnd = cl_random_state(l_rnd);
      l_phiExc = l_phiExc + params->noiseAmpE*cl_random_prob(l_rnd);
      l_rnd = cl_random_state(l_rnd);
   }

   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqI) {
      l_rnd = cl_random_state(l_rnd);
      l_phiInh = l_phiInh + params->noiseAmpI*cl_random_prob(l_rnd);
      l_rnd = cl_random_state(l_rnd);
   }

   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqIB) {
      l_rnd = cl_random_state(l_rnd);
      l_phiInhB = l_phiInhB + params->noiseAmpIB*cl_random_prob(l_rnd);
      l_rnd = cl_random_state(l_rnd);
   }

   l_G_E  = l_phiExc  + l_G_E *EXP(-dt/tauE );
   l_G_I  = l_phiInh  + l_G_I *EXP(-dt/tauI );
   l_G_IB = l_phiInhB + l_G_IB*EXP(-dt/tauIB);

   tauInf  = (dt/tau) * (1.0 + l_G_E + l_G_I + l_G_IB);
   VmemInf = (Vrest + l_G_E*Vexc + l_G_I*Vinh + l_G_IB*VinhB)
           / (1.0 + l_G_E + l_G_I + l_G_IB);

   l_V = VmemInf + (l_V - VmemInf)*EXP(-tauInf);

   //
   // start of LIF2_update_finish
   //

   l_phiExc  = 0.0f;
   l_phiInh  = 0.0f;
   l_phiInhB = 0.0f;

   l_Vth = VthRest + (l_Vth - VthRest)*EXP(-dt/tauVth);

   //
   // start of update_f
   //

   l_G_E  = (l_G_E  > GMAX) ? GMAX : l_G_E;
   l_G_I  = (l_G_I  > GMAX) ? GMAX : l_G_I;
   l_G_IB = (l_G_IB > GMAX) ? GMAX : l_G_IB;

   l_activ = activity[kex];

   l_activ = (l_V > l_Vth) ? 1.0f           : 0.0f;
   l_V     = (l_V > l_Vth) ? Vrest          : l_V;
   l_Vth   = (l_V > l_Vth) ? l_Vth + deltaVth : l_Vth;
   l_G_IB  = (l_V > l_Vth) ? l_G_IB + 1.0f    : l_G_IB;

   //
   // These actions must be done outside of kernel
   //    1. set activity to 0 in boundary (if needed)
   //    2. update active indices
   //

   // store local variables back to global memory
   //
   activity[kex] = l_activ;

   V[k]   = l_V;
   Vth[k] = l_Vth;

   G_E[k]  = l_G_E;
   G_I[k]  = l_G_I;
   G_IB[k] = l_G_IB;

   phiExc[k]  = l_phiExc;
   phiInh[k]  = l_phiInh;
   phiInhB[k] = l_phiInhB;

#ifndef __CL_PLATFORM_H
   } // loop over k
#endif

}

#ifndef __CL_PLATFORM_H
#  include <math.h>
#  define EXP expf
#  define CL_KERNEL
#  define CL_MEM_GLOBAL
#else
#  define EXP exp
#endif

#include "cl_random.cl"
#include "LIF_params.h"

//
// update the state of a retinal layer (spiking)
//
//    assume called with 1D kernel
//
CL_KERNEL
void LIF_update_state(
    const float time,
    const float dt,
    const LIF_params * params,

    const int nx,
    const int ny,
    const int nf,
    const int nb,

    CL_MEM_GLOBAL uint4 * rnd,
    CL_MEM_GLOBAL float * V,
    CL_MEM_GLOBAL float * Vth,
    CL_MEM_GLOBAL float * G_E,
    CL_MEM_GLOBAL float * G_I,
    CL_MEM_GLOBAL float * G_IB,
    CL_MEM_GLOBAL float * phiExc,
    CL_MEM_GLOBAL float * phiInh,
    CL_MEM_GLOBAL float * phiInhB,
    CL_MEM_GLOBAL float * activity)
{
   int k;
#ifndef __CL_PLATFORM_H
for (k = 0; k < nx*ny*nf; k++) {
#else
   k = get_global_id(0);
#endif

   int kex = kIndexExtended(k, nx, ny, nf, nb);

   //
   // kernel (nonheader part) begins here
   //

   // local param variables
   float tau, tauE, tauI, tauIB, Vrest, VthRest, Vexc, Vinh, VinhB, tauVth, deltaVth;

   float dt_sec;
   const float GMAX = 10.0;

   // local variables
   float l_activ;

   uint4 l_rnd = rnd[k];

   float l_V   = V[k];
   float l_Vth = Vth[k];

   float l_G_E  = G_E[k];
   float l_G_I  = G_I[k];
   float l_G_IB = G_IB[k];

   float l_phiExc  = phiExc[k];
   float l_phiInh  = phiInh[k];
   float l_phiInhB = phiInhB[k];

   // temporary arrays
   float tauInf, VmemInf;

   //
   // start of LIF2_update_exact_linear
   //

   // define local param variables
   //
   tau   = params->tau;
   tauE  = params->tauE;
   tauI  = params->tauI;
   tauIB = params->tauIB;

   Vrest = params->Vrest;
   Vexc  = params->Vexc;
   Vinh  = params->Vinh;
   VinhB = params->VinhB;

   tauVth   = params->tauVth;
   VthRest  = params->VthRest;
   deltaVth = params->deltaVth;

   // add noise
   //
   dt_sec = .001 * dt;   // convert to seconds

   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqE) {
      l_rnd = cl_random_state(l_rnd);
      l_phiExc = l_phiExc + params->noiseAmpE*cl_random_prob(l_rnd);
      l_rnd = cl_random_state(l_rnd);
   }

   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqI) {
      l_rnd = cl_random_state(l_rnd);
      l_phiInh = l_phiInh + params->noiseAmpI*cl_random_prob(l_rnd);
      l_rnd = cl_random_state(l_rnd);
   }

   if (cl_random_prob(l_rnd) < dt_sec*params->noiseFreqIB) {
      l_rnd = cl_random_state(l_rnd);
      l_phiInhB = l_phiInhB + params->noiseAmpIB*cl_random_prob(l_rnd);
      l_rnd = cl_random_state(l_rnd);
   }

   l_G_E  = l_phiExc  + l_G_E *EXP(-dt/tauE );
   l_G_I  = l_phiInh  + l_G_I *EXP(-dt/tauI );
   l_G_IB = l_phiInhB + l_G_IB*EXP(-dt/tauIB);

   tauInf  = (dt/tau) * (1.0 + l_G_E + l_G_I + l_G_IB);
   VmemInf = (Vrest + l_G_E*Vexc + l_G_I*Vinh + l_G_IB*VinhB)
           / (1.0 + l_G_E + l_G_I + l_G_IB);

   l_V = VmemInf + (l_V - VmemInf)*EXP(-tauInf);

   //
   // start of LIF2_update_finish
   //

   l_phiExc  = 0.0f;
   l_phiInh  = 0.0f;
   l_phiInhB = 0.0f;

   l_Vth = VthRest + (l_Vth - VthRest)*EXP(-dt/tauVth);

   //
   // start of update_f
   //

   l_G_E  = (l_G_E  > GMAX) ? GMAX : l_G_E;
   l_G_I  = (l_G_I  > GMAX) ? GMAX : l_G_I;
   l_G_IB = (l_G_IB > GMAX) ? GMAX : l_G_IB;

   l_activ = activity[kex];

   l_activ = (l_V > l_Vth) ? 1.0f           : 0.0f;
   l_V     = (l_V > l_Vth) ? Vrest          : l_V;
   l_Vth   = (l_V > l_Vth) ? l_Vth + deltaVth : l_Vth;
   l_G_IB  = (l_V > l_Vth) ? l_G_IB + 1.0f    : l_G_IB;

   //
   // These actions must be done outside of kernel
   //    1. set activity to 0 in boundary (if needed)
   //    2. update active indices
   //

   // store local variables back to global memory
   //
   activity[kex] = l_activ;

   V[k]   = l_V;
   Vth[k] = l_Vth;

   G_E[k]  = l_G_E;
   G_I[k]  = l_G_I;
   G_IB[k] = l_G_IB;

   phiExc[k]  = l_phiExc;
   phiInh[k]  = l_phiInh;
   phiInhB[k] = l_phiInhB;

#ifndef __CL_PLATFORM_H
   } // loop over k
#endif

}


Correção na substituição (AMD)

Correção na substituição (AMD)

typedef individuo data_t;
#define getKey(a) (a.aptidao)
#define getValue(a) (0)
/*
__kernel void RankSort(__global const data_t * in,__global data_t * out)
{
  int i = get_global_id(0);
  int n = get_global_size(0);
  data_t iData = in[i];
  float iKey = getKey(iData);

  // Encontra a posição da entrada in[i] no vetor ordenado
  int pos = 0;
  for (int j=0;j<n;j++)
  {
    float jKey = getKey(in[j]);
    bool smaller = (jKey < iKey) || (jKey == iKey && j < i);
    pos += (smaller) ? 1:0;
  }

  out[pos] = iData;
}*/
/*
__kernel void teste_async_copy( __global int* pop, __local int* program){

    __local uint program_size;

    program_size = 10;
    program[get_global_id(0)] = -1;
    event_t e_copy = async_work_group_copy(program, pop, program_size, 0 );
    wait_group_events( 1, &e_copy );
    e_copy = async_work_group_copy(pop, program, program_size, 0 );
    wait_group_events( 1, &e_copy );
}*/

__kernel void substituicao(__global data_t * geracaoAtual,
                           __global data_t * novaGeracao,
                           __global data_t * saida)
{

    int tid  = get_global_id(0),
        lid  = get_local_id(0),
        gid  = get_group_id(0);
    int localSize = get_local_size(0);
    int n = TAMANHO_POPULACAO;

    __local int pos1, pos2;

    if(lid==0){

        //Obtém o item geracaoAtual[gid]
        //data_t atualData = geracaoAtual[gid];
        float itemGeracaoAtual = getKey(geracaoAtual[gid]);

        //Obtém o item novaGeracao[i]
        //data_t novaData = novaGeracao[gid];
        float itemNovaGeracao = getKey(novaGeracao[gid]);

        //Encontra a posição da entrada geracaoAtual[i] e novaGeracao[i] no vetor ordenado utilizando rank sort
        pos1 = 0;
        pos2 = 0;

        float jKey1, jKey2;
        bool maior=0;

        for (int j=0;j<n;j++)
        {
            //Conta elementos menores que itemGeracaoAtual
            jKey1 = getKey(geracaoAtual[j]);
            maior = (jKey1 > itemGeracaoAtual) || (jKey1 == itemGeracaoAtual && j > gid);
            pos1 += (maior) ? 1:0;

            //Conta elementos menores que itemNovaGeracao
            jKey2 = getKey(novaGeracao[j]);
            maior = (jKey2 > itemNovaGeracao)  || (jKey2 == itemNovaGeracao &&  j > gid);
            pos2 += (maior) ? 1:0;
        }
    }

    barrier(CLK_LOCAL_MEM_FENCE);

    //Mantém a elite da geração atual
    if(pos1 < ELITE){

        //saida[pos1] = geracaoAtual[gid];

        /*for(int j = 0; j < TAMANHO_INDIVIDUO; j++){
            saida[pos1].genotipo[j] = geracaoAtual[gid].genotipo[j];
        }*/

        for(int j = lid; j < TAMANHO_INDIVIDUO; j+=localSize){
            saida[pos1].genotipo[j] = geracaoAtual[gid].genotipo[j];
        }

        saida[pos1].aptidao = geracaoAtual[gid].aptidao;

        //saida[pos1].genotipo[lid] = novaGeracao[gid].genotipo[lid];
        //saida[pos1].aptidao = novaGeracao[gid].aptidao;
    }

    //Substitui o elemento pelo indivíduo da geração atual.
    //No total serão substitúidos N-ELITE elementos.
    if(pos2 < n-ELITE){

        //saida[pos2+ELITE] = novaGeracao[gid];

        /*for(int j = 0; j < TAMANHO_INDIVIDUO; j++){
            saida[pos2+ELITE].genotipo[j] = novaGeracao[gid].genotipo[j];
        }

        saida[pos2+ELITE].aptidao = novaGeracao[gid].aptidao;*/

        for(int j = lid; j < TAMANHO_INDIVIDUO; j+=localSize){
            saida[pos2+ELITE].genotipo[j] = novaGeracao[gid].genotipo[j];
        }

        saida[pos2+ELITE].aptidao = novaGeracao[gid].aptidao;
        //saida[pos2+ELITE].genotipo[lid] = novaGeracao[gid].genotipo[lid];
    }
}

/*
__kernel void substituicao_gpu(__global data_t * geracaoAtual,
			        __global data_t * novaGeracao,
	    		    __global data_t * saida,
	    		    __local int *aux1,
	    		    __local int *aux2)

{
    int i  = get_global_id(0);
    int n  = get_global_size(0);
    int wg = get_local_size(0);

    int blockSize = wg; //tamanho do bloco

    if(i < TAMANHO_POPULACAO){

    	//Obtém o item geracaoAtual[i]
    	float itemGeracaoAtual = getKey(geracaoAtual[i]);

    	//Obtém o item novaGeracao[i]
    	float itemNovaGeracao = getKey(novaGeracao[i]);

    	// Encontra a posição das entradas geracaoAtual[i] e novaGeracao[i] no vetor ordenado utilizando rank sort
    	int pos1 = 0, pos2 = 0;
    	float jKey1, jKey2;
    	bool maior = 0;

    	// Laço em blocos de tamanho blockSize
  	for (int j=0; j<n; j+=blockSize)
  	{
	    //Copia n/blocksize para a memória local
	    barrier(CLK_LOCAL_MEM_FENCE);

	    for (int index=i;index<blockSize;index+=wg)
	    {
	      aux1[index] = getKey(geracaoAtual[j+index]);
      	      aux2[index] = getKey(novaGeracao[j+index]);
	    }

	    barrier(CLK_LOCAL_MEM_FENCE);

	    // Laço percorrendo os valores copiados para a memória local
	    for (int index=0;index<blockSize;index++)
	    {
	      jKey1 = aux1[index]; //recupera as chaves da memória local
	      jKey2 = aux2[index];

	      //Conta elementos menores que itemGeracaoAtual
	      maior = (jKey1 > itemGeracaoAtual) || (jKey1 == itemGeracaoAtual && (j+index) < i);
	      pos1  = (maior) ? 1:0;

	      //Conta elementos menores que itemNovaGeracao
	      maior = (jKey2 > itemNovaGeracao)  || (jKey2 == itemNovaGeracao &&  (j+index) < i);
	      pos2 += (maior) ? 1:0;

	    }
  	}

        //Mantém a elite da geração atual
        if(pos1 < ELITE){
	    saida[pos1] = geracaoAtual[i];
        }

        //Substitui o elemento pelo indivíduo da geração atual.
        //No total serão substitúidos N-ELITE elementos.
        if(pos2 < n-ELITE){
	    saida[pos2+ELITE] = novaGeracao[i];
        }
    }
}*/

typedef individuo data_t;
#define getKey(a) (a.aptidao)
#define getValue(a) (0)
/*
__kernel void RankSort(__global const data_t * in,__global data_t * out)
{
  int i = get_global_id(0);
  int n = get_global_size(0);
  data_t iData = in[i];
  float iKey = getKey(iData);

  // Encontra a posição da entrada in[i] no vetor ordenado
  int pos = 0;
  for (int j=0;j<n;j++)
  {
    float jKey = getKey(in[j]);
    bool smaller = (jKey < iKey) || (jKey == iKey && j < i);
    pos += (smaller) ? 1:0;
  }

  out[pos] = iData;
}*/
/*
__kernel void teste_async_copy( __global int* pop, __local int* program){

    __local uint program_size;

    program_size = 10;
    program[get_global_id(0)] = -1;
    event_t e_copy = async_work_group_copy(program, pop, program_size, 0 );
    wait_group_events( 1, &e_copy );
    e_copy = async_work_group_copy(pop, program, program_size, 0 );
    wait_group_events( 1, &e_copy );
}*/

__kernel void substituicao(__global data_t * geracaoAtual,
                           __global data_t * novaGeracao,
                           __global data_t * saida)
{

    int tid  = get_global_id(0),
        lid  = get_local_id(0),
        gid  = get_group_id(0);
    int localSize = get_local_size(0);
    int n = TAMANHO_POPULACAO;

    __local int pos1, pos2;

    if(lid==0){

        //Obtém o item geracaoAtual[gid]
        data_t atualData = geracaoAtual[gid];
        float itemGeracaoAtual = getKey(atualData);

        //Obtém o item novaGeracao[i]
        data_t novaData = novaGeracao[gid];
        float itemNovaGeracao = getKey(novaData);

        //Encontra a posição da entrada geracaoAtual[i] e novaGeracao[i] no vetor ordenado utilizando rank sort
        pos1 = 0;
        pos2 = 0;

        float jKey1, jKey2;
        bool maior=0;

        for (int j=0;j<n;j++)
        {
            //Conta elementos menores que itemGeracaoAtual
            jKey1 = getKey(geracaoAtual[j]);
            maior = (jKey1 > itemGeracaoAtual) || (jKey1 == itemGeracaoAtual && j > gid);
            pos1 += (maior) ? 1:0;

            //Conta elementos menores que itemNovaGeracao
            jKey2 = getKey(novaGeracao[j]);
            maior = (jKey2 > itemNovaGeracao)  || (jKey2 == itemNovaGeracao &&  j > gid);
            pos2 += (maior) ? 1:0;
        }
    }

    barrier(CLK_LOCAL_MEM_FENCE);

    //Mantém a elite da geração atual
    if(pos1 < ELITE){

        //saida[pos1] = geracaoAtual[gid];

        /*for(int j = 0; j < TAMANHO_INDIVIDUO; j++){
            saida[pos1].genotipo[j] = geracaoAtual[gid].genotipo[j];
        }*/

        for(int j = lid; j < TAMANHO_INDIVIDUO; j+=localSize){
            saida[pos1].genotipo[j] = geracaoAtual[gid].genotipo[j];
        }

        saida[pos1].aptidao = geracaoAtual[gid].aptidao;

        //saida[pos1].genotipo[lid] = novaGeracao[gid].genotipo[lid];
        //saida[pos1].aptidao = novaGeracao[gid].aptidao;
    }

    //Substitui o elemento pelo indivíduo da geração atual.
    //No total serão substitúidos N-ELITE elementos.
    if(pos2 < n-ELITE){

        //saida[pos2+ELITE] = novaGeracao[gid];

        /*for(int j = 0; j < TAMANHO_INDIVIDUO; j++){
            saida[pos2+ELITE].genotipo[j] = novaGeracao[gid].genotipo[j];
        }

        saida[pos2+ELITE].aptidao = novaGeracao[gid].aptidao;*/

        for(int j = lid; j < TAMANHO_INDIVIDUO; j+=localSize){
            saida[pos2+ELITE].genotipo[j] = novaGeracao[gid].genotipo[j];
        }

        saida[pos2+ELITE].aptidao = novaGeracao[gid].aptidao;
        //saida[pos2+ELITE].genotipo[lid] = novaGeracao[gid].genotipo[lid];
    }
}

/*
__kernel void substituicao_gpu(__global data_t * geracaoAtual,
			        __global data_t * novaGeracao,
	    		    __global data_t * saida,
	    		    __local int *aux1,
	    		    __local int *aux2)

{
    int i  = get_global_id(0);
    int n  = get_global_size(0);
    int wg = get_local_size(0);

    int blockSize = wg; //tamanho do bloco

    if(i < TAMANHO_POPULACAO){

    	//Obtém o item geracaoAtual[i]
    	float itemGeracaoAtual = getKey(geracaoAtual[i]);

    	//Obtém o item novaGeracao[i]
    	float itemNovaGeracao = getKey(novaGeracao[i]);

    	// Encontra a posição das entradas geracaoAtual[i] e novaGeracao[i] no vetor ordenado utilizando rank sort
    	int pos1 = 0, pos2 = 0;
    	float jKey1, jKey2;
    	bool maior = 0;

    	// Laço em blocos de tamanho blockSize
  	for (int j=0; j<n; j+=blockSize)
  	{
	    //Copia n/blocksize para a memória local
	    barrier(CLK_LOCAL_MEM_FENCE);

	    for (int index=i;index<blockSize;index+=wg)
	    {
	      aux1[index] = getKey(geracaoAtual[j+index]);
      	      aux2[index] = getKey(novaGeracao[j+index]);
	    }

	    barrier(CLK_LOCAL_MEM_FENCE);

	    // Laço percorrendo os valores copiados para a memória local
	    for (int index=0;index<blockSize;index++)
	    {
	      jKey1 = aux1[index]; //recupera as chaves da memória local
	      jKey2 = aux2[index];

	      //Conta elementos menores que itemGeracaoAtual
	      maior = (jKey1 > itemGeracaoAtual) || (jKey1 == itemGeracaoAtual && (j+index) < i);
	      pos1  = (maior) ? 1:0;

	      //Conta elementos menores que itemNovaGeracao
	      maior = (jKey2 > itemNovaGeracao)  || (jKey2 == itemNovaGeracao &&  (j+index) < i);
	      pos2 += (maior) ? 1:0;

	    }
  	}

        //Mantém a elite da geração atual
        if(pos1 < ELITE){
	    saida[pos1] = geracaoAtual[i];
        }

        //Substitui o elemento pelo indivíduo da geração atual.
        //No total serão substitúidos N-ELITE elementos.
        if(pos2 < n-ELITE){
	    saida[pos2+ELITE] = novaGeracao[i];
        }
    }
}*/