[Bf-blender-cvs] [a501a2dbff7] master: Images: add mirror extension type

Hallam Roberts noreply at git.blender.org
Wed Dec 14 19:27:40 CET 2022


Commit: a501a2dbff797829b61f21c5aeb9d19dba3e3874
Author: Hallam Roberts
Date:   Wed Dec 14 19:19:52 2022 +0100
Branches: master
https://developer.blender.org/rBa501a2dbff797829b61f21c5aeb9d19dba3e3874

Images: add mirror extension type

This adds a new mirror image extension type for shaders and
geometry nodes (next to the existing repeat, extend and clip
options).

See D16432 for a more detailed explanation of `wrap_mirror`.

This also adds a new sampler flag `GPU_SAMPLER_MIRROR_REPEAT`.
It acts as a modifier to `GPU_SAMPLER_REPEAT`, so any `REPEAT`
flag must be set for the `MIRROR` flag to have an effect.

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

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

M	intern/cycles/device/cuda/device_impl.cpp
M	intern/cycles/device/hip/device_impl.cpp
M	intern/cycles/device/metal/device_impl.mm
M	intern/cycles/kernel/device/cpu/image.h
M	intern/cycles/kernel/device/metal/compat.h
M	intern/cycles/kernel/device/metal/context_begin.h
M	intern/cycles/kernel/device/oneapi/image.h
M	intern/cycles/scene/shader_nodes.cpp
M	intern/cycles/util/texture.h
M	source/blender/draw/engines/workbench/workbench_materials.cc
M	source/blender/gpu/GPU_texture.h
M	source/blender/gpu/metal/mtl_context.mm
M	source/blender/gpu/opengl/gl_texture.cc
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesrna/intern/rna_nodetree.c
M	source/blender/nodes/geometry/nodes/node_geo_image_texture.cc
M	source/blender/nodes/shader/nodes/node_shader_tex_image.cc

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

diff --git a/intern/cycles/device/cuda/device_impl.cpp b/intern/cycles/device/cuda/device_impl.cpp
index c9764d1c21b..f354ba6aee1 100644
--- a/intern/cycles/device/cuda/device_impl.cpp
+++ b/intern/cycles/device/cuda/device_impl.cpp
@@ -952,6 +952,9 @@ void CUDADevice::tex_alloc(device_texture &mem)
     case EXTENSION_CLIP:
       address_mode = CU_TR_ADDRESS_MODE_BORDER;
       break;
+    case EXTENSION_MIRROR:
+      address_mode = CU_TR_ADDRESS_MODE_MIRROR;
+      break;
     default:
       assert(0);
       break;
diff --git a/intern/cycles/device/hip/device_impl.cpp b/intern/cycles/device/hip/device_impl.cpp
index a84f1edd70e..04de8619697 100644
--- a/intern/cycles/device/hip/device_impl.cpp
+++ b/intern/cycles/device/hip/device_impl.cpp
@@ -909,6 +909,9 @@ void HIPDevice::tex_alloc(device_texture &mem)
        * because it's unsupported in HIP. */
       address_mode = hipAddressModeClamp;
       break;
+    case EXTENSION_MIRROR:
+      address_mode = hipAddressModeMirror;
+      break;
     default:
       assert(0);
       break;
diff --git a/intern/cycles/device/metal/device_impl.mm b/intern/cycles/device/metal/device_impl.mm
index 24836e88755..95935ce2a3a 100644
--- a/intern/cycles/device/metal/device_impl.mm
+++ b/intern/cycles/device/metal/device_impl.mm
@@ -856,7 +856,7 @@ void MetalDevice::tex_alloc(device_texture &mem)
   /* sampler_index maps into the GPU's constant 'metal_samplers' array */
   uint64_t sampler_index = mem.info.extension;
   if (mem.info.interpolation != INTERPOLATION_CLOSEST) {
-    sampler_index += 3;
+    sampler_index += 4;
   }
 
   /* Image Texture Storage */
diff --git a/intern/cycles/kernel/device/cpu/image.h b/intern/cycles/kernel/device/cpu/image.h
index 320e6309128..eb50ac8217f 100644
--- a/intern/cycles/kernel/device/cpu/image.h
+++ b/intern/cycles/kernel/device/cpu/image.h
@@ -202,6 +202,14 @@ template<typename TexT, typename OutT = float4> struct TextureInterpolator {
     return clamp(x, 0, width - 1);
   }
 
+  static ccl_always_inline int wrap_mirror(int x, int width)
+  {
+    const int m = abs(x + (x < 0)) % (2 * width);
+    if (m >= width)
+      return 2 * width - m - 1;
+    return m;
+  }
+
   /* ********  2D interpolation ******** */
 
   static ccl_always_inline OutT interp_closest(const TextureInfo &info, float x, float y)
@@ -226,6 +234,10 @@ template<typename TexT, typename OutT = float4> struct TextureInterpolator {
         ix = wrap_clamp(ix, width);
         iy = wrap_clamp(iy, height);
         break;
+      case EXTENSION_MIRROR:
+        ix = wrap_mirror(ix, width);
+        iy = wrap_mirror(iy, height);
+        break;
       default:
         kernel_assert(0);
         return zero();
@@ -268,6 +280,12 @@ template<typename TexT, typename OutT = float4> struct TextureInterpolator {
         niy = wrap_clamp(iy + 1, height);
         iy = wrap_clamp(iy, height);
         break;
+      case EXTENSION_MIRROR:
+        nix = wrap_mirror(ix + 1, width);
+        ix = wrap_mirror(ix, width);
+        niy = wrap_mirror(iy + 1, height);
+        iy = wrap_mirror(iy, height);
+        break;
       default:
         kernel_assert(0);
         return zero();
@@ -331,6 +349,17 @@ template<typename TexT, typename OutT = float4> struct TextureInterpolator {
         nniy = wrap_clamp(iy + 2, height);
         iy = wrap_clamp(iy, height);
         break;
+      case EXTENSION_MIRROR:
+        pix = wrap_mirror(ix - 1, width);
+        nix = wrap_mirror(ix + 1, width);
+        nnix = wrap_mirror(ix + 2, width);
+        ix = wrap_mirror(ix, width);
+
+        piy = wrap_mirror(iy - 1, height);
+        niy = wrap_mirror(iy + 1, height);
+        nniy = wrap_mirror(iy + 2, height);
+        iy = wrap_mirror(iy, height);
+        break;
       default:
         kernel_assert(0);
         return zero();
@@ -403,6 +432,11 @@ template<typename TexT, typename OutT = float4> struct TextureInterpolator {
         iy = wrap_clamp(iy, height);
         iz = wrap_clamp(iz, depth);
         break;
+      case EXTENSION_MIRROR:
+        ix = wrap_mirror(ix, width);
+        iy = wrap_mirror(iy, height);
+        iz = wrap_mirror(iz, depth);
+        break;
       default:
         kernel_assert(0);
         return zero();
@@ -480,6 +514,16 @@ template<typename TexT, typename OutT = float4> struct TextureInterpolator {
         niz = wrap_clamp(iz + 1, depth);
         iz = wrap_clamp(iz, depth);
         break;
+      case EXTENSION_MIRROR:
+        nix = wrap_mirror(ix + 1, width);
+        ix = wrap_mirror(ix, width);
+
+        niy = wrap_mirror(iy + 1, height);
+        iy = wrap_mirror(iy, height);
+
+        niz = wrap_mirror(iz + 1, depth);
+        iz = wrap_mirror(iz, depth);
+        break;
       default:
         kernel_assert(0);
         return zero();
@@ -595,6 +639,22 @@ template<typename TexT, typename OutT = float4> struct TextureInterpolator {
         nniz = wrap_clamp(iz + 2, depth);
         iz = wrap_clamp(iz, depth);
         break;
+      case EXTENSION_MIRROR:
+        pix = wrap_mirror(ix - 1, width);
+        nix = wrap_mirror(ix + 1, width);
+        nnix = wrap_mirror(ix + 2, width);
+        ix = wrap_mirror(ix, width);
+
+        piy = wrap_mirror(iy - 1, height);
+        niy = wrap_mirror(iy + 1, height);
+        nniy = wrap_mirror(iy + 2, height);
+        iy = wrap_mirror(iy, height);
+
+        piz = wrap_mirror(iz - 1, depth);
+        niz = wrap_mirror(iz + 1, depth);
+        nniz = wrap_mirror(iz + 2, depth);
+        iz = wrap_mirror(iz, depth);
+        break;
       default:
         kernel_assert(0);
         return zero();
diff --git a/intern/cycles/kernel/device/metal/compat.h b/intern/cycles/kernel/device/metal/compat.h
index 2dd6cc98b59..3913931b4fb 100644
--- a/intern/cycles/kernel/device/metal/compat.h
+++ b/intern/cycles/kernel/device/metal/compat.h
@@ -301,10 +301,12 @@ enum SamplerType {
   SamplerFilterNearest_AddressRepeat,
   SamplerFilterNearest_AddressClampEdge,
   SamplerFilterNearest_AddressClampZero,
+  SamplerFilterNearest_AddressMirroredRepeat,
 
   SamplerFilterLinear_AddressRepeat,
   SamplerFilterLinear_AddressClampEdge,
   SamplerFilterLinear_AddressClampZero,
+  SamplerFilterLinear_AddressMirroredRepeat,
 
   SamplerCount
 };
@@ -313,7 +315,9 @@ constant constexpr array<sampler, SamplerCount> metal_samplers = {
     sampler(address::repeat, filter::nearest),
     sampler(address::clamp_to_edge, filter::nearest),
     sampler(address::clamp_to_zero, filter::nearest),
+    sampler(address::mirrored_repeat, filter::nearest),
     sampler(address::repeat, filter::linear),
     sampler(address::clamp_to_edge, filter::linear),
     sampler(address::clamp_to_zero, filter::linear),
+    sampler(address::mirrored_repeat, filter::linear),
 };
diff --git a/intern/cycles/kernel/device/metal/context_begin.h b/intern/cycles/kernel/device/metal/context_begin.h
index e75ec9cadec..4bde9be455a 100644
--- a/intern/cycles/kernel/device/metal/context_begin.h
+++ b/intern/cycles/kernel/device/metal/context_begin.h
@@ -47,9 +47,11 @@ class MetalKernelContext {
         case 0: return texture_array[tid].tex.sample(sampler(address::repeat, filter::nearest), coords);
         case 1: return texture_array[tid].tex.sample(sampler(address::clamp_to_edge, filter::nearest), coords);
         case 2: return texture_array[tid].tex.sample(sampler(address::clamp_to_zero, filter::nearest), coords);
-        case 3: return texture_array[tid].tex.sample(sampler(address::repeat, filter::linear), coords);
-        case 4: return texture_array[tid].tex.sample(sampler(address::clamp_to_edge, filter::linear), coords);
-        case 5: return texture_array[tid].tex.sample(sampler(address::clamp_to_zero, filter::linear), coords);
+        case 3: return texture_array[tid].tex.sample(sampler(address::mirrored_repeat, filter::nearest), coords);
+        case 4: return texture_array[tid].tex.sample(sampler(address::repeat, filter::linear), coords);
+        case 5: return texture_array[tid].tex.sample(sampler(address::clamp_to_edge, filter::linear), coords);
+        case 6: return texture_array[tid].tex.sample(sampler(address::clamp_to_zero, filter::linear), coords);
+        case 7: return texture_array[tid].tex.sample(sampler(address::mirrored_repeat, filter::linear), coords);
       }
     }
 #endif
diff --git a/intern/cycles/kernel/device/oneapi/image.h b/intern/cycles/kernel/device/oneapi/image.h
index 2417b8eac3b..bdb81bb8645 100644
--- a/intern/cycles/kernel/device/oneapi/image.h
+++ b/intern/cycles/kernel/device/oneapi/image.h
@@ -24,6 +24,14 @@ ccl_device_inline int svm_image_texture_wrap_clamp(int x, int width)
   return clamp(x, 0, width - 1);
 }
 
+ccl_device_inline int svm_image_texture_wrap_mirror(int x, int width)
+{
+  const int m = abs(x + (x < 0)) % (2 * width);
+  if (m >= width)
+    return 2 * width - m - 1;
+  return m;
+}
+
 ccl_device_inline float4 svm_image_texture_read(const TextureInfo &info, int x, int y, int z)
 {
   const int data_offset = x + info.width * y + info.width * info.height * z;
@@ -85,6 +93,10 @@ ccl_device_inline float4 svm_image_texture_read_2d(int id, int x, int y)
     x = svm_image_texture_wrap_clamp(x, info.width);
     y = svm_image_texture_wrap_clamp(y, info.height);
   }
+  else if (info.extension == EXTENSION_MIRROR) {
+    x = svm_image_texture_wrap_mirror(x, info.width);
+    y = svm_image_texture_wrap_mirror(y, info.height);
+  }
   else {
     if (x < 0 || x >= info.width || y < 0 || y >= info.height) {
       return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
@@ -109,6 +121,11 @@ ccl_device_inline float4 svm_image_texture_read_3d(int id, int x, int y, int z)
     y = svm_image_texture_wrap_clamp(y, info.height);
     z = svm_image_texture_wrap_clamp(z, info.depth);
   }
+  else if (info.extension == EXTENSION_MIRROR) {
+    x = svm_image_texture_wrap_mirror(x, info.width);
+    y = svm_image_texture_wrap_mirror(y, info.height);
+    z = svm_image_texture_wrap_mirror(z, info.depth);
+  }
   else {
     if (x < 0 || x >= info.width || y < 0 || y >= info.height || z < 0 || z >= info.depth) {
       return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp
i

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list