From 5290c580632cfb56847b863a32dc020a21d1c93e Mon Sep 17 00:00:00 2001 From: Yong He Date: Fri, 10 Jan 2025 10:57:04 -0800 Subject: Initial implementation of SP#015 `DescriptorHandle`. (#6028) * Initial implementation of `ResourcePtr`. * Update docs * Fix build error. * Add more discussion. * Update documentation. * Update TOC. * Fix. * Fix. * Add test case for custom `getResourceFromBindlessHandle`. * Add namehint to generated descriptor heap param. * Fix. * Fix. * format code * Rename to `DescriptorHandle`, and add `T.Handle` alias. * Fix compiler error. * Fix. * Fix build. * Renames. * Fix documentation. * Documentation fix. --------- Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> --- docs/user-guide/03-convenience-features.md | 114 +++++++++++++++++++++++++++++ docs/user-guide/toc.html | 1 + 2 files changed, 115 insertions(+) (limited to 'docs/user-guide') diff --git a/docs/user-guide/03-convenience-features.md b/docs/user-guide/03-convenience-features.md index aeec8eb28..e6b337eed 100644 --- a/docs/user-guide/03-convenience-features.md +++ b/docs/user-guide/03-convenience-features.md @@ -531,12 +531,126 @@ Pointer types can also be specified using the generic syntax: `Ptr` is e - Slang can produce pointers using the & operator from data in global memory. +- Slang doesn't support forming pointers to opaque handle types, e.g. `Texture2D`. For handle pointers, use `DescriptorHandle` instead. + - Slang doesn't support coherent load/stores. - Slang doesn't support custom alignment specification. - Slang currently does not support pointers to immutable values, i.e. `const T*`. +## `DescriptorHandle` for Bindless Descriptor Access + +Slang supports the `DescriptorHandle` type that represents a bindless handle to a resource. This feature provides a portable way of implementing +the bindless resource idiom. When targeting HLSL, GLSL and SPIRV where descriptor types (e.g. textures, samplers and buffers) are opaque handles, +`DescriptorHandle` will translate into a `uint2` so it can be defined in any memory location. The underlying `uint2` value is treated as an index +to access the global descriptor heap or resource array in order to obtain the actual resource handle. On targets with where resource handles +are not opaque handles, `DescriptorHandle` maps to `T` and will have the same size and alignment defined by the target. + +`DescriptorHandle` is declared as: +```slang +struct DescriptorHandle where T:IOpaqueDescriptor {} +``` +where `IOpaqueDescriptor` is an interface implemented by all resource types, including textures, +`ConstantBuffer`, `RaytracingAccelerationStructure`, `SamplerState`, `SamplerComparisonState` and all types of `StructuredBuffer`. + +You may also write `Texture2D.Handle` as a short-hand of `DescriptorHandle`. + +`DescriptorHandle` supports `operator *`, `operator ->`, and can implicitly convert to `T`, for example: + +```slang +uniform StructuredBuffer> textures; +uniform int textureIndex; + +// define a descriptor handle using builtin convenience typealias: +uniform StructuredBuffer.Handle output; + +[numthreads(1,1,1)] +void main() +{ + output[0] = textures[textureIndex].Load(int3(0)); + + // Alternatively, this syntax is also valid: + (*output)[0] = textures[textureIndex]->Load(int3(0)); +} +``` + +By default, when targeting HLSL, `DescriptorHandle` translates to uses of `ResourceDescriptorHeap[index]` and `SamplerDescriptorHeap[index]`. +In particular, when combined with combined texture sampler types (e.g. `Sampler2D`), Slang will fetch the texture using the first +component of the handle, and the sampler state from the second component of the handle. For example: + +``` +uniform DescriptorHandle s; +void test() +{ + s.Sample(uv); +} +``` + +translates to: + +```hlsl +uniform uint2 s; +void test() +{ + Texture2D(ResourceDescriptorHeap[s.x]).Sample( + SamplerState(SamplerDescriptorHeap[s.y]), + uv + ); +} +``` + +When targeting SPIRV, Slang will introduce a global array of descriptors and fetch from the global array. +The descriptor set ID of the global descriptor array can be configured with the `-bindless-space-index` +(or `CompilerOptionName::BindlessSpaceIndex` when using the API) option. + +> #### Note +> The default implementation for SPIRV may change in the future if SPIRV is extended to provide what is +> equivalent to D3D's `ResourceDescriptorHeap` construct. + +Users can override the default behavior of convering from bindless handle to resource handle, by providing a +`getDescriptorFromHandle` in user code. For example: + +```slang +// All texture and buffer handles are defined in descriptor set 100. +[vk::binding(0, 100)] +__DynamicResource<__DynamicResourceKind.General> resourceHandles[]; + +// All sampler handles are defined in descriptor set 101. +[vk::binding(0, 101)] +__DynamicResource<__DynamicResourceKind.Sampler> samplerHandles[]; + +export T getDescriptorFromHandle(DescriptorHandle handle) where T : IOpaqueDescriptor +{ + __target_switch + { + case spirv: + if (T.kind == ResourceKind.Sampler) + return samplerHandles[((uint2)handle).x].asOpaqueDescriptor(); + else + return resourceHandles[((uint2)handle).x].asOpaqueDescriptor(); + default: + return defaultGetDescriptorFromHandle(handle); + } +} +``` + +The user can call `defaultGetDescriptorFromHandle` function from their implementation of +`getDescriptorFromHandle` to dispatch to the default behavior. + +By default, the value of a `DescriptorHandle` object is assumed to be dynamically uniform across all +execution threads. If this is not the case, the user is required to mark the `DescriptorHandle` as `nonuniform` +*immediately* before dereferencing it: +```slang +void test(DescriptorHandle t) +{ + nonuniform(t)->Sample(...); +} +``` + +If the resource pointer value is not uniform and `nonuniform` is not called, the result may be +undefined. + Extensions -------------------- Slang allows defining additional methods for a type outside its initial definition. For example, suppose we already have a type defined: diff --git a/docs/user-guide/toc.html b/docs/user-guide/toc.html index b5a6cccbb..9f9085cdd 100644 --- a/docs/user-guide/toc.html +++ b/docs/user-guide/toc.html @@ -45,6 +45,7 @@
  • `if_let` syntax
  • `reinterpret<T>` operation
  • Pointers (limited)
  • +
  • `DescriptorHandle` for Bindless Descriptor Access
  • Extensions
  • Multi-level break
  • Force inlining
  • -- cgit v1.2.3