text: /*
   * Copyright 2011-2013 Blender Foundation
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  #ifndef __KERNEL_TYPES_H__
  #define __KERNEL_TYPES_H__
  
  #if !defined(__KERNEL_GPU__) && defined(WITH_EMBREE)
  #  include <embree3/rtcore.h>
  #  include <embree3/rtcore_scene.h>
  #  define __EMBREE__
  #endif
  
  #include "kernel/kernel_math.h"
  #include "kernel/svm/svm_types.h"
  #include "util/util_static_assert.h"
  
  #ifndef __KERNEL_GPU__
  #  define __KERNEL_CPU__
  #endif
  
  /* TODO(sergey): This is only to make it possible to include this header
   * from outside of the kernel. but this could be done somewhat cleaner?
   */
  #ifndef ccl_addr_space
  #  define ccl_addr_space
  #endif
  
  CCL_NAMESPACE_BEGIN
  
  /* Constants */
  #define OBJECT_MOTION_PASS_SIZE 2
  #define FILTER_TABLE_SIZE 1024
  #define RAMP_TABLE_SIZE 256
  #define SHUTTER_TABLE_SIZE 256
  
  #define BSSRDF_MIN_RADIUS 1e-8f
  #define BSSRDF_MAX_HITS 4
  #define BSSRDF_MAX_BOUNCES 256
  #define LOCAL_MAX_HITS 4
  
  #define VOLUME_BOUNDS_MAX 1024
  
  #define BECKMANN_TABLE_SIZE 256
  
  #define SHADER_NONE (~0)
  #define OBJECT_NONE (~0)
  #define PRIM_NONE (~0)
  #define LAMP_NONE (~0)
  #define ID_NONE (0.0f)
  
  #define VOLUME_STACK_SIZE 32
  
  /* Split kernel constants */
  #define WORK_POOL_SIZE_GPU 64
  #define WORK_POOL_SIZE_CPU 1
  #ifdef __KERNEL_GPU__
  #  define WORK_POOL_SIZE WORK_POOL_SIZE_GPU
  #else
  #  define WORK_POOL_SIZE WORK_POOL_SIZE_CPU
  #endif
  
  #define SHADER_SORT_BLOCK_SIZE 2048
  
  #ifdef __KERNEL_OPENCL__
  #  define SHADER_SORT_LOCAL_SIZE 64
  #elif defined(__KERNEL_CUDA__)
  #  define SHADER_SORT_LOCAL_SIZE 32
  #else
  #  define SHADER_SORT_LOCAL_SIZE 1
  #endif
  
  /* Kernel features */
  #define __SOBOL__
  #define __INSTANCING__
  #define __DPDU__
  #define __UV__
  #define __BACKGROUND__
  #define __CAUSTICS_TRICKS__
  #define __VISIBILITY_FLAG__
  #define __RAY_DIFFERENTIALS__
  #define __CAMERA_CLIPPING__
  #define __INTERSECTION_REFINE__
  #define __CLAMP_SAMPLE__
  #define __PATCH_EVAL__
  #define __SHADOW_TRICKS__
  #define __DENOISING_FEATURES__
  #define __SHADER_RAYTRACE__
  #define __AO__
  #define __PASSES__
  #define __HAIR__
  
  /* Without these we get an AO render, used by OpenCL preview kernel. */
  #ifndef __KERNEL_AO_PREVIEW__
  #  define __SVM__
  #  define __EMISSION__
  #  define __TEXTURES__
  #  define __EXTRA_NODES__
  #  define __HOLDOUT__
  #  define __MULTI_CLOSURE__
  #  define __TRANSPARENT_SHADOWS__
  #  define __BACKGROUND_MIS__
  #  define __LAMP_MIS__
  #  define __CAMERA_MOTION__
  #  define __OBJECT_MOTION__
  #  define __BAKING__
  #  define __PRINCIPLED__
  #  define __SUBSURFACE__
  #  define __VOLUME__
  #  define __VOLUME_SCATTER__
  #  define __CMJ__
  #  define __SHADOW_RECORD_ALL__
  #  define __BRANCHED_PATH__
  #endif
  
  /* Device specific features */
  #ifdef __KERNEL_CPU__
  #  ifdef __KERNEL_SSE2__
  #    define __QBVH__
  #  endif
  #  ifdef WITH_OSL
  #    define __OSL__
  #  endif
  #  define __VOLUME_DECOUPLED__
  #  define __VOLUME_RECORD_ALL__
  #endif /* __KERNEL_CPU__ */
  
  #ifdef __KERNEL_CUDA__
  #  ifdef __SPLIT_KERNEL__
  #    undef __BRANCHED_PATH__
  #  endif
  #endif /* __KERNEL_CUDA__ */
  
  #ifdef __KERNEL_OPTIX__
  #  undef __BAKING__
  #  undef __BRANCHED_PATH__
  /* TODO(pmours): Cannot use optixTrace in non-inlined functions */
  #  undef __SHADER_RAYTRACE__
  #endif /* __KERNEL_OPTIX__ */
  
  #ifdef __KERNEL_OPENCL__
  #endif /* __KERNEL_OPENCL__ */
  
  /* Scene-based selective features compilation. */
  #ifdef __NO_CAMERA_MOTION__
  #  undef __CAMERA_MOTION__
  #endif
  #ifdef __NO_OBJECT_MOTION__
  #  undef __OBJECT_MOTION__
  #endif
  #ifdef __NO_HAIR__
  #  undef __HAIR__
  #endif
  #ifdef __NO_VOLUME__
  #  undef __VOLUME__
  #  undef __VOLUME_SCATTER__
  #endif
  #ifdef __NO_SUBSURFACE__
  #  undef __SUBSURFACE__
  #endif
  #ifdef __NO_BAKING__
  #  undef __BAKING__
  #endif
  #ifdef __NO_BRANCHED_PATH__
  #  undef __BRANCHED_PATH__
  #endif
  #ifdef __NO_PATCH_EVAL__
  #  undef __PATCH_EVAL__
  #endif
  #ifdef __NO_TRANSPARENT__
  #  undef __TRANSPARENT_SHADOWS__
  #endif
  #ifdef __NO_SHADOW_TRICKS__
  #  undef __SHADOW_TRICKS__
  #endif
  #ifdef __NO_PRINCIPLED__
  #  undef __PRINCIPLED__
  #endif
  #ifdef __NO_DENOISING__
  #  undef __DENOISING_FEATURES__
  #endif
  #ifdef __NO_SHADER_RAYTRACE__
  #  undef __SHADER_RAYTRACE__
  #endif
  
  /* Features that enable others */
  #ifdef WITH_CYCLES_DEBUG
  #  define __KERNEL_DEBUG__
  #endif
  
  #if defined(__SUBSURFACE__) || defined(__SHADER_RAYTRACE__)
  #  define __BVH_LOCAL__
  #endif
  
  /* Shader Evaluation */
  
  typedef enum ShaderEvalType {
    SHADER_EVAL_DISPLACE,
    SHADER_EVAL_BACKGROUND,
    /* bake types */
    SHADER_EVAL_BAKE, /* no real shade, it's used in the code to
                       * differentiate the type of shader eval from the above
                       */
    /* data passes */
    SHADER_EVAL_NORMAL,
    SHADER_EVAL_UV,
    SHADER_EVAL_ROUGHNESS,
    SHADER_EVAL_DIFFUSE_COLOR,
    SHADER_EVAL_GLOSSY_COLOR,
    SHADER_EVAL_TRANSMISSION_COLOR,
    SHADER_EVAL_SUBSURFACE_COLOR,
    SHADER_EVAL_EMISSION,
    SHADER_EVAL_AOV_COLOR,
    SHADER_EVAL_AOV_VALUE,
  
    /* light passes */
    SHADER_EVAL_AO,
    SHADER_EVAL_COMBINED,
    SHADER_EVAL_SHADOW,
    SHADER_EVAL_DIFFUSE,
    SHADER_EVAL_GLOSSY,
    SHADER_EVAL_TRANSMISSION,
    SHADER_EVAL_SUBSURFACE,
  
    /* extra */
    SHADER_EVAL_ENVIRONMENT,
  } ShaderEvalType;
  
  /* Path Tracing
   * note we need to keep the u/v pairs at even values */
  
  enum PathTraceDimension {
    PRNG_FILTER_U = 0,
    PRNG_FILTER_V = 1,
    PRNG_LENS_U = 2,
    PRNG_LENS_V = 3,
    PRNG_TIME = 4,
    PRNG_UNUSED_0 = 5,
    PRNG_UNUSED_1 = 6, /* for some reason (6, 7) is a bad sobol pattern */
    PRNG_UNUSED_2 = 7, /* with a low number of samples (< 64) */
    PRNG_BASE_NUM = 10,
  
    PRNG_BSDF_U = 0,
    PRNG_BSDF_V = 1,
    PRNG_LIGHT_U = 2,
    PRNG_LIGHT_V = 3,
    PRNG_LIGHT_TERMINATE = 4,
    PRNG_TERMINATE = 5,
    PRNG_PHASE_CHANNEL = 6,
    PRNG_SCATTER_DISTANCE = 7,
    PRNG_BOUNCE_NUM = 8,
  
    PRNG_BEVEL_U = 6, /* reuse volume dimension, correlation won't harm */
    PRNG_BEVEL_V = 7,
  };
  
  enum SamplingPattern {
    SAMPLING_PATTERN_SOBOL = 0,
    SAMPLING_PATTERN_CMJ = 1,
  
    SAMPLING_NUM_PATTERNS,
  };
  
  /* these flags values correspond to raytypes in osl.cpp, so keep them in sync! */
  
  enum PathRayFlag {
    PATH_RAY_CAMERA = (1 << 0),
    PATH_RAY_REFLECT = (1 << 1),
    PATH_RAY_TRANSMIT = (1 << 2),
    PATH_RAY_DIFFUSE = (1 << 3),
    PATH_RAY_GLOSSY = (1 << 4),
    PATH_RAY_SINGULAR = (1 << 5),
    PATH_RAY_TRANSPARENT = (1 << 6),
  
    PATH_RAY_SHADOW_OPAQUE_NON_CATCHER = (1 << 7),
    PATH_RAY_SHADOW_OPAQUE_CATCHER = (1 << 8),
    PATH_RAY_SHADOW_OPAQUE = (PATH_RAY_SHADOW_OPAQUE_NON_CATCHER | PATH_RAY_SHADOW_OPAQUE_CATCHER),
    PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER = (1 << 9),
    PATH_RAY_SHADOW_TRANSPARENT_CATCHER = (1 << 10),
    PATH_RAY_SHADOW_TRANSPARENT = (PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER |
                                   PATH_RAY_SHADOW_TRANSPARENT_CATCHER),
    PATH_RAY_SHADOW_NON_CATCHER = (PATH_RAY_SHADOW_OPAQUE_NON_CATCHER |
                                   PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER),
    PATH_RAY_SHADOW = (PATH_RAY_SHADOW_OPAQUE | PATH_RAY_SHADOW_TRANSPARENT),
  
    PATH_RAY_CURVE = (1 << 11),          /* visibility flag to define curve segments */
    PATH_RAY_VOLUME_SCATTER = (1 << 12), /* volume scattering */
  
    /* Special flag to tag unaligned BVH nodes. */
    PATH_RAY_NODE_UNALIGNED = (1 << 13),
  
    PATH_RAY_ALL_VISIBILITY = ((1 << 14) - 1),
  
    /* Don't apply multiple importance sampling weights to emission from
     * lamp or surface hits, because they were not direct light sampled. */
    PATH_RAY_MIS_SKIP = (1 << 14),
    /* Diffuse bounce earlier in the path, skip SSS to improve performance
     * and avoid branching twice with disk sampling SSS. */
    PATH_RAY_DIFFUSE_ANCESTOR = (1 << 15),
    /* Single pass has been written. */
    PATH_RAY_SINGLE_PASS_DONE = (1 << 16),
    /* Ray is behind a shadow catcher .*/
    PATH_RAY_SHADOW_CATCHER = (1 << 17),
    /* Store shadow data for shadow catcher or denoising. */
    PATH_RAY_STORE_SHADOW_INFO = (1 << 18),
    /* Zero background alpha, for camera or transparent glass rays. */
    PATH_RAY_TRANSPARENT_BACKGROUND = (1 << 19),
    /* Terminate ray immediately at next bounce. */
    PATH_RAY_TERMINATE_IMMEDIATE = (1 << 20),
    /* Ray is to be terminated, but continue with transparent bounces and
     * emission as long as we encounter them. This is required to make the
     * MIS between direct and indirect light rays match, as shadow rays go
     * through transparent surfaces to reach emission too. */
    PATH_RAY_TERMINATE_AFTER_TRANSPARENT = (1 << 21),
    /* Ray is to be terminated. */
    PATH_RAY_TERMINATE = (PATH_RAY_TERMINATE_IMMEDIATE | PATH_RAY_TERMINATE_AFTER_TRANSPARENT),
    /* Path and shader is being evaluated for direct lighting emission. */
    PATH_RAY_EMISSION = (1 << 22)
  };
  
  /* Closure Label */
  
  typedef enum ClosureLabel {
    LABEL_NONE = 0,
    LABEL_TRANSMIT = 1,
    LABEL_REFLECT = 2,
    LABEL_DIFFUSE = 4,
    LABEL_GLOSSY = 8,
    LABEL_SINGULAR = 16,
    LABEL_TRANSPARENT = 32,
    LABEL_VOLUME_SCATTER = 64,
    LABEL_TRANSMIT_TRANSPARENT = 128,
  } ClosureLabel;
  
  /* Render Passes */
  
  #define PASS_NAME_JOIN(a, b) a##_##b
  #define PASSMASK(pass) (1 << ((PASS_NAME_JOIN(PASS, pass)) % 32))
  
  #define PASSMASK_COMPONENT(comp) \
    (PASSMASK(PASS_NAME_JOIN(comp, DIRECT)) | PASSMASK(PASS_NAME_JOIN(comp, INDIRECT)) | \
     PASSMASK(PASS_NAME_JOIN(comp, COLOR)))
  
  typedef enum PassType {
    PASS_NONE = 0,
  
    /* Main passes */
    PASS_COMBINED = 1,
    PASS_DEPTH,
    PASS_NORMAL,
    PASS_UV,
    PASS_OBJECT_ID,
    PASS_MATERIAL_ID,
    PASS_MOTION,
    PASS_MOTION_WEIGHT,
  #ifdef __KERNEL_DEBUG__
    PASS_BVH_TRAVERSED_NODES,
    PASS_BVH_TRAVERSED_INSTANCES,
    PASS_BVH_INTERSECTIONS,
    PASS_RAY_BOUNCES,
  #endif
    PASS_RENDER_TIME,
    PASS_CRYPTOMATTE,
    PASS_AOV_COLOR,
    PASS_AOV_VALUE,
    PASS_CATEGORY_MAIN_END = 31,
  
    PASS_MIST = 32,
    PASS_EMISSION,
    PASS_BACKGROUND,
    PASS_AO,
    PASS_SHADOW,
    PASS_LIGHT, /* no real pass, used to force use_light_pass */
    PASS_DIFFUSE_DIRECT,
    PASS_DIFFUSE_INDIRECT,
    PASS_DIFFUSE_COLOR,
    PASS_GLOSSY_DIRECT,
    PASS_GLOSSY_INDIRECT,
    PASS_GLOSSY_COLOR,
    PASS_TRANSMISSION_DIRECT,
    PASS_TRANSMISSION_INDIRECT,
    PASS_TRANSMISSION_COLOR,
    PASS_SUBSURFACE_DIRECT,
    PASS_SUBSURFACE_INDIRECT,
    PASS_SUBSURFACE_COLOR,
    PASS_VOLUME_DIRECT,
    PASS_VOLUME_INDIRECT,
    /* No Scatter color since it's tricky to define what it would even mean. */
    PASS_CATEGORY_LIGHT_END = 63,
  } PassType;
  
  #define PASS_ANY (~0)
  
  typedef enum CryptomatteType {
    CRYPT_NONE = 0,
    CRYPT_OBJECT = (1 << 0),
    CRYPT_MATERIAL = (1 << 1),
    CRYPT_ASSET = (1 << 2),
    CRYPT_ACCURATE = (1 << 3),
  } CryptomatteType;
  
  typedef enum DenoisingPassOffsets {
    DENOISING_PASS_NORMAL = 0,
    DENOISING_PASS_NORMAL_VAR = 3,
    DENOISING_PASS_ALBEDO = 6,
    DENOISING_PASS_ALBEDO_VAR = 9,
    DENOISING_PASS_DEPTH = 12,
    DENOISING_PASS_DEPTH_VAR = 13,
    DENOISING_PASS_SHADOW_A = 14,
    DENOISING_PASS_SHADOW_B = 17,
    DENOISING_PASS_COLOR = 20,
    DENOISING_PASS_COLOR_VAR = 23,
    DENOISING_PASS_CLEAN = 26,
  
    DENOISING_PASS_PREFILTERED_DEPTH = 0,
    DENOISING_PASS_PREFILTERED_NORMAL = 1,
    DENOISING_PASS_PREFILTERED_SHADOWING = 4,
    DENOISING_PASS_PREFILTERED_ALBEDO = 5,
    DENOISING_PASS_PREFILTERED_COLOR = 8,
    DENOISING_PASS_PREFILTERED_VARIANCE = 11,
    DENOISING_PASS_PREFILTERED_INTENSITY = 14,
  
    DENOISING_PASS_SIZE_BASE = 26,
    DENOISING_PASS_SIZE_CLEAN = 3,
    DENOISING_PASS_SIZE_PREFILTERED = 15,
  } DenoisingPassOffsets;
  
  typedef enum eBakePassFilter {
    BAKE_FILTER_NONE = 0,
    BAKE_FILTER_DIRECT = (1 << 0),
    BAKE_FILTER_INDIRECT = (1 << 1),
    BAKE_FILTER_COLOR = (1 << 2),
    BAKE_FILTER_DIFFUSE = (1 << 3),
    BAKE_FILTER_GLOSSY = (1 << 4),
    BAKE_FILTER_TRANSMISSION = (1 << 5),
    BAKE_FILTER_SUBSURFACE = (1 << 6),
    BAKE_FILTER_EMISSION = (1 << 7),
    BAKE_FILTER_AO = (1 << 8),
  } eBakePassFilter;
  
  typedef enum BakePassFilterCombos {
    BAKE_FILTER_COMBINED = (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT | BAKE_FILTER_DIFFUSE |
                            BAKE_FILTER_GLOSSY | BAKE_FILTER_TRANSMISSION | BAKE_FILTER_SUBSURFACE |
                            BAKE_FILTER_EMISSION | BAKE_FILTER_AO),
    BAKE_FILTER_DIFFUSE_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_DIFFUSE),
    BAKE_FILTER_GLOSSY_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_GLOSSY),
    BAKE_FILTER_TRANSMISSION_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_TRANSMISSION),
    BAKE_FILTER_SUBSURFACE_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_SUBSURFACE),
    BAKE_FILTER_DIFFUSE_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_DIFFUSE),
    BAKE_FILTER_GLOSSY_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_GLOSSY),
    BAKE_FILTER_TRANSMISSION_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_TRANSMISSION),
    BAKE_FILTER_SUBSURFACE_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_SUBSURFACE),
  } BakePassFilterCombos;
  
  typedef enum DenoiseFlag {
    DENOISING_CLEAN_DIFFUSE_DIR = (1 << 0),
    DENOISING_CLEAN_DIFFUSE_IND = (1 << 1),
    DENOISING_CLEAN_GLOSSY_DIR = (1 << 2),
    DENOISING_CLEAN_GLOSSY_IND = (1 << 3),
    DENOISING_CLEAN_TRANSMISSION_DIR = (1 << 4),
    DENOISING_CLEAN_TRANSMISSION_IND = (1 << 5),
    DENOISING_CLEAN_SUBSURFACE_DIR = (1 << 6),
    DENOISING_CLEAN_SUBSURFACE_IND = (1 << 7),
    DENOISING_CLEAN_ALL_PASSES = (1 << 8) - 1,
  } DenoiseFlag;
  
  #ifdef __KERNEL_DEBUG__
  /* NOTE: This is a runtime-only struct, alignment is not
   * really important here.
   */
  typedef struct DebugData {
    int num_bvh_traversed_nodes;
    int num_bvh_traversed_instances;
    int num_bvh_intersections;
    int num_ray_bounces;
  } DebugData;
  #endif
  
  typedef ccl_addr_space struct PathRadianceState {
  #ifdef __PASSES__
    float3 diffuse;
    float3 glossy;
    float3 transmission;
    float3 subsurface;
    float3 scatter;
  
    float3 direct;
  #endif
  } PathRadianceState;
  
  typedef ccl_addr_space struct PathRadiance {
  #ifdef __PASSES__
    int use_light_pass;
  #endif
  
    float transparent;
    float3 emission;
  #ifdef __PASSES__
    float3 background;
    float3 ao;
  
    float3 indirect;
    float3 direct_emission;
  
    float3 color_diffuse;
    float3 color_glossy;
    float3 color_transmission;
    float3 color_subsurface;
  
    float3 direct_diffuse;
    float3 direct_glossy;
    float3 direct_transmission;
    float3 direct_subsurface;
    float3 direct_scatter;
  
    float3 indirect_diffuse;
    float3 indirect_glossy;
    float3 indirect_transmission;
    float3 indirect_subsurface;
    float3 indirect_scatter;
  
    float4 shadow;
    float mist;
  #endif
  
    struct PathRadianceState state;
  
  #ifdef __SHADOW_TRICKS__
    /* Total light reachable across the path, ignoring shadow blocked queries. */
    float3 path_total;
    /* Total light reachable across the path with shadow blocked queries
     * applied here.
     *
     * Dividing this figure by path_total will give estimate of shadow pass.
     */
    float3 path_total_shaded;
  
    /* Color of the background on which shadow is alpha-overed. */
    float3 shadow_background_color;
  
    /* Path radiance sum and throughput at the moment when ray hits shadow
     * catcher object.
     */
    float shadow_throughput;
  
    /* Accumulated transparency along the path after shadow catcher bounce. */
    float shadow_transparency;
  
    /* Indicate if any shadow catcher data is set. */
    int has_shadow_catcher;
  #endif
  
  #ifdef __DENOISING_FEATURES__
    float3 denoising_normal;
    float3 denoising_albedo;
    float denoising_depth;
  #endif /* __DENOISING_FEATURES__ */
  
  #ifdef __KERNEL_DEBUG__
    DebugData debug_data;
  #endif /* __KERNEL_DEBUG__ */
  } PathRadiance;
  
  typedef struct BsdfEval {
  #ifdef __PASSES__
    int use_light_pass;
  #endif
  
    float3 diffuse;
  #ifdef __PASSES__
    float3 glossy;
    float3 transmission;
    float3 transparent;
    float3 subsurface;
    float3 scatter;
  #endif
  #ifdef __SHADOW_TRICKS__
    float3 sum_no_mis;
  #endif
  } BsdfEval;
  
  /* Shader Flag */
  
  typedef enum ShaderFlag {
    SHADER_SMOOTH_NORMAL = (1 << 31),
    SHADER_CAST_SHADOW = (1 << 30),
    SHADER_AREA_LIGHT = (1 << 29),
    SHADER_USE_MIS = (1 << 28),
    SHADER_EXCLUDE_DIFFUSE = (1 << 27),
    SHADER_EXCLUDE_GLOSSY = (1 << 26),
    SHADER_EXCLUDE_TRANSMIT = (1 << 25),
    SHADER_EXCLUDE_CAMERA = (1 << 24),
    SHADER_EXCLUDE_SCATTER = (1 << 23),
    SHADER_EXCLUDE_ANY = (SHADER_EXCLUDE_DIFFUSE | SHADER_EXCLUDE_GLOSSY | SHADER_EXCLUDE_TRANSMIT |
                          SHADER_EXCLUDE_CAMERA | SHADER_EXCLUDE_SCATTER),
  
    SHADER_MASK = ~(SHADER_SMOOTH_NORMAL | SHADER_CAST_SHADOW | SHADER_AREA_LIGHT | SHADER_USE_MIS |
                    SHADER_EXCLUDE_ANY)
  } ShaderFlag;
  
  /* Light Type */
  
  typedef enum LightType {
    LIGHT_POINT,
    LIGHT_DISTANT,
    LIGHT_BACKGROUND,
    LIGHT_AREA,
    LIGHT_SPOT,
    LIGHT_TRIANGLE
  } LightType;
  
  /* Camera Type */
  
  enum CameraType { CAMERA_PERSPECTIVE, CAMERA_ORTHOGRAPHIC, CAMERA_PANORAMA };
  
  /* Panorama Type */
  
  enum PanoramaType {
    PANORAMA_EQUIRECTANGULAR = 0,
    PANORAMA_FISHEYE_EQUIDISTANT = 1,
    PANORAMA_FISHEYE_EQUISOLID = 2,
    PANORAMA_MIRRORBALL = 3,
  
    PANORAMA_NUM_TYPES,
  };
  
  /* Differential */
  
  typedef struct differential3 {
    float3 dx;
    float3 dy;
  } differential3;
  
  typedef struct differential {
    float dx;
    float dy;
  } differential;
  
  /* Ray */
  
  typedef struct Ray {
  /* TODO(sergey): This is only needed because current AMD
   * compiler has hard time building the kernel with this
   * reshuffle. And at the same time reshuffle will cause
   * less optimal CPU code in certain places.
   *
   * We'll get rid of this nasty exception once AMD compiler
   * is fixed.
   */
  #ifndef __KERNEL_OPENCL_AMD__
    float3 P;   /* origin */
    float3 D;   /* direction */
    float t;    /* length of the ray */
    float time; /* time (for motion blur) */
  #else
    float t;    /* length of the ray */
    float time; /* time (for motion blur) */
    float3 P;   /* origin */
    float3 D;   /* direction */
  #endif
  
  #ifdef __RAY_DIFFERENTIALS__
    differential3 dP;
    differential3 dD;
  #endif
  } Ray;
  
  /* Intersection */
  
  typedef struct Intersection {
  #ifdef __EMBREE__
    float3 Ng;
  #endif
    float t, u, v;
    int prim;
    int object;
    int type;
  
  #ifdef __KERNEL_DEBUG__
    int num_traversed_nodes;
    int num_traversed_instances;
    int num_intersections;
  #endif
  } Intersection;
  
  /* Primitives */
  
  typedef enum PrimitiveType {
    PRIMITIVE_NONE = 0,
    PRIMITIVE_TRIANGLE = (1 << 0),
    PRIMITIVE_MOTION_TRIANGLE = (1 << 1),
    PRIMITIVE_CURVE = (1 << 2),
    PRIMITIVE_MOTION_CURVE = (1 << 3),
    /* Lamp primitive is not included below on purpose,
     * since it is no real traceable primitive.
     */
    PRIMITIVE_LAMP = (1 << 4),
  
    PRIMITIVE_ALL_TRIANGLE = (PRIMITIVE_TRIANGLE | PRIMITIVE_MOTION_TRIANGLE),
    PRIMITIVE_ALL_CURVE = (PRIMITIVE_CURVE | PRIMITIVE_MOTION_CURVE),
    PRIMITIVE_ALL_MOTION = (PRIMITIVE_MOTION_TRIANGLE | PRIMITIVE_MOTION_CURVE),
    PRIMITIVE_ALL = (PRIMITIVE_ALL_TRIANGLE | PRIMITIVE_ALL_CURVE),
  
    /* Total number of different traceable primitives.
     * NOTE: This is an actual value, not a bitflag.
     */
    PRIMITIVE_NUM_TOTAL = 4,
  } PrimitiveType;
  
  #define PRIMITIVE_PACK_SEGMENT(type, segment) ((segment << PRIMITIVE_NUM_TOTAL) | (type))
  #define PRIMITIVE_UNPACK_SEGMENT(type) (type >> PRIMITIVE_NUM_TOTAL)
  
  /* Attributes */
  
  typedef enum AttributePrimitive {
    ATTR_PRIM_TRIANGLE = 0,
    ATTR_PRIM_CURVE,
    ATTR_PRIM_SUBD,
  
    ATTR_PRIM_TYPES
  } AttributePrimitive;
  
  typedef enum AttributeElement {
    ATTR_ELEMENT_NONE,
    ATTR_ELEMENT_OBJECT,
    ATTR_ELEMENT_MESH,
    ATTR_ELEMENT_FACE,
    ATTR_ELEMENT_VERTEX,
    ATTR_ELEMENT_VERTEX_MOTION,
    ATTR_ELEMENT_CORNER,
    ATTR_ELEMENT_CORNER_BYTE,
    ATTR_ELEMENT_CURVE,
    ATTR_ELEMENT_CURVE_KEY,
    ATTR_ELEMENT_CURVE_KEY_MOTION,
    ATTR_ELEMENT_VOXEL
  } AttributeElement;
  
  typedef enum AttributeStandard {
    ATTR_STD_NONE = 0,
    ATTR_STD_VERTEX_NORMAL,
    ATTR_STD_FACE_NORMAL,
    ATTR_STD_UV,
    ATTR_STD_UV_TANGENT,
    ATTR_STD_UV_TANGENT_SIGN,
    ATTR_STD_GENERATED,
    ATTR_STD_GENERATED_TRANSFORM,
    ATTR_STD_POSITION_UNDEFORMED,
    ATTR_STD_POSITION_UNDISPLACED,
    ATTR_STD_MOTION_VERTEX_POSITION,
    ATTR_STD_MOTION_VERTEX_NORMAL,
    ATTR_STD_PARTICLE,
    ATTR_STD_CURVE_INTERCEPT,
    ATTR_STD_CURVE_RANDOM,
    ATTR_STD_CURVE_INDEX,
    ATTR_STD_CURVE_COUNT,
    ATTR_STD_CURVE_LENGTH,
    ATTR_STD_CURVE_KEY,
    ATTR_STD_CURVE_VALUE,
    ATTR_STD_PTEX_FACE_ID,
    ATTR_STD_PTEX_UV,
    ATTR_STD_VOLUME_DENSITY,
    ATTR_STD_VOLUME_COLOR,
    ATTR_STD_VOLUME_FLAME,
    ATTR_STD_VOLUME_HEAT,
    ATTR_STD_VOLUME_TEMPERATURE,
    ATTR_STD_VOLUME_VELOCITY,
    ATTR_STD_POINTINESS,
    ATTR_STD_RANDOM_PER_ISLAND,
    ATTR_STD_NUM,
  
    ATTR_STD_NOT_FOUND = ~0
  } AttributeStandard;
  
  typedef enum AttributeFlag {
    ATTR_FINAL_SIZE = (1 << 0),
    ATTR_SUBDIVIDED = (1 << 1),
  } AttributeFlag;
  
  typedef struct AttributeDescriptor {
    AttributeElement element;
    NodeAttributeType type;
    uint flags; /* see enum AttributeFlag */
    int offset;
  } AttributeDescriptor;
  
  /* Closure data */
  
  #ifdef __MULTI_CLOSURE__
  #  ifdef __SPLIT_KERNEL__
  #    define MAX_CLOSURE 1
  #  else
  #    ifndef __MAX_CLOSURE__
  #      define MAX_CLOSURE 64
  #    else
  #      define MAX_CLOSURE __MAX_CLOSURE__
  #    endif
  #  endif
  #else
  #  define MAX_CLOSURE 1
  #endif
  
  /* This struct is the base class for all closures. The common members are
   * duplicated in all derived classes since we don't have C++ in the kernel
   * yet, and because it lets us lay out the members to minimize padding. The
   * weight member is located at the beginning of the struct for this reason.
   *
   * ShaderClosure has a fixed size, and any extra space must be allocated
   * with closure_alloc_extra().
   *
   * We pad the struct to align to 16 bytes. All shader closures are assumed
   * to fit in this struct size. CPU sizes are a bit larger because float3 is
   * padded to be 16 bytes, while it's only 12 bytes on the GPU. */
  
  #define SHADER_CLOSURE_BASE \
    float3 weight; \
    ClosureType type; \
    float sample_weight; \
    float3 N
  
  typedef ccl_addr_space struct ccl_align(16) ShaderClosure
  {
    SHADER_CLOSURE_BASE;
  
  #ifdef __KERNEL_CPU__
    float pad[2];
  #endif
    float data[10];
  }
  ShaderClosure;
  
  /* Shader Data
   *
   * Main shader state at a point on the surface or in a volume. All coordinates
   * are in world space.
   */
  
  enum ShaderDataFlag {
    /* Runtime flags. */
  
    /* Set when ray hits backside of surface. */
    SD_BACKFACING = (1 << 0),
    /* Shader has non-zero emission. */
    SD_EMISSION = (1 << 1),
    /* Shader has BSDF closure. */
    SD_BSDF = (1 << 2),
    /* Shader has non-singular BSDF closure. */
    SD_BSDF_HAS_EVAL = (1 << 3),
    /* Shader has BSSRDF closure. */
    SD_BSSRDF = (1 << 4),
    /* Shader has holdout closure. */
    SD_HOLDOUT = (1 << 5),
    /* Shader has non-zero volume extinction. */
    SD_EXTINCTION = (1 << 6),
    /* Shader has have volume phase (scatter) closure. */
    SD_SCATTER = (1 << 7),
    /* Shader has transparent closure. */
    SD_TRANSPARENT = (1 << 9),
    /* BSDF requires LCG for evaluation. */
    SD_BSDF_NEEDS_LCG = (1 << 10),
  
    SD_CLOSURE_FLAGS = (SD_EMISSION | SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSSRDF | SD_HOLDOUT |
                        SD_EXTINCTION | SD_SCATTER | SD_BSDF_NEEDS_LCG),
  
    /* Shader flags. */
  
    /* direct light sample */
    SD_USE_MIS = (1 << 16),
    /* Has transparent shadow. */
    SD_HAS_TRANSPARENT_SHADOW = (1 << 17),
    /* Has volume shader. */
    SD_HAS_VOLUME = (1 << 18),
    /* Has only volume shader, no surface. */
    SD_HAS_ONLY_VOLUME = (1 << 19),
    /* Has heterogeneous volume. */
    SD_HETEROGENEOUS_VOLUME = (1 << 20),
    /* BSSRDF normal uses bump. */
    SD_HAS_BSSRDF_BUMP = (1 << 21),
    /* Use equiangular volume sampling */
    SD_VOLUME_EQUIANGULAR = (1 << 22),
    /* Use multiple importance volume sampling. */
    SD_VOLUME_MIS = (1 << 23),
    /* Use cubic interpolation for voxels. */
    SD_VOLUME_CUBIC = (1 << 24),
    /* Has data connected to the displacement input or uses bump map. */
    SD_HAS_BUMP = (1 << 25),
    /* Has true displacement. */
    SD_HAS_DISPLACEMENT = (1 << 26),
    /* Has constant emission (value stored in __shaders) */
    SD_HAS_CONSTANT_EMISSION = (1 << 27),
    /* Needs to access attributes */
    SD_NEED_ATTRIBUTES = (1 << 28),
  
    SD_SHADER_FLAGS = (SD_USE_MIS | SD_HAS_TRANSPARENT_SHADOW | SD_HAS_VOLUME | SD_HAS_ONLY_VOLUME |
                       SD_HETEROGENEOUS_VOLUME | SD_HAS_BSSRDF_BUMP | SD_VOLUME_EQUIANGULAR |
                       SD_VOLUME_MIS | SD_VOLUME_CUBIC | SD_HAS_BUMP | SD_HAS_DISPLACEMENT |
                       SD_HAS_CONSTANT_EMISSION | SD_NEED_ATTRIBUTES)
  };
  
  /* Object flags. */
  enum ShaderDataObjectFlag {
    /* Holdout for camera rays. */
    SD_OBJECT_HOLDOUT_MASK = (1 << 0),
    /* Has object motion blur. */
    SD_OBJECT_MOTION = (1 << 1),
    /* Vertices have transform applied. */
    SD_OBJECT_TRANSFORM_APPLIED = (1 << 2),
    /* Vertices have negative scale applied. */
    SD_OBJECT_NEGATIVE_SCALE_APPLIED = (1 << 3),
    /* Object has a volume shader. */
    SD_OBJECT_HAS_VOLUME = (1 << 4),
    /* Object intersects AABB of an object with volume shader. */
    SD_OBJECT_INTERSECTS_VOLUME = (1 << 5),
    /* Has position for motion vertices. */
    SD_OBJECT_HAS_VERTEX_MOTION = (1 << 6),
    /* object is used to catch shadows */
    SD_OBJECT_SHADOW_CATCHER = (1 << 7),
    /* object has volume attributes */
    SD_OBJECT_HAS_VOLUME_ATTRIBUTES = (1 << 8),
  
    SD_OBJECT_FLAGS = (SD_OBJECT_HOLDOUT_MASK | SD_OBJECT_MOTION | SD_OBJECT_TRANSFORM_APPLIED |
                       SD_OBJECT_NEGATIVE_SCALE_APPLIED | SD_OBJECT_HAS_VOLUME |
                       SD_OBJECT_INTERSECTS_VOLUME | SD_OBJECT_SHADOW_CATCHER |
                       SD_OBJECT_HAS_VOLUME_ATTRIBUTES)
  };
  
  typedef ccl_addr_space struct ccl_align(16) ShaderData
  {
    /* position */
    float3 P;
    /* smooth normal for shading */
    float3 N;
    /* true geometric normal */
    float3 Ng;
    /* view/incoming direction */
    float3 I;
  
    /* shader id */
    int shader;
    /* booleans describing shader, see ShaderDataFlag */
    int flag;
    /* booleans describing object of the shader, see ShaderDataObjectFlag */
    int object_flag;
  
    /* primitive id if there is one, ~0 otherwise */
    int prim;
  
    /* combined type and curve segment for hair */
    int type;
  
    /* parametric coordinates
     * - barycentric weights for triangles */
    float u;
    float v;
    /* object id if there is one, ~0 otherwise */
    int object;
    /* lamp id if there is one, ~0 otherwise */
    int lamp;
  
    /* motion blur sample time */
    float time;
  
    /* length of the ray being shaded */
    float ray_length;
  
  #ifdef __RAY_DIFFERENTIALS__
    /* differential of P. these are orthogonal to Ng, not N */
    differential3 dP;
    /* differential of I */
    differential3 dI;
    /* differential of u, v */
    differential du;
    differential dv;
  #endif
  #ifdef __DPDU__
    /* differential of P w.r.t. parametric coordinates. note that dPdu is
     * not readily suitable as a tangent for shading on triangles. */
    float3 dPdu;
    float3 dPdv;
  #endif
  
  #ifdef __OBJECT_MOTION__
    /* object <-> world space transformations, cached to avoid
     * re-interpolating them constantly for shading */
    Transform ob_tfm;
    Transform ob_itfm;
  #endif
  
    /* ray start position, only set for backgrounds */
    float3 ray_P;
    differential3 ray_dP;
  
  #ifdef __OSL__
    struct KernelGlobals *osl_globals;
    struct PathState *osl_path_state;
  #endif
  
    /* LCG state for closures that require additional random numbers. */
    uint lcg_state;
  
    /* Closure data, we store a fixed array of closures */
    int num_closure;
    int num_closure_left;
    float randb_closure;
    float3 svm_closure_weight;
  
    /* Closure weights summed directly, so we can evaluate
     * emission and shadow transparency with MAX_CLOSURE 0. */
    float3 closure_emission_background;
    float3 closure_transparent_extinction;
  
    /* At the end so we can adjust size in ShaderDataTinyStorage. */
    struct ShaderClosure closure[MAX_CLOSURE];
  }
  ShaderData;
  
  /* ShaderDataTinyStorage needs the same alignment as ShaderData, or else
   * the pointer cast in AS_SHADER_DATA invokes undefined behavior. */
  typedef ccl_addr_space struct ccl_align(16) ShaderDataTinyStorage
  {
    char pad[sizeof(ShaderData) - sizeof(ShaderClosure) * MAX_CLOSURE];
  }
  ShaderDataTinyStorage;
  #define AS_SHADER_DATA(shader_data_tiny_storage) ((ShaderData *)shader_data_tiny_storage)
  
  /* Path State */
  
  #ifdef __VOLUME__
  typedef struct VolumeStack {
    int object;
    int shader;
  } VolumeStack;
  #endif
  
  typedef struct PathState {
    /* see enum PathRayFlag */
    int flag;
  
    /* random number generator state */
    uint rng_hash;       /* per pixel hash */
    int rng_offset;      /* dimension offset */
    int sample;          /* path sample number */
    int num_samples;     /* total number of times this path will be sampled */
    float branch_factor; /* number of branches in indirect paths */
  
    /* bounce counting */
    int bounce;
    int diffuse_bounce;
    int glossy_bounce;
    int transmission_bounce;
    int transparent_bounce;
  
  #ifdef __DENOISING_FEATURES__
    float denoising_feature_weight;
  #endif /* __DENOISING_FEATURES__ */
  
    /* multiple importance sampling */
    float min_ray_pdf; /* smallest bounce pdf over entire path up to now */
    float ray_pdf;     /* last bounce pdf */
  #ifdef __LAMP_MIS__
    float ray_t; /* accumulated distance through transparent surfaces */
  #endif
  
    /* volume rendering */
  #ifdef __VOLUME__
    int volume_bounce;
    int volume_bounds_bounce;
    VolumeStack volume_stack[VOLUME_STACK_SIZE];
  #endif
  } PathState;
  
  #ifdef __VOLUME__
  typedef struct VolumeState {
  #  ifdef __SPLIT_KERNEL__
  #  else
    PathState ps;
  #  endif
  } VolumeState;
  #endif
  
  /* Struct to gather multiple nearby intersections. */
  typedef struct LocalIntersection {
    Ray ray;
    float3 weight[LOCAL_MAX_HITS];
  
    int num_hits;
    struct Intersection hits[LOCAL_MAX_HITS];
    float3 Ng[LOCAL_MAX_HITS];
  } LocalIntersection;
  
  /* Subsurface */
  
  /* Struct to gather SSS indirect rays and delay tracing them. */
  typedef struct SubsurfaceIndirectRays {
    PathState state[BSSRDF_MAX_HITS];
  
    int num_rays;
  
    struct Ray rays[BSSRDF_MAX_HITS];
    float3 throughputs[BSSRDF_MAX_HITS];
    struct PathRadianceState L_state[BSSRDF_MAX_HITS];
  } SubsurfaceIndirectRays;
  static_assert(BSSRDF_MAX_HITS <= LOCAL_MAX_HITS, "BSSRDF hits too high.");
  
  /* Constant Kernel Data
   *
   * These structs are passed from CPU to various devices, and the struct layout
   * must match exactly. Structs are padded to ensure 16 byte alignment, and we
   * do not use float3 because its size may not be the same on all devices. */
  
  typedef struct KernelCamera {
    /* type */
    int type;
  
    /* panorama */
    int panorama_type;
    float fisheye_fov;
    float fisheye_lens;
    float4 equirectangular_range;
  
    /* stereo */
    float interocular_offset;
    float convergence_distance;
    float pole_merge_angle_from;
    float pole_merge_angle_to;
  
    /* matrices */
    Transform cameratoworld;
    ProjectionTransform rastertocamera;
  
    /* differentials */
    float4 dx;
    float4 dy;
  
    /* depth of field */
    float aperturesize;
    float blades;
    float bladesrotation;
    float focaldistance;
  
    /* motion blur */
    float shuttertime;
    int num_motion_steps, have_perspective_motion;
  
    /* clipping */
    float nearclip;
    float cliplength;
  
    /* sensor size */
    float sensorwidth;
    float sensorheight;
  
    /* render size */
    float width, height;
    int resolution;
  
    /* anamorphic lens bokeh */
    float inv_aperture_ratio;
  
    int is_inside_volume;
  
    /* more matrices */
    ProjectionTransform screentoworld;
    ProjectionTransform rastertoworld;
    ProjectionTransform ndctoworld;
    ProjectionTransform worldtoscreen;
    ProjectionTransform worldtoraster;
    ProjectionTransform worldtondc;
    Transform worldtocamera;
  
    /* Stores changes in the projection matrix. Use for camera zoom motion
     * blur and motion pass output for perspective camera. */
    ProjectionTransform perspective_pre;
    ProjectionTransform perspective_post;
  
    /* Transforms for motion pass. */
    Transform motion_pass_pre;
    Transform motion_pass_post;
  
    int shutter_table_offset;
  
    /* Rolling shutter */
    int rolling_shutter_type;
    float rolling_shutter_duration;
  
    int pad;
  } KernelCamera;
  static_assert_align(KernelCamera, 16);
  
  typedef struct KernelFilm {
    float exposure;
    int pass_flag;
  
    int light_pass_flag;
    int pass_stride;
    int use_light_pass;
  
    int pass_combined;
    int pass_depth;
    int pass_normal;
    int pass_motion;
  
    int pass_motion_weight;
    int pass_uv;
    int pass_object_id;
    int pass_material_id;
  
    int pass_diffuse_color;
    int pass_glossy_color;
    int pass_transmission_color;
    int pass_subsurface_color;
  
    int pass_diffuse_indirect;
    int pass_glossy_indirect;
    int pass_transmission_indirect;
    int pass_subsurface_indirect;
    int pass_volume_indirect;
  
    int pass_diffuse_direct;
    int pass_glossy_direct;
    int pass_transmission_direct;
    int pass_subsurface_direct;
    int pass_volume_direct;
  
    int pass_emission;
    int pass_background;
    int pass_ao;
    float pass_alpha_threshold;
  
    int pass_shadow;
    float pass_shadow_scale;
    int filter_table_offset;
    int cryptomatte_passes;
    int cryptomatte_depth;
    int pass_cryptomatte;
  
    int pass_mist;
    float mist_start;
    float mist_inv_depth;
    float mist_falloff;
  
    int pass_denoising_data;
    int pass_denoising_clean;
    int denoising_flags;
  
    int pass_aov_color;
    int pass_aov_value;
    int pad1;
    int pad2;
  
    /* XYZ to rendering color space transform. float4 instead of float3 to
     * ensure consistent padding/alignment across devices. */
    float4 xyz_to_r;
    float4 xyz_to_g;
    float4 xyz_to_b;
    float4 rgb_to_y;
  
  #ifdef __KERNEL_DEBUG__
    int pass_bvh_traversed_nodes;
    int pass_bvh_traversed_instances;
    int pass_bvh_intersections;
    int pass_ray_bounces;
  #endif
  
    /* viewport rendering options */
    int display_pass_stride;
    int display_pass_components;
    int display_divide_pass_stride;
    int use_display_exposure;
    int use_display_pass_alpha;
  } KernelFilm;
  static_assert_align(KernelFilm, 16);
  
  typedef struct KernelBackground {
    /* only shader index */
    int surface_shader;
    int volume_shader;
    int transparent;
    float transparent_roughness_squared_threshold;
  
    /* ambient occlusion */
    float ao_factor;
    float ao_distance;
    float ao_bounces_factor;
    float ao_pad;
  } KernelBackground;
  static_assert_align(KernelBackground, 16);
  
  typedef struct KernelIntegrator {
    /* emission */
    int use_direct_light;
    int use_ambient_occlusion;
    int num_distribution;
    int num_all_lights;
    float pdf_triangles;
    float pdf_lights;
    int pdf_background_res_x;
    int pdf_background_res_y;
    float light_inv_rr_threshold;
  
    /* light portals */
    float portal_pdf;
    int num_portals;
    int portal_offset;
  
    /* bounces */
    int min_bounce;
    int max_bounce;
  
    int max_diffuse_bounce;
    int max_glossy_bounce;
    int max_transmission_bounce;
    int max_volume_bounce;
  
    int ao_bounces;
  
    /* transparent */
    int transparent_min_bounce;
    int transparent_max_bounce;
    int transparent_shadows;
  
    /* caustics */
    int caustics_reflective;
    int caustics_refractive;
    float filter_glossy;
  
    /* seed */
    int seed;
  
    /* clamp */
    float sample_clamp_direct;
    float sample_clamp_indirect;
  
    /* branched path */
    int branched;
    int volume_decoupled;
    int diffuse_samples;
    int glossy_samples;
    int transmission_samples;
    int ao_samples;
    int mesh_light_samples;
    int subsurface_samples;
    int sample_all_lights_direct;
    int sample_all_lights_indirect;
  
    /* mis */
    int use_lamp_mis;
  
    /* sampler */
    int sampling_pattern;
    int aa_samples;
  
    /* volume render */
    int use_volumes;
    int volume_max_steps;
    float volume_step_size;
    int volume_samples;
  
    int start_sample;
  
    int max_closures;
  
    int pad1;
  } KernelIntegrator;
  static_assert_align(KernelIntegrator, 16);
  
  typedef enum KernelBVHLayout {
    BVH_LAYOUT_NONE = 0,
  
    BVH_LAYOUT_BVH2 = (1 << 0),
    BVH_LAYOUT_BVH4 = (1 << 1),
    BVH_LAYOUT_BVH8 = (1 << 2),
  
    BVH_LAYOUT_EMBREE = (1 << 3),
    BVH_LAYOUT_OPTIX = (1 << 4),
  
    BVH_LAYOUT_DEFAULT = BVH_LAYOUT_BVH8,
    BVH_LAYOUT_ALL = (unsigned int)(~0u),
  } KernelBVHLayout;
  
  typedef struct KernelBVH {
    /* Own BVH */
    int root;
    int have_motion;
    int have_curves;
    int have_instancing;
    int bvh_layout;
    int use_bvh_steps;
  
    /* Custom BVH */
  #ifdef __KERNEL_OPTIX__
    OptixTraversableHandle scene;
  #else
  #  ifdef __EMBREE__
    RTCScene scene;
  #    ifndef __KERNEL_64_BIT__
    int pad2;
  #    endif
  #  else
    int scene, pad2;
  #  endif
  #endif
  } KernelBVH;
  static_assert_align(KernelBVH, 16);
  
  typedef enum CurveFlag {
    /* runtime flags */
    CURVE_KN_BACKFACING = 1,           /* backside of cylinder? */
    CURVE_KN_ENCLOSEFILTER = 2,        /* don't consider strands surrounding start point? */
    CURVE_KN_INTERPOLATE = 4,          /* render as a curve? */
    CURVE_KN_ACCURATE = 8,             /* use accurate intersections test? */
    CURVE_KN_INTERSECTCORRECTION = 16, /* correct for width after determing closest midpoint? */
    CURVE_KN_TRUETANGENTGNORMAL = 32,  /* use tangent normal for geometry? */
    CURVE_KN_RIBBONS = 64,             /* use flat curve ribbons */
  } CurveFlag;
  
  typedef struct KernelCurves {
    int curveflags;
    int subdivisions;
  
    int pad1, pad2;
  } KernelCurves;
  static_assert_align(KernelCurves, 16);
  
  typedef struct KernelTables {
    int beckmann_offset;
    int pad1, pad2, pad3;
  } KernelTables;
  static_assert_align(KernelTables, 16);
  
  typedef struct KernelData {
    KernelCamera cam;
    KernelFilm film;
    KernelBackground background;
    KernelIntegrator integrator;
    KernelBVH bvh;
    KernelCurves curve;
    KernelTables tables;
  } KernelData;
  static_assert_align(KernelData, 16);
  
  /* Kernel data structures. */
  
  typedef struct KernelObject {
    Transform tfm;
    Transform itfm;
  
    float surface_area;
    float pass_id;
    float random_number;
    float color[3];
    int particle_index;
  
    float dupli_generated[3];
    float dupli_uv[2];
  
    int numkeys;
    int numsteps;
    int numverts;
  
    uint patch_map_offset;
    uint attribute_map_offset;
    uint motion_offset;
  
    float cryptomatte_object;
    float cryptomatte_asset;
  } KernelObject;
  static_assert_align(KernelObject, 16);
  
  typedef struct KernelSpotLight {
    float radius;
    float invarea;
    float spot_angle;
    float spot_smooth;
    float dir[3];
    float pad;
  } KernelSpotLight;
  
  /* PointLight is SpotLight with only radius and invarea being used. */
  
  typedef struct KernelAreaLight {
    float axisu[3];
    float invarea;
    float axisv[3];
    float pad1;
    float dir[3];
    float pad2;
  } KernelAreaLight;
  
  typedef struct KernelDistantLight {
    float radius;
    float cosangle;
    float invarea;
    float pad;
  } KernelDistantLight;
  
  typedef struct KernelLight {
    int type;
    float co[3];
    int shader_id;
    int samples;
    float max_bounces;
    float random;
    float strength[3];
    float pad1;
    Transform tfm;
    Transform itfm;
    union {
      KernelSpotLight spot;
      KernelAreaLight area;
      KernelDistantLight distant;
    };
  } KernelLight;
  static_assert_align(KernelLight, 16);
  
  typedef struct KernelLightDistribution {
    float totarea;
    int prim;
    union {
      struct {
        int shader_flag;
        int object_id;
      } mesh_light;
      struct {
        float pad;
        float size;
      } lamp;
    };
  } KernelLightDistribution;
  static_assert_align(KernelLightDistribution, 16);
  
  typedef struct KernelParticle {
    int index;
    float age;
    float lifetime;
    float size;
    float4 rotation;
    /* Only xyz are used of the following. float4 instead of float3 are used
     * to ensure consistent padding/alignment across devices. */
    float4 location;
    float4 velocity;
    float4 angular_velocity;
  } KernelParticle;
  static_assert_align(KernelParticle, 16);
  
  typedef struct KernelShader {
    float constant_emission[3];
    float cryptomatte_id;
    int flags;
    int pass_id;
    int pad2, pad3;
  } KernelShader;
  static_assert_align(KernelShader, 16);
  
  /* Declarations required for split kernel */
  
  /* Macro for queues */
  /* Value marking queue's empty slot */
  #define QUEUE_EMPTY_SLOT -1
  
  /*
   * Queue 1 - Active rays
   * Queue 2 - Background queue
   * Queue 3 - Shadow ray cast kernel - AO
   * Queue 4 - Shadow ray cast kernel - direct lighting
   */
  
  /* Queue names */
  enum QueueNumber {
    /* All active rays and regenerated rays are enqueued here. */
    QUEUE_ACTIVE_AND_REGENERATED_RAYS = 0,
  
    /* All
     * 1. Background-hit rays,
     * 2. Rays that has exited path-iteration but needs to update output buffer
     * 3. Rays to be regenerated
     * are enqueued here.
     */
    QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
  
    /* All rays for which a shadow ray should be cast to determine radiance
     * contribution for AO are enqueued here.
     */
    QUEUE_SHADOW_RAY_CAST_AO_RAYS,
  
    /* All rays for which a shadow ray should be cast to determine radiance
     * contributing for direct lighting are enqueued here.
     */
    QUEUE_SHADOW_RAY_CAST_DL_RAYS,
  
    /* Rays sorted according to shader->id */
    QUEUE_SHADER_SORTED_RAYS,
  
  #ifdef __BRANCHED_PATH__
    /* All rays moving to next iteration of the indirect loop for light */
    QUEUE_LIGHT_INDIRECT_ITER,
    /* Queue of all inactive rays. These are candidates for sharing work of indirect loops */
    QUEUE_INACTIVE_RAYS,
  #  ifdef __VOLUME__
    /* All rays moving to next iteration of the indirect loop for volumes */
    QUEUE_VOLUME_INDIRECT_ITER,
  #  endif
  #  ifdef __SUBSURFACE__
    /* All rays moving to next iteration of the indirect loop for subsurface */
    QUEUE_SUBSURFACE_INDIRECT_ITER,
  #  endif
  #endif /* __BRANCHED_PATH__ */
  
    NUM_QUEUES
  };
  
  /* We use RAY_STATE_MASK to get ray_state */
  #define RAY_STATE_MASK 0x0F
  #define RAY_FLAG_MASK 0xF0
  enum RayState {
    RAY_INVALID = 0,
    /* Denotes ray is actively involved in path-iteration. */
    RAY_ACTIVE,
    /* Denotes ray has completed processing all samples and is inactive. */
    RAY_INACTIVE,
    /* Denotes ray has exited path-iteration and needs to update output buffer. */
    RAY_UPDATE_BUFFER,
    /* Denotes ray needs to skip most surface shader work. */
    RAY_HAS_ONLY_VOLUME,
    /* Donotes ray has hit background */
    RAY_HIT_BACKGROUND,
    /* Denotes ray has to be regenerated */
    RAY_TO_REGENERATE,
    /* Denotes ray has been regenerated */
    RAY_REGENERATED,
    /* Denotes ray is moving to next iteration of the branched indirect loop */
    RAY_LIGHT_INDIRECT_NEXT_ITER,
    RAY_VOLUME_INDIRECT_NEXT_ITER,
    RAY_SUBSURFACE_INDIRECT_NEXT_ITER,
  
    /* Ray flags */
  
    /* Flags to denote that the ray is currently evaluating the branched indirect loop */
    RAY_BRANCHED_LIGHT_INDIRECT = (1 << 4),
    RAY_BRANCHED_VOLUME_INDIRECT = (1 << 5),
    RAY_BRANCHED_SUBSURFACE_INDIRECT = (1 << 6),
    RAY_BRANCHED_INDIRECT = (RAY_BRANCHED_LIGHT_INDIRECT | RAY_BRANCHED_VOLUME_INDIRECT |
                             RAY_BRANCHED_SUBSURFACE_INDIRECT),
  
    /* Ray is evaluating an iteration of an indirect loop for another thread */
    RAY_BRANCHED_INDIRECT_SHARED = (1 << 7),
  };
  
  #define ASSIGN_RAY_STATE(ray_state, ray_index, state) \
    (ray_state[ray_index] = ((ray_state[ray_index] & RAY_FLAG_MASK) | state))
  #define IS_STATE(ray_state, ray_index, state) \
    ((ray_index) != QUEUE_EMPTY_SLOT && ((ray_state)[(ray_index)] & RAY_STATE_MASK) == (state))
  #define ADD_RAY_FLAG(ray_state, ray_index, flag) \
    (ray_state[ray_index] = (ray_state[ray_index] | flag))
  #define REMOVE_RAY_FLAG(ray_state, ray_index, flag) \
    (ray_state[ray_index] = (ray_state[ray_index] & (~flag)))
  #define IS_FLAG(ray_state, ray_index, flag) (ray_state[ray_index] & flag)
  
  /* Patches */
  
  #define PATCH_MAX_CONTROL_VERTS 16
  
  /* Patch map node flags */
  
  #define PATCH_MAP_NODE_IS_SET (1 << 30)
  #define PATCH_MAP_NODE_IS_LEAF (1u << 31)
  #define PATCH_MAP_NODE_INDEX_MASK (~(PATCH_MAP_NODE_IS_SET | PATCH_MAP_NODE_IS_LEAF))
  
  /* Work Tiles */
  
  typedef struct WorkTile {
    uint x, y, w, h;
  
    uint start_sample;
    uint num_samples;
  
    uint offset;
    uint stride;
  
    ccl_global float *buffer;
  } WorkTile;
  
  CCL_NAMESPACE_END
  
  #endif /*  __KERNEL_TYPES_H__ */
  