Cycles: Add AttributeDescriptor

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
This commit is contained in:
Mai Lavelle
2016-07-01 17:36:27 -04:00
parent 734e0aca38
commit cd809b95d8
16 changed files with 249 additions and 254 deletions

View 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 */ /* 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) if(ccl_fetch(sd, object) == PRIM_NONE) {
return (int)ATTR_STD_NOT_FOUND; return attribute_not_found();
}
/* for SVM, find attribute by unique id */ /* for SVM, find attribute by unique id */
uint attr_offset = ccl_fetch(sd, object)*kernel_data.bvh.attributes_map_stride; 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) { while(attr_map.x != id) {
if(UNLIKELY(attr_map.x == ATTR_STD_NONE)) { if(UNLIKELY(attr_map.x == ATTR_STD_NONE)) {
return ATTR_STD_NOT_FOUND; return attribute_not_found();
} }
attr_offset += ATTR_PRIM_TYPES; attr_offset += ATTR_PRIM_TYPES;
attr_map = kernel_tex_fetch(__attributes_map, attr_offset); 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) if(ccl_fetch(sd, prim) == PRIM_NONE && desc.element != ATTR_ELEMENT_MESH) {
return ATTR_STD_NOT_FOUND; return attribute_not_found();
}
/* return result */ /* 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 */ /* 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; Transform tfm;
tfm.x = kernel_tex_fetch(__attributes_float3, offset + 0); tfm.x = kernel_tex_fetch(__attributes_float3, desc.offset + 0);
tfm.y = kernel_tex_fetch(__attributes_float3, offset + 1); tfm.y = kernel_tex_fetch(__attributes_float3, desc.offset + 1);
tfm.z = kernel_tex_fetch(__attributes_float3, offset + 2); tfm.z = kernel_tex_fetch(__attributes_float3, desc.offset + 2);
tfm.w = kernel_tex_fetch(__attributes_float3, offset + 3); tfm.w = kernel_tex_fetch(__attributes_float3, desc.offset + 3);
return tfm; return tfm;
} }

View File

@@ -24,23 +24,23 @@ CCL_NAMESPACE_BEGIN
/* Reading attributes on various curve elements */ /* 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__ #ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = 0.0f; if(dx) *dx = 0.0f;
if(dy) *dy = 0.0f; if(dy) *dy = 0.0f;
#endif #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)); 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 k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type));
int k1 = k0 + 1; int k1 = k0 + 1;
float f0 = kernel_tex_fetch(__attributes_float, offset + k0); float f0 = kernel_tex_fetch(__attributes_float, desc.offset + k0);
float f1 = kernel_tex_fetch(__attributes_float, offset + k1); float f1 = kernel_tex_fetch(__attributes_float, desc.offset + k1);
#ifdef __RAY_DIFFERENTIALS__ #ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = ccl_fetch(sd, du).dx*(f1 - f0); 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 /* idea: we can't derive any useful differentials here, but for tiled
* mipmap image caching it would be useful to avoid reading the highest * mipmap image caching it would be useful to avoid reading the highest
* detail level always. maybe a derivative based on the hair density * 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); if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
#endif #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)); 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 k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type));
int k1 = k0 + 1; int k1 = k0 + 1;
float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k0)); float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + k0));
float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k1)); float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + k1));
#ifdef __RAY_DIFFERENTIALS__ #ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = ccl_fetch(sd, du).dx*(f1 - f0); if(dx) *dx = ccl_fetch(sd, du).dx*(f1 - f0);

View File

@@ -25,24 +25,23 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline float primitive_attribute_float(KernelGlobals *kg, ccl_device_inline float primitive_attribute_float(KernelGlobals *kg,
const ShaderData *sd, const ShaderData *sd,
AttributeElement elem, const AttributeDescriptor desc,
int offset,
float *dx, float *dy) float *dx, float *dy)
{ {
if(ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) { if(ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) {
if(subd_triangle_patch(kg, sd) == ~0) 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 else
return subd_triangle_attribute_float(kg, sd, elem, offset, dx, dy); return subd_triangle_attribute_float(kg, sd, desc, dx, dy);
} }
#ifdef __HAIR__ #ifdef __HAIR__
else if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) { 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 #endif
#ifdef __VOLUME__ #ifdef __VOLUME__
else if(ccl_fetch(sd, object) != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) { else if(ccl_fetch(sd, object) != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
return volume_attribute_float(kg, sd, elem, offset, dx, dy); return volume_attribute_float(kg, sd, desc, dx, dy);
} }
#endif #endif
else { else {
@@ -54,25 +53,23 @@ ccl_device_inline float primitive_attribute_float(KernelGlobals *kg,
ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg, ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg,
const ShaderData *sd, const ShaderData *sd,
AttributeElement elem, const AttributeDescriptor desc,
int offset, float3 *dx, float3 *dy)
float3 *dx,
float3 *dy)
{ {
if(ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) { if(ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) {
if(subd_triangle_patch(kg, sd) == ~0) 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 else
return subd_triangle_attribute_float3(kg, sd, elem, offset, dx, dy); return subd_triangle_attribute_float3(kg, sd, desc, dx, dy);
} }
#ifdef __HAIR__ #ifdef __HAIR__
else if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) { 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 #endif
#ifdef __VOLUME__ #ifdef __VOLUME__
else if(ccl_fetch(sd, object) != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) { else if(ccl_fetch(sd, object) != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
return volume_attribute_float3(kg, sd, elem, offset, dx, dy); return volume_attribute_float3(kg, sd, desc, dx, dy);
} }
#endif #endif
else { else {
@@ -86,13 +83,12 @@ ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg,
ccl_device_inline float3 primitive_uv(KernelGlobals *kg, ShaderData *sd) ccl_device_inline float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
{ {
AttributeElement elem_uv; const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_UV);
int offset_uv = find_attribute(kg, sd, ATTR_STD_UV, &elem_uv);
if(offset_uv == ATTR_STD_NOT_FOUND) if(desc.offset == ATTR_STD_NOT_FOUND)
return make_float3(0.0f, 0.0f, 0.0f); 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; uv.z = 1.0f;
return uv; 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) 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 */ /* storing ptex data as attributes is not memory efficient but simple for tests */
AttributeElement elem_face_id, elem_uv; const AttributeDescriptor desc_face_id = find_attribute(kg, sd, ATTR_STD_PTEX_FACE_ID);
int offset_face_id = find_attribute(kg, sd, ATTR_STD_PTEX_FACE_ID, &elem_face_id); const AttributeDescriptor desc_uv = find_attribute(kg, sd, ATTR_STD_PTEX_UV);
int offset_uv = find_attribute(kg, sd, ATTR_STD_PTEX_UV, &elem_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; return false;
float3 uv3 = primitive_attribute_float3(kg, sd, elem_uv, offset_uv, NULL, NULL); float3 uv3 = primitive_attribute_float3(kg, sd, desc_uv, NULL, NULL);
float face_id_f = primitive_attribute_float(kg, sd, elem_face_id, offset_face_id, NULL, NULL); float face_id_f = primitive_attribute_float(kg, sd, desc_face_id, NULL, NULL);
*uv = make_float2(uv3.x, uv3.y); *uv = make_float2(uv3.x, uv3.y);
*face_id = (int)face_id_f; *face_id = (int)face_id_f;
@@ -132,11 +127,10 @@ ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
#endif #endif
/* try to create spherical tangent from generated coordinates */ /* try to create spherical tangent from generated coordinates */
AttributeElement attr_elem; const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_GENERATED);
int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED, &attr_elem);
if(attr_offset != ATTR_STD_NOT_FOUND) { if(desc.offset != ATTR_STD_NOT_FOUND) {
float3 data = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL); float3 data = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f); data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
object_normal_transform(kg, sd, &data); object_normal_transform(kg, sd, &data);
return cross(ccl_fetch(sd, N), normalize(cross(data, ccl_fetch(sd, N)))); 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; float3 motion_pre = center, motion_post = center;
/* deformation motion */ /* deformation motion */
AttributeElement elem; AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_MOTION_VERTEX_POSITION);
int offset = find_attribute(kg, sd, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
if(offset != ATTR_STD_NOT_FOUND) { if(desc.offset != ATTR_STD_NOT_FOUND) {
/* get motion info */ /* get motion info */
int numverts, numkeys; int numverts, numkeys;
object_motion_info(kg, ccl_fetch(sd, object), NULL, &numverts, &numkeys); object_motion_info(kg, ccl_fetch(sd, object), NULL, &numverts, &numkeys);
/* lookup attributes */ /* 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); desc.offset += (ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE)? numverts: numkeys;
motion_post = primitive_attribute_float3(kg, sd, elem, offset_next, NULL, NULL); motion_post = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
#ifdef __HAIR__ #ifdef __HAIR__
if(is_curve_primitive && (ccl_fetch(sd, flag) & SD_OBJECT_HAS_VERTEX_MOTION) == 0) { if(is_curve_primitive && (ccl_fetch(sd, flag) & SD_OBJECT_HAS_VERTEX_MOTION) == 0) {

View File

@@ -97,27 +97,27 @@ ccl_device_inline void subd_triangle_patch_corners(KernelGlobals *kg, int patch,
/* Reading attributes on various subdivision triangle elements */ /* 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); int patch = subd_triangle_patch(kg, sd);
if(elem == ATTR_ELEMENT_FACE) { if(desc.element == ATTR_ELEMENT_FACE) {
if(dx) *dx = 0.0f; if(dx) *dx = 0.0f;
if(dy) *dy = 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]; float2 uv[3];
subd_triangle_patch_uv(kg, sd, uv); subd_triangle_patch_uv(kg, sd, uv);
uint4 v = subd_triangle_patch_indices(kg, patch); uint4 v = subd_triangle_patch_indices(kg, patch);
float a, b, c; float a, b, c;
float f0 = kernel_tex_fetch(__attributes_float, offset + v.x); float f0 = kernel_tex_fetch(__attributes_float, desc.offset + v.x);
float f1 = kernel_tex_fetch(__attributes_float, offset + v.y); float f1 = kernel_tex_fetch(__attributes_float, desc.offset + v.y);
float f2 = kernel_tex_fetch(__attributes_float, offset + v.z); float f2 = kernel_tex_fetch(__attributes_float, desc.offset + v.z);
float f3 = kernel_tex_fetch(__attributes_float, offset + v.w); float f3 = kernel_tex_fetch(__attributes_float, desc.offset + v.w);
if(subd_triangle_patch_num_corners(kg, patch) != 4) { if(subd_triangle_patch_num_corners(kg, patch) != 4) {
f1 = (f1+f0)*0.5f; 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; 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]; int corners[4];
subd_triangle_patch_corners(kg, patch, corners); 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 a, b, c;
float f0 = kernel_tex_fetch(__attributes_float, corners[0] + offset); float f0 = kernel_tex_fetch(__attributes_float, corners[0] + desc.offset);
float f1 = kernel_tex_fetch(__attributes_float, corners[1] + offset); float f1 = kernel_tex_fetch(__attributes_float, corners[1] + desc.offset);
float f2 = kernel_tex_fetch(__attributes_float, corners[2] + offset); float f2 = kernel_tex_fetch(__attributes_float, corners[2] + desc.offset);
float f3 = kernel_tex_fetch(__attributes_float, corners[3] + offset); float f3 = kernel_tex_fetch(__attributes_float, corners[3] + desc.offset);
if(subd_triangle_patch_num_corners(kg, patch) != 4) { if(subd_triangle_patch_num_corners(kg, patch) != 4) {
f1 = (f1+f0)*0.5f; 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); 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(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
if(dy) *dy = 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]; float2 uv[3];
subd_triangle_patch_uv(kg, sd, uv); subd_triangle_patch_uv(kg, sd, uv);
uint4 v = subd_triangle_patch_indices(kg, patch); uint4 v = subd_triangle_patch_indices(kg, patch);
float3 a, b, c; float3 a, b, c;
float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + v.x)); float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.x));
float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + v.y)); float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.y));
float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + v.z)); float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.z));
float3 f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + v.w)); float3 f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.w));
if(subd_triangle_patch_num_corners(kg, patch) != 4) { if(subd_triangle_patch_num_corners(kg, patch) != 4) {
f1 = (f1+f0)*0.5f; 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; 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]; int corners[4];
subd_triangle_patch_corners(kg, patch, corners); 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 a, b, c;
float3 f0, f1, f2, f3; float3 f0, f1, f2, f3;
if(elem == ATTR_ELEMENT_CORNER) { if(desc.element == ATTR_ELEMENT_CORNER) {
f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[0] + offset)); f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[0] + desc.offset));
f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[1] + 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] + 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] + offset)); f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[3] + desc.offset));
} }
else { else {
f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[0] + 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] + 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] + 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] + offset)); f3 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[3] + desc.offset));
} }
if(subd_triangle_patch_num_corners(kg, patch) != 4) { if(subd_triangle_patch_num_corners(kg, patch) != 4) {

View File

@@ -105,20 +105,20 @@ ccl_device_inline void triangle_dPdudv(KernelGlobals *kg, int prim, ccl_addr_spa
/* Reading attributes on various triangle elements */ /* 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(dx) *dx = 0.0f;
if(dy) *dy = 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)); uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim));
float f0 = kernel_tex_fetch(__attributes_float, offset + tri_vindex.x); float f0 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.x);
float f1 = kernel_tex_fetch(__attributes_float, offset + tri_vindex.y); float f1 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.y);
float f2 = kernel_tex_fetch(__attributes_float, offset + tri_vindex.z); float f2 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.z);
#ifdef __RAY_DIFFERENTIALS__ #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; 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; 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) { else if(desc.element == ATTR_ELEMENT_CORNER) {
int tri = offset + ccl_fetch(sd, prim)*3; int tri = desc.offset + ccl_fetch(sd, prim)*3;
float f0 = kernel_tex_fetch(__attributes_float, tri + 0); float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
float f1 = kernel_tex_fetch(__attributes_float, tri + 1); float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
float f2 = kernel_tex_fetch(__attributes_float, tri + 2); 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(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
if(dy) *dy = 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)); 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 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x));
float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.y)); 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, offset + tri_vindex.z)); float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z));
#ifdef __RAY_DIFFERENTIALS__ #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; 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; 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) { else if(desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) {
int tri = offset + ccl_fetch(sd, prim)*3; int tri = desc.offset + ccl_fetch(sd, prim)*3;
float3 f0, f1, f2; 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)); f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1)); f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2)); f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));

View 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 /* todo: optimize this so it's just a single matrix multiplication when
* possible (not motion blur), or perhaps even just translation + scale */ * possible (not motion blur), or perhaps even just translation + scale */
AttributeElement attr_elem; const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM);
int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM, &attr_elem);
object_inverse_position_transform(kg, sd, &P); object_inverse_position_transform(kg, sd, &P);
if(attr_offset != ATTR_STD_NOT_FOUND) { if(desc.offset != ATTR_STD_NOT_FOUND) {
Transform tfm = primitive_attribute_matrix(kg, sd, attr_offset); Transform tfm = primitive_attribute_matrix(kg, sd, desc);
P = transform_point(&tfm, P); P = transform_point(&tfm, P);
} }
return 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); float3 P = volume_normalized_position(kg, sd, sd->P);
#ifdef __KERNEL_GPU__ #ifdef __KERNEL_GPU__
# if __CUDA_ARCH__ >= 300 # 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); float f = kernel_tex_image_interp_3d_float(tex, P.x, P.y, P.z);
float4 r = make_float4(f, f, f, 1.0); float4 r = make_float4(f, f, f, 1.0);
# else # 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 # endif
#else #else
float4 r; float4 r;
if(sd->flag & SD_VOLUME_CUBIC) 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 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 #endif
if(dx) *dx = 0.0f; 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)); 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); float3 P = volume_normalized_position(kg, sd, sd->P);
#ifdef __KERNEL_GPU__ #ifdef __KERNEL_GPU__
# if __CUDA_ARCH__ >= 300 # 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); float4 r = kernel_tex_image_interp_3d_float4(tex, P.x, P.y, P.z);
# else # 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 # endif
#else #else
float4 r; float4 r;
if(sd->flag & SD_VOLUME_CUBIC) 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 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 #endif
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f); if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);

View File

@@ -624,6 +624,12 @@ typedef enum AttributeStandard {
ATTR_STD_NOT_FOUND = ~0 ATTR_STD_NOT_FOUND = ~0
} AttributeStandard; } AttributeStandard;
typedef struct AttributeDescriptor {
AttributeElement element;
NodeAttributeType type;
int offset;
} AttributeDescriptor;
/* Closure data */ /* Closure data */
#ifdef __MULTI_CLOSURE__ #ifdef __MULTI_CLOSURE__

View File

@@ -59,8 +59,7 @@ struct OSLGlobals {
/* attributes */ /* attributes */
struct Attribute { struct Attribute {
TypeDesc type; TypeDesc type;
AttributeElement elem; AttributeDescriptor desc;
int offset;
ParamValue value; ParamValue value;
}; };

View File

@@ -554,13 +554,13 @@ static bool get_mesh_element_attribute(KernelGlobals *kg, const ShaderData *sd,
attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor)
{ {
float3 fval[3]; 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); (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
return set_attribute_float3(fval, type, derivatives, val); return set_attribute_float3(fval, type, derivatives, val);
} }
else if(attr.type == TypeDesc::TypeFloat) { else if(attr.type == TypeDesc::TypeFloat) {
float fval[3]; 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); (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
return set_attribute_float(fval, type, derivatives, val); 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) const TypeDesc& type, bool derivatives, void *val)
{ {
if(attr.type == TypeDesc::TypeMatrix) { 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); return set_attribute_matrix(tfm, type, val);
} }
else { else {
@@ -815,7 +815,7 @@ bool OSLRenderServices::get_attribute(ShaderData *sd, bool derivatives, ustring
if(it != attribute_map.end()) { if(it != attribute_map.end()) {
const OSLGlobals::Attribute& attr = it->second; const OSLGlobals::Attribute& attr = it->second;
if(attr.elem != ATTR_ELEMENT_OBJECT) { if(attr.desc.element != ATTR_ELEMENT_OBJECT) {
/* triangle and vertex attributes */ /* triangle and vertex attributes */
if(get_mesh_element_attribute(kg, sd, attr, type, derivatives, val)) if(get_mesh_element_attribute(kg, sd, attr, type, derivatives, val))
return true; return true;

View File

@@ -334,7 +334,7 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderConte
/* Attributes */ /* 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. */ /* for OSL, a hash map is used to lookup the attribute by name. */
int object = sd->object*ATTR_PRIM_TYPES; 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()) { if(it != attr_map.end()) {
const OSLGlobals::Attribute &osl_attr = it->second; 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 ATTR_STD_NOT_FOUND;
}
/* return result */ /* 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; return (int)ATTR_STD_NOT_FOUND;
}
} }
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -59,7 +59,7 @@ public:
static void eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx); static void eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx);
/* attributes */ /* 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 CCL_NAMESPACE_END

View File

@@ -18,70 +18,57 @@ CCL_NAMESPACE_BEGIN
/* Attribute Node */ /* 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, uint4 node, NodeAttributeType *type,
NodeAttributeType *mesh_type, AttributeElement *elem, int *offset, uint *out_offset) uint *out_offset)
{ {
*out_offset = node.z; *out_offset = node.z;
*type = (NodeAttributeType)node.w; *type = (NodeAttributeType)node.w;
AttributeDescriptor desc;
if(ccl_fetch(sd, object) != OBJECT_NONE) { if(ccl_fetch(sd, object) != OBJECT_NONE) {
/* find attribute by unique id */ desc = find_attribute(kg, sd, node.y);
uint id = node.y; if(desc.offset == ATTR_STD_NOT_FOUND) {
uint attr_offset = ccl_fetch(sd, object)*kernel_data.bvh.attributes_map_stride; desc.element = ATTR_ELEMENT_NONE;
attr_offset += attribute_primitive_type(kg, sd); desc.offset = 0;
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset); desc.type = (NodeAttributeType)node.w;
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);
} }
/* return result */
*elem = (AttributeElement)attr_map.y;
*offset = as_int(attr_map.z);
*mesh_type = (NodeAttributeType)attr_map.w;
} }
else { else {
/* background */ /* background */
*elem = ATTR_ELEMENT_NONE; desc.element = ATTR_ELEMENT_NONE;
*offset = 0; desc.offset = 0;
*mesh_type = (NodeAttributeType)node.w; desc.type = (NodeAttributeType)node.w;
} }
return desc;
} }
ccl_device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) ccl_device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{ {
NodeAttributeType type, mesh_type; NodeAttributeType type;
AttributeElement elem;
uint out_offset; uint out_offset;
int offset; AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
/* fetch and store attribute */ /* fetch and store attribute */
if(type == NODE_ATTR_FLOAT) { if(type == NODE_ATTR_FLOAT) {
if(mesh_type == NODE_ATTR_FLOAT) { if(desc.type == NODE_ATTR_FLOAT) {
float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL); float f = primitive_attribute_float(kg, sd, desc, NULL, NULL);
stack_store_float(stack, out_offset, f); stack_store_float(stack, out_offset, f);
} }
else { 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)); stack_store_float(stack, out_offset, average(f));
} }
} }
else { else {
if(mesh_type == NODE_ATTR_FLOAT3) { if(desc.type == NODE_ATTR_FLOAT3) {
float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL); float3 f = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
stack_store_float3(stack, out_offset, f); stack_store_float3(stack, out_offset, f);
} }
else { 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)); stack_store_float3(stack, out_offset, make_float3(f, f, f));
} }
} }
@@ -94,35 +81,32 @@ ccl_device_noinline
#endif #endif
void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{ {
NodeAttributeType type, mesh_type; NodeAttributeType type;
AttributeElement elem;
uint out_offset; uint out_offset;
int offset; AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
/* fetch and store attribute */ /* fetch and store attribute */
if(type == NODE_ATTR_FLOAT) { if(type == NODE_ATTR_FLOAT) {
if(mesh_type == NODE_ATTR_FLOAT) { if(desc.type == NODE_ATTR_FLOAT) {
float dx; 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); stack_store_float(stack, out_offset, f+dx);
} }
else { else {
float3 dx; 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)); stack_store_float(stack, out_offset, average(f+dx));
} }
} }
else { else {
if(mesh_type == NODE_ATTR_FLOAT3) { if(desc.type == NODE_ATTR_FLOAT3) {
float3 dx; 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); stack_store_float3(stack, out_offset, f+dx);
} }
else { else {
float dx; 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)); 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, float *stack,
uint4 node) uint4 node)
{ {
NodeAttributeType type, mesh_type; NodeAttributeType type;
AttributeElement elem;
uint out_offset; uint out_offset;
int offset; AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
/* fetch and store attribute */ /* fetch and store attribute */
if(type == NODE_ATTR_FLOAT) { if(type == NODE_ATTR_FLOAT) {
if(mesh_type == NODE_ATTR_FLOAT) { if(desc.type == NODE_ATTR_FLOAT) {
float dy; 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); stack_store_float(stack, out_offset, f+dy);
} }
else { else {
float3 dy; 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)); stack_store_float(stack, out_offset, average(f+dy));
} }
} }
else { else {
if(mesh_type == NODE_ATTR_FLOAT3) { if(desc.type == NODE_ATTR_FLOAT3) {
float3 dy; 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); stack_store_float3(stack, out_offset, f+dy);
} }
else { else {
float dy; 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)); stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy));
} }
} }

View File

@@ -287,23 +287,22 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
} }
/* first try to get tangent attribute */ /* first try to get tangent attribute */
AttributeElement attr_elem, attr_sign_elem, attr_normal_elem; const AttributeDescriptor attr = find_attribute(kg, sd, node.z);
int attr_offset = find_attribute(kg, sd, node.z, &attr_elem); const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.w);
int attr_sign_offset = find_attribute(kg, sd, node.w, &attr_sign_elem); const AttributeDescriptor attr_normal = find_attribute(kg, sd, ATTR_STD_VERTEX_NORMAL);
int attr_normal_offset = find_attribute(kg, sd, ATTR_STD_VERTEX_NORMAL, &attr_normal_elem);
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)); stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
return; return;
} }
/* get _unnormalized_ interpolated normal and tangent */ /* get _unnormalized_ interpolated normal and tangent */
float3 tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL); float3 tangent = primitive_attribute_float3(kg, sd, attr, NULL, NULL);
float sign = primitive_attribute_float(kg, sd, attr_sign_elem, attr_sign_offset, NULL, NULL); float sign = primitive_attribute_float(kg, sd, attr_sign, NULL, NULL);
float3 normal; float3 normal;
if(ccl_fetch(sd, shader) & SHADER_SMOOTH_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 { else {
normal = ccl_fetch(sd, Ng); 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) { if(direction_type == NODE_TANGENT_UVMAP) {
/* UV map */ /* UV map */
AttributeElement attr_elem; const AttributeDescriptor desc = find_attribute(kg, sd, node.z);
int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
if(attr_offset == ATTR_STD_NOT_FOUND) if(desc.offset == ATTR_STD_NOT_FOUND)
tangent = make_float3(0.0f, 0.0f, 0.0f); tangent = make_float3(0.0f, 0.0f, 0.0f);
else else
tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL); tangent = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
} }
else { else {
/* radial */ /* radial */
AttributeElement attr_elem; const AttributeDescriptor desc = find_attribute(kg, sd, node.z);
int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
float3 generated; float3 generated;
if(attr_offset == ATTR_STD_NOT_FOUND) if(desc.offset == ATTR_STD_NOT_FOUND)
generated = ccl_fetch(sd, P); generated = ccl_fetch(sd, P);
else 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) if(axis == NODE_TANGENT_AXIS_X)
tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f)); tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f));

View File

@@ -517,16 +517,19 @@ AttributeRequest::AttributeRequest(ustring name_)
std = ATTR_STD_NONE; std = ATTR_STD_NONE;
triangle_type = TypeDesc::TypeFloat; triangle_type = TypeDesc::TypeFloat;
triangle_element = ATTR_ELEMENT_NONE; triangle_desc.element = ATTR_ELEMENT_NONE;
triangle_offset = 0; triangle_desc.offset = 0;
triangle_desc.type = NODE_ATTR_FLOAT;
curve_type = TypeDesc::TypeFloat; curve_type = TypeDesc::TypeFloat;
curve_element = ATTR_ELEMENT_NONE; curve_desc.element = ATTR_ELEMENT_NONE;
curve_offset = 0; curve_desc.offset = 0;
curve_desc.type = NODE_ATTR_FLOAT;
subd_type = TypeDesc::TypeFloat; subd_type = TypeDesc::TypeFloat;
subd_element = ATTR_ELEMENT_NONE; subd_desc.element = ATTR_ELEMENT_NONE;
subd_offset = 0; subd_desc.offset = 0;
subd_desc.type = NODE_ATTR_FLOAT;
} }
AttributeRequest::AttributeRequest(AttributeStandard std_) AttributeRequest::AttributeRequest(AttributeStandard std_)
@@ -535,16 +538,19 @@ AttributeRequest::AttributeRequest(AttributeStandard std_)
std = std_; std = std_;
triangle_type = TypeDesc::TypeFloat; triangle_type = TypeDesc::TypeFloat;
triangle_element = ATTR_ELEMENT_NONE; triangle_desc.element = ATTR_ELEMENT_NONE;
triangle_offset = 0; triangle_desc.offset = 0;
triangle_desc.type = NODE_ATTR_FLOAT;
curve_type = TypeDesc::TypeFloat; curve_type = TypeDesc::TypeFloat;
curve_element = ATTR_ELEMENT_NONE; curve_desc.element = ATTR_ELEMENT_NONE;
curve_offset = 0; curve_desc.offset = 0;
curve_desc.type = NODE_ATTR_FLOAT;
subd_type = TypeDesc::TypeFloat; subd_type = TypeDesc::TypeFloat;
subd_element = ATTR_ELEMENT_NONE; subd_desc.element = ATTR_ELEMENT_NONE;
subd_offset = 0; subd_desc.offset = 0;
subd_desc.type = NODE_ATTR_FLOAT;
} }
/* AttributeRequestSet */ /* AttributeRequestSet */

View File

@@ -135,8 +135,7 @@ public:
/* temporary variables used by MeshManager */ /* temporary variables used by MeshManager */
TypeDesc triangle_type, curve_type, subd_type; TypeDesc triangle_type, curve_type, subd_type;
AttributeElement triangle_element, curve_element, subd_element; AttributeDescriptor triangle_desc, curve_desc, subd_desc;
int triangle_offset, curve_offset, subd_offset;
explicit AttributeRequest(ustring name_); explicit AttributeRequest(ustring name_);
explicit AttributeRequest(AttributeStandard std); explicit AttributeRequest(AttributeStandard std);

View File

@@ -831,9 +831,9 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
OSLGlobals::Attribute osl_attr; OSLGlobals::Attribute osl_attr;
osl_attr.type = attr.type(); osl_attr.type = attr.type();
osl_attr.elem = ATTR_ELEMENT_OBJECT; osl_attr.desc.element = ATTR_ELEMENT_OBJECT;
osl_attr.value = attr; 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_TRIANGLE][attr.name()] = osl_attr;
og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][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) { foreach(AttributeRequest& req, attributes.requests) {
OSLGlobals::Attribute osl_attr; OSLGlobals::Attribute osl_attr;
if(req.triangle_element != ATTR_ELEMENT_NONE) { if(req.triangle_desc.element != ATTR_ELEMENT_NONE) {
osl_attr.elem = req.triangle_element; osl_attr.desc = req.triangle_desc;
osl_attr.offset = req.triangle_offset;
if(req.triangle_type == TypeDesc::TypeFloat) if(req.triangle_type == TypeDesc::TypeFloat)
osl_attr.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) { if(req.curve_desc.element != ATTR_ELEMENT_NONE) {
osl_attr.elem = req.curve_element; osl_attr.desc = req.curve_desc;
osl_attr.offset = req.curve_offset;
if(req.curve_type == TypeDesc::TypeFloat) if(req.curve_type == TypeDesc::TypeFloat)
osl_attr.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) { if(req.subd_desc.element != ATTR_ELEMENT_NONE) {
osl_attr.elem = req.subd_element; osl_attr.desc = req.subd_desc;
osl_attr.offset = req.subd_offset;
if(req.subd_type == TypeDesc::TypeFloat) if(req.subd_type == TypeDesc::TypeFloat)
osl_attr.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()) { if(mesh->num_triangles()) {
attr_map[index].x = id; attr_map[index].x = id;
attr_map[index].y = req.triangle_element; attr_map[index].y = req.triangle_desc.element;
attr_map[index].z = as_uint(req.triangle_offset); attr_map[index].z = as_uint(req.triangle_desc.offset);
if(req.triangle_type == TypeDesc::TypeFloat) if(req.triangle_type == TypeDesc::TypeFloat)
attr_map[index].w = NODE_ATTR_FLOAT; 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()) { if(mesh->num_curves()) {
attr_map[index].x = id; attr_map[index].x = id;
attr_map[index].y = req.curve_element; attr_map[index].y = req.curve_desc.element;
attr_map[index].z = as_uint(req.curve_offset); attr_map[index].z = as_uint(req.curve_desc.offset);
if(req.curve_type == TypeDesc::TypeFloat) if(req.curve_type == TypeDesc::TypeFloat)
attr_map[index].w = NODE_ATTR_FLOAT; 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()) { if(mesh->subd_faces.size()) {
attr_map[index].x = id; attr_map[index].x = id;
attr_map[index].y = req.subd_element; attr_map[index].y = req.subd_desc.element;
attr_map[index].z = as_uint(req.subd_offset); attr_map[index].z = as_uint(req.subd_desc.offset);
if(req.subd_type == TypeDesc::TypeFloat) if(req.subd_type == TypeDesc::TypeFloat)
attr_map[index].w = NODE_ATTR_FLOAT; attr_map[index].w = NODE_ATTR_FLOAT;
@@ -1069,17 +1066,19 @@ static void update_attribute_element_offset(Mesh *mesh,
Attribute *mattr, Attribute *mattr,
AttributePrimitive prim, AttributePrimitive prim,
TypeDesc& type, TypeDesc& type,
int& offset, AttributeDescriptor& desc)
AttributeElement& element)
{ {
if(mattr) { if(mattr) {
/* store element and type */ /* store element and type */
element = mattr->element; desc.element = mattr->element;
type = mattr->type; type = mattr->type;
/* store attribute data in arrays */ /* store attribute data in arrays */
size_t size = mattr->element_size(mesh, prim); size_t size = mattr->element_size(mesh, prim);
AttributeElement& element = desc.element;
int& offset = desc.offset;
if(mattr->element == ATTR_ELEMENT_VOXEL) { if(mattr->element == ATTR_ELEMENT_VOXEL) {
/* store slot in offset value */ /* store slot in offset value */
VoxelAttribute *voxel_data = mattr->data_voxel(); VoxelAttribute *voxel_data = mattr->data_voxel();
@@ -1153,8 +1152,8 @@ static void update_attribute_element_offset(Mesh *mesh,
} }
else { else {
/* attribute not found */ /* attribute not found */
element = ATTR_ELEMENT_NONE; desc.element = ATTR_ELEMENT_NONE;
offset = 0; desc.offset = 0;
} }
} }
@@ -1243,8 +1242,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
triangle_mattr, triangle_mattr,
ATTR_PRIM_TRIANGLE, ATTR_PRIM_TRIANGLE,
req.triangle_type, req.triangle_type,
req.triangle_offset, req.triangle_desc);
req.triangle_element);
update_attribute_element_offset(mesh, update_attribute_element_offset(mesh,
attr_float, attr_float_offset, attr_float, attr_float_offset,
@@ -1253,8 +1251,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
curve_mattr, curve_mattr,
ATTR_PRIM_CURVE, ATTR_PRIM_CURVE,
req.curve_type, req.curve_type,
req.curve_offset, req.curve_desc);
req.curve_element);
update_attribute_element_offset(mesh, update_attribute_element_offset(mesh,
attr_float, attr_float_offset, attr_float, attr_float_offset,
@@ -1263,8 +1260,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
subd_mattr, subd_mattr,
ATTR_PRIM_SUBD, ATTR_PRIM_SUBD,
req.subd_type, req.subd_type,
req.subd_offset, req.subd_desc);
req.subd_element);
if(progress.get_cancel()) return; if(progress.get_cancel()) return;
} }