Cycles: Add AttributeDescriptor
authorMai Lavelle <mai.lavelle@gmail.com>
Fri, 1 Jul 2016 21:36:27 +0000 (17:36 -0400)
committerMai Lavelle <mai.lavelle@gmail.com>
Sat, 6 Aug 2016 03:49:21 +0000 (23:49 -0400)
Adds a descriptor for attributes that can easily be passed around and extended
to contain more data. Will be used for attributes on subdivision meshes.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D2110

16 files changed:
intern/cycles/kernel/geom/geom_attribute.h
intern/cycles/kernel/geom/geom_curve.h
intern/cycles/kernel/geom/geom_primitive.h
intern/cycles/kernel/geom/geom_subd_triangle.h
intern/cycles/kernel/geom/geom_triangle.h
intern/cycles/kernel/geom/geom_volume.h
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/osl/osl_globals.h
intern/cycles/kernel/osl/osl_services.cpp
intern/cycles/kernel/osl/osl_shader.cpp
intern/cycles/kernel/osl/osl_shader.h
intern/cycles/kernel/svm/svm_attribute.h
intern/cycles/kernel/svm/svm_tex_coord.h
intern/cycles/render/attribute.cpp
intern/cycles/render/attribute.h
intern/cycles/render/mesh.cpp

index 5d78cf8..e036c27 100644 (file)
@@ -43,12 +43,19 @@ ccl_device_inline uint attribute_primitive_type(KernelGlobals *kg, const ShaderD
        }
 }
 
+ccl_device_inline AttributeDescriptor attribute_not_found()
+{
+       const AttributeDescriptor desc = {ATTR_ELEMENT_NONE, (NodeAttributeType)0, ATTR_STD_NOT_FOUND};
+       return desc;
+}
+
 /* Find attribute based on ID */
 
-ccl_device_inline int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem)
+ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id)
 {
-       if(ccl_fetch(sd, object) == PRIM_NONE)
-               return (int)ATTR_STD_NOT_FOUND;
+       if(ccl_fetch(sd, object) == PRIM_NONE) {
+               return attribute_not_found();
+       }
 
        /* for SVM, find attribute by unique id */
        uint attr_offset = ccl_fetch(sd, object)*kernel_data.bvh.attributes_map_stride;
@@ -57,31 +64,36 @@ ccl_device_inline int find_attribute(KernelGlobals *kg, const ShaderData *sd, ui
        
        while(attr_map.x != id) {
                if(UNLIKELY(attr_map.x == ATTR_STD_NONE)) {
-                       return ATTR_STD_NOT_FOUND;
+                       return attribute_not_found();
                }
                attr_offset += ATTR_PRIM_TYPES;
                attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
        }
 
-       *elem = (AttributeElement)attr_map.y;
+       AttributeDescriptor desc;
+       desc.element = (AttributeElement)attr_map.y;
        
-       if(ccl_fetch(sd, prim) == PRIM_NONE && (AttributeElement)attr_map.y != ATTR_ELEMENT_MESH)
-               return ATTR_STD_NOT_FOUND;
+       if(ccl_fetch(sd, prim) == PRIM_NONE && desc.element != ATTR_ELEMENT_MESH) {
+               return attribute_not_found();
+       }
 
        /* return result */
-       return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
+       desc.offset = (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
+       desc.type = (NodeAttributeType)attr_map.w;
+
+       return desc;
 }
 
 /* Transform matrix attribute on meshes */
 
-ccl_device Transform primitive_attribute_matrix(KernelGlobals *kg, const ShaderData *sd, int offset)
+ccl_device Transform primitive_attribute_matrix(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc)
 {
        Transform tfm;
 
-       tfm.x = kernel_tex_fetch(__attributes_float3, offset + 0);
-       tfm.y = kernel_tex_fetch(__attributes_float3, offset + 1);
-       tfm.z = kernel_tex_fetch(__attributes_float3, offset + 2);
-       tfm.w = kernel_tex_fetch(__attributes_float3, offset + 3);
+       tfm.x = kernel_tex_fetch(__attributes_float3, desc.offset + 0);
+       tfm.y = kernel_tex_fetch(__attributes_float3, desc.offset + 1);
+       tfm.z = kernel_tex_fetch(__attributes_float3, desc.offset + 2);
+       tfm.w = kernel_tex_fetch(__attributes_float3, desc.offset + 3);
 
        return tfm;
 }
index 292e1bf..aa9cd29 100644 (file)
@@ -24,23 +24,23 @@ CCL_NAMESPACE_BEGIN
 
 /* Reading attributes on various curve elements */
 
-ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
+ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
 {
-       if(elem == ATTR_ELEMENT_CURVE) {
+       if(desc.element == ATTR_ELEMENT_CURVE) {
 #ifdef __RAY_DIFFERENTIALS__
                if(dx) *dx = 0.0f;
                if(dy) *dy = 0.0f;
 #endif
 
-               return kernel_tex_fetch(__attributes_float, offset + ccl_fetch(sd, prim));
+               return kernel_tex_fetch(__attributes_float, desc.offset + ccl_fetch(sd, prim));
        }
-       else if(elem == ATTR_ELEMENT_CURVE_KEY || elem == ATTR_ELEMENT_CURVE_KEY_MOTION) {
+       else if(desc.element == ATTR_ELEMENT_CURVE_KEY || desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
                float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim));
                int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type));
                int k1 = k0 + 1;
 
-               float f0 = kernel_tex_fetch(__attributes_float, offset + k0);
-               float f1 = kernel_tex_fetch(__attributes_float, offset + k1);
+               float f0 = kernel_tex_fetch(__attributes_float, desc.offset + k0);
+               float f1 = kernel_tex_fetch(__attributes_float, desc.offset + k1);
 
 #ifdef __RAY_DIFFERENTIALS__
                if(dx) *dx = ccl_fetch(sd, du).dx*(f1 - f0);
@@ -59,9 +59,9 @@ ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd,
        }
 }
 
-ccl_device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
+ccl_device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float3 *dx, float3 *dy)
 {
-       if(elem == ATTR_ELEMENT_CURVE) {
+       if(desc.element == ATTR_ELEMENT_CURVE) {
                /* idea: we can't derive any useful differentials here, but for tiled
                 * mipmap image caching it would be useful to avoid reading the highest
                 * detail level always. maybe a derivative based on the hair density
@@ -71,15 +71,15 @@ ccl_device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd
                if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
 #endif
 
-               return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + ccl_fetch(sd, prim)));
+               return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + ccl_fetch(sd, prim)));
        }
-       else if(elem == ATTR_ELEMENT_CURVE_KEY || elem == ATTR_ELEMENT_CURVE_KEY_MOTION) {
+       else if(desc.element == ATTR_ELEMENT_CURVE_KEY || desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
                float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim));
                int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type));
                int k1 = k0 + 1;
 
-               float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k0));
-               float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k1));
+               float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + k0));
+               float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + k1));
 
 #ifdef __RAY_DIFFERENTIALS__
                if(dx) *dx = ccl_fetch(sd, du).dx*(f1 - f0);
index b16f0c9..4384c20 100644 (file)
@@ -25,24 +25,23 @@ CCL_NAMESPACE_BEGIN
 
 ccl_device_inline float primitive_attribute_float(KernelGlobals *kg,
                                                   const ShaderData *sd,
-                                                  AttributeElement elem,
-                                                  int offset,
+                                                  const AttributeDescriptor desc,
                                                   float *dx, float *dy)
 {
        if(ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) {
                if(subd_triangle_patch(kg, sd) == ~0)
-                       return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
+                       return triangle_attribute_float(kg, sd, desc, dx, dy);
                else
-                       return subd_triangle_attribute_float(kg, sd, elem, offset, dx, dy);
+                       return subd_triangle_attribute_float(kg, sd, desc, dx, dy);
        }
 #ifdef __HAIR__
        else if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
-               return curve_attribute_float(kg, sd, elem, offset, dx, dy);
+               return curve_attribute_float(kg, sd, desc, dx, dy);
        }
 #endif
 #ifdef __VOLUME__
-       else if(ccl_fetch(sd, object) != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) {
-               return volume_attribute_float(kg, sd, elem, offset, dx, dy);
+       else if(ccl_fetch(sd, object) != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
+               return volume_attribute_float(kg, sd, desc, dx, dy);
        }
 #endif
        else {
@@ -54,25 +53,23 @@ ccl_device_inline float primitive_attribute_float(KernelGlobals *kg,
 
 ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg,
                                                     const ShaderData *sd,
-                                                    AttributeElement elem,
-                                                    int offset,
-                                                    float3 *dx,
-                                                    float3 *dy)
+                                                    const AttributeDescriptor desc,
+                                                    float3 *dx, float3 *dy)
 {
        if(ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) {
                if(subd_triangle_patch(kg, sd) == ~0)
-                       return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
+                       return triangle_attribute_float3(kg, sd, desc, dx, dy);
                else
-                       return subd_triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
+                       return subd_triangle_attribute_float3(kg, sd, desc, dx, dy);
        }
 #ifdef __HAIR__
        else if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
-               return curve_attribute_float3(kg, sd, elem, offset, dx, dy);
+               return curve_attribute_float3(kg, sd, desc, dx, dy);
        }
 #endif
 #ifdef __VOLUME__
-       else if(ccl_fetch(sd, object) != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) {
-               return volume_attribute_float3(kg, sd, elem, offset, dx, dy);
+       else if(ccl_fetch(sd, object) != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
+               return volume_attribute_float3(kg, sd, desc, dx, dy);
        }
 #endif
        else {
@@ -86,13 +83,12 @@ ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg,
 
 ccl_device_inline float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
 {
-       AttributeElement elem_uv;
-       int offset_uv = find_attribute(kg, sd, ATTR_STD_UV, &elem_uv);
+       const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_UV);
 
-       if(offset_uv == ATTR_STD_NOT_FOUND)
+       if(desc.offset == ATTR_STD_NOT_FOUND)
                return make_float3(0.0f, 0.0f, 0.0f);
 
-       float3 uv = primitive_attribute_float3(kg, sd, elem_uv, offset_uv, NULL, NULL);
+       float3 uv = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
        uv.z = 1.0f;
        return uv;
 }
@@ -102,15 +98,14 @@ ccl_device_inline float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
 ccl_device bool primitive_ptex(KernelGlobals *kg, ShaderData *sd, float2 *uv, int *face_id)
 {
        /* storing ptex data as attributes is not memory efficient but simple for tests */
-       AttributeElement elem_face_id, elem_uv;
-       int offset_face_id = find_attribute(kg, sd, ATTR_STD_PTEX_FACE_ID, &elem_face_id);
-       int offset_uv = find_attribute(kg, sd, ATTR_STD_PTEX_UV, &elem_uv);
+       const AttributeDescriptor desc_face_id = find_attribute(kg, sd, ATTR_STD_PTEX_FACE_ID);
+       const AttributeDescriptor desc_uv = find_attribute(kg, sd, ATTR_STD_PTEX_UV);
 
-       if(offset_face_id == ATTR_STD_NOT_FOUND || offset_uv == ATTR_STD_NOT_FOUND)
+       if(desc_face_id.offset == ATTR_STD_NOT_FOUND || desc_uv.offset == ATTR_STD_NOT_FOUND)
                return false;
 
-       float3 uv3 = primitive_attribute_float3(kg, sd, elem_uv, offset_uv, NULL, NULL);
-       float face_id_f = primitive_attribute_float(kg, sd, elem_face_id, offset_face_id, NULL, NULL);
+       float3 uv3 = primitive_attribute_float3(kg, sd, desc_uv, NULL, NULL);
+       float face_id_f = primitive_attribute_float(kg, sd, desc_face_id, NULL, NULL);
 
        *uv = make_float2(uv3.x, uv3.y);
        *face_id = (int)face_id_f;
@@ -132,11 +127,10 @@ ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
 #endif
 
        /* try to create spherical tangent from generated coordinates */
-       AttributeElement attr_elem;
-       int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED, &attr_elem);
+       const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_GENERATED);
 
-       if(attr_offset != ATTR_STD_NOT_FOUND) {
-               float3 data = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
+       if(desc.offset != ATTR_STD_NOT_FOUND) {
+               float3 data = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
                data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
                object_normal_transform(kg, sd, &data);
                return cross(ccl_fetch(sd, N), normalize(cross(data, ccl_fetch(sd, N))));
@@ -173,19 +167,18 @@ ccl_device_inline float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *
        float3 motion_pre = center, motion_post = center;
 
        /* deformation motion */
-       AttributeElement elem;
-       int offset = find_attribute(kg, sd, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
+       AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_MOTION_VERTEX_POSITION);
 
-       if(offset != ATTR_STD_NOT_FOUND) {
+       if(desc.offset != ATTR_STD_NOT_FOUND) {
                /* get motion info */
                int numverts, numkeys;
                object_motion_info(kg, ccl_fetch(sd, object), NULL, &numverts, &numkeys);
 
                /* lookup attributes */
-               int offset_next = (ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE)? offset + numverts: offset + numkeys;
+               motion_pre = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
 
-               motion_pre = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
-               motion_post = primitive_attribute_float3(kg, sd, elem, offset_next, NULL, NULL);
+               desc.offset += (ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE)? numverts: numkeys;
+               motion_post = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
 
 #ifdef __HAIR__
                if(is_curve_primitive && (ccl_fetch(sd, flag) & SD_OBJECT_HAS_VERTEX_MOTION) == 0) {
index bf9be18..79a2ce5 100644 (file)
@@ -97,27 +97,27 @@ ccl_device_inline void subd_triangle_patch_corners(KernelGlobals *kg, int patch,
 
 /* Reading attributes on various subdivision triangle elements */
 
-ccl_device float subd_triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
+ccl_device float subd_triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
 {
        int patch = subd_triangle_patch(kg, sd);
 
-       if(elem == ATTR_ELEMENT_FACE) {
+       if(desc.element == ATTR_ELEMENT_FACE) {
                if(dx) *dx = 0.0f;
                if(dy) *dy = 0.0f;
 
-               return kernel_tex_fetch(__attributes_float, offset + subd_triangle_patch_face(kg, patch));
+               return kernel_tex_fetch(__attributes_float, desc.offset + subd_triangle_patch_face(kg, patch));
        }
-       else if(elem == ATTR_ELEMENT_VERTEX || elem == ATTR_ELEMENT_VERTEX_MOTION) {
+       else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
                float2 uv[3];
                subd_triangle_patch_uv(kg, sd, uv);
                uint4 v = subd_triangle_patch_indices(kg, patch);
 
                float a, b, c;
 
-               float f0 = kernel_tex_fetch(__attributes_float, offset + v.x);
-               float f1 = kernel_tex_fetch(__attributes_float, offset + v.y);
-               float f2 = kernel_tex_fetch(__attributes_float, offset + v.z);
-               float f3 = kernel_tex_fetch(__attributes_float, offset + v.w);
+               float f0 = kernel_tex_fetch(__attributes_float, desc.offset + v.x);
+               float f1 = kernel_tex_fetch(__attributes_float, desc.offset + v.y);
+               float f2 = kernel_tex_fetch(__attributes_float, desc.offset + v.z);
+               float f3 = kernel_tex_fetch(__attributes_float, desc.offset + v.w);
 
                if(subd_triangle_patch_num_corners(kg, patch) != 4) {
                        f1 = (f1+f0)*0.5f;
@@ -135,7 +135,7 @@ ccl_device float subd_triangle_attribute_float(KernelGlobals *kg, const ShaderDa
 
                return ccl_fetch(sd, u)*a + ccl_fetch(sd, v)*b + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*c;
        }
-       else if(elem == ATTR_ELEMENT_CORNER) {
+       else if(desc.element == ATTR_ELEMENT_CORNER) {
                int corners[4];
                subd_triangle_patch_corners(kg, patch, corners);
 
@@ -144,10 +144,10 @@ ccl_device float subd_triangle_attribute_float(KernelGlobals *kg, const ShaderDa
 
                float a, b, c;
 
-               float f0 = kernel_tex_fetch(__attributes_float, corners[0] + offset);
-               float f1 = kernel_tex_fetch(__attributes_float, corners[1] + offset);
-               float f2 = kernel_tex_fetch(__attributes_float, corners[2] + offset);
-               float f3 = kernel_tex_fetch(__attributes_float, corners[3] + offset);
+               float f0 = kernel_tex_fetch(__attributes_float, corners[0] + desc.offset);
+               float f1 = kernel_tex_fetch(__attributes_float, corners[1] + desc.offset);
+               float f2 = kernel_tex_fetch(__attributes_float, corners[2] + desc.offset);
+               float f3 = kernel_tex_fetch(__attributes_float, corners[3] + desc.offset);
 
                if(subd_triangle_patch_num_corners(kg, patch) != 4) {
                        f1 = (f1+f0)*0.5f;
@@ -173,27 +173,27 @@ ccl_device float subd_triangle_attribute_float(KernelGlobals *kg, const ShaderDa
        }
 }
 
-ccl_device float3 subd_triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
+ccl_device float3 subd_triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float3 *dx, float3 *dy)
 {
        int patch = subd_triangle_patch(kg, sd);
 
-       if(elem == ATTR_ELEMENT_FACE) {
+       if(desc.element == ATTR_ELEMENT_FACE) {
                if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
                if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
 
-               return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + subd_triangle_patch_face(kg, patch)));
+               return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + subd_triangle_patch_face(kg, patch)));
        }
-       else if(elem == ATTR_ELEMENT_VERTEX || elem == ATTR_ELEMENT_VERTEX_MOTION) {
+       else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
                float2 uv[3];
                subd_triangle_patch_uv(kg, sd, uv);
                uint4 v = subd_triangle_patch_indices(kg, patch);
 
                float3 a, b, c;
 
-               float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + v.x));
-               float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + v.y));
-               float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + v.z));
-               float3 f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + v.w));
+               float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.x));
+               float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.y));
+               float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.z));
+               float3 f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.w));
 
                if(subd_triangle_patch_num_corners(kg, patch) != 4) {
                        f1 = (f1+f0)*0.5f;
@@ -211,7 +211,7 @@ ccl_device float3 subd_triangle_attribute_float3(KernelGlobals *kg, const Shader
 
                return ccl_fetch(sd, u)*a + ccl_fetch(sd, v)*b + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*c;
        }
-       else if(elem == ATTR_ELEMENT_CORNER || elem == ATTR_ELEMENT_CORNER_BYTE) {
+       else if(desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) {
                int corners[4];
                subd_triangle_patch_corners(kg, patch, corners);
 
@@ -221,17 +221,17 @@ ccl_device float3 subd_triangle_attribute_float3(KernelGlobals *kg, const Shader
                float3 a, b, c;
                float3 f0, f1, f2, f3;
 
-               if(elem == ATTR_ELEMENT_CORNER) {
-                       f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[0] + offset));
-                       f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[1] + offset));
-                       f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[2] + offset));
-                       f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[3] + offset));
+               if(desc.element == ATTR_ELEMENT_CORNER) {
+                       f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[0] + desc.offset));
+                       f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[1] + desc.offset));
+                       f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[2] + desc.offset));
+                       f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[3] + desc.offset));
                }
                else {
-                       f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[0] + offset));
-                       f1 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[1] + offset));
-                       f2 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[2] + offset));
-                       f3 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[3] + offset));
+                       f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[0] + desc.offset));
+                       f1 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[1] + desc.offset));
+                       f2 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[2] + desc.offset));
+                       f3 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[3] + desc.offset));
                }
 
                if(subd_triangle_patch_num_corners(kg, patch) != 4) {
index 0c2351e..d3289d6 100644 (file)
@@ -105,20 +105,20 @@ ccl_device_inline void triangle_dPdudv(KernelGlobals *kg, int prim, ccl_addr_spa
 
 /* Reading attributes on various triangle elements */
 
-ccl_device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
+ccl_device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
 {
-       if(elem == ATTR_ELEMENT_FACE) {
+       if(desc.element == ATTR_ELEMENT_FACE) {
                if(dx) *dx = 0.0f;
                if(dy) *dy = 0.0f;
 
-               return kernel_tex_fetch(__attributes_float, offset + ccl_fetch(sd, prim));
+               return kernel_tex_fetch(__attributes_float, desc.offset + ccl_fetch(sd, prim));
        }
-       else if(elem == ATTR_ELEMENT_VERTEX || elem == ATTR_ELEMENT_VERTEX_MOTION) {
+       else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
                uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim));
 
-               float f0 = kernel_tex_fetch(__attributes_float, offset + tri_vindex.x);
-               float f1 = kernel_tex_fetch(__attributes_float, offset + tri_vindex.y);
-               float f2 = kernel_tex_fetch(__attributes_float, offset + tri_vindex.z);
+               float f0 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.x);
+               float f1 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.y);
+               float f2 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.z);
 
 #ifdef __RAY_DIFFERENTIALS__
                if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2;
@@ -127,8 +127,8 @@ ccl_device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *s
 
                return ccl_fetch(sd, u)*f0 + ccl_fetch(sd, v)*f1 + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*f2;
        }
-       else if(elem == ATTR_ELEMENT_CORNER) {
-               int tri = offset + ccl_fetch(sd, prim)*3;
+       else if(desc.element == ATTR_ELEMENT_CORNER) {
+               int tri = desc.offset + ccl_fetch(sd, prim)*3;
                float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
                float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
                float f2 = kernel_tex_fetch(__attributes_float, tri + 2);
@@ -148,20 +148,20 @@ ccl_device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *s
        }
 }
 
-ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
+ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float3 *dx, float3 *dy)
 {
-       if(elem == ATTR_ELEMENT_FACE) {
+       if(desc.element == ATTR_ELEMENT_FACE) {
                if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
                if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
 
-               return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + ccl_fetch(sd, prim)));
+               return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + ccl_fetch(sd, prim)));
        }
-       else if(elem == ATTR_ELEMENT_VERTEX || elem == ATTR_ELEMENT_VERTEX_MOTION) {
+       else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
                uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim));
 
-               float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.x));
-               float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.y));
-               float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.z));
+               float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x));
+               float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y));
+               float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z));
 
 #ifdef __RAY_DIFFERENTIALS__
                if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2;
@@ -170,11 +170,11 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData
 
                return ccl_fetch(sd, u)*f0 + ccl_fetch(sd, v)*f1 + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*f2;
        }
-       else if(elem == ATTR_ELEMENT_CORNER || elem == ATTR_ELEMENT_CORNER_BYTE) {
-               int tri = offset + ccl_fetch(sd, prim)*3;
+       else if(desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) {
+               int tri = desc.offset + ccl_fetch(sd, prim)*3;
                float3 f0, f1, f2;
 
-               if(elem == ATTR_ELEMENT_CORNER) {
+               if(desc.element == ATTR_ELEMENT_CORNER) {
                        f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
                        f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
                        f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
index 7c8182b..efe540a 100644 (file)
@@ -50,36 +50,35 @@ ccl_device_inline float3 volume_normalized_position(KernelGlobals *kg,
 {
        /* todo: optimize this so it's just a single matrix multiplication when
         * possible (not motion blur), or perhaps even just translation + scale */
-       AttributeElement attr_elem;
-       int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM, &attr_elem);
+       const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM);
 
        object_inverse_position_transform(kg, sd, &P);
 
-       if(attr_offset != ATTR_STD_NOT_FOUND) {
-               Transform tfm = primitive_attribute_matrix(kg, sd, attr_offset);
+       if(desc.offset != ATTR_STD_NOT_FOUND) {
+               Transform tfm = primitive_attribute_matrix(kg, sd, desc);
                P = transform_point(&tfm, P);
        }
 
        return P;
 }
 
-ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int id, float *dx, float *dy)
+ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
 {
        float3 P = volume_normalized_position(kg, sd, sd->P);
 #ifdef __KERNEL_GPU__
 #  if __CUDA_ARCH__ >= 300
-       CUtexObject tex = kernel_tex_fetch(__bindless_mapping, id);
+       CUtexObject tex = kernel_tex_fetch(__bindless_mapping, desc.offset);
        float f = kernel_tex_image_interp_3d_float(tex, P.x, P.y, P.z);
        float4 r = make_float4(f, f, f, 1.0);
 #  else
-       float4 r = volume_image_texture_3d(id, P.x, P.y, P.z);
+       float4 r = volume_image_texture_3d(desc.offset, P.x, P.y, P.z);
 #  endif
 #else
        float4 r;
        if(sd->flag & SD_VOLUME_CUBIC)
-               r = kernel_tex_image_interp_3d_ex(id, P.x, P.y, P.z, INTERPOLATION_CUBIC);
+               r = kernel_tex_image_interp_3d_ex(desc.offset, P.x, P.y, P.z, INTERPOLATION_CUBIC);
        else
-               r = kernel_tex_image_interp_3d(id, P.x, P.y, P.z);
+               r = kernel_tex_image_interp_3d(desc.offset, P.x, P.y, P.z);
 #endif
 
        if(dx) *dx = 0.0f;
@@ -88,22 +87,22 @@ ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd,
        return average(float4_to_float3(r));
 }
 
-ccl_device float3 volume_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int id, float3 *dx, float3 *dy)
+ccl_device float3 volume_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float3 *dx, float3 *dy)
 {
        float3 P = volume_normalized_position(kg, sd, sd->P);
 #ifdef __KERNEL_GPU__
 #  if __CUDA_ARCH__ >= 300
-       CUtexObject tex = kernel_tex_fetch(__bindless_mapping, id);
+       CUtexObject tex = kernel_tex_fetch(__bindless_mapping, desc.offset);
        float4 r = kernel_tex_image_interp_3d_float4(tex, P.x, P.y, P.z);
 #  else
-       float4 r = volume_image_texture_3d(id, P.x, P.y, P.z);
+       float4 r = volume_image_texture_3d(desc.offset, P.x, P.y, P.z);
 #  endif
 #else
        float4 r;
        if(sd->flag & SD_VOLUME_CUBIC)
-               r = kernel_tex_image_interp_3d_ex(id, P.x, P.y, P.z, INTERPOLATION_CUBIC);
+               r = kernel_tex_image_interp_3d_ex(desc.offset, P.x, P.y, P.z, INTERPOLATION_CUBIC);
        else
-               r = kernel_tex_image_interp_3d(id, P.x, P.y, P.z);
+               r = kernel_tex_image_interp_3d(desc.offset, P.x, P.y, P.z);
 #endif
 
        if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
index 18b5c35..57b116e 100644 (file)
@@ -624,6 +624,12 @@ typedef enum AttributeStandard {
        ATTR_STD_NOT_FOUND = ~0
 } AttributeStandard;
 
+typedef struct AttributeDescriptor {
+       AttributeElement element;
+       NodeAttributeType type;
+       int offset;
+} AttributeDescriptor;
+
 /* Closure data */
 
 #ifdef __MULTI_CLOSURE__
index 916542e..8353c4e 100644 (file)
@@ -59,8 +59,7 @@ struct OSLGlobals {
        /* attributes */
        struct Attribute {
                TypeDesc type;
-               AttributeElement elem;
-               int offset;
+               AttributeDescriptor desc;
                ParamValue value;
        };
 
index caae244..153ebad 100644 (file)
@@ -554,13 +554,13 @@ static bool get_mesh_element_attribute(KernelGlobals *kg, const ShaderData *sd,
           attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor)
        {
                float3 fval[3];
-               fval[0] = primitive_attribute_float3(kg, sd, attr.elem, attr.offset,
+               fval[0] = primitive_attribute_float3(kg, sd, attr.desc,
                                                     (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
                return set_attribute_float3(fval, type, derivatives, val);
        }
        else if(attr.type == TypeDesc::TypeFloat) {
                float fval[3];
-               fval[0] = primitive_attribute_float(kg, sd, attr.elem, attr.offset,
+               fval[0] = primitive_attribute_float(kg, sd, attr.desc,
                                                    (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
                return set_attribute_float(fval, type, derivatives, val);
        }
@@ -573,7 +573,7 @@ static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OS
                                const TypeDesc& type, bool derivatives, void *val)
 {
        if(attr.type == TypeDesc::TypeMatrix) {
-               Transform tfm = primitive_attribute_matrix(kg, sd, attr.offset);
+               Transform tfm = primitive_attribute_matrix(kg, sd, attr.desc);
                return set_attribute_matrix(tfm, type, val);
        }
        else {
@@ -815,7 +815,7 @@ bool OSLRenderServices::get_attribute(ShaderData *sd, bool derivatives, ustring
        if(it != attribute_map.end()) {
                const OSLGlobals::Attribute& attr = it->second;
 
-               if(attr.elem != ATTR_ELEMENT_OBJECT) {
+               if(attr.desc.element != ATTR_ELEMENT_OBJECT) {
                        /* triangle and vertex attributes */
                        if(get_mesh_element_attribute(kg, sd, attr, type, derivatives, val))
                                return true;
index de02ec8..20dd167 100644 (file)
@@ -334,7 +334,7 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderConte
 
 /* Attributes */
 
-int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem)
+int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeDescriptor *desc)
 {
        /* for OSL, a hash map is used to lookup the attribute by name. */
        int object = sd->object*ATTR_PRIM_TYPES;
@@ -348,16 +348,23 @@ int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id,
 
        if(it != attr_map.end()) {
                const OSLGlobals::Attribute &osl_attr = it->second;
-               *elem = osl_attr.elem;
+               *desc = osl_attr.desc;
 
-               if(sd->prim == PRIM_NONE && (AttributeElement)osl_attr.elem != ATTR_ELEMENT_MESH)
+               if(sd->prim == PRIM_NONE && (AttributeElement)osl_attr.desc.element != ATTR_ELEMENT_MESH) {
+                       desc->offset = ATTR_STD_NOT_FOUND;
                        return ATTR_STD_NOT_FOUND;
+               }
 
                /* return result */
-               return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset;
+               if(osl_attr.desc.element == ATTR_ELEMENT_NONE) {
+                       desc->offset = ATTR_STD_NOT_FOUND;
+               }
+               return desc->offset;
        }
-       else
+       else {
+               desc->offset = ATTR_STD_NOT_FOUND;
                return (int)ATTR_STD_NOT_FOUND;
+       }
 }
 
 CCL_NAMESPACE_END
index a185b8b..ad06dd6 100644 (file)
@@ -59,7 +59,7 @@ public:
        static void eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx);
 
        /* attributes */
-       static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem);
+       static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeDescriptor *desc);
 };
 
 CCL_NAMESPACE_END
index 0f0858b..de978a4 100644 (file)
@@ -18,70 +18,57 @@ CCL_NAMESPACE_BEGIN
 
 /* Attribute Node */
 
-ccl_device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd,
+ccl_device AttributeDescriptor svm_node_attr_init(KernelGlobals *kg, ShaderData *sd,
        uint4 node, NodeAttributeType *type,
-       NodeAttributeType *mesh_type, AttributeElement *elem, int *offset, uint *out_offset)
+       uint *out_offset)
 {
        *out_offset = node.z;
        *type = (NodeAttributeType)node.w;
+
+       AttributeDescriptor desc;
+
        if(ccl_fetch(sd, object) != OBJECT_NONE) {
-               /* find attribute by unique id */
-               uint id = node.y;
-               uint attr_offset = ccl_fetch(sd, object)*kernel_data.bvh.attributes_map_stride;
-               attr_offset += attribute_primitive_type(kg, sd);
-               uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
-               
-               while(attr_map.x != id) {
-                       if(UNLIKELY(attr_map.x == ATTR_STD_NONE)) {
-                               *elem = ATTR_ELEMENT_NONE;
-                               *offset = 0;
-                               *mesh_type = (NodeAttributeType)node.w;
-                               return;
-                       }
-                       attr_offset += ATTR_PRIM_TYPES;
-                       attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
+               desc = find_attribute(kg, sd, node.y);
+               if(desc.offset == ATTR_STD_NOT_FOUND) {
+                       desc.element = ATTR_ELEMENT_NONE;
+                       desc.offset = 0;
+                       desc.type = (NodeAttributeType)node.w;
                }
-
-               /* return result */
-               *elem = (AttributeElement)attr_map.y;
-               *offset = as_int(attr_map.z);
-               *mesh_type = (NodeAttributeType)attr_map.w;
        }
        else {
                /* background */
-               *elem = ATTR_ELEMENT_NONE;
-               *offset = 0;
-               *mesh_type = (NodeAttributeType)node.w;
+               desc.element = ATTR_ELEMENT_NONE;
+               desc.offset = 0;
+               desc.type = (NodeAttributeType)node.w;
        }
+
+       return desc;
 }
 
 ccl_device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
 {
-       NodeAttributeType type, mesh_type;
-       AttributeElement elem;
+       NodeAttributeType type;
        uint out_offset;
-       int offset;
-
-       svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
+       AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
 
        /* fetch and store attribute */
        if(type == NODE_ATTR_FLOAT) {
-               if(mesh_type == NODE_ATTR_FLOAT) {
-                       float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL);
+               if(desc.type == NODE_ATTR_FLOAT) {
+                       float f = primitive_attribute_float(kg, sd, desc, NULL, NULL);
                        stack_store_float(stack, out_offset, f);
                }
                else {
-                       float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
+                       float3 f = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
                        stack_store_float(stack, out_offset, average(f));
                }
        }
        else {
-               if(mesh_type == NODE_ATTR_FLOAT3) {
-                       float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
+               if(desc.type == NODE_ATTR_FLOAT3) {
+                       float3 f = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
                        stack_store_float3(stack, out_offset, f);
                }
                else {
-                       float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL);
+                       float f = primitive_attribute_float(kg, sd, desc, NULL, NULL);
                        stack_store_float3(stack, out_offset, make_float3(f, f, f));
                }
        }
@@ -94,35 +81,32 @@ ccl_device_noinline
 #endif
 void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
 {
-       NodeAttributeType type, mesh_type;
-       AttributeElement elem;
+       NodeAttributeType type;
        uint out_offset;
-       int offset;
-
-       svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
+       AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
 
        /* fetch and store attribute */
        if(type == NODE_ATTR_FLOAT) {
-               if(mesh_type == NODE_ATTR_FLOAT) {
+               if(desc.type == NODE_ATTR_FLOAT) {
                        float dx;
-                       float f = primitive_attribute_float(kg, sd, elem, offset, &dx, NULL);
+                       float f = primitive_attribute_float(kg, sd, desc, &dx, NULL);
                        stack_store_float(stack, out_offset, f+dx);
                }
                else {
                        float3 dx;
-                       float3 f = primitive_attribute_float3(kg, sd, elem, offset, &dx, NULL);
+                       float3 f = primitive_attribute_float3(kg, sd, desc, &dx, NULL);
                        stack_store_float(stack, out_offset, average(f+dx));
                }
        }
        else {
-               if(mesh_type == NODE_ATTR_FLOAT3) {
+               if(desc.type == NODE_ATTR_FLOAT3) {
                        float3 dx;
-                       float3 f = primitive_attribute_float3(kg, sd, elem, offset, &dx, NULL);
+                       float3 f = primitive_attribute_float3(kg, sd, desc, &dx, NULL);
                        stack_store_float3(stack, out_offset, f+dx);
                }
                else {
                        float dx;
-                       float f = primitive_attribute_float(kg, sd, elem, offset, &dx, NULL);
+                       float f = primitive_attribute_float(kg, sd, desc, &dx, NULL);
                        stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx));
                }
        }
@@ -138,35 +122,32 @@ void svm_node_attr_bump_dy(KernelGlobals *kg,
                            float *stack,
                            uint4 node)
 {
-       NodeAttributeType type, mesh_type;
-       AttributeElement elem;
+       NodeAttributeType type;
        uint out_offset;
-       int offset;
-
-       svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
+       AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
 
        /* fetch and store attribute */
        if(type == NODE_ATTR_FLOAT) {
-               if(mesh_type == NODE_ATTR_FLOAT) {
+               if(desc.type == NODE_ATTR_FLOAT) {
                        float dy;
-                       float f = primitive_attribute_float(kg, sd, elem, offset, NULL, &dy);
+                       float f = primitive_attribute_float(kg, sd, desc, NULL, &dy);
                        stack_store_float(stack, out_offset, f+dy);
                }
                else {
                        float3 dy;
-                       float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, &dy);
+                       float3 f = primitive_attribute_float3(kg, sd, desc, NULL, &dy);
                        stack_store_float(stack, out_offset, average(f+dy));
                }
        }
        else {
-               if(mesh_type == NODE_ATTR_FLOAT3) {
+               if(desc.type == NODE_ATTR_FLOAT3) {
                        float3 dy;
-                       float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, &dy);
+                       float3 f = primitive_attribute_float3(kg, sd, desc, NULL, &dy);
                        stack_store_float3(stack, out_offset, f+dy);
                }
                else {
                        float dy;
-                       float f = primitive_attribute_float(kg, sd, elem, offset, NULL, &dy);
+                       float f = primitive_attribute_float(kg, sd, desc, NULL, &dy);
                        stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy));
                }
        }
index b39d6a3..01dede3 100644 (file)
@@ -287,23 +287,22 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
                }
 
                /* first try to get tangent attribute */
-               AttributeElement attr_elem, attr_sign_elem, attr_normal_elem;
-               int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
-               int attr_sign_offset = find_attribute(kg, sd, node.w, &attr_sign_elem);
-               int attr_normal_offset = find_attribute(kg, sd, ATTR_STD_VERTEX_NORMAL, &attr_normal_elem);
+               const AttributeDescriptor attr = find_attribute(kg, sd, node.z);
+               const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.w);
+               const AttributeDescriptor attr_normal = find_attribute(kg, sd, ATTR_STD_VERTEX_NORMAL);
 
-               if(attr_offset == ATTR_STD_NOT_FOUND || attr_sign_offset == ATTR_STD_NOT_FOUND || attr_normal_offset == ATTR_STD_NOT_FOUND) {
+               if(attr.offset == ATTR_STD_NOT_FOUND || attr_sign.offset == ATTR_STD_NOT_FOUND || attr_normal.offset == ATTR_STD_NOT_FOUND) {
                        stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
                        return;
                }
 
                /* get _unnormalized_ interpolated normal and tangent */
-               float3 tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
-               float sign = primitive_attribute_float(kg, sd, attr_sign_elem, attr_sign_offset, NULL, NULL);
+               float3 tangent = primitive_attribute_float3(kg, sd, attr, NULL, NULL);
+               float sign = primitive_attribute_float(kg, sd, attr_sign, NULL, NULL);
                float3 normal;
 
                if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) {
-                       normal = primitive_attribute_float3(kg, sd, attr_normal_elem, attr_normal_offset, NULL, NULL);
+                       normal = primitive_attribute_float3(kg, sd, attr_normal, NULL, NULL);
                }
                else {
                        normal = ccl_fetch(sd, Ng);
@@ -356,24 +355,22 @@ ccl_device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack
 
        if(direction_type == NODE_TANGENT_UVMAP) {
                /* UV map */
-               AttributeElement attr_elem;
-               int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
+               const AttributeDescriptor desc = find_attribute(kg, sd, node.z);
 
-               if(attr_offset == ATTR_STD_NOT_FOUND)
+               if(desc.offset == ATTR_STD_NOT_FOUND)
                        tangent = make_float3(0.0f, 0.0f, 0.0f);
                else
-                       tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
+                       tangent = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
        }
        else {
                /* radial */
-               AttributeElement attr_elem;
-               int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
+               const AttributeDescriptor desc = find_attribute(kg, sd, node.z);
                float3 generated;
 
-               if(attr_offset == ATTR_STD_NOT_FOUND)
+               if(desc.offset == ATTR_STD_NOT_FOUND)
                        generated = ccl_fetch(sd, P);
                else
-                       generated = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
+                       generated = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
 
                if(axis == NODE_TANGENT_AXIS_X)
                        tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f));
index e8ff81f..a77ae11 100644 (file)
@@ -517,16 +517,19 @@ AttributeRequest::AttributeRequest(ustring name_)
        std = ATTR_STD_NONE;
 
        triangle_type = TypeDesc::TypeFloat;
-       triangle_element = ATTR_ELEMENT_NONE;
-       triangle_offset = 0;
+       triangle_desc.element = ATTR_ELEMENT_NONE;
+       triangle_desc.offset = 0;
+       triangle_desc.type = NODE_ATTR_FLOAT;
 
        curve_type = TypeDesc::TypeFloat;
-       curve_element = ATTR_ELEMENT_NONE;
-       curve_offset = 0;
+       curve_desc.element = ATTR_ELEMENT_NONE;
+       curve_desc.offset = 0;
+       curve_desc.type = NODE_ATTR_FLOAT;
 
        subd_type = TypeDesc::TypeFloat;
-       subd_element = ATTR_ELEMENT_NONE;
-       subd_offset = 0;
+       subd_desc.element = ATTR_ELEMENT_NONE;
+       subd_desc.offset = 0;
+       subd_desc.type = NODE_ATTR_FLOAT;
 }
 
 AttributeRequest::AttributeRequest(AttributeStandard std_)
@@ -535,16 +538,19 @@ AttributeRequest::AttributeRequest(AttributeStandard std_)
        std = std_;
 
        triangle_type = TypeDesc::TypeFloat;
-       triangle_element = ATTR_ELEMENT_NONE;
-       triangle_offset = 0;
+       triangle_desc.element = ATTR_ELEMENT_NONE;
+       triangle_desc.offset = 0;
+       triangle_desc.type = NODE_ATTR_FLOAT;
 
        curve_type = TypeDesc::TypeFloat;
-       curve_element = ATTR_ELEMENT_NONE;
-       curve_offset = 0;
+       curve_desc.element = ATTR_ELEMENT_NONE;
+       curve_desc.offset = 0;
+       curve_desc.type = NODE_ATTR_FLOAT;
 
        subd_type = TypeDesc::TypeFloat;
-       subd_element = ATTR_ELEMENT_NONE;
-       subd_offset = 0;
+       subd_desc.element = ATTR_ELEMENT_NONE;
+       subd_desc.offset = 0;
+       subd_desc.type = NODE_ATTR_FLOAT;
 }
 
 /* AttributeRequestSet */
index e51bdf2..67d067d 100644 (file)
@@ -135,8 +135,7 @@ public:
 
        /* temporary variables used by MeshManager */
        TypeDesc triangle_type, curve_type, subd_type;
-       AttributeElement triangle_element, curve_element, subd_element;
-       int triangle_offset, curve_offset, subd_offset;
+       AttributeDescriptor triangle_desc, curve_desc, subd_desc;
 
        explicit AttributeRequest(ustring name_);
        explicit AttributeRequest(AttributeStandard std);
index 4cf0a78..2edec40 100644 (file)
@@ -831,9 +831,9 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
                        OSLGlobals::Attribute osl_attr;
 
                        osl_attr.type = attr.type();
-                       osl_attr.elem = ATTR_ELEMENT_OBJECT;
+                       osl_attr.desc.element = ATTR_ELEMENT_OBJECT;
                        osl_attr.value = attr;
-                       osl_attr.offset = 0;
+                       osl_attr.desc.offset = 0;
 
                        og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][attr.name()] = osl_attr;
                        og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][attr.name()] = osl_attr;
@@ -853,9 +853,8 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
                foreach(AttributeRequest& req, attributes.requests) {
                        OSLGlobals::Attribute osl_attr;
 
-                       if(req.triangle_element != ATTR_ELEMENT_NONE) {
-                               osl_attr.elem = req.triangle_element;
-                               osl_attr.offset = req.triangle_offset;
+                       if(req.triangle_desc.element != ATTR_ELEMENT_NONE) {
+                               osl_attr.desc = req.triangle_desc;
 
                                if(req.triangle_type == TypeDesc::TypeFloat)
                                        osl_attr.type = TypeDesc::TypeFloat;
@@ -875,9 +874,8 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
                                }
                        }
 
-                       if(req.curve_element != ATTR_ELEMENT_NONE) {
-                               osl_attr.elem = req.curve_element;
-                               osl_attr.offset = req.curve_offset;
+                       if(req.curve_desc.element != ATTR_ELEMENT_NONE) {
+                               osl_attr.desc = req.curve_desc;
 
                                if(req.curve_type == TypeDesc::TypeFloat)
                                        osl_attr.type = TypeDesc::TypeFloat;
@@ -897,9 +895,8 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
                                }
                        }
 
-                       if(req.subd_element != ATTR_ELEMENT_NONE) {
-                               osl_attr.elem = req.subd_element;
-                               osl_attr.offset = req.subd_offset;
+                       if(req.subd_desc.element != ATTR_ELEMENT_NONE) {
+                               osl_attr.desc = req.subd_desc;
 
                                if(req.subd_type == TypeDesc::TypeFloat)
                                        osl_attr.type = TypeDesc::TypeFloat;
@@ -971,8 +968,8 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
 
                        if(mesh->num_triangles()) {
                                attr_map[index].x = id;
-                               attr_map[index].y = req.triangle_element;
-                               attr_map[index].z = as_uint(req.triangle_offset);
+                               attr_map[index].y = req.triangle_desc.element;
+                               attr_map[index].z = as_uint(req.triangle_desc.offset);
 
                                if(req.triangle_type == TypeDesc::TypeFloat)
                                        attr_map[index].w = NODE_ATTR_FLOAT;
@@ -986,8 +983,8 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
 
                        if(mesh->num_curves()) {
                                attr_map[index].x = id;
-                               attr_map[index].y = req.curve_element;
-                               attr_map[index].z = as_uint(req.curve_offset);
+                               attr_map[index].y = req.curve_desc.element;
+                               attr_map[index].z = as_uint(req.curve_desc.offset);
 
                                if(req.curve_type == TypeDesc::TypeFloat)
                                        attr_map[index].w = NODE_ATTR_FLOAT;
@@ -1001,8 +998,8 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
 
                        if(mesh->subd_faces.size()) {
                                attr_map[index].x = id;
-                               attr_map[index].y = req.subd_element;
-                               attr_map[index].z = as_uint(req.subd_offset);
+                               attr_map[index].y = req.subd_desc.element;
+                               attr_map[index].z = as_uint(req.subd_desc.offset);
 
                                if(req.subd_type == TypeDesc::TypeFloat)
                                        attr_map[index].w = NODE_ATTR_FLOAT;
@@ -1069,17 +1066,19 @@ static void update_attribute_element_offset(Mesh *mesh,
                                             Attribute *mattr,
                                             AttributePrimitive prim,
                                             TypeDesc& type,
-                                            int& offset,
-                                            AttributeElement& element)
+                                            AttributeDescriptor& desc)
 {
        if(mattr) {
                /* store element and type */
-               element = mattr->element;
+               desc.element = mattr->element;
                type = mattr->type;
 
                /* store attribute data in arrays */
                size_t size = mattr->element_size(mesh, prim);
 
+               AttributeElement& element = desc.element;
+               int& offset = desc.offset;
+
                if(mattr->element == ATTR_ELEMENT_VOXEL) {
                        /* store slot in offset value */
                        VoxelAttribute *voxel_data = mattr->data_voxel();
@@ -1153,8 +1152,8 @@ static void update_attribute_element_offset(Mesh *mesh,
        }
        else {
                /* attribute not found */
-               element = ATTR_ELEMENT_NONE;
-               offset = 0;
+               desc.element = ATTR_ELEMENT_NONE;
+               desc.offset = 0;
        }
 }
 
@@ -1243,8 +1242,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
                                                        triangle_mattr,
                                                        ATTR_PRIM_TRIANGLE,
                                                        req.triangle_type,
-                                                       req.triangle_offset,
-                                                       req.triangle_element);
+                                                       req.triangle_desc);
 
                        update_attribute_element_offset(mesh,
                                                        attr_float, attr_float_offset,
@@ -1253,8 +1251,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
                                                        curve_mattr,
                                                        ATTR_PRIM_CURVE,
                                                        req.curve_type,
-                                                       req.curve_offset,
-                                                       req.curve_element);
+                                                       req.curve_desc);
 
                        update_attribute_element_offset(mesh,
                                                        attr_float, attr_float_offset,
@@ -1263,8 +1260,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
                                                        subd_mattr,
                                                        ATTR_PRIM_SUBD,
                                                        req.subd_type,
-                                                       req.subd_offset,
-                                                       req.subd_element);
+                                                       req.subd_desc);
 
                        if(progress.get_cancel()) return;
                }