Commit: b2933ff1412fab809bc639cdc99c6b74750323ee
Author: Mai Lavelle
Date:   Wed Jul 13 20:23:42 2016 -0400
Branches: temp-cycles-microdisplacement
https://developer.blender.org/rBb2933ff1412fab809bc639cdc99c6b74750323ee

Reduce number of calls to patch_eval_*

This alleviates a ~5% performance regression caused by calling patch_eval_*
functions multiple times to calculate differentials. Differentials for
subdivided attributes are now calculated directly from the limit.

Thanks to Lukas Stockner for checking my math.

===================================================================

M       intern/cycles/kernel/geom/geom_patch.h
M       intern/cycles/kernel/geom/geom_triangle.h

===================================================================

diff --git a/intern/cycles/kernel/geom/geom_patch.h 
b/intern/cycles/kernel/geom/geom_patch.h
index 65fa41c..6a0ff5a 100644
--- a/intern/cycles/kernel/geom/geom_patch.h
+++ b/intern/cycles/kernel/geom/geom_patch.h
@@ -213,6 +213,11 @@ ccl_device_inline void patch_eval_basis(KernelGlobals *kg, 
const PatchHandle *ha
        uint patch_bits = kernel_tex_fetch(__patches, handle->patch_index + 1); 
/* read patch param */
        float d_scale = 1 << patch_eval_depth(patch_bits);
 
+       bool non_quad_root = (patch_bits >> 4) & 0x1;
+       if(non_quad_root) {
+               d_scale *= 0.5f;
+       }
+
        patch_eval_normalize_coords(patch_bits, &u, &v);
 
        /* XXX: regular patches only for now. */
@@ -266,6 +271,8 @@ ccl_device float patch_eval_float(KernelGlobals *kg, const 
ShaderData *sd, int o
                                                   indices, weights, 
weights_du, weights_dv);
 
        float val = 0.0f;
+       if(du) *du = 0.0f;
+       if(dv) *dv = 0.0f;
 
        for(int i = 0; i < num_control; i++) {
                float v = kernel_tex_fetch(__attributes_float, offset + 
indices[i]);
@@ -291,6 +298,8 @@ ccl_device float3 patch_eval_float3(KernelGlobals *kg, 
const ShaderData *sd, int
                                                   indices, weights, 
weights_du, weights_dv);
 
        float3 val = make_float3(0.0f, 0.0f, 0.0f);
+       if(du) *du = make_float3(0.0f, 0.0f, 0.0f);
+       if(dv) *dv = make_float3(0.0f, 0.0f, 0.0f);
 
        for(int i = 0; i < num_control; i++) {
                float3 v = 
float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + indices[i]));
@@ -316,6 +325,8 @@ ccl_device float3 patch_eval_uchar4(KernelGlobals *kg, 
const ShaderData *sd, int
                                                   indices, weights, 
weights_du, weights_dv);
 
        float3 val = make_float3(0.0f, 0.0f, 0.0f);
+       if(du) *du = make_float3(0.0f, 0.0f, 0.0f);
+       if(dv) *dv = make_float3(0.0f, 0.0f, 0.0f);
 
        for(int i = 0; i < num_control; i++) {
                float3 v = 
color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, offset + indices[i]));
diff --git a/intern/cycles/kernel/geom/geom_triangle.h 
b/intern/cycles/kernel/geom/geom_triangle.h
index e211534..9181d01 100644
--- a/intern/cycles/kernel/geom/geom_triangle.h
+++ b/intern/cycles/kernel/geom/geom_triangle.h
@@ -283,7 +283,50 @@ ccl_device float 
subd_triangle_attribute_float(KernelGlobals *kg, const ShaderDa
 {
        int patch = subd_triangle_patch(kg, sd);
 
-       if(desc->element == ATTR_ELEMENT_FACE) {
+       if(desc->flags & ATTR_SUBDIVIDED) {
+               float2 uv[3];
+               subd_triangle_patch_uv(kg, sd, uv);
+
+               float2 dpdu = uv[0] - uv[2];
+               float2 dpdv = uv[1] - uv[2];
+
+               /* p is [s, t] */
+               float2 p = dpdu * ccl_fetch(sd, u) + dpdv * ccl_fetch(sd, v) + 
uv[2];
+
+               float a, dads, dadt;
+               a = patch_eval_float(kg, sd, desc->offset, patch, p.x, p.y, 0, 
&dads, &dadt);
+
+#ifdef __RAY_DIFFERENTIALS__
+               if(dx || dy) {
+                       float dsdu = dpdu.x;
+                       float dtdu = dpdu.y;
+                       float dsdv = dpdv.x;
+                       float dtdv = dpdv.y;
+
+                       if(dx) {
+                               float dudx = ccl_fetch(sd, du).dx;
+                               float dvdx = ccl_fetch(sd, dv).dx;
+
+                               float dsdx = dsdu*dudx + dsdv*dvdx;
+                               float dtdx = dtdu*dudx + dtdv*dvdx;
+
+                               *dx = dads*dsdx + dadt*dtdx;
+                       }
+                       if(dy) {
+                               float dudy = ccl_fetch(sd, du).dy;
+                               float dvdy = ccl_fetch(sd, dv).dy;
+
+                               float dsdy = dsdu*dudy + dsdv*dvdy;
+                               float dtdy = dtdu*dudy + dtdv*dvdy;
+
+                               *dy = dads*dsdy + dadt*dtdy;
+                       }
+               }
+#endif
+
+               return a;
+       }
+       else if(desc->element == ATTR_ELEMENT_FACE) {
                if(dx) *dx = 0.0f;
                if(dy) *dy = 0.0f;
 
@@ -293,31 +336,22 @@ ccl_device float 
subd_triangle_attribute_float(KernelGlobals *kg, const ShaderDa
                float2 uv[3];
                subd_triangle_patch_uv(kg, sd, uv);
 
-               float a, b, c;
+               uint4 v = subd_triangle_patch_indices(kg, patch);
 
-               if(desc->flags & ATTR_SUBDIVIDED) {
-                       a = patch_eval_float(kg, sd, desc->offset, patch, 
uv[0].x, uv[0].y, 0, NULL, NULL);
-                       b = patch_eval_float(kg, sd, desc->offset, patch, 
uv[1].x, uv[1].y, 0, NULL, NULL);
-                       c = patch_eval_float(kg, sd, desc->offset, patch, 
uv[2].x, uv[2].y, 0, NULL, NULL);
-               }
-               else {
-                       uint4 v = subd_triangle_patch_indices(kg, patch);
+               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);
 
-                       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;
-                               f3 = (f3+f0)*0.5f;
-                       }
-
-                       a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), 
uv[0].y);
-                       b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), 
uv[1].y);
-                       c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), 
uv[2].y);
+               if(subd_triangle_patch_num_corners(kg, patch) != 4) {
+                       f1 = (f1+f0)*0.5f;
+                       f3 = (f3+f0)*0.5f;
                }
 
+               float a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), 
uv[0].y);
+               float b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), 
uv[1].y);
+               float c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), 
uv[2].y);
+
 #ifdef __RAY_DIFFERENTIALS__
                if(dx) *dx = ccl_fetch(sd, du).dx*a + ccl_fetch(sd, dv).dx*b - 
(ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*c;
                if(dy) *dy = ccl_fetch(sd, du).dy*a + ccl_fetch(sd, dv).dy*b - 
(ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*c;
@@ -329,32 +363,23 @@ ccl_device float 
subd_triangle_attribute_float(KernelGlobals *kg, const ShaderDa
                float2 uv[3];
                subd_triangle_patch_uv(kg, sd, uv);
 
-               float a, b, c;
-
-               if(desc->flags & ATTR_SUBDIVIDED) {
-                       a = patch_eval_float(kg, sd, desc->offset, patch, 
uv[0].x, uv[0].y, 0, NULL, NULL);
-                       b = patch_eval_float(kg, sd, desc->offset, patch, 
uv[1].x, uv[1].y, 0, NULL, NULL);
-                       c = patch_eval_float(kg, sd, desc->offset, patch, 
uv[2].x, uv[2].y, 0, NULL, NULL);
-               }
-               else {
-                       int corners[4];
-                       subd_triangle_patch_corners(kg, patch, corners);
-
-                       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);
+               int corners[4];
+               subd_triangle_patch_corners(kg, patch, corners);
 
-                       if(subd_triangle_patch_num_corners(kg, patch) != 4) {
-                               f1 = (f1+f0)*0.5f;
-                               f3 = (f3+f0)*0.5f;
-                       }
+               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);
 
-                       a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), 
uv[0].y);
-                       b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), 
uv[1].y);
-                       c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), 
uv[2].y);
+               if(subd_triangle_patch_num_corners(kg, patch) != 4) {
+                       f1 = (f1+f0)*0.5f;
+                       f3 = (f3+f0)*0.5f;
                }
 
+               float a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), 
uv[0].y);
+               float b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), 
uv[1].y);
+               float c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), 
uv[2].y);
+
 #ifdef __RAY_DIFFERENTIALS__
                if(dx) *dx = ccl_fetch(sd, du).dx*a + ccl_fetch(sd, dv).dx*b - 
(ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*c;
                if(dy) *dy = ccl_fetch(sd, du).dy*a + ccl_fetch(sd, dv).dy*b - 
(ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*c;
@@ -374,7 +399,56 @@ ccl_device float3 
subd_triangle_attribute_float3(KernelGlobals *kg, const Shader
 {
        int patch = subd_triangle_patch(kg, sd);
 
-       if(desc->element == ATTR_ELEMENT_FACE) {
+       if(desc->flags & ATTR_SUBDIVIDED) {
+               float2 uv[3];
+               subd_triangle_patch_uv(kg, sd, uv);
+
+               float2 dpdu = uv[0] - uv[2];
+               float2 dpdv = uv[1] - uv[2];
+
+               /* p is [s, t] */
+               float2 p = dpdu * ccl_fetch(sd, u) + dpdv * ccl_fetch(sd, v) + 
uv[2];
+
+               float3 a, dads, dadt;
+
+               if(desc->element == ATTR_ELEMENT_CORNER_BYTE) {
+                       a = patch_eval_uchar4(kg, sd, desc->offset, patch, p.x, 
p.y, 0, &dads, &dadt);
+               }
+               else {
+                       a = patch_eval_float3(kg, sd, desc->offset, patch, p.x, 
p.y, 0, &dads, &dadt);
+               }
+
+#ifdef __RAY_DIFFERENTIALS__
+               if(dx || dy) {
+                       float dsdu = dpdu.x;
+                       float dtdu = dpdu.y;
+                       float dsdv = dpdv.x;
+                       float dtdv = dpdv.y;
+
+                       if(dx) {
+                               float dudx = ccl_fetch(sd, du).dx;
+                               float dvdx = ccl_fetch(sd, dv).dx;
+
+                               float dsdx = dsdu*dudx + dsdv*dvdx;
+                               float dtdx = dtdu*dudx + dtdv*dvdx;
+
+                               *dx = dads*dsdx + dadt*dtdx;
+                       }
+                       if(dy) {
+                               float dudy = ccl_fetch(sd, du).dy;
+                               float dvdy = ccl_fetch(sd, dv).dy;
+
+                               float dsdy = dsdu*dudy + dsdv*dvdy;
+                               float dtdy = dtdu*dudy + dtdv*dvdy;
+
+                               *dy = dads*dsdy + dadt*dtdy;
+                       }
+               }
+#endif
+
+               return a;
+       }
+       else 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);
 
@@ -384,31 +458,22 @@ ccl_device float3 
subd_triangle_attribute_float3(KernelGlobals *kg, const Shader
                float2 uv[3];
                subd_triangle_patch_uv(kg, sd, uv);
 
-               float3 a, b, c;
+               uint4 v = subd_triangle_patch_indices(kg, patch);
 
-               if(desc->flags & ATTR_SUBDIVIDED) {
-                       a = patch_eval_float3(kg, sd, desc->offset, patch, 
uv[0].x, uv[0].y, 0, NULL, NULL);
-                       b = patch_eval_float3(kg, sd, desc->offset, patch, 
uv[1].x, uv[1].y, 0, NULL, NULL);
-                       c = patch_eval_float3(kg, sd, desc->offset, patch, 
uv[2].x, uv[2].y, 0, NULL, NULL);
-               }
-               else {
-                       uint4 v = subd_triangle_patch_indices(kg, patch);
-
-                       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) !

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to