From d58b55b55a0197c397810766446f18d64a8d4a6b Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Mon, 26 Oct 2020 18:23:40 +0100 Subject: Cycles: internal support for float4 geometry attributes Previously only float3 and byte4 was supported. Ref D2057 --- intern/cycles/kernel/geom/geom_patch.h | 37 +++++++ intern/cycles/kernel/geom/geom_subd_triangle.h | 75 +++++++++++--- intern/cycles/kernel/geom/geom_triangle.h | 37 +++++-- intern/cycles/kernel/osl/osl_services.cpp | 137 ++++++++++++++++++++++--- intern/cycles/kernel/svm/svm_attribute.h | 6 +- intern/cycles/kernel/svm/svm_types.h | 1 + 6 files changed, 254 insertions(+), 39 deletions(-) (limited to 'intern/cycles/kernel') diff --git a/intern/cycles/kernel/geom/geom_patch.h b/intern/cycles/kernel/geom/geom_patch.h index 8b4b91b96c8..1de05fa9e0d 100644 --- a/intern/cycles/kernel/geom/geom_patch.h +++ b/intern/cycles/kernel/geom/geom_patch.h @@ -380,6 +380,43 @@ ccl_device float3 patch_eval_float3(KernelGlobals *kg, return val; } +ccl_device float4 patch_eval_float4(KernelGlobals *kg, + const ShaderData *sd, + int offset, + int patch, + float u, + float v, + int channel, + float4 *du, + float4 *dv) +{ + int indices[PATCH_MAX_CONTROL_VERTS]; + float weights[PATCH_MAX_CONTROL_VERTS]; + float weights_du[PATCH_MAX_CONTROL_VERTS]; + float weights_dv[PATCH_MAX_CONTROL_VERTS]; + + int num_control = patch_eval_control_verts( + kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv); + + float4 val = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + if (du) + *du = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + if (dv) + *dv = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + + for (int i = 0; i < num_control; i++) { + float4 v = kernel_tex_fetch(__attributes_float3, offset + indices[i]); + + val += v * weights[i]; + if (du) + *du += v * weights_du[i]; + if (dv) + *dv += v * weights_dv[i]; + } + + return val; +} + ccl_device float4 patch_eval_uchar4(KernelGlobals *kg, const ShaderData *sd, int offset, diff --git a/intern/cycles/kernel/geom/geom_subd_triangle.h b/intern/cycles/kernel/geom/geom_subd_triangle.h index 3eef9857ae3..2a569852659 100644 --- a/intern/cycles/kernel/geom/geom_subd_triangle.h +++ b/intern/cycles/kernel/geom/geom_subd_triangle.h @@ -539,9 +539,13 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals *kg, /* p is [s, t] */ float2 p = dpdu * sd->u + dpdv * sd->v + uv[2]; - float4 dads, dadt; - - float4 a = patch_eval_uchar4(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt); + float4 a, dads, dadt; + if (desc.type == NODE_ATTR_RGBA) { + a = patch_eval_uchar4(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt); + } + else { + a = patch_eval_float4(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt); + } # ifdef __RAY_DIFFERENTIALS__ if (dx || dy) { @@ -570,25 +574,70 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals *kg, } } # endif + return a; } else #endif /* __PATCH_EVAL__ */ - if (desc.element == ATTR_ELEMENT_CORNER_BYTE) { + if (desc.element == ATTR_ELEMENT_FACE) { + if (dx) + *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + if (dy) + *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + + return kernel_tex_fetch(__attributes_float3, + desc.offset + subd_triangle_patch_face(kg, patch)); + } + 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); + + float4 f0 = kernel_tex_fetch(__attributes_float3, desc.offset + v.x); + float4 f1 = kernel_tex_fetch(__attributes_float3, desc.offset + v.y); + float4 f2 = kernel_tex_fetch(__attributes_float3, desc.offset + v.z); + float4 f3 = kernel_tex_fetch(__attributes_float3, desc.offset + v.w); + + if (subd_triangle_patch_num_corners(kg, patch) != 4) { + f1 = (f1 + f0) * 0.5f; + f3 = (f3 + f0) * 0.5f; + } + + float4 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y); + float4 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y); + float4 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y); + +#ifdef __RAY_DIFFERENTIALS__ + if (dx) + *dx = sd->du.dx * a + sd->dv.dx * b - (sd->du.dx + sd->dv.dx) * c; + if (dy) + *dy = sd->du.dy * a + sd->dv.dy * b - (sd->du.dy + sd->dv.dy) * c; +#endif + + return sd->u * a + sd->v * b + (1.0f - sd->u - sd->v) * c; + } + else if (desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) { float2 uv[3]; subd_triangle_patch_uv(kg, sd, uv); int corners[4]; subd_triangle_patch_corners(kg, patch, corners); - float4 f0 = color_uchar4_to_float4( - kernel_tex_fetch(__attributes_uchar4, corners[0] + desc.offset)); - float4 f1 = color_uchar4_to_float4( - kernel_tex_fetch(__attributes_uchar4, corners[1] + desc.offset)); - float4 f2 = color_uchar4_to_float4( - kernel_tex_fetch(__attributes_uchar4, corners[2] + desc.offset)); - float4 f3 = color_uchar4_to_float4( - kernel_tex_fetch(__attributes_uchar4, corners[3] + desc.offset)); + float4 f0, f1, f2, f3; + + if (desc.element == ATTR_ELEMENT_CORNER_BYTE) { + f0 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[0] + desc.offset)); + f1 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[1] + desc.offset)); + f2 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[2] + desc.offset)); + f3 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, corners[3] + desc.offset)); + } + else { + f0 = kernel_tex_fetch(__attributes_float3, corners[0] + desc.offset); + f1 = kernel_tex_fetch(__attributes_float3, corners[1] + desc.offset); + f2 = kernel_tex_fetch(__attributes_float3, corners[2] + desc.offset); + f3 = kernel_tex_fetch(__attributes_float3, corners[3] + desc.offset); + } if (subd_triangle_patch_num_corners(kg, patch) != 4) { f1 = (f1 + f0) * 0.5f; @@ -614,7 +663,7 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals *kg, if (dy) *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - return color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, desc.offset)); + return kernel_tex_fetch(__attributes_float3, desc.offset); } else { if (dx) diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h index 0278f3ade8e..45fd761b13f 100644 --- a/intern/cycles/kernel/geom/geom_triangle.h +++ b/intern/cycles/kernel/geom/geom_triangle.h @@ -312,20 +312,43 @@ ccl_device float4 triangle_attribute_float4(KernelGlobals *kg, float4 *dx, float4 *dy) { - if (desc.element == ATTR_ELEMENT_CORNER_BYTE || desc.element == ATTR_ELEMENT_VERTEX) { + if (desc.element == ATTR_ELEMENT_FACE) { + if (dx) + *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + if (dy) + *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + + return kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim); + } + else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) { + uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); + + float4 f0 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x); + float4 f1 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y); + float4 f2 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z); + +#ifdef __RAY_DIFFERENTIALS__ + if (dx) + *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2; + if (dy) + *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2; +#endif + + return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2; + } + else if (desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) { + int tri = desc.offset + sd->prim * 3; float4 f0, f1, f2; if (desc.element == ATTR_ELEMENT_CORNER_BYTE) { - int tri = desc.offset + sd->prim * 3; f0 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 0)); f1 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 1)); f2 = color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 2)); } else { - uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim); - f0 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x); - f1 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y); - f2 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z); + f0 = kernel_tex_fetch(__attributes_float3, tri + 0); + f1 = kernel_tex_fetch(__attributes_float3, tri + 1); + f2 = kernel_tex_fetch(__attributes_float3, tri + 2); } #ifdef __RAY_DIFFERENTIALS__ @@ -343,7 +366,7 @@ ccl_device float4 triangle_attribute_float4(KernelGlobals *kg, if (dy) *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - return color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, desc.offset)); + return kernel_tex_fetch(__attributes_float3, desc.offset); } else { if (dx) diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 7d1d1ae20c1..2a4a1dfe325 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -403,8 +403,28 @@ bool OSLRenderServices::get_array_attribute(OSL::ShaderGlobals *sg, static bool set_attribute_float2(float2 f[3], TypeDesc type, bool derivatives, void *val) { - if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || - type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { + if (type == TypeFloatArray4) { + float *fval = (float *)val; + fval[0] = f[0].x; + fval[1] = f[0].y; + fval[2] = 0.0f; + fval[3] = 1.0f; + + if (derivatives) { + fval[4] = f[1].x; + fval[5] = f[1].y; + fval[6] = 0.0f; + fval[7] = 0.0f; + + fval[8] = f[2].x; + fval[9] = f[2].y; + fval[10] = 0.0f; + fval[11] = 0.0f; + } + return true; + } + else if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || + type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { float *fval = (float *)val; fval[0] = f[0].x; @@ -438,10 +458,41 @@ static bool set_attribute_float2(float2 f[3], TypeDesc type, bool derivatives, v return false; } +static bool set_attribute_float2(float2 f, TypeDesc type, bool derivatives, void *val) +{ + float2 fv[3]; + + fv[0] = f; + fv[1] = make_float2(0.0f, 0.0f); + fv[2] = make_float2(0.0f, 0.0f); + + return set_attribute_float2(fv, type, derivatives, val); +} + static bool set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val) { - if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || - type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { + if (type == TypeFloatArray4) { + float *fval = (float *)val; + fval[0] = f[0].x; + fval[1] = f[0].y; + fval[2] = f[0].z; + fval[3] = 1.0f; + + if (derivatives) { + fval[4] = f[1].x; + fval[5] = f[1].y; + fval[6] = f[1].z; + fval[7] = 0.0f; + + fval[8] = f[2].x; + fval[9] = f[2].y; + fval[10] = f[2].z; + fval[11] = 0.0f; + } + return true; + } + else if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || + type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { float *fval = (float *)val; fval[0] = f[0].x; @@ -545,14 +596,45 @@ static bool set_attribute_float4(float4 f[3], TypeDesc type, bool derivatives, v return false; } +static bool set_attribute_float4(float4 f, TypeDesc type, bool derivatives, void *val) +{ + float4 fv[3]; + + fv[0] = f; + fv[1] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + fv[2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + + return set_attribute_float4(fv, type, derivatives, val); +} + static bool set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val) { - if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || - type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { + if (type == TypeFloatArray4) { float *fval = (float *)val; fval[0] = f[0]; - fval[1] = f[1]; - fval[2] = f[2]; + fval[1] = f[0]; + fval[2] = f[0]; + fval[3] = 1.0f; + + if (derivatives) { + fval[4] = f[1]; + fval[5] = f[1]; + fval[6] = f[1]; + fval[7] = 0.0f; + + fval[8] = f[2]; + fval[9] = f[2]; + fval[10] = f[2]; + fval[11] = 0.0f; + } + return true; + } + else if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || + type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { + float *fval = (float *)val; + fval[0] = f[0]; + fval[1] = f[0]; + fval[2] = f[0]; if (derivatives) { fval[3] = f[1]; @@ -709,7 +791,7 @@ static bool get_primitive_attribute(KernelGlobals *kg, } return set_attribute_float(fval, type, derivatives, val); } - else if (attr.type == TypeRGBA) { + else if (attr.type == TypeDesc::TypeFloat4 || attr.type == TypeRGBA) { float4 fval[3]; if (primitive_is_volume_attribute(sd, attr.desc)) { memset(fval, 0, sizeof(fval)); @@ -742,13 +824,37 @@ static bool get_mesh_attribute(KernelGlobals *kg, } } -static void get_object_attribute(const OSLGlobals::Attribute &attr, bool derivatives, void *val) +static bool get_object_attribute(const OSLGlobals::Attribute &attr, + TypeDesc type, + bool derivatives, + void *val) { - size_t datasize = attr.value.datasize(); + if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || + attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) { + return set_attribute_float3(*(float3 *)attr.value.data(), type, derivatives, val); + } + else if (attr.type == TypeFloat2) { + return set_attribute_float2(*(float2 *)attr.value.data(), type, derivatives, val); + } + else if (attr.type == TypeDesc::TypeFloat) { + return set_attribute_float(*(float *)attr.value.data(), type, derivatives, val); + } + else if (attr.type == TypeRGBA || attr.type == TypeDesc::TypeFloat4) { + return set_attribute_float4(*(float4 *)attr.value.data(), type, derivatives, val); + } + else if (attr.type == type) { + size_t datasize = attr.value.datasize(); - memcpy(val, attr.value.data(), datasize); - if (derivatives) - memset((char *)val + datasize, 0, datasize * 2); + memcpy(val, attr.value.data(), datasize); + if (derivatives) { + memset((char *)val + datasize, 0, datasize * 2); + } + + return true; + } + else { + return false; + } } bool OSLRenderServices::get_object_standard_attribute( @@ -1011,8 +1117,7 @@ bool OSLRenderServices::get_attribute( } else { /* object attribute */ - get_object_attribute(attr, derivatives, val); - return true; + return get_object_attribute(attr, type, derivatives, val); } } else { diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h index e26a85f5b36..079aac6ae44 100644 --- a/intern/cycles/kernel/svm/svm_attribute.h +++ b/intern/cycles/kernel/svm/svm_attribute.h @@ -87,7 +87,7 @@ ccl_device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, u stack_store_float3(stack, out_offset, make_float3(f.x, f.y, 0.0f)); } } - else if (desc.type == NODE_ATTR_RGBA) { + else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) { float4 f = primitive_surface_attribute_float4(kg, sd, desc, NULL, NULL); if (type == NODE_ATTR_FLOAT) { stack_store_float(stack, out_offset, average(float4_to_float3(f))); @@ -147,7 +147,7 @@ ccl_device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float * stack_store_float3(stack, out_offset, make_float3(f.x + dx.x, f.y + dx.y, 0.0f)); } } - else if (desc.type == NODE_ATTR_RGBA) { + else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) { float4 dx; float4 f = primitive_surface_attribute_float4(kg, sd, desc, &dx, NULL); if (type == NODE_ATTR_FLOAT) { @@ -209,7 +209,7 @@ ccl_device void svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float * stack_store_float3(stack, out_offset, make_float3(f.x + dy.x, f.y + dy.y, 0.0f)); } } - else if (desc.type == NODE_ATTR_RGBA) { + else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) { float4 dy; float4 f = primitive_surface_attribute_float4(kg, sd, desc, NULL, &dy); if (type == NODE_ATTR_FLOAT) { diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index f1ebb37e23e..cd32e0404b5 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -161,6 +161,7 @@ typedef enum NodeAttributeType { NODE_ATTR_FLOAT = 0, NODE_ATTR_FLOAT2, NODE_ATTR_FLOAT3, + NODE_ATTR_FLOAT4, NODE_ATTR_RGBA, NODE_ATTR_MATRIX } NodeAttributeType; -- cgit v1.2.3