[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