From 0244c96d637f47fa264d441a82d3dca78889373b Mon Sep 17 00:00:00 2001 From: ArielG-NV <159081215+ArielG-NV@users.noreply.github.com> Date: Fri, 16 May 2025 11:57:17 -0700 Subject: Fix correct bindings for bindless resource model [SPIRV and GLSL] (#7131) Fix correct bindings for bindless resource model [spirv and glsl] fixes: #6952 Problem: * Currently all bindless objects are placed in the same set (fine) and same binding (incorrect behavior for vulkan). This is incorrect since as per [spec](https://registry.khronos.org/vulkan/specs/latest/man/html/VkDescriptorType.html), only 1 resource type may be written to each index inside a set (these rules are loosened with VK_EXT_mutable_descriptor_type) * This means currently generated bindings do not work in practice if we (for example) use `Sampler2D.Handle` and `Texture1D.Handle` in a shader since we would place 2 incompatible objects in the same binding-index and set. Solution: * `__getDynamicResourceHeap` was modified to allow bindings to chosen dynamically for a descriptor * use `IOpaqueDescriptor` to check compile-time information of resource types so that we can identify different resources * Using this information of `IOpaqueDescriptor`, we modify `defaultGetDescriptorFromHandle` to provide a binding model (1 resource per binding-index) which produces legal spirv/glsl. * To support `VK_EXT_mutable_descriptor_type` the function `defaultGetDescriptorFromHandle` has a set of options (`BindlessDescriptorOptions`) for a user to pick-from to support their binding model. Capabilities are not used here for flexibility purposes (specifically old shaders mixed with modern vulkan extensions). Other changes: * Added `TexelBuffer` DescriptorKind to aid in generating correct bindings * format code * Add to docs bindless changes, make AccelerationStructure use its handle directly, adjust tests accordingly --------- Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> --- .../descriptor-handle/desc-handle-2.slang | 2 +- .../descriptor-handle/desc-handle-default.slang | 159 +++++++++++++++++++++ .../desc-handle-vk-mutable-descriptor.slang | 79 ++++++++++ 3 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 tests/language-feature/descriptor-handle/desc-handle-default.slang create mode 100644 tests/language-feature/descriptor-handle/desc-handle-vk-mutable-descriptor.slang (limited to 'tests') diff --git a/tests/language-feature/descriptor-handle/desc-handle-2.slang b/tests/language-feature/descriptor-handle/desc-handle-2.slang index fa7f73b31..f9eb02cbe 100644 --- a/tests/language-feature/descriptor-handle/desc-handle-2.slang +++ b/tests/language-feature/descriptor-handle/desc-handle-2.slang @@ -1,6 +1,6 @@ //TEST:SIMPLE(filecheck=SPV): -target spirv -bindless-space-index 101 -// SPV: OpDecorate %__slang_resource_heap{{.*}} Binding 0 +// SPV: OpDecorate %__slang_resource_heap{{.*}} Binding 1 // SPV: OpDecorate %__slang_resource_heap{{.*}} DescriptorSet 101 // SPV: OpImageSample diff --git a/tests/language-feature/descriptor-handle/desc-handle-default.slang b/tests/language-feature/descriptor-handle/desc-handle-default.slang new file mode 100644 index 000000000..d442fb610 --- /dev/null +++ b/tests/language-feature/descriptor-handle/desc-handle-default.slang @@ -0,0 +1,159 @@ +//TEST:SIMPLE(filecheck=SAMPLER): -target spirv -stage compute -entry computeMain -DSAMPLER +//TEST:SIMPLE(filecheck=COMBINED_IMAGE_SAMPLER): -target spirv -stage compute -entry computeMain -DCOMBINED_IMAGE_SAMPLER +//TEST:SIMPLE(filecheck=SAMPLED_IMAGE): -target spirv -stage compute -entry computeMain -DSAMPLED_IMAGE +//TEST:SIMPLE(filecheck=STORAGE_IMAGE): -target spirv -stage compute -entry computeMain -DSTORAGE_IMAGE +//TEST:SIMPLE(filecheck=UNIFORM_TEXEL_BUFFER): -target spirv -stage compute -entry computeMain -DUNIFORM_TEXEL_BUFFER +//TEST:SIMPLE(filecheck=STORAGE_TEXEL_BUFFER): -target spirv -stage compute -entry computeMain -DSTORAGE_TEXEL_BUFFER +//TEST:SIMPLE(filecheck=UNIFORM_BUFFER): -target spirv -stage compute -entry computeMain -DUNIFORM_BUFFER +//TEST:SIMPLE(filecheck=STORAGE_BUFFER): -target spirv -stage compute -entry computeMain -DSTORAGE_BUFFER +//TEST:SIMPLE(filecheck=ACCELERATION_STRUCTURE): -target spirv -stage compute -entry computeMain -DACCELERATION_STRUCTURE +//TEST:SIMPLE(filecheck=SAMPLED_IMAGE): -target spirv -stage compute -entry computeMain -DSAMPLED_IMAGE +//TEST:SIMPLE(filecheck=MIX): -target spirv -stage compute -entry computeMain -DSAMPLER -DSTORAGE_TEXEL_BUFFER -DUNIFORM_BUFFER -DACCELERATION_STRUCTURE + +// To intentionally fill up binding slots +[[vk::binding(0, 1)]] +RWTexture1D t1; + +[[vk::binding(0, 2)]] +RWTexture1D t2; + +[[vk::binding(0, 4)]] +RWTexture1D t3; + +[[vk::binding(1, 4)]] +Texture1D t4; + +//MIX-DAG: OpDecorate %__slang_resource_heap{{.*}} Binding 0 +//MIX-DAG: OpDecorate %__slang_resource_heap{{.*}} Binding 5 +//MIX-DAG: OpDecorate %__slang_resource_heap{{.*}} Binding 6 + +//MIX-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 1 +//MIX-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 2 +//MIX-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 3 +//MIX-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 4 +//MIX-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 7 +//MIX-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 8 + +#ifdef SAMPLER +//SAMPLER: OpDecorate %__slang_resource_heap{{.*}} Binding 0 +//SAMPLER-NEXT: OpDecorate %__slang_resource_heap{{.*}} DescriptorSet 3 + +//SAMPLER-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 1 +//SAMPLER-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 2 +//SAMPLER-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 3 +//SAMPLER-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 4 +//SAMPLER-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 5 +//SAMPLER-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 6 +//SAMPLER-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 7 +//SAMPLER-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 8 +uniform SamplerState.Handle sampler; +#endif + +#ifdef COMBINED_IMAGE_SAMPLER +//COMBINED_IMAGE_SAMPLER: OpDecorate %__slang_resource_heap{{.*}} Binding 1 +//COMBINED_IMAGE_SAMPLER-NEXT: OpDecorate %__slang_resource_heap{{.*}} DescriptorSet 3 +uniform Sampler1DShadow.Handle combinedSampler; +#endif + +#ifdef SAMPLED_IMAGE +//SAMPLED_IMAGE: OpDecorate %__slang_resource_heap{{.*}} Binding 2 +//SAMPLED_IMAGE-NEXT: OpDecorate %__slang_resource_heap{{.*}} DescriptorSet 3 +uniform Texture1D.Handle texture; +#endif + +#ifdef STORAGE_IMAGE +//STORAGE_IMAGE: OpDecorate %__slang_resource_heap{{.*}} Binding 3 +//STORAGE_IMAGE-NEXT: OpDecorate %__slang_resource_heap{{.*}} DescriptorSet 3 +uniform RWTexture1D.Handle rwTexture1; +uniform RWTexture2D.Handle rwTexture2; +#endif + +#ifdef UNIFORM_TEXEL_BUFFER +//UNIFORM_TEXEL_BUFFER: OpDecorate %__slang_resource_heap{{.*}} Binding 4 +//UNIFORM_TEXEL_BUFFER-NEXT: OpDecorate %__slang_resource_heap{{.*}} DescriptorSet 3 +uniform Buffer.Handle texelBuffer; +#endif + +#ifdef STORAGE_TEXEL_BUFFER +//STORAGE_TEXEL_BUFFER: OpDecorate %__slang_resource_heap{{.*}} Binding 5 +//STORAGE_TEXEL_BUFFER-NEXT: OpDecorate %__slang_resource_heap{{.*}} DescriptorSet 3 +uniform RWBuffer.Handle rwTexelBuffer; +#endif + +#ifdef UNIFORM_BUFFER +//UNIFORM_BUFFER: OpDecorate %__slang_resource_heap{{.*}} Binding 6 +//UNIFORM_BUFFER-NEXT: OpDecorate %__slang_resource_heap{{.*}} DescriptorSet 3 +struct Data +{ + float v; +} +uniform ConstantBuffer.Handle buffer1; +uniform StructuredBuffer.Handle buffer2; +#endif + +#ifdef STORAGE_BUFFER +//STORAGE_BUFFER: OpDecorate %__slang_resource_heap{{.*}} Binding 7 +//STORAGE_BUFFER-NEXT: OpDecorate %__slang_resource_heap{{.*}} DescriptorSet 3 +uniform RWStructuredBuffer.Handle rwBuffer; +#endif + +#ifdef ACCELERATION_STRUCTURE +//ACCELERATION_STRUCTURE-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 8 +//ACCELERATION_STRUCTURE: OpConvertUToAccelerationStructureKHR +uniform RaytracingAccelerationStructure.Handle rayAcceleration; +#endif + +[shader("compute")] +void computeMain() +{ + + t1[0] = t2[0] + t2[0] + t4[0]; + +#ifdef SAMPLER + t1[2] = t4.Sample(sampler, 0); +#endif + +#ifdef COMBINED_IMAGE_SAMPLER + t1[8] = combinedSampler.Sample(0); +#endif + +#ifdef SAMPLED_IMAGE + t1[0] = texture[0]; +#endif + +#ifdef STORAGE_IMAGE + t1[11] = rwTexture1[0]; + t1[12] = rwTexture2[0]; +#endif + +#ifdef UNIFORM_TEXEL_BUFFER + t1[10] = texelBuffer[0]; +#endif + +#ifdef STORAGE_TEXEL_BUFFER + t1[9] = rwTexelBuffer[0]; +#endif + +#ifdef UNIFORM_BUFFER + t1[4] = (*buffer1).v; + t1[6] = buffer2[0]; +#endif + +#ifdef STORAGE_BUFFER + t1[0] += rwBuffer[0]; +#endif + +#ifdef ACCELERATION_STRUCTURE + RayDesc ray; + ray.Origin = float3(0.1f, 0.1f, 0.0f); + ray.Direction = float3(0.0f, 0.0f, 1.0f); + ray.TMin = 0.0f; + ray.TMax = 100.0f; + RayQuery rq; + rq.TraceRayInline(rayAcceleration, RAY_FLAG_FORCE_NON_OPAQUE, 0xff, ray); + bool proceed = rq.Proceed(); + rq.CommitNonOpaqueTriangleHit(); + rq.Abort(); + t1[13] = (float)rq.RayFlags(); +#endif +} \ No newline at end of file diff --git a/tests/language-feature/descriptor-handle/desc-handle-vk-mutable-descriptor.slang b/tests/language-feature/descriptor-handle/desc-handle-vk-mutable-descriptor.slang new file mode 100644 index 000000000..8fc2d3283 --- /dev/null +++ b/tests/language-feature/descriptor-handle/desc-handle-vk-mutable-descriptor.slang @@ -0,0 +1,79 @@ +//TEST:SIMPLE(filecheck=CHECK): -target spirv -stage compute -entry computeMain + +// To intentionally fill up binding slots +[[vk::binding(0, 1)]] +RWTexture1D t1; + +[[vk::binding(0, 2)]] +RWTexture1D t2; + +[[vk::binding(0, 4)]] +RWTexture1D t3; + +[[vk::binding(1, 4)]] +Texture1D t4; + +//CHECK-DAG: OpDecorate %__slang_resource_heap{{.*}} Binding 0 +//CHECK-DAG: OpDecorate %__slang_resource_heap{{.*}} Binding 1 +//CHECK-DAG: OpDecorate %__slang_resource_heap{{.*}} Binding 2 +//CHECK-DAG: OpConvertUToAccelerationStructureKHR + +//CHECK-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 3 +//CHECK-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 4 +//CHECK-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 5 +//CHECK-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 6 +//CHECK-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 7 +//CHECK-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 8 +//CHECK-NOT: OpDecorate %__slang_resource_heap{{.*}} Binding 9 +export T getDescriptorFromHandle(DescriptorHandle handleValue) +{ + return defaultGetDescriptorFromHandle(handleValue, BindlessDescriptorOptions.VkMutable); +} + +uniform SamplerState.Handle sampler; +uniform Sampler1DShadow.Handle combinedSampler; +uniform Texture1D.Handle texture; +uniform RWTexture1D.Handle rwTexture1; +uniform RWTexture2D.Handle rwTexture2; +uniform Buffer.Handle texelBuffer; +uniform RWBuffer.Handle rwTexelBuffer; + +struct Data +{ + float v; +} +uniform ConstantBuffer.Handle buffer1; +uniform StructuredBuffer.Handle buffer2; +uniform RWStructuredBuffer.Handle rwBuffer; +uniform RaytracingAccelerationStructure.Handle rayAcceleration; + + +[shader("compute")] +void computeMain() +{ + + t1[0] = t2[0] + t2[0] + t4[0]; + t1[2] = t4.Sample(sampler, 0); + t1[8] = combinedSampler.Sample(0); + t1[0] = texture[0]; + t1[11] = rwTexture1[0]; + t1[12] = rwTexture2[0]; + t1[10] = texelBuffer[0]; + t1[9] = rwTexelBuffer[0]; + t1[4] = (*buffer1).v; + t1[6] = buffer2[0]; + t1[0] += rwBuffer[0]; + + RayDesc ray; + ray.Origin = float3(0.1f, 0.1f, 0.0f); + ray.Direction = float3(0.0f, 0.0f, 1.0f); + ray.TMin = 0.0f; + ray.TMax = 100.0f; + RayQuery rq; + rq.TraceRayInline(rayAcceleration, RAY_FLAG_FORCE_NON_OPAQUE, 0xff, ray); + bool proceed = rq.Proceed(); + rq.CommitNonOpaqueTriangleHit(); + rq.Abort(); + t1[13] = (float)rq.RayFlags(); + +} \ No newline at end of file -- cgit v1.2.3