More optimizations

More optimizations

/**********************************************************************
Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved.

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.
********************************************************************/

/*************************************************************************
INCLUDES
**************************************************************************/
#include <../RadeonRays/src/kernels/CL/common.cl>
/*************************************************************************
EXTENSIONS
**************************************************************************/

/*************************************************************************
TYPE DEFINITIONS
**************************************************************************/
#define STARTIDX(x)     (((int)(x.pmin.w)) >> 4)
#define NUMPRIMS(x)     (((int)(x.pmin.w)) & 0xF)
#define LEAFNODE(x)     (((x).pmin.w) != -1.f)
#define CHILD(x,i)         ((int)x.bounds[i].pmax.w)
#define SHORT_STACK_SIZE 16
#define WAVEFRONT_SIZE 64

//#define GLOBAL_STACK

typedef struct
{
    union
    {
        struct
        {
            bbox lbound;
            bbox rbound;
        };

        struct
        {
            bbox bounds[2];
        };
    };

} FatBvhNode;

typedef struct
{
    // BVH structure
    __global FatBvhNode const*     nodes;
    // Scene positional data
    __global float3 const*         vertices;
    // Scene indices
    __global Face const*         faces;
    // Shape IDs
    __global ShapeData const*     shapes;
    // Extra data
    __global int const*             extra;
} SceneData;

/*************************************************************************
HELPER FUNCTIONS
**************************************************************************/

/*************************************************************************
BVH FUNCTIONS
**************************************************************************/
//  intersect a ray with leaf BVH node
inline
void IntersectLeafClosest(
    SceneData const* scenedata,
    int startidx,
    int numprims,
    ray const* r,                // ray to instersect
    Intersection* isect          // Intersection structure
    )
{
    float3 v1, v2, v3;
    Face face;
    for (int i = 0; i < numprims; ++i)
    {
        face = scenedata->faces[startidx + i];
        v1 = scenedata->vertices[face.idx[0]];
        v2 = scenedata->vertices[face.idx[1]];
        v3 = scenedata->vertices[face.idx[2]];

#ifdef RR_RAY_MASK
        int shapemask = scenedata->shapes[face.shapeidx].mask;

        if (Ray_GetMask(r) & shapemask)
#endif
        {
            if (IntersectTriangle(r, v1, v2, v3, isect))
            {
                isect->primid = face.id;
                isect->shapeid = face.shapeidx;
            }
        }
    }
}

//  intersect a ray with leaf BVH node
inline
bool IntersectLeafAny(
    SceneData const* scenedata,
    int startidx,
    int numprims,
    ray const* r                      // ray to instersect
    )
{
    float3 v1, v2, v3;
    Face face;

    bool hit = false;
    for (int i = 0; i < numprims; ++i)
    {
        face = scenedata->faces[startidx + i];
        v1 = scenedata->vertices[face.idx[0]];
        v2 = scenedata->vertices[face.idx[1]];
        v3 = scenedata->vertices[face.idx[2]];

#ifdef RR_RAY_MASK
        int shapemask = scenedata->shapes[face.shapeidx].mask;

        if (Ray_GetMask(r) & shapemask)
#endif
        {
            if (IntersectTriangleP(r, v1, v2, v3))
            {
                hit =  true;
                break;
            }
        }
    }

    return hit;
}

inline
bool intersect(
    SceneData const* scenedata,
    ray const* r,
    Intersection* isect,
    __global int* displacement,
    __global int* hash,
    int t
    )
{
    const float3 invdir = native_recip(r->d.xyz);
    isect->uvwt = make_float4(0.f, 0.f, 0.f, r->o.w);
    isect->shapeid = -1;
    isect->primid = -1;

    int bittrail = 0;
    int nodeidx = 1;
    int addr = 0;

    FatBvhNode node;

    while (addr > -1)
    {
        node = scenedata->nodes[addr];
        bool l0 = LEAFNODE(node.lbound);
        bool l1 = LEAFNODE(node.rbound);
        float d0 = -1.f;
        float d1 = -1.f;

        if (l0)
        {
            IntersectLeafClosest(scenedata, STARTIDX(node.lbound), NUMPRIMS(node.lbound), r, isect);
        }
        else
        {
            d0 = IntersectBoxF(r, invdir, node.lbound, isect->uvwt.w);
        }

        if (l1)
        {
            IntersectLeafClosest(scenedata, STARTIDX(node.rbound), NUMPRIMS(node.rbound), r, isect);
        }
        else
        {
            d1 = IntersectBoxF(r, invdir, node.rbound, isect->uvwt.w);
        }

        if (d0 > 0 && d1 > 0)
        {
            bittrail = bittrail << 1;
            nodeidx = nodeidx << 1;
            bittrail = bittrail ^ 0x1;

            if (d0 > d1)
            {
                addr = CHILD(node, 1);
                nodeidx = nodeidx ^ 0x1;
            }
            else
            {
                addr = CHILD(node, 0);
            }
            continue;
        }
        else if (d0 > 0)
        {
            bittrail = bittrail << 1;
            nodeidx = nodeidx << 1;
            addr = CHILD(node, 0);
            continue;
        }
        else if (d1 > 0)
        {
            bittrail = bittrail << 1;
            nodeidx = nodeidx << 1;
            nodeidx = nodeidx ^ 0x1;
            addr = CHILD(node, 1);
            continue;
        }

        if (bittrail == 0)
        {
            addr = -1;
            continue;
        }

        int num_levels = 31 - clz(bittrail & -bittrail);
        bittrail = (bittrail >> num_levels) ^ 0x1;
        nodeidx = (nodeidx >> num_levels) ^ 0x1;

        int d = displacement[nodeidx / t];
        addr = hash[d + (nodeidx & (t - 1))];
    }

    return isect->shapeid >= 0;
}

// intersect Ray against the whole BVH structure
inline
bool occluded(SceneData const* scenedata, ray const* r)
{
    const float3 invdir = native_recip(r->d.xyz);

    int stack[32];
    int* sptr = stack;
    *sptr++ = -1;

    int idx = 0;
    FatBvhNode node;

    while (idx > -1)
    {
        while (idx > -1)
        {
            node = scenedata->nodes[idx];

            bool l0 = LEAFNODE(node.lbound);
            bool l1 = LEAFNODE(node.rbound);
            float d0 = -1.f;
            float d1 = -1.f;

            if (l0)
            {
                bool hit = IntersectLeafAny(scenedata, STARTIDX(node.lbound), NUMPRIMS(node.lbound), r);
                if (hit)
                {
                    return true;
                }
            }
            else
            {
                d0 = IntersectBoxF(r, invdir, node.lbound, r->o.w);
            }

            if (l1)
            {
                bool hit = IntersectLeafAny(scenedata, STARTIDX(node.rbound), NUMPRIMS(node.rbound), r);
                if (hit)
                {
                    return true;
                }
            }
            else
            {
                d1 = IntersectBoxF(r, invdir, node.rbound, r->o.w);
            }

            if (d0 > 0 && d1 > 0)
            {
                int deferred = -1;
                if (d0 > d1)
                {
                    idx = CHILD(node, 1);
                    deferred = CHILD(node, 0);
                }
                else
                {
                    idx = CHILD(node, 0);
                    deferred = CHILD(node, 1);
                }

                *sptr++ = deferred;
                continue;
            }
            else if (d0 > 0)
            {
                idx = CHILD(node, 0);
                continue;
            }
            else if (d1 > 0)
            {
                idx = CHILD(node, 1);
                continue;
            }

            idx = *--sptr;
        }
    }

    return false;
}

__attribute__((always_inline))
float IntersectTriangleLight(ray r, float3 v1, float3 v2, float3 v3, float t_max)
{
    const float3 e1 = v2 - v1;
    const float3 e2 = v3 - v1;
    const float3 s1 = cross(r.d.xyz, e2);
    const float  invd = native_recip(dot(s1, e1));
    const float3 d = r.o.xyz - v1;
    const float  b1 = dot(d, s1) * invd;
    const float3 s2 = cross(d, e1);
    const float  b2 = dot(r.d.xyz, s2) * invd;
    const float temp = dot(e2, s2) * invd;

    if (b1 < 0.f || b1 > 1.f || b2 < 0.f || b1 + b2 > 1.f
        || temp < 0.f || temp > t_max)
    {
        return t_max;
    }
    else
    {
        return temp;
    }
}

__attribute__((reqd_work_group_size(64, 1, 1)))
__kernel void IntersectClosest(
    // Input
    __global FatBvhNode const* nodes,   // BVH nodes
    __global float3 const* vertices, // Scene positional data
    __global Face const* faces,    // Scene indices
    __global ShapeData const* shapes, // Shape data
    __global ray const* rays,        // Ray workload
    int offset,                // Offset in rays array
    int numrays,               // Number of rays to process
    __global int const* displacement,
    __global int const* hashmap,
    int t,
    __global Intersection* hits // Hit datas
    )
{
    int global_id = get_global_id(0);
    int local_id = get_local_id(0);
    int group_id = get_group_id(0);

    if (global_id < numrays)
    {
        // Fetch ray
        ray r = rays[global_id];

        if (Ray_IsActive(&r))
        {
            // Calculate closest hit
            //intersect(&scenedata, &r, &isect, displacement, hashmap, t);
            float3 const invdir = native_recip(r.d.xyz);
            float3 const oxinvdir = r.o.xyz * invdir;
            float t_max = r.o.w;

            int bittrail = 0;
            int nodeidx = 1;
            int addr = 0;
            int faceidx = -1;
            int postponed = -1;
            //int deferred[3];
            //int cnt = 0;
            bool found = false;
            int p1 = -1;
            int p2 = -1;

            float3 v1, v2, v3;
            Face face;
            FatBvhNode node;

            while (addr > -1)
            {
                while (addr > -1 && !found)
                {
                    node = nodes[addr];
                    bool l0 = LEAFNODE(node.lbound);
                    bool l1 = LEAFNODE(node.rbound);
                    float d0 = -1.f;
                    float d1 = -1.f;

                    if (l0)
                    {
                        p1 = STARTIDX(node.lbound);
                        found = true;
                    }
                    else
                    {
                        const float3 f = mad(node.lbound.pmax.xyz, invdir, oxinvdir);
                        const float3 n = mad(node.lbound.pmin.xyz, invdir, oxinvdir);
                        const float3 tmax = max(f, n);
                        const float3 tmin = min(f, n);
                        const float t1 = amd_min3(tmax.x, tmax.y, tmax.z);
                        const float t0 = amd_max3(tmin.x, tmin.y, tmin.z);
                        if (t0 < t1)
                        {
                            d0 = t0 > 0.f ? t0 : min(t1, t_max);
                        }
                    }

                    if (l1)
                    {
                        if (found)
                            p2 = STARTIDX(node.rbound);
                        else
                            p1 = STARTIDX(node.rbound);

                        found = true;
                    }
                    else
                    {
                        const float3 f = mad(node.rbound.pmax.xyz, invdir, oxinvdir);
                        const float3 n = mad(node.rbound.pmin.xyz, invdir, oxinvdir);
                        const float3 tmax = max(f, n);
                        const float3 tmin = min(f, n);
                        const float t1 = amd_min3(tmax.x, tmax.y, tmax.z);
                        const float t0 = amd_max3(tmin.x, tmin.y, tmin.z);
                        if (t0 < t1)
                        {
                            d1 = t0 > 0.f ? t0 : min(t1, t_max);
                        }
                    }

                    if (d0 > 0 && d1 > 0)
                    {
                        bittrail = bittrail << 1;
                        nodeidx = nodeidx << 1;
                        bittrail = bittrail ^ 0x1;

                        if (d0 > d1)
                        {
                            addr = CHILD(node, 1);
                            nodeidx = nodeidx ^ 0x1;
                            postponed = CHILD(node, 0);
                        }
                        else
                        {
                            addr = CHILD(node, 0);
                            postponed = CHILD(node, 1);
                        }
                        continue;
                    }
                    else if (d0 > 0)
                    {
                        bittrail = bittrail << 1;
                        nodeidx = nodeidx << 1;
                        addr = CHILD(node, 0);
                        continue;
                    }
                    else if (d1 > 0)
                    {
                        bittrail = bittrail << 1;
                        nodeidx = nodeidx << 1;
                        nodeidx = nodeidx ^ 0x1;
                        addr = CHILD(node, 1);
                        continue;
                    }
                }

                if (found)
                {
                    face = faces[p1];
                    v1 = vertices[face.idx[0]];
                    v2 = vertices[face.idx[1]];
                    v3 = vertices[face.idx[2]];

                    float f = IntersectTriangleLight(r, v1, v2, v3, t_max);
                    if (f < t_max)
                    {
                        faceidx = p1;
                        t_max = f;
                    }

                    if (p2 != -1)
                    {
                        face = faces[p2];
                        v1 = vertices[face.idx[0]];
                        v2 = vertices[face.idx[1]];
                        v3 = vertices[face.idx[2]];

                        float f = IntersectTriangleLight(r, v1, v2, v3, t_max);
                        if (f < t_max)
                        {
                            faceidx = p2;
                            t_max = f;
                        }
                    }

                    p1 = p2 = -1;
                    found = false;
                }

                if (bittrail == 0)
                {
                    addr = -1;
                    continue;
                }

                int num_levels = 31 - clz(bittrail & -bittrail);
                bittrail = (bittrail >> num_levels) ^ 0x1;
                nodeidx = (nodeidx >> num_levels) ^ 0x1;

                if (postponed != -1)
                {
                    addr = postponed;
                    postponed = -1;
                    continue;
                }

                int d = displacement[nodeidx / t];
                addr = hashmap[d + (nodeidx & (t - 1))];
            }

            if (faceidx != -1)
            {
                face = faces[p2];
                hits[global_id].shapeid = face.shapeidx;
                hits[global_id].primid = face.id;

                v1 = vertices[face.idx[0]];
                v2 = vertices[face.idx[1]];
                v3 = vertices[face.idx[2]];

                const float3 e1 = v2 - v1;
                const float3 e2 = v3 - v1;
                const float3 s1 = cross(r.d.xyz, e2);
                const float  invd = native_recip(dot(s1, e1));
                const float3 d = r.o.xyz - v1;
                const float  b1 = dot(d, s1) * invd;
                const float3 s2 = cross(d, e1);
                const float  b2 = dot(r.d.xyz, s2) * invd;
                hits[global_id].uvwt = make_float4(b1, b2, 0.f, t_max);
            }
            else
            {
                hits[global_id].shapeid = -1;
                hits[global_id].primid = -1;
            }
        }
    }
}

__attribute__((reqd_work_group_size(64, 1, 1)))
__kernel void IntersectAny(
    // Input
    __global FatBvhNode const* nodes,   // BVH nodes
    __global float3 const* vertices, // Scene positional data
    __global Face const* faces,    // Scene indices
    __global ShapeData const* shapes,     // Shape data
    __global ray const* rays,        // Ray workload
    int offset,                // Offset in rays array
    int numrays,               // Number of rays to process
    __global int const* displacement,
    __global int const* hashmap,
    int t,
    __global int* hitresults  // Hit results
    )
{
    int global_id = get_global_id(0);
    int local_id = get_local_id(0);
    int group_id = get_group_id(0);

    // Fill scene data
    SceneData scenedata =
    {
        nodes,
        vertices,
        faces,
        shapes,
        0
    };

    if (global_id < numrays)
    {
        // Fetch ray
        ray r = rays[global_id];

        if (Ray_IsActive(&r))
        {
            // Calculate any intersection
            hitresults[global_id] = occluded(&scenedata, &r) ? 1 : -1;
        }
    }
}

__attribute__((reqd_work_group_size(64, 1, 1)))
// Version with range check
__kernel void IntersectClosestRC(
    __global FatBvhNode const* nodes,   // BVH nodes
    __global float3 const* vertices, // Scene positional data
    __global Face const* faces,      // Scene indices
    __global ShapeData const* shapes,     // Shape data
    __global ray const* rays,        // Ray workload
    int offset,                // Offset in rays array
    __global int const* numrays,     // Number of rays in the workload
    __global int const* displacement,
    __global int const* hashmap,
    int t,
    __global Intersection* hits
    )
{
    int global_id = get_global_id(0);
    int local_id = get_local_id(0);
    int group_id = get_group_id(0);

    // Fill scene data
    SceneData scenedata =
    {
        nodes,
        vertices,
        faces,
        shapes,
        0
    };

    // Handle only working subset
    if (global_id < *numrays)
    {
        // Fetch ray
        ray r = rays[global_id];

        if (Ray_IsActive(&r))
        {
            // Calculate closest hit
            Intersection isect;
            intersect(&scenedata, &r, &isect, displacement, hashmap, t);
            // Write data back in case of a hit
            hits[global_id] = isect;
        }
    }
}

__attribute__((reqd_work_group_size(64, 1, 1)))
// Version with range check
__kernel void IntersectAnyRC(
    // Input
    __global FatBvhNode const* nodes,   // BVH nodes
    __global float3 const* vertices, // Scene positional data
    __global Face const* faces,    // Scene indices
    __global ShapeData const* shapes,     // Shape data
    __global ray const* rays,        // Ray workload
    int offset,                // Offset in rays array
    __global int const* numrays,     // Number of rays in the workload
    __global int const* displacement,
    __global int const* hashmap,
    int t,
    __global int* hitresults   // Hit results
    )
{
    int global_id = get_global_id(0);
    int local_id = get_local_id(0);
    int group_id = get_group_id(0);

    // Fill scene data
    SceneData scenedata =
    {
        nodes,
        vertices,
        faces,
        shapes,
        0
    };

    // Handle only working subset
    if (global_id < *numrays)
    {
        // Fetch ray
        ray r = rays[global_id];

        if (Ray_IsActive(&r))
        {
            // Calculate any intersection
            hitresults[global_id] = occluded(&scenedata, &r) ? 1 : -1;
        }
    }
}

/**********************************************************************
Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved.

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.
********************************************************************/

/*************************************************************************
INCLUDES
**************************************************************************/
#include <../RadeonRays/src/kernels/CL/common.cl>
/*************************************************************************
EXTENSIONS
**************************************************************************/

/*************************************************************************
TYPE DEFINITIONS
**************************************************************************/
#define STARTIDX(x)     (((int)(x.pmin.w)) >> 4)
#define NUMPRIMS(x)     (((int)(x.pmin.w)) & 0xF)
#define LEAFNODE(x)     (((x).pmin.w) != -1.f)
#define CHILD(x,i)         ((int)x.bounds[i].pmax.w)
#define SHORT_STACK_SIZE 16
#define WAVEFRONT_SIZE 64

//#define GLOBAL_STACK

typedef struct
{
    union
    {
        struct
        {
            bbox lbound;
            bbox rbound;
        };

        struct
        {
            bbox bounds[2];
        };
    };

} FatBvhNode;

typedef struct
{
    // BVH structure
    __global FatBvhNode const*     nodes;
    // Scene positional data
    __global float3 const*         vertices;
    // Scene indices
    __global Face const*         faces;
    // Shape IDs
    __global ShapeData const*     shapes;
    // Extra data
    __global int const*             extra;
} SceneData;

/*************************************************************************
HELPER FUNCTIONS
**************************************************************************/

/*************************************************************************
BVH FUNCTIONS
**************************************************************************/
//  intersect a ray with leaf BVH node
inline
void IntersectLeafClosest(
    SceneData const* scenedata,
    int startidx,
    int numprims,
    ray const* r,                // ray to instersect
    Intersection* isect          // Intersection structure
    )
{
    float3 v1, v2, v3;
    Face face;
    for (int i = 0; i < numprims; ++i)
    {
        face = scenedata->faces[startidx + i];
        v1 = scenedata->vertices[face.idx[0]];
        v2 = scenedata->vertices[face.idx[1]];
        v3 = scenedata->vertices[face.idx[2]];

#ifdef RR_RAY_MASK
        int shapemask = scenedata->shapes[face.shapeidx].mask;

        if (Ray_GetMask(r) & shapemask)
#endif
        {
            if (IntersectTriangle(r, v1, v2, v3, isect))
            {
                isect->primid = face.id;
                isect->shapeid = face.shapeidx;
            }
        }
    }
}

//  intersect a ray with leaf BVH node
inline
bool IntersectLeafAny(
    SceneData const* scenedata,
    int startidx,
    int numprims,
    ray const* r                      // ray to instersect
    )
{
    float3 v1, v2, v3;
    Face face;

    bool hit = false;
    for (int i = 0; i < numprims; ++i)
    {
        face = scenedata->faces[startidx + i];
        v1 = scenedata->vertices[face.idx[0]];
        v2 = scenedata->vertices[face.idx[1]];
        v3 = scenedata->vertices[face.idx[2]];

#ifdef RR_RAY_MASK
        int shapemask = scenedata->shapes[face.shapeidx].mask;

        if (Ray_GetMask(r) & shapemask)
#endif
        {
            if (IntersectTriangleP(r, v1, v2, v3))
            {
                hit =  true;
                break;
            }
        }
    }

    return hit;
}

inline
bool intersect(
    SceneData const* scenedata,
    ray const* r,
    Intersection* isect,
    __global int* displacement,
    __global int* hash,
    int t
    )
{
    const float3 invdir = native_recip(r->d.xyz);
    isect->uvwt = make_float4(0.f, 0.f, 0.f, r->o.w);
    isect->shapeid = -1;
    isect->primid = -1;

    int bittrail = 0;
    int nodeidx = 1;
    int addr = 0;

    FatBvhNode node;

    while (addr > -1)
    {
        node = scenedata->nodes[addr];
        bool l0 = LEAFNODE(node.lbound);
        bool l1 = LEAFNODE(node.rbound);
        float d0 = -1.f;
        float d1 = -1.f;

        if (l0)
        {
            IntersectLeafClosest(scenedata, STARTIDX(node.lbound), NUMPRIMS(node.lbound), r, isect);
        }
        else
        {
            d0 = IntersectBoxF(r, invdir, node.lbound, isect->uvwt.w);
        }

        if (l1)
        {
            IntersectLeafClosest(scenedata, STARTIDX(node.rbound), NUMPRIMS(node.rbound), r, isect);
        }
        else
        {
            d1 = IntersectBoxF(r, invdir, node.rbound, isect->uvwt.w);
        }

        if (d0 > 0 && d1 > 0)
        {
            bittrail = bittrail << 1;
            nodeidx = nodeidx << 1;
            bittrail = bittrail ^ 0x1;

            if (d0 > d1)
            {
                addr = CHILD(node, 1);
                nodeidx = nodeidx ^ 0x1;
            }
            else
            {
                addr = CHILD(node, 0);
            }
            continue;
        }
        else if (d0 > 0)
        {
            bittrail = bittrail << 1;
            nodeidx = nodeidx << 1;
            addr = CHILD(node, 0);
            continue;
        }
        else if (d1 > 0)
        {
            bittrail = bittrail << 1;
            nodeidx = nodeidx << 1;
            nodeidx = nodeidx ^ 0x1;
            addr = CHILD(node, 1);
            continue;
        }

        if (bittrail == 0)
        {
            addr = -1;
            continue;
        }

        int num_levels = 31 - clz(bittrail & -bittrail);
        bittrail = (bittrail >> num_levels) ^ 0x1;
        nodeidx = (nodeidx >> num_levels) ^ 0x1;

        int d = displacement[nodeidx / t];
        addr = hash[d + (nodeidx & (t - 1))];
    }

    return isect->shapeid >= 0;
}

// intersect Ray against the whole BVH structure
inline
bool occluded(SceneData const* scenedata, ray const* r)
{
    const float3 invdir = native_recip(r->d.xyz);

    int stack[32];
    int* sptr = stack;
    *sptr++ = -1;

    int idx = 0;
    FatBvhNode node;

    while (idx > -1)
    {
        while (idx > -1)
        {
            node = scenedata->nodes[idx];

            bool l0 = LEAFNODE(node.lbound);
            bool l1 = LEAFNODE(node.rbound);
            float d0 = -1.f;
            float d1 = -1.f;

            if (l0)
            {
                bool hit = IntersectLeafAny(scenedata, STARTIDX(node.lbound), NUMPRIMS(node.lbound), r);
                if (hit)
                {
                    return true;
                }
            }
            else
            {
                d0 = IntersectBoxF(r, invdir, node.lbound, r->o.w);
            }

            if (l1)
            {
                bool hit = IntersectLeafAny(scenedata, STARTIDX(node.rbound), NUMPRIMS(node.rbound), r);
                if (hit)
                {
                    return true;
                }
            }
            else
            {
                d1 = IntersectBoxF(r, invdir, node.rbound, r->o.w);
            }

            if (d0 > 0 && d1 > 0)
            {
                int deferred = -1;
                if (d0 > d1)
                {
                    idx = CHILD(node, 1);
                    deferred = CHILD(node, 0);
                }
                else
                {
                    idx = CHILD(node, 0);
                    deferred = CHILD(node, 1);
                }

                *sptr++ = deferred;
                continue;
            }
            else if (d0 > 0)
            {
                idx = CHILD(node, 0);
                continue;
            }
            else if (d1 > 0)
            {
                idx = CHILD(node, 1);
                continue;
            }

            idx = *--sptr;
        }
    }

    return false;
}

__attribute__((reqd_work_group_size(64, 1, 1)))
__kernel void IntersectClosest(
    // Input
    __global FatBvhNode const* nodes,   // BVH nodes
    __global float3 const* vertices, // Scene positional data
    __global Face const* faces,    // Scene indices
    __global ShapeData const* shapes, // Shape data
    __global ray const* rays,        // Ray workload
    int offset,                // Offset in rays array
    int numrays,               // Number of rays to process
    __global int const* displacement,
    __global int const* hashmap,
    int t,
    __global Intersection* hits // Hit datas
    )
{
    int global_id = get_global_id(0);
    int local_id = get_local_id(0);
    int group_id = get_group_id(0);

    if (global_id < numrays)
    {
        // Fetch ray
        ray r = rays[global_id];

        if (Ray_IsActive(&r))
        {
            // Calculate closest hit
            Intersection isect;
            //intersect(&scenedata, &r, &isect, displacement, hashmap, t);
            float3 const invdir = native_recip(r.d.xyz);
            isect.uvwt = make_float4(0.f, 0.f, 0.f, r.o.w);
            isect.shapeid = -1;
            isect.primid = -1;

            int bittrail = 0;
            int nodeidx = 1;
            int addr = 0;
            int faceidx = -1;
            int deferred[3];
            int cnt = 0;

            float3 v1, v2, v3;
            Face face;
            FatBvhNode node;

            while (addr > -1)
            {
                while (addr > -1 && cnt < 2)
                {
                    node = nodes[addr];
                    bool l0 = LEAFNODE(node.lbound);
                    bool l1 = LEAFNODE(node.rbound);
                    float d0 = -1.f;
                    float d1 = -1.f;

                    if (l0)
                    {
                        deferred[cnt++] = STARTIDX(node.lbound);
                    }
                    else
                    {
                        d0 = IntersectBoxF(&r, invdir, node.lbound, isect.uvwt.w);
                    }

                    if (l1)
                    {
                        deferred[cnt++] = STARTIDX(node.rbound);
                    }
                    else
                    {
                        d1 = IntersectBoxF(&r, invdir, node.rbound, isect.uvwt.w);
                    }

                    if (d0 > 0 && d1 > 0)
                    {
                        bittrail = bittrail << 1;
                        nodeidx = nodeidx << 1;
                        bittrail = bittrail ^ 0x1;

                        if (d0 > d1)
                        {
                            addr = CHILD(node, 1);
                            nodeidx = nodeidx ^ 0x1;
                        }
                        else
                        {
                            addr = CHILD(node, 0);
                        }
                        continue;
                    }
                    else if (d0 > 0)
                    {
                        bittrail = bittrail << 1;
                        nodeidx = nodeidx << 1;
                        addr = CHILD(node, 0);
                        continue;
                    }
                    else if (d1 > 0)
                    {
                        bittrail = bittrail << 1;
                        nodeidx = nodeidx << 1;
                        nodeidx = nodeidx ^ 0x1;
                        addr = CHILD(node, 1);
                        continue;
                    }
                }

                if (cnt > 0)
                {
                    for (int i = 0; i < cnt; ++i)
                    {
                        face = faces[deferred[i]];
                        v1 = vertices[face.idx[0]];
                        v2 = vertices[face.idx[1]];
                        v3 = vertices[face.idx[2]];

                        if (IntersectTriangle(&r, v1, v2, v3, &isect))
                        {
                            faceidx = deferred[i];
                        }
                    }

                    cnt = 0;
                }

                if (bittrail == 0)
                {
                    addr = -1;
                    continue;
                }

                int num_levels = 31 - clz(bittrail & -bittrail);
                bittrail = (bittrail >> num_levels) ^ 0x1;
                nodeidx = (nodeidx >> num_levels) ^ 0x1;

                int d = displacement[nodeidx / t];
                addr = hashmap[d + (nodeidx & (t - 1))];
            }

            if (faceidx != -1)
            {
                isect.shapeid = faces[faceidx].shapeidx;
                isect.primid = faces[faceidx].id;
            }

            // Write data back in case of a hit
            hits[global_id] = isect;
        }
    }
}

__attribute__((reqd_work_group_size(64, 1, 1)))
__kernel void IntersectAny(
    // Input
    __global FatBvhNode const* nodes,   // BVH nodes
    __global float3 const* vertices, // Scene positional data
    __global Face const* faces,    // Scene indices
    __global ShapeData const* shapes,     // Shape data
    __global ray const* rays,        // Ray workload
    int offset,                // Offset in rays array
    int numrays,               // Number of rays to process
    __global int const* displacement,
    __global int const* hashmap,
    int t,
    __global int* hitresults  // Hit results
    )
{
    int global_id = get_global_id(0);
    int local_id = get_local_id(0);
    int group_id = get_group_id(0);

    // Fill scene data
    SceneData scenedata =
    {
        nodes,
        vertices,
        faces,
        shapes,
        0
    };

    if (global_id < numrays)
    {
        // Fetch ray
        ray r = rays[global_id];

        if (Ray_IsActive(&r))
        {
            // Calculate any intersection
            hitresults[global_id] = occluded(&scenedata, &r) ? 1 : -1;
        }
    }
}

__attribute__((reqd_work_group_size(64, 1, 1)))
// Version with range check
__kernel void IntersectClosestRC(
    __global FatBvhNode const* nodes,   // BVH nodes
    __global float3 const* vertices, // Scene positional data
    __global Face const* faces,      // Scene indices
    __global ShapeData const* shapes,     // Shape data
    __global ray const* rays,        // Ray workload
    int offset,                // Offset in rays array
    __global int const* numrays,     // Number of rays in the workload
    __global int const* displacement,
    __global int const* hashmap,
    int t,
    __global Intersection* hits
    )
{
    int global_id = get_global_id(0);
    int local_id = get_local_id(0);
    int group_id = get_group_id(0);

    // Fill scene data
    SceneData scenedata =
    {
        nodes,
        vertices,
        faces,
        shapes,
        0
    };

    // Handle only working subset
    if (global_id < *numrays)
    {
        // Fetch ray
        ray r = rays[global_id];

        if (Ray_IsActive(&r))
        {
            // Calculate closest hit
            Intersection isect;
            intersect(&scenedata, &r, &isect, displacement, hashmap, t);
            // Write data back in case of a hit
            hits[global_id] = isect;
        }
    }
}

__attribute__((reqd_work_group_size(64, 1, 1)))
// Version with range check
__kernel void IntersectAnyRC(
    // Input
    __global FatBvhNode const* nodes,   // BVH nodes
    __global float3 const* vertices, // Scene positional data
    __global Face const* faces,    // Scene indices
    __global ShapeData const* shapes,     // Shape data
    __global ray const* rays,        // Ray workload
    int offset,                // Offset in rays array
    __global int const* numrays,     // Number of rays in the workload
    __global int const* displacement,
    __global int const* hashmap,
    int t,
    __global int* hitresults   // Hit results
    )
{
    int global_id = get_global_id(0);
    int local_id = get_local_id(0);
    int group_id = get_group_id(0);

    // Fill scene data
    SceneData scenedata =
    {
        nodes,
        vertices,
        faces,
        shapes,
        0
    };

    // Handle only working subset
    if (global_id < *numrays)
    {
        // Fetch ray
        ray r = rays[global_id];

        if (Ray_IsActive(&r))
        {
            // Calculate any intersection
            hitresults[global_id] = occluded(&scenedata, &r) ? 1 : -1;
        }
    }
}


Root Level Handler Completed

Root Level Handler Completed

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/CLBplustree/CLBplustree.git/'


[OpenCL] Add test case for previous commit.

git-svn-id: ffe668792ed300d6c2daa1f6eba2e0aa28d7ec6c@198422 91177308-0d34-0410-b5e6-96231b3b80d8

// RUN: %clang_cc1 -verify %s
constant int no_init; // expected-error {{variable in constant address space must be initialized}}

error: pathspec 'test/SemaOpenCL/invalid-constant.cl' did not match any file(s) known to git


[Fix] missing kernel

[Fix] missing kernel

__kernel void square(
    __global float* input,
   __global float* output,
   unsigned int count)
{
    unsigned int i = get_global_id(0);
    if (i < count)
        output[i] = input[i] * input[i];
}

error: pathspec 'test/kernels/square.cl' did not match any file(s) known to git


correlate_500x500.cl: kernel for 500x500 problem size

#define HADD(v) ((v).x+(v).y+(v).z+(v).w)

#define W 1
#define SUMLEN (W*8)
#define STRIDE 10
#define CACHE (SUMLEN+STRIDE)

__attribute__((required_work_group_size(64,1,1)))
__kernel void correlate (
  __global float8 *correlation,
  const int corr_size,
  __constant float4 *base,
  __constant float4 *mask,
  const int sample_size,
  const int stride )
{
  float4 l_base[CACHE], l_mask[CACHE];
  float4 sums[SUMLEN]; for(int i=0; i<SUMLEN; i++) sums[i] = 0;
  int gid = get_global_id(0);
  int offset_y = gid*(W*8) / corr_size;
  int offset_x = gid*(W*8) - (offset_y*corr_size);
  for (int y=0; y < sample_size-offset_y; y++) {
    int mask_idx = y*stride - offset_x;
    int mi = max(mask_idx, 0);
    int base_idx = (offset_y+y)*stride;
    for (int x=offset_x%STRIDE; x < sample_size; x+=STRIDE) {
      if (x < offset_x) {
        for (int i=0; i<8; i++) {
          l_base[i] = base[base_idx+x+i];
          l_mask[i] = mask[mi+x+i];
        }
      } else {
        for (int i=0; i<CACHE; i++) {
          l_base[i] = base[base_idx+x+i];
          l_mask[i] = mask[mask_idx+x+i];
        }
        for (int i=0; i<STRIDE; i++)
          for (int j=0; j<SUMLEN; j++)
            sums[j] += l_base[i+j] * l_mask[i];
      }
    }
  }
  for (int i=0; i<W; i++)
  correlation[gid*W+i] = (float8)(
    HADD(sums[i*8+0]),
    HADD(sums[i*8+1]),
    HADD(sums[i*8+2]),
    HADD(sums[i*8+3]),
    HADD(sums[i*8+4]),
    HADD(sums[i*8+5]),
    HADD(sums[i*8+6]),
    HADD(sums[i*8+7])
  );
}

error: pathspec 'correlate_500x500.cl' did not match any file(s) known to git


Add diffuse lighting (with some hacks and magic numbers to make it better for differentiating parallel surfaces).

/* Size of the texture currently hard-coded */
#define SCREEN_W 640
#define SCREEN_H 480

/* With the current algorithm, this is the maximum number of voxels to
   traverse */
#define LOOP_LIMIT 100

/* Colors for the various sides of wall blocks */
#define COLOR_WALL  ((float4)(0.45,0.75,0.75,1.0))
#define COLOR_WALLG  ((float4)(0.45,0.75,0.45,1.0))

/* Multipliers for calculating shading on block faces */
#define LIGHTEN (4.0/3.0)
#define DARKEN (2.0/3.0)

/* Edge types - what appears at the end of the grid */
#define ET_WALL         0
#define ET_PORTAL_TORUS 1
#define ET_SOLID_AIR    2

/* Block types */
#define BK_AIR      0
#define BK_WALL     1
#define BK_WALLG    2

/* Handy macro for computing nearest axis boundary */
#define POSITIVE(X) ((X) > 0 ? (X) : 0)

typedef struct world_t {
    __constant uchar *grid;
    uchar4 bounds;
    uint edge_type;
} world_t;

typedef struct ray_t {
    int4 P;
    float4 ray_color;
    uint outside;
    char4 last_step;
} ray_t;

/* `shading' values > 1.0 brighten, < 1.0 darken. */
float4 color_mix_shade(float4 color, float shading) {
    return (float4)(fmin(color.x * shading, 1.0f),
                    fmin(color.y * shading, 1.0f),
                    fmin(color.z * shading, 1.0f),
                    color.w);
}

float dot_prod(float4 i, float4 j) {
    return i.x * j.x + i.y * j.y + i.z * j.z + i.w * j.w;
}

/* Returns new ray_color. Halts ray if alpha is 1.0f.
   v is the unit vector of the ray; t is how far down the ray we are. */
float4 color_ray(world_t w, ray_t r, float4 v, float t)
{
    uchar block_type = BK_AIR;

    if (r.outside) {
        if (w.edge_type == ET_WALL) {
            block_type = BK_WALL;
        } else {
            /* else leave block_type as BK_AIR */
            // TODO ET_PORTAL_TORUS
            return (float4)(0.0f, 0.0f, 0.0f, 1.0f);
        }
    } else {
        block_type = w.grid[r.P.x + (r.P.y * w.bounds.x) +
            (r.P.z * w.bounds.x * w.bounds.y)];
    }

    float4 new_ray_color = r.ray_color;

    if (block_type != BK_AIR) {
        switch (block_type) {
        case BK_WALL:
            new_ray_color = COLOR_WALL;
            break;
        case BK_WALLG:
            new_ray_color = COLOR_WALLG;
            break;
        }

        /* Calculate ambient lighting on this face */
        if (r.last_step.y == -1) {
            // viewing block from above
            new_ray_color = color_mix_shade(new_ray_color, LIGHTEN);
        } else if (r.last_step.y == 1) {
            // viewing block from below
            new_ray_color = color_mix_shade(new_ray_color, DARKEN);
        }

        /* Calculate diffuse lighting, reusing camera's position
           as light source. */
        float4 normal = (float4)(-r.last_step.x,
                               -r.last_step.y,
                               -r.last_step.z,
                               -r.last_step.w);
        float diffuse_light = dot_prod(normal, v);
        /* The dot-product gives us -1.0 for fully lit surfaces,
           and 0.0 or < 0.0 for orthogonal and far surfaces */
        if (diffuse_light < 0.0f)
            /* Some magic numbers to make things look nice.
               Technically, it should be 1/t^2, but who cares about
               realism? */
            diffuse_light = 0.5f - diffuse_light / (0.6f * t);
        else
            diffuse_light = 0.0f;
        new_ray_color = color_mix_shade(new_ray_color, diffuse_light);
    }

    return new_ray_color;
}

__kernel void raytrace(__write_only __global image2d_t bmp,
    uchar x_size, uchar y_size, uchar z_size, uchar edge_type,
    float rot_x, float rot_y, float cam_x, float cam_y, float cam_z,
    float fov_x, float fov_y, __constant uchar *grid)
{
    world_t w;
    w.grid = grid;
    w.edge_type = edge_type;
    w.bounds = (uchar4)(x_size, y_size, z_size, 0); /* Grid dimensions */

    /* Screen pixel position: */
    int2 p_pos = (int2)(get_global_id(0), get_global_id(1));

    float4 ray_rot = (float4)(rot_x, rot_y,
                              (p_pos.x * fov_x) / SCREEN_W - fov_x/2,
                              (p_pos.y * fov_y) / SCREEN_H - fov_y/2);
    float4 rot_sin = sin(ray_rot),
           rot_cos = cos(ray_rot);

    /* Voxel traversal ray-tracing algorithm based on John Amanatides'
       and Andrew Woo's paper. */

    /* n is the vector of the ray as if the camera was looking directly
       down the z-axis without any rotation around it.
       Multiply it by rotation matrices to get v (below) */
    float4 n = (float4)(rot_cos.w * rot_sin.z,
                        -rot_sin.w,
                        rot_cos.w * rot_cos.z,
                        0.0f);

    ray_t r;

    // v is the unit vector along the ray in actual world coords
    float4 v = (float4)(
      n.x*rot_cos.x + n.y*rot_sin.x*rot_sin.y + n.z*rot_sin.x*rot_cos.y,
      n.y*rot_cos.y - n.z*rot_sin.y,
      -n.x*rot_sin.x + n.y*rot_cos.x*rot_sin.y + n.z*rot_cos.x*rot_cos.y,
      0.0f);

    /* u is the starting point of the ray */
    float4 u = (float4)(cam_x, cam_y, cam_z, 0.0f);
    // Thus equation of the ray = u + vt

    // P = (X,Y,Z) = current voxel coordinates
    r.P = (int4)((int)u.x, (int)u.y, (int)u.z, 0);
    // TODO handle P being outside bounds of grid

    /* step = (stepX, stepY, stepZ) = values are either 1, 0, or -1.
       Components are determined from the sign of the components of v */
    char4 step = (char4)((char)sign(v.x), (char)sign(v.y),
                     (char)sign(v.z), 0);

    /* tmax = (tmaxX, tmaxY, tmaxZ) = values of t at which ray next
       crosses a voxel boundary in the respective direction */
    float4 tmax = (float4)((r.P.x + POSITIVE(step.x) - u.x)/v.x,
                      (r.P.y + POSITIVE(step.y) - u.y)/v.y,
                      (r.P.z + POSITIVE(step.z) - u.z)/v.z,
                      0.0f);

    /* dt = (dtX, dtY, dtZ) = how far along ray (in units of t) we must
       move for x/y/z component of move to equal width of one voxel */
    float4 dt = (float4)(step.x / v.x,
                    step.y / v.y,
                    step.z / v.z,
                    0.0f);

    /* justOut vector - used for checking we remain within the bounds
       of the grid */
    int4 justOut = (int4)(step.x == -1 ? -1 : w.bounds.x,
                     step.y == -1 ? -1 : w.bounds.y,
                     step.z == -1 ? -1 : w.bounds.z,
                     0);

    r.ray_color = (float4)(0.0f, 0.0f, 0.0f, 0.0f);
    r.outside = false;
    r.last_step = (char4)(0,0,0,0);
    float t = 0.0f;

    // FIXME assuming camera is always inside the grid
    r.ray_color = color_ray(w, r, v, t);

    #define STEP(dim) do { \
                        r.P.dim += step.dim; \
                        r.last_step = (char4)(0,0,0,0); \
                        r.last_step.dim = step.dim; \
                        t = tmax.dim; \
                        if (r.P.dim == justOut.dim) { \
                            r.outside = true; \
                        } else \
                        tmax.dim += dt.dim; \
                      } while (0)

    for (uint iter_count = 0; iter_count < LOOP_LIMIT;
         iter_count++)
    {

        if (tmax.x < tmax.y) {
            if (tmax.x < tmax.z) {
                STEP(x);
            } else {
                STEP(z);
            }
        } else {
            if (tmax.y < tmax.z) {
                STEP(y);
            } else {
                STEP(z);
            }
        }

        r.ray_color = color_ray(w, r, v, t);

        if (r.ray_color.w == 1.0f)
            break;

    }

    write_imagef(bmp, p_pos, r.ray_color);
}

/* Size of the texture currently hard-coded */
#define SCREEN_W 640
#define SCREEN_H 480

/* With the current algorithm, this is the maximum number of voxels to
   traverse */
#define LOOP_LIMIT 100

/* Colors for the various sides of wall blocks */
#define COLOR_WALL  ((float4)(0.45,0.75,0.75,1.0))
#define COLOR_WALLG  ((float4)(0.45,0.75,0.45,1.0))

/* Multipliers for calculating shading on block faces */
#define LIGHTEN (4.0/3.0)
#define DARKEN (2.0/3.0)

/* Edge types - what appears at the end of the grid */
#define ET_WALL         0
#define ET_PORTAL_TORUS 1
#define ET_SOLID_AIR    2

/* Block types */
#define BK_AIR      0
#define BK_WALL     1
#define BK_WALLG    2

/* Handy macro for computing nearest axis boundary */
#define POSITIVE(X) ((X) > 0 ? (X) : 0)

typedef struct world_t {
    __constant uchar *grid;
    uchar4 bounds;
    uint edge_type;
} world_t;

typedef struct ray_t {
    int4 P;
    float4 ray_color;
    uint outside;
    char4 last_step;
} ray_t;

/* `shading' values > 1.0 brighten, < 1.0 darken. */
float4 color_mix_shade(float4 color, float shading) {
    return (float4)(fmin(color.x * shading, 1.0f),
                    fmin(color.y * shading, 1.0f),
                    fmin(color.z * shading, 1.0f),
                    color.w);
}

/* Returns new ray_color. Halts ray if alpha is 1.0f */
float4 color_ray(world_t w, ray_t r)
{
    uchar block_type = BK_AIR;

    if (r.outside) {
        if (w.edge_type == ET_WALL) {
            block_type = BK_WALL;
        } else {
            /* else leave block_type as BK_AIR */
            // TODO ET_PORTAL_TORUS
            return (float4)(0.0f, 0.0f, 0.0f, 1.0f);
        }
    } else {
        block_type = w.grid[r.P.x + (r.P.y * w.bounds.x) +
            (r.P.z * w.bounds.x * w.bounds.y)];
    }

    float4 new_ray_color = r.ray_color;

    if (block_type != BK_AIR) {
        switch (block_type) {
        case BK_WALL:
            new_ray_color = COLOR_WALL;
            break;
        case BK_WALLG:
            new_ray_color = COLOR_WALLG;
            break;
        }

        if (r.last_step.y == -1) {
            // viewing block from above
            new_ray_color = color_mix_shade(new_ray_color, LIGHTEN);
        } else if (r.last_step.y == 1) {
            // viewing block from below
            new_ray_color = color_mix_shade(new_ray_color, DARKEN);
        }
    }

    return new_ray_color;
}

__kernel void raytrace(__write_only __global image2d_t bmp,
    uchar x_size, uchar y_size, uchar z_size, uchar edge_type,
    float rot_x, float rot_y, float cam_x, float cam_y, float cam_z,
    float fov_x, float fov_y, __constant uchar *grid)
{
    world_t w;
    w.grid = grid;
    w.edge_type = edge_type;
    w.bounds = (uchar4)(x_size, y_size, z_size, 0); /* Grid dimensions */

    /* Screen pixel position: */
    int2 p_pos = (int2)(get_global_id(0), get_global_id(1));

    float4 ray_rot = (float4)(rot_x, rot_y,
                              (p_pos.x * fov_x) / SCREEN_W - fov_x/2,
                              (p_pos.y * fov_y) / SCREEN_H - fov_y/2);
    float4 rot_sin = sin(ray_rot),
           rot_cos = cos(ray_rot);

    /* Voxel traversal ray-tracing algorithm based on John Amanatides'
       and Andrew Woo's paper. */

    /* n is the vector of the ray as if the camera was looking directly
       down the z-axis without any rotation around it.
       Multiply it by rotation matrices to get v (below) */
    float4 n = (float4)(rot_cos.w * rot_sin.z,
                        -rot_sin.w,
                        rot_cos.w * rot_cos.z,
                        0.0f);

    ray_t r;

    // v is the unit vector along the ray in actual world coords
    float4 v = (float4)(
      n.x*rot_cos.x + n.y*rot_sin.x*rot_sin.y + n.z*rot_sin.x*rot_cos.y,
      n.y*rot_cos.y - n.z*rot_sin.y,
      -n.x*rot_sin.x + n.y*rot_cos.x*rot_sin.y + n.z*rot_cos.x*rot_cos.y,
      0.0f);

    /* u is the starting point of the ray */
    float4 u = (float4)(cam_x, cam_y, cam_z, 0.0f);
    // Thus equation of the ray = u + vt

    // P = (X,Y,Z) = current voxel coordinates
    r.P = (int4)((int)u.x, (int)u.y, (int)u.z, 0);
    // TODO handle P being outside bounds of grid

    /* step = (stepX, stepY, stepZ) = values are either 1, 0, or -1.
       Components are determined from the sign of the components of v */
    char4 step = (char4)((char)sign(v.x), (char)sign(v.y),
                     (char)sign(v.z), 0);

    /* tmax = (tmaxX, tmaxY, tmaxZ) = values of t at which ray next
       crosses a voxel boundary in the respective direction */
    float4 tmax = (float4)((r.P.x + POSITIVE(step.x) - u.x)/v.x,
                      (r.P.y + POSITIVE(step.y) - u.y)/v.y,
                      (r.P.z + POSITIVE(step.z) - u.z)/v.z,
                      0.0f);

    /* dt = (dtX, dtY, dtZ) = how far along ray (in units of t) we must
       move for x/y/z component of move to equal width of one voxel */
    float4 dt = (float4)(step.x / v.x,
                    step.y / v.y,
                    step.z / v.z,
                    0.0f);

    /* justOut vector - used for checking we remain within the bounds
       of the grid */
    int4 justOut = (int4)(step.x == -1 ? -1 : w.bounds.x,
                     step.y == -1 ? -1 : w.bounds.y,
                     step.z == -1 ? -1 : w.bounds.z,
                     0);

    r.ray_color = (float4)(0.0f, 0.0f, 0.0f, 0.0f);
    r.outside = false;
    r.last_step = (char4)(0,0,0,0);

    // FIXME assuming camera is always inside the grid
    r.ray_color = color_ray(w, r);

    #define STEP(dim) do { \
                        r.P.dim += step.dim; \
                        r.last_step = (char4)(0,0,0,0); \
                        r.last_step.dim = step.dim; \
                        if (r.P.dim == justOut.dim) { \
                            r.outside = true; \
                        } else \
                        tmax.dim += dt.dim; \
                      } while (0)

    for (uint iter_count = 0; iter_count < LOOP_LIMIT;
         iter_count++)
    {

        if (tmax.x < tmax.y) {
            if (tmax.x < tmax.z) {
                STEP(x);
            } else {
                STEP(z);
            }
        } else {
            if (tmax.y < tmax.z) {
                STEP(y);
            } else {
                STEP(z);
            }
        }

        r.ray_color = color_ray(w, r);

        if (r.ray_color.w == 1.0f)
            break;

    }

    write_imagef(bmp, p_pos, r.ray_color);
}


Fixed spike to use rnd_state.

Fixed spike to use rnd_state.

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

#include "Retina_params.h"
#include "cl_random.cl"

#ifndef PI
#  define PI 3.1415926535897932
#endif

#ifndef __CL_PLATFORM_H

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

#else

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

// This stuff needs to be moved to (or obtained from) separate file
// perhaps conversions.h

static inline int kxPos(int k, int nx, int ny, int nf)
{
   return (k/nf) % nx;
}

static inline int kyPos(int k, int nx, int ny, int nf)
{
   return k / (nx*nf);
}

static inline int kIndex(int kx, int ky, int kf, int nx, int ny, int nf)
{
   return kf + (kx + (ky * nx)) * nf;
}

static inline int featureIndex(int k, int nx, int ny, int nf)
{
   return k % nf;
}

static inline int kIndexExtended(int k, int nx, int ny, int nf, int nb)
{
   const int kx_ex = nb + kxPos(k, nx, ny, nf);
   const int ky_ex = nb + kyPos(k, nx, ny, nf);
   const int kf = featureIndex(k, nx, ny, nf);
   return kIndex(kx_ex, ky_ex, kf, nx + 2*nb, ny + 2*nb, nf);
}

#endif /* __CL_PLATFORM_H */

/*
 * Spiking method for Retina
 * Returns 1 if an event should occur, 0 otherwise. This is a stochastic model.
 *
 * REMARKS:
 *      - During ABS_REFACTORY_PERIOD a neuron does not spike
 *      - The neurons that correspond to stimuli (on Image pixels)
 *        spike with probability probStim.
 *      - The neurons that correspond to background image pixels
 *        spike with probability probBase.
 *      - After ABS_REFACTORY_PERIOD the spiking probability
 *        grows exponentially to probBase and probStim respectively.
 *      - The burst of the retina is periodic with period T set by
 *        T = 1000/burstFreq in miliseconds
 *      - When the time t is such that mT < t < mT + burstDuration, where m is
 *        an integer, the burstStatus is set to 1.
 *      - The burstStatus is also determined by the condition that
 *        beginStim < t < endStim. These parameters are set in the input
 *        params file params.stdp
 *      - sinAmp modulates the spiking probability only when burstDuration <= 0
 *        or burstFreq = 0
 *      - probSpike is set to probBase for all neurons.
 *      - for neurons exposed to Image on pixels, probSpike increases with probStim.
 *      - When the probability is negative, the neuron does not spike.
 *
 * NOTES:
 *      - time is measured in milliseconds.
 *
 */
static inline
int spike(float time, float dt,
          float prev, float stimFactor, uint4 * rnd_state, const Retina_params * params)
{
   float probSpike;
   float burstStatus = 1;
   float sinAmp = 1.0;

   // input parameters
   //
   float probBase  = params->probBase;
   float probStim  = params->probStim * stimFactor;

   // see if neuron is in a refactory period
   //
   if ((time - prev) < params->abs_refactory_period) {
      return 0;
   }
   else {
      float delta = time - prev - params->abs_refactory_period;
      float refact = 1.0f - EXP(-delta/params->refactory_period);
      refact = (refact < 0) ? 0 : refact;
      probBase *= refact;
      probStim *= refact;
   }

   if (params->burstDuration <= 0 || params->burstFreq == 0) {
      sinAmp = cos( 2*PI*time * params->burstFreq / 1000. );
   }
   else {
      burstStatus = FMOD(time, 1000. / params->burstFreq);
      burstStatus = burstStatus <= params->burstDuration;
   }

   burstStatus *= (int) ( (time >= params->beginStim) && (time < params->endStim) );
   probSpike = probBase;

   if ((int)burstStatus) {
      probSpike += probStim * sinAmp;  // negative prob is OK
   }

   int spike_flag = (cl_random_prob(*rnd_state) < probSpike);
   *rnd_state = cl_random_state(*rnd_state);
   return spike_flag;
}

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

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

    CL_MEM_GLOBAL uint4 * rnd,
    CL_MEM_GLOBAL float * phiExc,
    CL_MEM_GLOBAL float * phiInh,
    CL_MEM_GLOBAL float * activity,
    CL_MEM_GLOBAL float * prevTime)
{
   int k;
#ifndef PV_USE_OPENCL
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
   //

   // load local variables from global memory
   //
   uint4 l_rnd = rnd[k];
   float l_phiExc = phiExc[k];
   float l_phiInh = phiInh[k];
   float l_prev   = prevTime[kex];
   float l_activ  = activity[kex];

   l_activ = (float) spike(time, dt, l_prev, (l_phiExc - l_phiInh), &l_rnd, params);
   l_prev  = (l_activ > 0.0f) ? time : l_prev;

   l_phiExc = 0.0f;
   l_phiInh = 0.0f;

   // store local variables back to global memory
   //
   rnd[k] = l_rnd;
   phiExc[k] = l_phiExc;
   phiInh[k] = l_phiInh;
   prevTime[kex] = l_prev;
   activity[kex] = l_activ;

#ifndef PV_USE_OPENCL
   }
#endif

}

#include "Retina_params.h"
#include "cl_random.cl"

#ifndef PI
#  define PI 3.1415926535897932
#endif

#ifndef __CL_PLATFORM_H

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

#else

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

// This stuff needs to be moved to (or obtained from) separate file
// perhaps conversions.h

static inline int kxPos(int k, int nx, int ny, int nf)
{
   return (k/nf) % nx;
}

static inline int kyPos(int k, int nx, int ny, int nf)
{
   return k / (nx*nf);
}

static inline int kIndex(int kx, int ky, int kf, int nx, int ny, int nf)
{
   return kf + (kx + (ky * nx)) * nf;
}

static inline int featureIndex(int k, int nx, int ny, int nf)
{
   return k % nf;
}

static inline int kIndexExtended(int k, int nx, int ny, int nf, int nb)
{
   const int kx_ex = nb + kxPos(k, nx, ny, nf);
   const int ky_ex = nb + kyPos(k, nx, ny, nf);
   const int kf = featureIndex(k, nx, ny, nf);
   return kIndex(kx_ex, ky_ex, kf, nx + 2*nb, ny + 2*nb, nf);
}

#endif /* __CL_PLATFORM_H */

/*
 * Spiking method for Retina
 * Returns 1 if an event should occur, 0 otherwise. This is a stochastic model.
 *
 * REMARKS:
 *      - During ABS_REFACTORY_PERIOD a neuron does not spike
 *      - The neurons that correspond to stimuli (on Image pixels)
 *        spike with probability probStim.
 *      - The neurons that correspond to background image pixels
 *        spike with probability probBase.
 *      - After ABS_REFACTORY_PERIOD the spiking probability
 *        grows exponentially to probBase and probStim respectively.
 *      - The burst of the retina is periodic with period T set by
 *        T = 1000/burstFreq in miliseconds
 *      - When the time t is such that mT < t < mT + burstDuration, where m is
 *        an integer, the burstStatus is set to 1.
 *      - The burstStatus is also determined by the condition that
 *        beginStim < t < endStim. These parameters are set in the input
 *        params file params.stdp
 *      - sinAmp modulates the spiking probability only when burstDuration <= 0
 *        or burstFreq = 0
 *      - probSpike is set to probBase for all neurons.
 *      - for neurons exposed to Image on pixels, probSpike increases with probStim.
 *      - When the probability is negative, the neuron does not spike.
 *
 * NOTES:
 *      - time is measured in milliseconds.
 *
 */
static inline
int spike(float time, float dt,
          float prev, float stimFactor, uint4 rnd_state, const Retina_params * params)
{
   float probSpike;
   float burstStatus = 1;
   float sinAmp = 1.0;

   // input parameters
   //
   float probBase  = params->probBase;
   float probStim  = params->probStim * stimFactor;

   // see if neuron is in a refactory period
   //
   if ((time - prev) < params->abs_refactory_period) {
      return 0;
   }
   else {
      float delta = time - prev - params->abs_refactory_period;
      float refact = 1.0f - EXP(-delta/params->refactory_period);
      refact = (refact < 0) ? 0 : refact;
      probBase *= refact;
      probStim *= refact;
   }

   if (params->burstDuration <= 0 || params->burstFreq == 0) {
      sinAmp = cos( 2*PI*time * params->burstFreq / 1000. );
   }
   else {
      burstStatus = FMOD(time, 1000. / params->burstFreq);
      burstStatus = burstStatus <= params->burstDuration;
   }

   burstStatus *= (int) ( (time >= params->beginStim) && (time < params->endStim) );
   probSpike = probBase;

   if ((int)burstStatus) {
      probSpike += probStim * sinAmp;  // negative prob is OK
   }
   return ( pv_random_prob() < probSpike );
}

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

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

    CL_MEM_GLOBAL uint4 * rnd,
    CL_MEM_GLOBAL float * phiExc,
    CL_MEM_GLOBAL float * phiInh,
    CL_MEM_GLOBAL float * activity,
    CL_MEM_GLOBAL float * prevTime)
{
   int k;
#ifndef PV_USE_OPENCL
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
   //

   // load local variables from global memory
   //
   uint4 l_rnd = rnd[k];
   float l_phiExc = phiExc[k];
   float l_phiInh = phiInh[k];
   float l_prev   = prevTime[kex];
   float l_activ  = activity[kex];

   l_activ = spike(time, dt, l_prev, (l_phiExc - l_phiInh), l_rnd, params);
   l_prev  = (l_activ > 0.0f) ? time : l_prev;

   l_phiExc = 0.0f;
   l_phiInh = 0.0f;

   // store local variables back to global memory
   //
   phiExc[k] = l_phiExc;
   phiInh[k] = l_phiInh;
   prevTime[kex] = l_prev;
   activity[kex] = l_activ;

#ifndef PV_USE_OPENCL
   }
#endif

}


more pong

more pong

Arboreta container draft v1.0

(defcontainer paddle (rect)
	:width 40
	:height 200
	:color "#CCCCCC")

(defcontainer ball (rect)
	:height 20
	:width 20
	(velocity-x 0)
	(velocity-y 0))

(defcontainer pong-container ()
	:width 600
	:height 400
	(:subcontainer player
		(make-container paddle
			(:initially (align this :horizontal 1/3 :vertical 1/2))))
	(:subcontainer enemy
		(make-container paddle
			(:initially (align this :horizontal 2/3 :vertical 1/2))))
	(:subcontainer ball
		(make-container ball))
	(:keyevent (arrow-down) (event)
		(decf (y (player this)) 30))
	(:keyevent (arrow-up) (event)
		(incf (y (player this)) 30)))

error: pathspec 'doc/draft.cl' did not match any file(s) known to git


Added simple List example

Added simple List example

class List
{
    item: String;
    next: List;

    init(i:String, n:List):List
    {
        {
            item <- i;
            next <- n;
            self;
        }
    };

    flatten(): String
    {
        if(isvoid next) then
            item
        else
            item.concat(next.flatten())
        fi
    };
};

class Main inherits IO
{
    main(): Object
    {
        let hello: String <- "Hello ",
            world: String <- "World ",
            newline: String <- "\n",
            nil: List,
            list: List <-
                (new List).init(hello,
                    (new List).init(world,
                        (new List).init(newline, nil)))
        in
            out_string(list.flatten())
    };
};

error: pathspec 'samples/list.cl' did not match any file(s) known to git


Draft of parse-replace script

Draft of parse-replace script

(defun file-string (path)
  (with-open-file (stream path)
    (let ((data (make-string (file-length stream))))
      (read-sequence data stream)
      data)))

(defmacro get-next-substr-index (str &key start-marker end-marker start-index end-index (next-index 0))
  `(progn
    (let ((start-marker-index (search ,start-marker ,str :start2 ,next-index))
         )
      (cond ((null start-marker-index) nil)
            (t
              (setq ,start-index (+ start-marker-index (length ,start-marker)))
              (setq ,end-index (search ,end-marker ,str :start2 ,start-index))
              (cond ((null ,end-index) nil)
                    (t
                      (+ ,end-index (length ,end-marker))
                    )
              )
            )
      )
    )
  )
)
(defun concat-string-list (s)
  (format nil "~{~A~}" s))

(defun parse-replace (str &optional template)
;;  (load template :verbose nil)
    (concat-string-list
      (let ( (str-out nil)
           )
           ;(setq sm "<AdditionalIncludeDirectories>")
           ;(setq em "</AdditionalIncludeDirectories>")
           (setq sm "[")
           (setq em "]")
           (loop  with index = 0
                  do (setq next-index (get-next-substr-index str :start-marker sm
                               :end-marker em
                               :start-index si
                               :end-index ei
                               :next-index index))
                  while next-index
                  collect (subseq str index si)
                  collect "_"
                  collect (subseq str ei next-index)
                  do (write-line (format nil "~A -> ~A" si ei))
                     (setq index next-index)
           )
      )
    )
)

(defun _ () (load "parse-replace.cl" :verbose nil))
(setq f1 "abc [123] fdsa [9090] lala")
(defun t1 ()
  (write-line (parse-replace f1))
)
(when (>= (length *args*) 2)
  (setq path (car *args*))
  (setq template (cdr *args*))
  (parse-replace (file-string path) template)
)

(t1)

error: pathspec 'lpp/parse-replace.cl' did not match any file(s) known to git


Renamed mc to monte_carlo

Renamed mc to monte_carlo

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/HongjianLi/idock.git/'


Rebased (remade) opencl branch based on working Riemann theta code from master.

/*
  finite_sum_opencl.cl

  OpenCL code for computing the finite sum in the computation of the Riemann
  theta function.
*/

/*
 */
#define PI 3.141592653589793

float exppart(int, __global float*, __global float*, __global float*, int,
	      __global float*, int);

float normpart(int, __global float*, __global float*, int,
	       __global float* int);

/*
  Given integer vector S[i], compte the exppart of the sum.
*/
float exppart(int i,
	      __global float* X,
	      __global float* intshift,
	      __global float* x,
	      int N,
	      __global float* S,
	      int L)
{
  // perform dot product of matrix mult
  float sum = 0;
  float v_j, Xw_j;
  for (int j=0; j<N; j++) {
    // jth component of a-intshift
    v_j = S[i*N+j]-intshift[j];

    // jth component of (1/2) X*(a-intshift) + x
    Xw_j = 0;
    for (int k=0; k<N; k++) {
      Xw_j += 0.5 * X[j*N+k] * (S[i*N+k]-intshift[k]) + x[j];
    }

    // add the jth component to the dot product container
    sum += v_j*Xw_j
  }

  // scale and return
  sum *= 2*PI;
  return sum
}

/*
  Given integer vector S[i], compte the exppart of the sum.
*/
float normpart(int i,
	       __global float* T,
	       __global float* fracshift,
	       int N,
	       __global float* S,
	       int L);
{
  float sum = 0;
  float v_j;

  // loop over elements of two vectors
  for (int j=0; j<N; j++){
    // calculate jth component of v=T(a+fracshift)
    v_j = 0;
    for (int k=0; k<N; k++) {
      v_j += T[j*N+k] * (S[i*N+k]-fracshift[k]);
    }

    sum += -PI*v_j*v_j;
  }
}

__kernel void
finite_sum_without_derivs(__global float* X,
			  __global float* Yinv,
			  __global float* T,
			  __global float* x,
			  __global float* y,
			  int N
			  __global float* S,
			  int L
			  __global float fsum_real,
			  __global float fsum_imag)
{
  float ept, npt, cpart, spart;
  int i;
  i = get_global_id(0);

  // compute exponential and norm parts
  ept = exppart(i,X,intshift,x,N,S,L);
  npt = exp(normpart(i,T,fracshift,N,S,L));

  // split up into real and imaginary (cosine and sine) parts
  cpart = npt * cos(ept);
  spart = npt * sin(ept);

  // add to real and imaginary parts of summation
  fsum_real += cpart;
  fsum_imag += spart;
}

error: pathspec 'abelfunctions/riemanntheta/finite_sum_opencl.cl' did not match any file(s) known to git