diff --git a/slangpy/builtin/texture.py b/slangpy/builtin/texture.py index 9c0f2f9e..81032923 100644 --- a/slangpy/builtin/texture.py +++ b/slangpy/builtin/texture.py @@ -176,6 +176,19 @@ def resolve_types(self, context: BindContext, bound_type: refl.SlangType): # Otherwise, use default behaviour from marshall return None + def resolve_dimensionality( + self, + context: BindContext, + binding: "BoundVariable", + vector_target_type: refl.SlangType, + ): + # If target type is a texture, the texture is passed directly (broadcast as-is) + if isinstance(vector_target_type, refl.TextureType): + return 0 + + # the texture is being used for per-pixel operations + return self.texture_dims + # Texture is writable if it has unordered access view. @property def is_writable(self): diff --git a/slangpy/tests/slangpy_tests/test_textures.py b/slangpy/tests/slangpy_tests/test_textures.py index 408167f8..af397b2a 100644 --- a/slangpy/tests/slangpy_tests/test_textures.py +++ b/slangpy/tests/slangpy_tests/test_textures.py @@ -526,5 +526,89 @@ def test_texture_return_value_str( texture_return_value_impl(device_type, texel_name, dims, channels, "texture") +@pytest.mark.parametrize("device_type", helpers.DEFAULT_DEVICE_TYPES) +def test_texture_1d_broadcast(device_type: DeviceType): + if device_type == DeviceType.cuda: + pytest.skip("1D texture read returns zero on CUDA backend") + module = load_test_module(device_type) + + # Non-square: width=8, sample at position 2 + tex_data = np.zeros((8, 1), dtype=np.float32) + tex_data[2, 0] = 5.5 # Value at x=2 + tex = module.device.create_texture( + type=TextureType.texture_1d, + width=8, + usage=TextureUsage.shader_resource | TextureUsage.unordered_access, + format=Format.r32_float, + data=tex_data, + ) + + result = module.sample_texture_1d_broadcast(tex) + assert result == pytest.approx(5.5) + + +@pytest.mark.parametrize("device_type", helpers.DEFAULT_DEVICE_TYPES) +def test_texture_2d_broadcast(device_type: DeviceType): + module = load_test_module(device_type) + + # Non-square: width=8, height=4, sample at position (3, 1) + tex_data = np.zeros((4, 8, 1), dtype=np.float32) + tex_data[1, 3, 0] = 7.25 # Value at x=3, y=1 -> numpy[y, x, channel] + tex = module.device.create_texture( + type=TextureType.texture_2d, + width=8, + height=4, + usage=TextureUsage.shader_resource | TextureUsage.unordered_access, + format=Format.r32_float, + data=tex_data, + ) + + result = module.sample_texture_2d_broadcast(tex) + assert result == pytest.approx(7.25) + + +@pytest.mark.parametrize("device_type", helpers.DEFAULT_DEVICE_TYPES) +def test_texture_3d_broadcast(device_type: DeviceType): + module = load_test_module(device_type) + + # Non-square: width=8, height=6, depth=4, sample at position (2, 1, 3) + tex_data = np.zeros((4, 6, 8, 1), dtype=np.float32) + tex_data[3, 1, 2, 0] = 3.14 # Value at x=2, y=1, z=3 -> numpy[z, y, x, channel] + tex = module.device.create_texture( + type=TextureType.texture_3d, + width=8, + height=6, + depth=4, + usage=TextureUsage.shader_resource | TextureUsage.unordered_access, + format=Format.r32_float, + data=tex_data, + ) + + result = module.sample_texture_3d_broadcast(tex) + assert result == pytest.approx(3.14) + + +@pytest.mark.parametrize("device_type", helpers.DEFAULT_DEVICE_TYPES) +def test_texture_3d_broadcast_with_scalar(device_type: DeviceType): + module = load_test_module(device_type) + + # Non-square: width=8, height=6, depth=4, sample at position (2, 1, 3) + tex_data = np.zeros((4, 6, 8, 1), dtype=np.float32) + tex_data[3, 1, 2, 0] = 2.0 # Value at x=2, y=1, z=3 -> numpy[z, y, x, channel] + tex = module.device.create_texture( + type=TextureType.texture_3d, + width=8, + height=6, + depth=4, + usage=TextureUsage.shader_resource | TextureUsage.unordered_access, + format=Format.r32_float, + data=tex_data, + ) + + # tex[2,1,3] = 2.0, value = 3.0, so result should be 6.0 + result = module.sample_texture_3d_with_scalar(3.0, tex) + assert result == pytest.approx(6.0) + + if __name__ == "__main__": pytest.main([__file__, "-v", "-s"]) diff --git a/slangpy/tests/slangpy_tests/test_textures.slang b/slangpy/tests/slangpy_tests/test_textures.slang index d1d3f1c7..2ba4270a 100644 --- a/slangpy/tests/slangpy_tests/test_textures.slang +++ b/slangpy/tests/slangpy_tests/test_textures.slang @@ -42,3 +42,23 @@ T passthru(T t) { return t; } + +float sample_texture_1d_broadcast(Texture1D tex) +{ + return tex[uint(2)]; +} + +float sample_texture_2d_broadcast(Texture2D tex) +{ + return tex[uint2(3, 1)]; +} + +float sample_texture_3d_broadcast(Texture3D tex) +{ + return tex[uint3(2, 1, 3)]; +} + +float sample_texture_3d_with_scalar(float value, Texture3D tex) +{ + return tex[uint3(2, 1, 3)] * value; +}