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. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs