/******************************************************************************
 * @file     prngcl_common.cl
 * @author   Vadim Demchik <vadimdi@yahoo.com>
 * @version  1.1.1
 *
 * @brief    [PRNGCL library]
 *           common module for all PRNG implementations
 *           contains precision selection, etc.
 *
 *
 * @section  CREDITS
 *
 *   Vadim Demchik and Alexey Gulov,
 *   "Increasing precision of uniform pseudorandom number generators",
 *   arXiv: 1402.xxxx [xx.xx].
 *
 *
 * @section  LICENSE
 *
 * Copyright (c) 2013, 2014 Vadim Demchik
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *    Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *
 *    Redistributions 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.
 *
 * 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 COPYRIGHT HOLDER 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.
 *
 *****************************************************************************/

#ifndef PRNGCL_COMMON_CL
#define PRNGCL_COMMON_CL

#define GID_SIZE    (get_global_size(0) * get_global_size(1) * get_global_size(2))
#define GID         (get_global_id(0) + get_global_id(1) * get_global_size(0) + get_global_id(2) * get_global_size(0) * get_global_size(1))

#define hgpu_single  float
#define hgpu_single2 float2
#define hgpu_single3 float3
#define hgpu_single4 float4

#if defined(cl_khr_fp64)

#define hgpu_double     double
#define hgpu_double2    double2
#define hgpu_double3    double3
#define hgpu_double4    double4

//#define PRNG_SKIP_CHECK     // if defined = skip uniformity checking in double precision

#if defined(cl_amd_fp64)    // AMD extension available?
	#pragma OPENCL EXTENSION cl_amd_fp64 : enable
#elif defined(cl_khr_fp64)  // Khronos extension available?
	#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#endif

#ifndef PRNG_PRECISION
#define PRNG_PRECISION   0       // single precision by default
#endif

#if ((PRNG_PRECISION==0)||(PRNG_PRECISION==1))
#define PRECISION_SINGLE            // define single precision
#elif (PRNG_PRECISION==2)
#define PRECISION_DOUBLE            // define double precision
#endif

#ifdef PRECISION_DOUBLE
#define hgpu_float   hgpu_double
#define hgpu_float2  hgpu_double2
#define hgpu_float3  hgpu_double3
#define hgpu_float4  hgpu_double4
#else
#define hgpu_float   float
#define hgpu_float2  float2
#define hgpu_float3  float3
#define hgpu_float4  float4
#endif

inline hgpu_double4 hgpu_uint4_2_double4(uint4 x){
    hgpu_double4 result;
    result.x = (double) x.x;
    result.y = (double) x.y;
    result.z = (double) x.z;
    result.w = (double) x.w;

    return result;
}

inline hgpu_double hgpu_uint_to_double(uint rnd1, uint rnd2, uint rnd_min, uint rnd_max, double k){
    hgpu_double result = (rnd1 + k * rnd2 - (rnd_min + k * rnd_max)) / ((rnd_max - rnd_min) * (1.0 - k));
    return result;
}

inline hgpu_double4 hgpu_uint4_to_double4(uint4 rnd1, uint4 rnd2, uint rnd_min, uint rnd_max, double k){
    hgpu_double4 result;
    hgpu_double4 drnd1 = hgpu_uint4_2_double4(rnd1);
    hgpu_double4 drnd2 = hgpu_uint4_2_double4(rnd2);
    double a1 = (rnd_min + k * rnd_max);
    double a2 = ((rnd_max - rnd_min) * (1.0 - k));
        result.x = (drnd1.x + k * drnd2.x - a1) / a2;
        result.y = (drnd1.y + k * drnd2.y - a1) / a2;
        result.z = (drnd1.z + k * drnd2.z - a1) / a2;
        result.w = (drnd1.w + k * drnd2.w - a1) / a2;
        return result;
}

inline hgpu_double hgpu_float_to_double(float rnd1, float rnd2, double rnd_min, double rnd_max, double k){
    double a1 = (rnd_max - rnd_min);
    double a2 = trunc((a1-2.0*k) / k) + a1;
        return (trunc((rnd1-rnd_min-k) / k) + rnd2 - rnd_min) / a2 * (1.0-k*k);
}

inline hgpu_double2 hgpu_float4_to_double2(float4 rnd, double rnd_min, double rnd_max, double k){
    hgpu_double2 result;
    double a1 = (rnd_max - rnd_min);
    double a2 = trunc((a1-2.0*k) / k) + a1;
        result.x = (trunc((rnd.x-rnd_min-k) / k) + rnd.y - rnd_min) / a2 * (1.0-k*k);
        result.y = (trunc((rnd.z-rnd_min-k) / k) + rnd.w - rnd_min) / a2 * (1.0-k*k);
        return result;
}

inline hgpu_double4 hgpu_float4_to_double4(float4 rnd1, float4 rnd2, double rnd_min, double rnd_max, double k){
    hgpu_double4 result;
    double a1 = (rnd_max - rnd_min);
    double a2 = trunc((a1-2.0*k) / k) + a1;
        result.x = (trunc((rnd1.x-rnd_min-k) / k) + rnd2.x - rnd_min) / a2 * (1.0-k*k);
        result.y = (trunc((rnd1.y-rnd_min-k) / k) + rnd2.y - rnd_min) / a2 * (1.0-k*k);
        result.z = (trunc((rnd1.z-rnd_min-k) / k) + rnd2.z - rnd_min) / a2 * (1.0-k*k);
        result.w = (trunc((rnd1.w-rnd_min-k) / k) + rnd2.w - rnd_min) / a2 * (1.0-k*k);
        return result;
}

#else

#define hgpu_float   float
#define hgpu_float2  float2
#define hgpu_float3  float3
#define hgpu_float4  float4

#endif

inline float4 hgpu_uint4_to_float4(uint4 x){
    float4 result;
    result.x = (float) x.x;
    result.y = (float) x.y;
    result.z = (float) x.z;
    result.w = (float) x.w;

    return result;
}

typedef union _Uint_and_Float   // Uint <---> Float converter
{
    uint uint_value;
    float float_value;
} Uint_and_Float;

#endif

/******************************************************************************
 * @file     prngcl_common.cl
 * @author   Vadim Demchik <vadimdi@yahoo.com>
 * @version  1.1.1
 *
 * @brief    [PRNGCL library]
 *           common module for all PRNG implementations
 *           contains precision selection, etc.
 *
 *
 * @section  LICENSE
 *
 * Copyright (c) 2013, 2014 Vadim Demchik
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *    Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *
 *    Redistributions 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.
 *
 * 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 COPYRIGHT HOLDER 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.
 *
 *****************************************************************************/

#ifndef PRNGCL_COMMON_CL
#define PRNGCL_COMMON_CL

#define GID_SIZE    (get_global_size(0) * get_global_size(1) * get_global_size(2))
#define GID         (get_global_id(0) + get_global_id(1) * get_global_size(0) + get_global_id(2) * get_global_size(0) * get_global_size(1))

#define hgpu_single  float
#define hgpu_single2 float2
#define hgpu_single3 float3
#define hgpu_single4 float4

#if defined(cl_khr_fp64)

#define hgpu_double     double
#define hgpu_double2    double2
#define hgpu_double3    double3
#define hgpu_double4    double4

//#define PRNG_SKIP_CHECK     // if defined = skip uniformity checking in double precision

#if defined(cl_amd_fp64)    // AMD extension available?
	#pragma OPENCL EXTENSION cl_amd_fp64 : enable
#elif defined(cl_khr_fp64)  // Khronos extension available?
	#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#endif

#ifndef PRNG_PRECISION
#define PRNG_PRECISION   0       // single precision by default
#endif

#if ((PRNG_PRECISION==0)||(PRNG_PRECISION==1))
#define PRECISION_SINGLE            // define single precision
#elif (PRNG_PRECISION==2)
#define PRECISION_DOUBLE            // define double precision
#endif

#ifdef PRECISION_DOUBLE
#define hgpu_float   hgpu_double
#define hgpu_float2  hgpu_double2
#define hgpu_float3  hgpu_double3
#define hgpu_float4  hgpu_double4
#else
#define hgpu_float   float
#define hgpu_float2  float2
#define hgpu_float3  float3
#define hgpu_float4  float4
#endif

inline hgpu_double4 hgpu_uint4_2_double4(uint4 x){
    hgpu_double4 result;
    result.x = (double) x.x;
    result.y = (double) x.y;
    result.z = (double) x.z;
    result.w = (double) x.w;

    return result;
}

inline hgpu_double hgpu_uint_to_double(uint rnd1, uint rnd2, uint rnd_min, uint rnd_max, double k){
    hgpu_double result = (rnd1 + k * rnd2 - (rnd_min + k * rnd_max)) / ((rnd_max - rnd_min) * (1.0 - k));
    return result;
}

inline hgpu_double4 hgpu_uint4_to_double4(uint4 rnd1, uint4 rnd2, uint rnd_min, uint rnd_max, double k){
    hgpu_double4 result;
    hgpu_double4 drnd1 = hgpu_uint4_2_double4(rnd1);
    hgpu_double4 drnd2 = hgpu_uint4_2_double4(rnd2);
    double a1 = (rnd_min + k * rnd_max);
    double a2 = ((rnd_max - rnd_min) * (1.0 - k));
        result.x = (drnd1.x + k * drnd2.x - a1) / a2;
        result.y = (drnd1.y + k * drnd2.y - a1) / a2;
        result.z = (drnd1.z + k * drnd2.z - a1) / a2;
        result.w = (drnd1.w + k * drnd2.w - a1) / a2;
        return result;
}

inline hgpu_double hgpu_float_to_double(float rnd1, float rnd2, double rnd_min, double rnd_max, double k){
    double a1 = (rnd_max - rnd_min);
    double a2 = trunc((a1-2.0*k) / k) + a1;
        return (trunc((rnd1-rnd_min-k) / k) + rnd2 - rnd_min) / a2 * (1.0-k*k);
}

inline hgpu_double2 hgpu_float4_to_double2(float4 rnd, double rnd_min, double rnd_max, double k){
    hgpu_double2 result;
    double a1 = (rnd_max - rnd_min);
    double a2 = trunc((a1-2.0*k) / k) + a1;
        result.x = (trunc((rnd.x-rnd_min-k) / k) + rnd.y - rnd_min) / a2 * (1.0-k*k);
        result.y = (trunc((rnd.z-rnd_min-k) / k) + rnd.w - rnd_min) / a2 * (1.0-k*k);
        return result;
}

inline hgpu_double4 hgpu_float4_to_double4(float4 rnd1, float4 rnd2, double rnd_min, double rnd_max, double k){
    hgpu_double4 result;
    double a1 = (rnd_max - rnd_min);
    double a2 = trunc((a1-2.0*k) / k) + a1;
        result.x = (trunc((rnd1.x-rnd_min-k) / k) + rnd2.x - rnd_min) / a2 * (1.0-k*k);
        result.y = (trunc((rnd1.y-rnd_min-k) / k) + rnd2.y - rnd_min) / a2 * (1.0-k*k);
        result.z = (trunc((rnd1.z-rnd_min-k) / k) + rnd2.z - rnd_min) / a2 * (1.0-k*k);
        result.w = (trunc((rnd1.w-rnd_min-k) / k) + rnd2.w - rnd_min) / a2 * (1.0-k*k);
        return result;
}

#else

#define hgpu_float   float
#define hgpu_float2  float2
#define hgpu_float3  float3
#define hgpu_float4  float4

#endif

inline float4 hgpu_uint4_to_float4(uint4 x){
    float4 result;
    result.x = (float) x.x;
    result.y = (float) x.y;
    result.z = (float) x.z;
    result.w = (float) x.w;

    return result;
}

typedef union _Uint_and_Float   // Uint <---> Float converter
{
    uint uint_value;
    float float_value;
} Uint_and_Float;

#endif


async_work_group_copy.cl: Reformat

async_work_group_copy.cl: Reformat

/* OpenCL built-in library: async_work_group_copy()

   Copyright (c) 2012 Pekka Jääskeläinen / Tampere University of Technology

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

#include "templates.h"

/* The default implementation for "async copies" is a
   blocking one which doesn't actually need events for
   anything.

   The devices (actually, platforms) should override these to
   implement proper block copies or similar. */

#define IMPLEMENT_ASYNC_COPY_FUNCS_SINGLE(GENTYPE)                      \
  __attribute__((overloadable))                                         \
  event_t async_work_group_copy(__local GENTYPE *dst,                   \
                                const __global GENTYPE *src,            \
                                size_t num_gentypes,                    \
                                event_t event)                          \
  {                                                                     \
    __SINGLE_WI {                                                       \
      for (size_t i = 0; i < num_gentypes; ++i) dst[i] = src[i];        \
    }                                                                   \
    return event;                                                       \
  }                                                                     \
                                                                        \
  __attribute__((overloadable))                                         \
  event_t async_work_group_copy(__global GENTYPE *dst,                  \
                                const __local GENTYPE *src,             \
                                size_t num_gentypes,                    \
                                event_t event)                          \
  {                                                                     \
    __SINGLE_WI {                                                       \
      for (size_t i = 0; i < num_gentypes; ++i) dst[i] = src[i];        \
    }                                                                   \
    return event;                                                       \
  }

#define IMPLEMENT_ASYNC_COPY_FUNCS(GENTYPE)             \
  IMPLEMENT_ASYNC_COPY_FUNCS_SINGLE(GENTYPE)            \
  IMPLEMENT_ASYNC_COPY_FUNCS_SINGLE(GENTYPE##2)         \
  IMPLEMENT_ASYNC_COPY_FUNCS_SINGLE(GENTYPE##3)         \
  IMPLEMENT_ASYNC_COPY_FUNCS_SINGLE(GENTYPE##4)         \
  IMPLEMENT_ASYNC_COPY_FUNCS_SINGLE(GENTYPE##8)         \
  IMPLEMENT_ASYNC_COPY_FUNCS_SINGLE(GENTYPE##16)

IMPLEMENT_ASYNC_COPY_FUNCS(char);
IMPLEMENT_ASYNC_COPY_FUNCS(uchar);
IMPLEMENT_ASYNC_COPY_FUNCS(short);
IMPLEMENT_ASYNC_COPY_FUNCS(ushort);
IMPLEMENT_ASYNC_COPY_FUNCS(int);
IMPLEMENT_ASYNC_COPY_FUNCS(uint);
__IF_INT64(IMPLEMENT_ASYNC_COPY_FUNCS(long));
__IF_INT64(IMPLEMENT_ASYNC_COPY_FUNCS(ulong));

IMPLEMENT_ASYNC_COPY_FUNCS(float);
__IF_FP64(IMPLEMENT_ASYNC_COPY_FUNCS(double));

/* OpenCL built-in library: async_work_group_copy()

   Copyright (c) 2012 Pekka Jääskeläinen / Tampere University of Technology

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

/* The default implementation for "async copies" is a
   blocking one which doesn't actually need events for
   anything.

   The devices (actually, platforms) should override these to
   implement proper block copies or similar. */

#include "templates.h"

#define IMPLEMENT_ASYNC_COPY_FUNCS_SINGLE(GENTYPE)              \
    __attribute__ ((overloadable))                              \
  event_t async_work_group_copy (__local GENTYPE *dst,          \
                                 const __global GENTYPE *src,   \
                                 size_t num_gentypes,           \
                                 event_t event)                 \
  {                                                             \
      __SINGLE_WI {                                             \
          size_t i;                                             \
          for (i = 0; i < num_gentypes; ++i) dst[i] = src[i];   \
      }                                                         \
      return event;                                             \
  }                                                             \
                                                                \
                                                                \
    __attribute__ ((overloadable))                              \
  event_t async_work_group_copy (__global GENTYPE *dst,         \
                                 const __local GENTYPE *src,    \
                                 size_t num_gentypes,           \
                                 event_t event)                 \
  {                                                             \
      __SINGLE_WI {                                             \
          size_t i;                                             \
          for (i = 0; i < num_gentypes; ++i) dst[i] = src[i];   \
      }                                                         \
      return event;                                             \
  }                                                             \

#define IMPLEMENT_ASYNC_COPY_FUNCS(GENTYPE)      \
  IMPLEMENT_ASYNC_COPY_FUNCS_SINGLE(GENTYPE)     \
  IMPLEMENT_ASYNC_COPY_FUNCS_SINGLE(GENTYPE##2)   \
  IMPLEMENT_ASYNC_COPY_FUNCS_SINGLE(GENTYPE##3)   \
  IMPLEMENT_ASYNC_COPY_FUNCS_SINGLE(GENTYPE##4)   \
  IMPLEMENT_ASYNC_COPY_FUNCS_SINGLE(GENTYPE##8)   \
  IMPLEMENT_ASYNC_COPY_FUNCS_SINGLE(GENTYPE##16)  \

IMPLEMENT_ASYNC_COPY_FUNCS(char);
IMPLEMENT_ASYNC_COPY_FUNCS(uchar);
IMPLEMENT_ASYNC_COPY_FUNCS(short);
IMPLEMENT_ASYNC_COPY_FUNCS(ushort);
IMPLEMENT_ASYNC_COPY_FUNCS(int);
IMPLEMENT_ASYNC_COPY_FUNCS(uint);
__IF_INT64(IMPLEMENT_ASYNC_COPY_FUNCS(long));
__IF_INT64(IMPLEMENT_ASYNC_COPY_FUNCS(ulong));

IMPLEMENT_ASYNC_COPY_FUNCS(float);
__IF_FP64(IMPLEMENT_ASYNC_COPY_FUNCS(double));


perturbation funky

perturbation funky

#include "kernel_header.hcl"
#include "kernel_matrix.hcl"
#include "kernel_cam.hcl"
#include "kernel_color.hcl"
#include "kernel_cone.hcl"
#include "kernel_cylinder.hcl"
#include "kernel_data.hcl"
#include "kernel_plane.hcl"
#include "kernel_sphere.hcl"

static t_hit			ray_hit(const __local t_scene *scene, const float3 origin, const float3 ray)
{
	unsigned int			i;
	int						max;
	t_hit					hit;
	float					dist;

	max = get_max_obj(scene);
	dist = 0;
	i = 0;
	hit = hit_init();
	while (i < max)
	{
		if (i < scene->n_cones)
			if (((dist = inter_cone(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 1;
				hit.id = i;
			}
		if (i < scene->n_cylinders)
			if (((dist = inter_cylinder(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 2;
				hit.id = i;
			}
		if (i < scene->n_planes)
			if (((dist = inter_plan(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 4;
				hit.id = i;
			}
		if (i < scene->n_spheres)
			if (((dist = inter_sphere(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 5;
				hit.id = i;
			}
		i++;
	}
	return (hit);
}

float3			get_hit_normale(const __local t_scene *scene, float3 ray, t_hit hit)
{
	float3		res, save;

	if (hit.type == 1)
		res = get_cone_normale(scene, hit);
	else if (hit.type == 2)
		res = get_cylinder_normal(scene, hit);
	else if (hit.type == 4)
	{
		if (dot(PLANE[hit.id].normale, -ray) < 0)
			res = -PLANE[hit.id].normale;
		else
			res = PLANE[hit.id].normale;

		if (scene->flag & OPTION_WAVE)
		{
			save = res;
			save.x = res.x + 0.8 * cos(hit.pos.y * 10 + scene->u_time);
			save.z = res.z + 0.8 * cos((hit.pos.x * 10 + scene->u_time));
			save.y = save.y + 0.8 * cos(hit.pos.z * 10 + scene->u_time);
			return (fast_normalize(save));
		}
	}
	else if (hit.type == 5)
		res = hit.pos - SPHERE[hit.id].pos;
	save = res;
	if (scene->flag & OPTION_WAVE)
	{
		save.x = res.x + 0.8 * sin(res.y * 10 + scene->u_time);
		save.z = save.z + 0.8 * sin(save.x * 10 + scene->u_time);
		save.y = res.y + 0.8 * sin(res.x * 10 + scene->u_time);
	}

	return (fast_normalize(save));
}

unsigned int			phong(const __local t_scene *scene, const t_hit hit, const float3 ray)
{
	int					i;
	i = 0;
	unsigned int		res_color;
	res_color = get_ambient(scene, get_obj_hue(scene, hit));
	float				tmp;
	tmp = 0;
	float3				reflect;
	reflect = 0;
	float3 __private	diffuse;
	diffuse = 0;
	float __private	brightness;
	brightness = 0;
	int __private hue;
	hue = 0;
	int __private hue_light;
	hue_light = 0;
	unsigned int __private col_r, col_g, col_b, obj_r, obj_g, obj_b, l_r, l_b, l_g;
	col_r = 0;
	col_g = 0;
	col_b = 0;
	obj_r = 0;
	obj_g = 0;
	obj_b = 0;
	l_r = 0;
	l_g = 0;
	l_b = 0;
	t_light_ray			light_ray;
	t_hit				light_hit;
	float __private pow_of_spec;
	pow_of_spec = 0;
	int __private light_color;
	light_color = 0;
	float3 __private speculos;
	speculos = 0;

	while (i < scene->n_lights)
	{
		tmp = 0;
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = fast_length(light_ray.dir);
		light_ray.dir = fast_normalize(light_ray.dir);
		light_hit = ray_hit(scene, hit.pos, light_ray.dir);
		light_hit.id = i;
		light_hit.type = 3;
		if (light_hit.dist < light_ray.dist && light_hit.dist > 0.f)
			;
		else
		{
			tmp = dot(hit.normale, light_ray.dir);
			if (tmp > 0.f)
			{
				brightness = (float __private)LIGHT[light_hit.id].brightness;

				if (hit.type == 1)
					diffuse = (float3 __private)CONES[hit.id].diff;
				else if (hit.type == 2)
					diffuse = (float3 __private)CYLIND[hit.id].diff;
				else if (hit.type == 4)
					diffuse = (float3 __private)PLANE[hit.id].diff;
				else if (hit.type == 5)
					diffuse = (float3 __private)SPHERE[hit.id].diff;
				else
					diffuse = 0.f;

				if (hit.type == 1)
					hue = (int __private)CONES[hit.id].color;
				if (hit.type == 2)
					hue = (int __private)CYLIND[hit.id].color;
				if (hit.type == 3)
					hue = (int __private)LIGHT[hit.id].color;
				if (hit.type == 4)
					hue = (int __private)PLANE[hit.id].color;
				if (hit.type == 5)
					hue = (int __private)SPHERE[hit.id].color;

				if (hit.type == 1)
					hue_light = (int __private)CONES[light_hit.id].color;
				if (hit.type == 2)
					hue_light = (int __private)CYLIND[light_hit.id].color;
				if (hit.type == 3)
					hue_light = (int __private)LIGHT[light_hit.id].color;
				if (hit.type == 4)
					hue_light = (int __private)PLANE[light_hit.id].color;
				if (hit.type == 5)
					hue_light = (int __private)SPHERE[light_hit.id].color;
				col_r = (res_color & 0xFF0000) >> 16;
				col_g = (res_color & 0x00FF00) >> 8;
				col_b = (res_color & 0x0000FF);
				obj_r = (hue & 0xFF0000) >> 16;
				obj_g = (hue & 0x00FF00) >> 8;
				obj_b = (hue & 0x00000FF);
				l_r = (hue_light & 0xFF0000) >> 16;
				l_g = (hue_light & 0x00FF00) >> 8;
				l_b = (hue_light & 0x0000FF);

				col_r += ((l_r * brightness) + obj_r) * tmp * diffuse.x;
				col_g += ((l_g * brightness) + obj_g) * tmp * diffuse.y;
				col_b += ((l_b * brightness) + obj_b) * tmp * diffuse.z;
				(col_r > 255 ? col_r = 255 : 0);
				(col_g > 255 ? col_g = 255 : 0);
				(col_b > 255 ? col_b = 255 : 0);
				res_color = ((col_r << 16) + (col_g << 8) + col_b);
			}
			reflect = fast_normalize(((float)(2.0 * dot(hit.normale, light_ray.dir)) * hit.normale) - light_ray.dir);
			tmp = dot(reflect, -ray);
			if (tmp > 0.f)
			{
				speculos = 0.f;
				if (hit.type == 1)
					speculos = (float3 __private)CONES[hit.id].spec;
				else if (hit.type == 2)
					speculos = (float3 __private)CYLIND[hit.id].spec;
				else if (hit.type == 4)
					speculos = (float3 __private)PLANE[hit.id].spec;
				else if (hit.type == 5)
					speculos = (float3 __private)SPHERE[hit.id].spec;
				else
					speculos = 0.f;
				col_r = (res_color & 0x00FF0000) >> 16;
				col_g = (res_color & 0x0000FF00) >> 8;
				col_b = (res_color & 0x000000FF);

				pow_of_spec = native_powr(tmp, (LIGHT[light_hit.id].shrink));
				light_color = LIGHT[light_hit.id].color;
				col_r += (((light_color & 0xFF0000) >> 16) * pow_of_spec) * speculos.x;
				col_g += ((light_color & 0x00FF00) >> 8) * pow_of_spec * speculos.y;
				col_b += (light_color & 0x0000FF) * pow_of_spec * speculos.z;
				(col_r > 255 ? col_r = 255 : 0);
				(col_g > 255 ? col_g = 255 : 0);
				(col_b > 255 ? col_b = 255 : 0);
				res_color = ((col_r << 16) + (col_g << 8) + col_b);
			}
		}
		i++;
	}
	return (res_color);
}

unsigned int			phong2(const __local t_scene *scene, const t_hit hit, const float3 ray)
{

	int __private hue_light;
	unsigned int __private col_r, col_g, col_b, obj_r, obj_g, obj_b, l_r, l_b, l_g;
	int __private modx, mody, modz;
	int __private hue;
	float __private	brightness;
	float3 __private	diffuse;
	float3				reflect;
	float				tmp;
	unsigned int		res_color;
	int					i;
	int __private light_color;
	float3 __private speculos;
	float __private pow_of_spec;
	t_light_ray			light_ray;
	t_hit				light_hit;

	i = 0;
	if (hit.type == 1)
		hue = (int __private)CONES[hit.id].color;
	else if (hit.type == 2)
		hue = (int __private)CYLIND[hit.id].color;
	else if (hit.type == 3)
		hue = (int __private)LIGHT[hit.id].color;
	else if (hit.type == 4)
		hue = (int __private)PLANE[hit.id].color;
	else if (hit.type == 5)
		hue = (int __private)SPHERE[hit.id].color;

	if (hit.type == 1)
		hue_light = (int __private)CONES[0].color;
	else if (hit.type == 2)
		hue_light = (int __private)CYLIND[0].color;
	else if (hit.type == 3)
		hue_light = (int __private)LIGHT[0].color;
	else if (hit.type == 4)
		hue_light = (int __private)PLANE[0].color;
	else if (hit.type == 5)
		hue_light = (int __private)SPHERE[0].color;

	if (hit.type == 1)
		speculos = (float3 __private)CONES[hit.id].spec;
	else if (hit.type == 2)
		speculos = (float3 __private)CYLIND[hit.id].spec;
	else if (hit.type == 4)
		speculos = 0;
	else if (hit.type == 5)
		speculos = (float3 __private)SPHERE[hit.id].spec;
	else
		speculos = 0.f;

	col_r = (hue & 0x00FF0000) >> 16;
	col_g = (hue & 0x0000FF00) >> 8;
	col_b = (hue & 0x000000FF);
	col_r = (0.01 + col_r * scene->ambient.x > 255 ? 255 : 0.01 + col_r * scene->ambient.x);
	col_g = (0.01 + col_g * scene->ambient.y > 255 ? 255 : 0.01 + col_g * scene->ambient.y);
	col_b = (0.01 + col_b * scene->ambient.z > 255 ? 255 : 0.01 + col_b * scene->ambient.z);
	res_color = ((col_r << 16) + (col_g << 8) + col_b);

	while (++i < scene->n_lights)
	{
	light_ray.dir = LIGHT[i].pos - hit.pos;
	light_ray.dist = fast_length(light_ray.dir);
	light_ray.dir = fast_normalize(light_ray.dir);
	light_hit = ray_hit(scene, hit.pos, light_ray.dir);
	light_hit.id = i;
	light_hit.type = 3;

	reflect = 0;
	diffuse = 0;
	brightness = 0;
	modx = 0;
	mody = 0;
	modz = 0;
	col_r = 0;
	col_g = 0;
	col_b = 0;
	obj_r = 0;
	obj_g = 0;
	obj_b = 0;
	l_r = 0;
	l_g = 0;
	l_b = 0;
	pow_of_spec = 0;
	light_color = 0;
	tmp = 0;

	float3 touch;
	touch = scene->cameras->pos + scene->cameras->dir * hit.dist;

		if (!(light_hit.dist < light_ray.dist && light_hit.dist > 0))
		{
			tmp = dot(hit.normale, light_ray.dir);
			if (tmp > 0.f)
			{
				brightness = (float __private)LIGHT[light_hit.id].brightness;

				if (hit.type == 1)
					diffuse = (float3 __private)CONES[hit.id].diff;
				else if (hit.type == 2)
					diffuse = (float3 __private)CYLIND[hit.id].diff;
				else if (hit.type == 4)
				{
					diffuse = (float3 __private)PLANE[hit.id].diff;
					modx = hit.pos.x;
					mody = hit.pos.y;
					modz = hit.pos.z;
					modx = abs((int)(hit.pos.x) % 4);
					mody = abs((int)(hit.pos.y) % 4);
					modz = abs((int)(hit.pos.z) % 4);
					if (modx)
					{
						if ((modz && mody) || (!modz && !mody))
							hue = 0xFFFFFFFF;
						else
							hue = 0;
					}
					else
					{
						if ((modz && mody) || (!modz && !mody))
							hue = 0;
						else
						{
							hue = 0xFFFFFFFF;
						}
					}
				}
				else if (hit.type == 5)
					diffuse = (float3 __private)SPHERE[hit.id].diff;
				else
					diffuse = 0;

				col_r = (res_color & 0xFF0000) >> 16;
				col_g = (res_color & 0x00FF00) >> 8;
				col_b = (res_color & 0x0000FF);
				obj_r = (hue & 0xFF0000) >> 16;
				obj_g = (hue & 0x00FF00) >> 8;
				obj_b = (hue & 0x00000FF);
				l_r = (hue_light & 0xFF0000) >> 16;
				l_g = (hue_light & 0x00FF00) >> 8;
				l_b = (hue_light & 0x0000FF);

				col_r += ((l_r * brightness) + obj_r) * tmp * diffuse.x;
				col_g += ((l_g * brightness) + obj_g) * tmp * diffuse.y;
				col_b += ((l_b * brightness) + obj_b) * tmp * diffuse.z;
				(col_r > 255 ? col_r = 255 : 0);
				(col_g > 255 ? col_g = 255 : 0);
				(col_b > 255 ? col_b = 255 : 0);
				res_color = ((col_r << 16) + (col_g << 8) + col_b);
			}
			reflect = fast_normalize(((float)(2.0 * dot(hit.normale, light_ray.dir)) * hit.normale) - light_ray.dir);
			tmp = dot(reflect, -ray);
			if (tmp > 0.f)
			{
				col_r = (res_color & 0x00FF0000) >> 16;
				col_g = (res_color & 0x0000FF00) >> 8;
				col_b = (res_color & 0x000000FF);

				pow_of_spec = native_powr(tmp, (LIGHT[light_hit.id].shrink));
				light_color = LIGHT[light_hit.id].color;
				col_r += (((light_color & 0xFF0000) >> 16) * pow_of_spec) * speculos.x;
				col_g += ((light_color & 0x00FF00) >> 8) * pow_of_spec * speculos.y;
				col_b += (light_color & 0x0000FF) * pow_of_spec * speculos.z;
				(col_r > 255 ? col_r = 255 : 0);
				(col_g > 255 ? col_g = 255 : 0);
				(col_b > 255 ? col_b = 255 : 0);
				res_color = ((col_r << 16) + (col_g << 8) + col_b);
			}
		}
		i++;
	}
	return (res_color);
}

static unsigned int		bounce(const __local t_scene *scene, const float3 ray, t_hit old_hit, int depth)
{
	unsigned int	color = 0;
	float3			reflex = ray;
	t_hit			new_hit;
	float			reflex_coef = get_obj_reflex(scene, old_hit);
	while (depth > 0)
	{
		reflex = fast_normalize(reflex - (2 * (float)dot(old_hit.normale, reflex) * old_hit.normale));
		new_hit.dist = MAX_DIST;
		new_hit = ray_hit(scene, old_hit.pos, reflex);
		if (new_hit.dist > 0 && new_hit.dist < MAX_DIST)
		{
			new_hit.pos = (new_hit.dist * reflex) + old_hit.pos;
			new_hit.normale = get_hit_normale(scene, reflex, new_hit);
			new_hit.pos = new_hit.pos + ((new_hit.dist / 100) * new_hit.normale);
			color = blend_factor(blend_add(color, phong(scene, new_hit, reflex)), reflex_coef);
		}
		if ((reflex_coef = get_obj_reflex(scene, new_hit)) == 0)
			return (color);
		old_hit = new_hit;
		--depth;
	}
	return (color);
}

static unsigned int	get_pixel_color(const __local t_scene *scene, float3 ray)
{
	t_hit			hit;
	unsigned int	color  = 0;
	unsigned int	bounce_color = 0;

	hit.dist = MAX_DIST;
	hit = ray_hit(scene, (ACTIVECAM.pos), ray);
	if (hit.dist > 0 && hit.dist < MAX_DIST)
	{
		hit.pos = (hit.dist * ray) + (ACTIVECAM.pos);
		hit.normale = get_hit_normale(scene, ray, hit);
		hit.pos = hit.pos + ((hit.dist / SHADOW_BIAS) * hit.normale);
		color = phong(scene, hit, ray);
		if (scene->depth > 0  && (get_obj_reflex(scene, hit) > 0))
			bounce_color = bounce(scene, ray, hit, scene->depth);
		return (blend_add(color, bounce_color));
	}
	return (get_ambient(scene, BACKCOLOR));
}

__kernel void	ray_trace(	__global	char		*output,
							__global	t_hit		*target_obj,
							__global	t_scene		*scene_data,
							__global	t_cam		*cameras_data,
							__global	t_cone		*cones_data,
							__global	t_cylinder	*cylinders_data,
							__global	t_light		*lights_data,
							__global	t_plane		*planes_data,
							__global	t_sphere	*spheres_data,
							__local		t_scene		*scene,
							__local		t_cam		*cameras,
							__local		t_cone		*cones,
							__local		t_cylinder	*cylinders,
							__local		t_light		*lights,
							__local		t_plane		*planes,
							__local		t_sphere	*spheres,
							__private	float		u_time)
{
 	event_t	ev;
	ev = async_work_group_copy((__local char *)scene, (__global char *)scene_data, sizeof(t_scene), 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)cameras, (__global char *)cameras_data, sizeof(t_cam) * scene->n_cams, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)cones, (__global char *)cones_data, sizeof(t_cone) * scene->n_cones, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)cylinders, (__global char *)cylinders_data, sizeof(t_cylinder) * scene->n_cylinders, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)lights, (__global char *)lights_data, sizeof(t_light) * scene->n_lights, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)planes, (__global char *)planes_data, sizeof(t_plane) * scene->n_planes, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)spheres, (__global char *)spheres_data, sizeof(t_sphere) * scene->n_spheres, 0);
	wait_group_events(1, &ev);

	uint2	pix;
	pix.x = get_global_id(0);
	pix.y = get_global_id(1);

	scene->cameras = cameras;
	scene->cones = cones;
	scene->cylinders = cylinders;
	scene->lights = lights;
	scene->planes = planes;
	scene->spheres = spheres;
	scene->u_time = u_time;
	int			id = pix.x + (scene->win_w * pix.y);

	float3	prim_ray = get_ray_cam(scene, pix);

	if (pix.x == scene->mou_x && pix.y == scene->mou_y)
		*target_obj = ray_hit(scene, ACTIVECAM.pos, prim_ray);

	OUTPUT = get_pixel_color(scene, prim_ray);
}

#include "kernel_header.hcl"
#include "kernel_matrix.hcl"
#include "kernel_cam.hcl"
#include "kernel_color.hcl"
#include "kernel_cone.hcl"
#include "kernel_cylinder.hcl"
#include "kernel_data.hcl"
#include "kernel_plane.hcl"
#include "kernel_sphere.hcl"

static t_hit			ray_hit(const __local t_scene *scene, const float3 origin, const float3 ray)
{
	unsigned int			i;
	int						max;
	t_hit					hit;
	float					dist;

	max = get_max_obj(scene);
	dist = 0;
	i = 0;
	hit = hit_init();
	while (i < max)
	{
		if (i < scene->n_cones)
			if (((dist = inter_cone(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 1;
				hit.id = i;
			}
		if (i < scene->n_cylinders)
			if (((dist = inter_cylinder(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 2;
				hit.id = i;
			}
		if (i < scene->n_planes)
			if (((dist = inter_plan(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 4;
				hit.id = i;
			}
		if (i < scene->n_spheres)
			if (((dist = inter_sphere(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 5;
				hit.id = i;
			}
		i++;
	}
	return (hit);
}

float3			get_hit_normale(const __local t_scene *scene, float3 ray, t_hit hit)
{
	float3		res, save;

	if (hit.type == 1)
		res = get_cone_normale(scene, hit);
	else if (hit.type == 2)
		res = get_cylinder_normal(scene, hit);
	else if (hit.type == 4)
	{
		if (dot(PLANE[hit.id].normale, -ray) < 0)
			res = -PLANE[hit.id].normale;
		else
			res = PLANE[hit.id].normale;

		if (scene->flag & OPTION_WAVE)
		{
			save = res;
			save.x = res.x + 0.8 * sin(hit.pos.y * 10 /*+ scene->u_time*/);
			save.z = res.z + 0.8 * sin((hit.pos.x /*+scene->u_time*/));
			save.y = save.y + 0.8 * sin(hit.pos.z * 10 /*+ scene->u_time*/);
			return (fast_normalize(save));
		}
	}
	else if (hit.type == 5)
		res = hit.pos - SPHERE[hit.id].pos;
	save = res;
	if (scene->flag & OPTION_WAVE)
	{
		save.x = res.x + 0.8 * sin(res.y * 10 + scene->u_time);
		save.z = save.z + 0.8 * sin(save.x * 10 + scene->u_time);
		save.y = res.y + 0.8 * sin(res.x * 10 + scene->u_time);
	}

	return (fast_normalize(save));
}

unsigned int			phong(const __local t_scene *scene, const t_hit hit, const float3 ray)
{
	int					i;
	i = 0;
	unsigned int		res_color;
	res_color = get_ambient(scene, get_obj_hue(scene, hit));
	float				tmp;
	tmp = 0;
	float3				reflect;
	reflect = 0;
	float3 __private	diffuse;
	diffuse = 0;
	float __private	brightness;
	brightness = 0;
	int __private hue;
	hue = 0;
	int __private hue_light;
	hue_light = 0;
	unsigned int __private col_r, col_g, col_b, obj_r, obj_g, obj_b, l_r, l_b, l_g;
	col_r = 0;
	col_g = 0;
	col_b = 0;
	obj_r = 0;
	obj_g = 0;
	obj_b = 0;
	l_r = 0;
	l_g = 0;
	l_b = 0;
	t_light_ray			light_ray;
	t_hit				light_hit;
	float __private pow_of_spec;
	pow_of_spec = 0;
	int __private light_color;
	light_color = 0;
	float3 __private speculos;
	speculos = 0;

	while (i < scene->n_lights)
	{
		tmp = 0;
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = fast_length(light_ray.dir);
		light_ray.dir = fast_normalize(light_ray.dir);
		light_hit = ray_hit(scene, hit.pos, light_ray.dir);
		light_hit.id = i;
		light_hit.type = 3;
		if (light_hit.dist < light_ray.dist && light_hit.dist > 0.f)
			;
		else
		{
			tmp = dot(hit.normale, light_ray.dir);
			if (tmp > 0.f)
			{
				brightness = (float __private)LIGHT[light_hit.id].brightness;

				if (hit.type == 1)
					diffuse = (float3 __private)CONES[hit.id].diff;
				else if (hit.type == 2)
					diffuse = (float3 __private)CYLIND[hit.id].diff;
				else if (hit.type == 4)
					diffuse = (float3 __private)PLANE[hit.id].diff;
				else if (hit.type == 5)
					diffuse = (float3 __private)SPHERE[hit.id].diff;
				else
					diffuse = 0.f;

				if (hit.type == 1)
					hue = (int __private)CONES[hit.id].color;
				if (hit.type == 2)
					hue = (int __private)CYLIND[hit.id].color;
				if (hit.type == 3)
					hue = (int __private)LIGHT[hit.id].color;
				if (hit.type == 4)
					hue = (int __private)PLANE[hit.id].color;
				if (hit.type == 5)
					hue = (int __private)SPHERE[hit.id].color;

				if (hit.type == 1)
					hue_light = (int __private)CONES[light_hit.id].color;
				if (hit.type == 2)
					hue_light = (int __private)CYLIND[light_hit.id].color;
				if (hit.type == 3)
					hue_light = (int __private)LIGHT[light_hit.id].color;
				if (hit.type == 4)
					hue_light = (int __private)PLANE[light_hit.id].color;
				if (hit.type == 5)
					hue_light = (int __private)SPHERE[light_hit.id].color;
				col_r = (res_color & 0xFF0000) >> 16;
				col_g = (res_color & 0x00FF00) >> 8;
				col_b = (res_color & 0x0000FF);
				obj_r = (hue & 0xFF0000) >> 16;
				obj_g = (hue & 0x00FF00) >> 8;
				obj_b = (hue & 0x00000FF);
				l_r = (hue_light & 0xFF0000) >> 16;
				l_g = (hue_light & 0x00FF00) >> 8;
				l_b = (hue_light & 0x0000FF);

				col_r += ((l_r * brightness) + obj_r) * tmp * diffuse.x;
				col_g += ((l_g * brightness) + obj_g) * tmp * diffuse.y;
				col_b += ((l_b * brightness) + obj_b) * tmp * diffuse.z;
				(col_r > 255 ? col_r = 255 : 0);
				(col_g > 255 ? col_g = 255 : 0);
				(col_b > 255 ? col_b = 255 : 0);
				res_color = ((col_r << 16) + (col_g << 8) + col_b);
			}
			reflect = fast_normalize(((float)(2.0 * dot(hit.normale, light_ray.dir)) * hit.normale) - light_ray.dir);
			tmp = dot(reflect, -ray);
			if (tmp > 0.f)
			{
				speculos = 0.f;
				if (hit.type == 1)
					speculos = (float3 __private)CONES[hit.id].spec;
				else if (hit.type == 2)
					speculos = (float3 __private)CYLIND[hit.id].spec;
				else if (hit.type == 4)
					speculos = (float3 __private)PLANE[hit.id].spec;
				else if (hit.type == 5)
					speculos = (float3 __private)SPHERE[hit.id].spec;
				else
					speculos = 0.f;
				col_r = (res_color & 0x00FF0000) >> 16;
				col_g = (res_color & 0x0000FF00) >> 8;
				col_b = (res_color & 0x000000FF);

				pow_of_spec = native_powr(tmp, (LIGHT[light_hit.id].shrink));
				light_color = LIGHT[light_hit.id].color;
				col_r += (((light_color & 0xFF0000) >> 16) * pow_of_spec) * speculos.x;
				col_g += ((light_color & 0x00FF00) >> 8) * pow_of_spec * speculos.y;
				col_b += (light_color & 0x0000FF) * pow_of_spec * speculos.z;
				(col_r > 255 ? col_r = 255 : 0);
				(col_g > 255 ? col_g = 255 : 0);
				(col_b > 255 ? col_b = 255 : 0);
				res_color = ((col_r << 16) + (col_g << 8) + col_b);
			}
		}
		i++;
	}
	return (res_color);
}

unsigned int			phong2(const __local t_scene *scene, const t_hit hit, const float3 ray)
{

	int __private hue_light;
	unsigned int __private col_r, col_g, col_b, obj_r, obj_g, obj_b, l_r, l_b, l_g;
	int __private modx, mody, modz;
	int __private hue;
	float __private	brightness;
	float3 __private	diffuse;
	float3				reflect;
	float				tmp;
	unsigned int		res_color;
	int					i;
	int __private light_color;
	float3 __private speculos;
	float __private pow_of_spec;
	t_light_ray			light_ray;
	t_hit				light_hit;

	i = 0;
	if (hit.type == 1)
		hue = (int __private)CONES[hit.id].color;
	else if (hit.type == 2)
		hue = (int __private)CYLIND[hit.id].color;
	else if (hit.type == 3)
		hue = (int __private)LIGHT[hit.id].color;
	else if (hit.type == 4)
		hue = (int __private)PLANE[hit.id].color;
	else if (hit.type == 5)
		hue = (int __private)SPHERE[hit.id].color;

	if (hit.type == 1)
		hue_light = (int __private)CONES[0].color;
	else if (hit.type == 2)
		hue_light = (int __private)CYLIND[0].color;
	else if (hit.type == 3)
		hue_light = (int __private)LIGHT[0].color;
	else if (hit.type == 4)
		hue_light = (int __private)PLANE[0].color;
	else if (hit.type == 5)
		hue_light = (int __private)SPHERE[0].color;

	if (hit.type == 1)
		speculos = (float3 __private)CONES[hit.id].spec;
	else if (hit.type == 2)
		speculos = (float3 __private)CYLIND[hit.id].spec;
	else if (hit.type == 4)
		speculos = 0;
	else if (hit.type == 5)
		speculos = (float3 __private)SPHERE[hit.id].spec;
	else
		speculos = 0.f;

	col_r = (hue & 0x00FF0000) >> 16;
	col_g = (hue & 0x0000FF00) >> 8;
	col_b = (hue & 0x000000FF);
	col_r = (0.01 + col_r * scene->ambient.x > 255 ? 255 : 0.01 + col_r * scene->ambient.x);
	col_g = (0.01 + col_g * scene->ambient.y > 255 ? 255 : 0.01 + col_g * scene->ambient.y);
	col_b = (0.01 + col_b * scene->ambient.z > 255 ? 255 : 0.01 + col_b * scene->ambient.z);
	res_color = ((col_r << 16) + (col_g << 8) + col_b);

	while (++i < scene->n_lights)
	{
	light_ray.dir = LIGHT[i].pos - hit.pos;
	light_ray.dist = fast_length(light_ray.dir);
	light_ray.dir = fast_normalize(light_ray.dir);
	light_hit = ray_hit(scene, hit.pos, light_ray.dir);
	light_hit.id = i;
	light_hit.type = 3;

	reflect = 0;
	diffuse = 0;
	brightness = 0;
	modx = 0;
	mody = 0;
	modz = 0;
	col_r = 0;
	col_g = 0;
	col_b = 0;
	obj_r = 0;
	obj_g = 0;
	obj_b = 0;
	l_r = 0;
	l_g = 0;
	l_b = 0;
	pow_of_spec = 0;
	light_color = 0;
	tmp = 0;

	float3 touch;
	touch = scene->cameras->pos + scene->cameras->dir * hit.dist;

		if (!(light_hit.dist < light_ray.dist && light_hit.dist > 0))
		{
			tmp = dot(hit.normale, light_ray.dir);
			if (tmp > 0.f)
			{
				brightness = (float __private)LIGHT[light_hit.id].brightness;

				if (hit.type == 1)
					diffuse = (float3 __private)CONES[hit.id].diff;
				else if (hit.type == 2)
					diffuse = (float3 __private)CYLIND[hit.id].diff;
				else if (hit.type == 4)
				{
					diffuse = (float3 __private)PLANE[hit.id].diff;
					modx = hit.pos.x;
					mody = hit.pos.y;
					modz = hit.pos.z;
					modx = abs((int)(hit.pos.x) % 4);
					mody = abs((int)(hit.pos.y) % 4);
					modz = abs((int)(hit.pos.z) % 4);
					if (modx)
					{
						if ((modz && mody) || (!modz && !mody))
							hue = 0xFFFFFFFF;
						else
							hue = 0;
					}
					else
					{
						if ((modz && mody) || (!modz && !mody))
							hue = 0;
						else
						{
							hue = 0xFFFFFFFF;
						}
					}
				}
				else if (hit.type == 5)
					diffuse = (float3 __private)SPHERE[hit.id].diff;
				else
					diffuse = 0;

				col_r = (res_color & 0xFF0000) >> 16;
				col_g = (res_color & 0x00FF00) >> 8;
				col_b = (res_color & 0x0000FF);
				obj_r = (hue & 0xFF0000) >> 16;
				obj_g = (hue & 0x00FF00) >> 8;
				obj_b = (hue & 0x00000FF);
				l_r = (hue_light & 0xFF0000) >> 16;
				l_g = (hue_light & 0x00FF00) >> 8;
				l_b = (hue_light & 0x0000FF);

				col_r += ((l_r * brightness) + obj_r) * tmp * diffuse.x;
				col_g += ((l_g * brightness) + obj_g) * tmp * diffuse.y;
				col_b += ((l_b * brightness) + obj_b) * tmp * diffuse.z;
				(col_r > 255 ? col_r = 255 : 0);
				(col_g > 255 ? col_g = 255 : 0);
				(col_b > 255 ? col_b = 255 : 0);
				res_color = ((col_r << 16) + (col_g << 8) + col_b);
			}
			reflect = fast_normalize(((float)(2.0 * dot(hit.normale, light_ray.dir)) * hit.normale) - light_ray.dir);
			tmp = dot(reflect, -ray);
			if (tmp > 0.f)
			{
				col_r = (res_color & 0x00FF0000) >> 16;
				col_g = (res_color & 0x0000FF00) >> 8;
				col_b = (res_color & 0x000000FF);

				pow_of_spec = native_powr(tmp, (LIGHT[light_hit.id].shrink));
				light_color = LIGHT[light_hit.id].color;
				col_r += (((light_color & 0xFF0000) >> 16) * pow_of_spec) * speculos.x;
				col_g += ((light_color & 0x00FF00) >> 8) * pow_of_spec * speculos.y;
				col_b += (light_color & 0x0000FF) * pow_of_spec * speculos.z;
				(col_r > 255 ? col_r = 255 : 0);
				(col_g > 255 ? col_g = 255 : 0);
				(col_b > 255 ? col_b = 255 : 0);
				res_color = ((col_r << 16) + (col_g << 8) + col_b);
			}
		}
		i++;
	}
	return (res_color);
}

static unsigned int		bounce(const __local t_scene *scene, const float3 ray, t_hit old_hit, int depth)
{
	unsigned int	color = 0;
	float3			reflex = ray;
	t_hit			new_hit;
	float			reflex_coef = get_obj_reflex(scene, old_hit);
	while (depth > 0)
	{
		reflex = fast_normalize(reflex - (2 * (float)dot(old_hit.normale, reflex) * old_hit.normale));
		new_hit.dist = MAX_DIST;
		new_hit = ray_hit(scene, old_hit.pos, reflex);
		if (new_hit.dist > 0 && new_hit.dist < MAX_DIST)
		{
			new_hit.pos = (new_hit.dist * reflex) + old_hit.pos;
			new_hit.normale = get_hit_normale(scene, reflex, new_hit);
			new_hit.pos = new_hit.pos + ((new_hit.dist / 100) * new_hit.normale);
			color = blend_factor(blend_add(color, phong(scene, new_hit, reflex)), reflex_coef);
		}
		if ((reflex_coef = get_obj_reflex(scene, new_hit)) == 0)
			return (color);
		old_hit = new_hit;
		--depth;
	}
	return (color);
}

static unsigned int	get_pixel_color(const __local t_scene *scene, float3 ray)
{
	t_hit			hit;
	unsigned int	color  = 0;
	unsigned int	bounce_color = 0;

	hit.dist = MAX_DIST;
	hit = ray_hit(scene, (ACTIVECAM.pos), ray);
	if (hit.dist > 0 && hit.dist < MAX_DIST)
	{
		hit.pos = (hit.dist * ray) + (ACTIVECAM.pos);
		hit.normale = get_hit_normale(scene, ray, hit);
		hit.pos = hit.pos + ((hit.dist / SHADOW_BIAS) * hit.normale);
		color = phong(scene, hit, ray);
		if (scene->depth > 0  && (get_obj_reflex(scene, hit) > 0))
			bounce_color = bounce(scene, ray, hit, scene->depth);
		return (blend_add(color, bounce_color));
	}
	return (get_ambient(scene, BACKCOLOR));
}

__kernel void	ray_trace(	__global	char		*output,
							__global	t_hit		*target_obj,
							__global	t_scene		*scene_data,
							__global	t_cam		*cameras_data,
							__global	t_cone		*cones_data,
							__global	t_cylinder	*cylinders_data,
							__global	t_light		*lights_data,
							__global	t_plane		*planes_data,
							__global	t_sphere	*spheres_data,
							__local		t_scene		*scene,
							__local		t_cam		*cameras,
							__local		t_cone		*cones,
							__local		t_cylinder	*cylinders,
							__local		t_light		*lights,
							__local		t_plane		*planes,
							__local		t_sphere	*spheres,
							__private	float		u_time)
{
 	event_t	ev;
	ev = async_work_group_copy((__local char *)scene, (__global char *)scene_data, sizeof(t_scene), 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)cameras, (__global char *)cameras_data, sizeof(t_cam) * scene->n_cams, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)cones, (__global char *)cones_data, sizeof(t_cone) * scene->n_cones, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)cylinders, (__global char *)cylinders_data, sizeof(t_cylinder) * scene->n_cylinders, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)lights, (__global char *)lights_data, sizeof(t_light) * scene->n_lights, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)planes, (__global char *)planes_data, sizeof(t_plane) * scene->n_planes, 0);
	wait_group_events(1, &ev);
	ev = async_work_group_copy((__local char *)spheres, (__global char *)spheres_data, sizeof(t_sphere) * scene->n_spheres, 0);
	wait_group_events(1, &ev);

	uint2	pix;
	pix.x = get_global_id(0);
	pix.y = get_global_id(1);

	scene->cameras = cameras;
	scene->cones = cones;
	scene->cylinders = cylinders;
	scene->lights = lights;
	scene->planes = planes;
	scene->spheres = spheres;
	scene->u_time = u_time;
	int			id = pix.x + (scene->win_w * pix.y);

	float3	prim_ray = get_ray_cam(scene, pix);

	if (pix.x == scene->mou_x && pix.y == scene->mou_y)
		*target_obj = ray_hit(scene, ACTIVECAM.pos, prim_ray);

	OUTPUT = get_pixel_color(scene, prim_ray);
}


OpenCL: Try to fix bot test failure

OpenCL: Try to fix bot test failure

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

// RUN: cp %s %t
// RUN: %clang_cc1 -cl-std=CL1.2 -pedantic -Wall -fixit %t
// RUN: %clang_cc1 -cl-std=CL1.2 -fsyntax-only -pedantic -Wall -Werror %t
// RUN: %clang_cc1 -cl-std=CL1.2 -E -o - %t | FileCheck %s

#pragma OPENCL EXTENSION cl_khr_fp64 : enable

typedef __attribute__((ext_vector_type(4))) char char4;
typedef __attribute__((ext_vector_type(4))) short short4;
typedef __attribute__((ext_vector_type(4))) int int4;
typedef __attribute__((ext_vector_type(4))) unsigned int uint4;
typedef __attribute__((ext_vector_type(8))) int int8;
typedef __attribute__((ext_vector_type(4))) long long4;
typedef __attribute__((ext_vector_type(4))) float float4;
typedef __attribute__((ext_vector_type(4))) double double4;

int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));

void vector_fixits() {
  printf("%v4f", (int4) 123);
  // CHECK: printf("%v4hld", (int4) 123);

  printf("%v8d", (int4) 123);
  // CHECK: printf("%v4hld", (int4) 123);

  printf("%v4d", (int8) 123);
  // CHECK: printf("%v8hld", (int8) 123);

  printf("%v4f", (int8) 123);
  // CHECK: printf("%v8hld", (int8) 123);

  printf("%v4ld", (int8) 123);
  // CHECK: printf("%v8hld", (int8) 123);

  printf("%v4hlf", (int4) 123);
  // CHECK: printf("%v4hld", (int4) 123);

  printf("%v8hld", (int4) 123);
  // CHECK: printf("%v4hld", (int4) 123);

  printf("%v4hld", (int8) 123);
  // CHECK: printf("%v8hld", (int8) 123);

  printf("%v4hlf", (int8) 123);
  // CHECK: printf("%v8hld", (int8) 123);

  printf("%v4hd", (int4) 123);
  // CHECK: printf("%v4hld", (int4) 123);

  printf("%v4hld", (short4) 123);
  // CHECK: printf("%v4hd", (short4) 123);

  printf("%v4ld", (short4) 123);
  // CHECK: printf("%v4hd", (short4) 123);

  printf("%v4hld", (long4) 123);
  // CHECK: printf("%v4ld", (long4) 123);

  printf("%v8f", (float4) 2.0f);
  // CHECK: printf("%v4hlf", (float4) 2.0f);

  printf("%v4f", (float4) 2.0f);
  // CHECK: printf("%v4hlf", (float4) 2.0f);

  printf("%v4lf", (double4) 2.0);
  // CHECK: printf("%v4lf", (double4) 2.0);

  /// FIXME: This should be fixed
  printf("%v4hhd", (int4) 123);
  // CHECK: printf("%v4hhd", (int4) 123);

  /// FIXME: This should be fixed
  printf("%v4hhd", (int8) 123);
  // CHECK: printf("%v4hhd", (int8) 123);
}

// RUN: cp %s %t
// RUN: %clang_cc1 -cl-std=CL1.2 -pedantic -Wall -fixit %t
// RUN: %clang_cc1 -cl-std=CL1.2 -fsyntax-only -pedantic -Wall -Werror %t
// RUN: %clang_cc1 -cl-std=CL1.2 -E -o - %t | FileCheck %s

typedef __attribute__((ext_vector_type(4))) char char4;
typedef __attribute__((ext_vector_type(4))) short short4;
typedef __attribute__((ext_vector_type(4))) int int4;
typedef __attribute__((ext_vector_type(4))) unsigned int uint4;
typedef __attribute__((ext_vector_type(8))) int int8;
typedef __attribute__((ext_vector_type(4))) long long4;
typedef __attribute__((ext_vector_type(4))) float float4;
typedef __attribute__((ext_vector_type(4))) double double4;

int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));

void vector_fixits() {
  printf("%v4f", (int4) 123);
  // CHECK: printf("%v4hld", (int4) 123);

  printf("%v8d", (int4) 123);
  // CHECK: printf("%v4hld", (int4) 123);

  printf("%v4d", (int8) 123);
  // CHECK: printf("%v8hld", (int8) 123);

  printf("%v4f", (int8) 123);
  // CHECK: printf("%v8hld", (int8) 123);

  printf("%v4ld", (int8) 123);
  // CHECK: printf("%v8hld", (int8) 123);

  printf("%v4hlf", (int4) 123);
  // CHECK: printf("%v4hld", (int4) 123);

  printf("%v8hld", (int4) 123);
  // CHECK: printf("%v4hld", (int4) 123);

  printf("%v4hld", (int8) 123);
  // CHECK: printf("%v8hld", (int8) 123);

  printf("%v4hlf", (int8) 123);
  // CHECK: printf("%v8hld", (int8) 123);

  printf("%v4hd", (int4) 123);
  // CHECK: printf("%v4hld", (int4) 123);

  printf("%v4hld", (short4) 123);
  // CHECK: printf("%v4hd", (short4) 123);

  printf("%v4ld", (short4) 123);
  // CHECK: printf("%v4hd", (short4) 123);

  printf("%v4hld", (long4) 123);
  // CHECK: printf("%v4ld", (long4) 123);

  printf("%v8f", (float4) 2.0f);
  // CHECK: printf("%v4hlf", (float4) 2.0f);

  printf("%v4f", (float4) 2.0f);
  // CHECK: printf("%v4hlf", (float4) 2.0f);

  printf("%v4lf", (double4) 2.0);
  // CHECK: printf("%v4lf", (double4) 2.0);

  /// FIXME: This should be fixed
  printf("%v4hhd", (int4) 123);
  // CHECK: printf("%v4hhd", (int4) 123);

  /// FIXME: This should be fixed
  printf("%v4hhd", (int8) 123);
  // CHECK: printf("%v4hhd", (int8) 123);
}