diff options
| author | Yong He <yonghe@outlook.com> | 2025-04-30 16:38:57 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-30 16:38:57 -0700 |
| commit | a8d7bb9f781fd77080f07bfaab54fbbcf3a3686d (patch) | |
| tree | 3bda97cf2a0d9a7800e7201e948354962e13d2a4 | |
| parent | 7f1df9d0b31413e59846cc955d2a955d3f361e2a (diff) | |
Add `IOpaqueDescriptor::descriptorAccess`. (#6967)
* Add `IOpaqueHandle::descriptorAccess`.
* Update doc.
* fix.
| -rw-r--r-- | docs/user-guide/03-convenience-features.md | 41 | ||||
| -rw-r--r-- | source/slang/hlsl.meta.slang | 43 | ||||
| -rw-r--r-- | tests/language-feature/descriptor-handle/desc-handle-4.slang | 34 |
3 files changed, 104 insertions, 14 deletions
diff --git a/docs/user-guide/03-convenience-features.md b/docs/user-guide/03-convenience-features.md index afde98f24..1e9a79882 100644 --- a/docs/user-guide/03-convenience-features.md +++ b/docs/user-guide/03-convenience-features.md @@ -635,9 +635,50 @@ export T getDescriptorFromHandle<T>(DescriptorHandle<T> handle) where T : IOpaqu } ``` +Note that the `getDescriptorFromHandle` is not supposed to be called from the user code directly, +it will be automatically called by the compiler to dereference a `DescriptorHandle<T>` to get `T`. +Think about providing `getDescriptorFromHandle` as a way to override `operator->` for `DescriptorHandle<T>`. + +The `IOpaqueDescriptor` interface is defined as: + +```slang +interface IOpaqueDescriptor +{ + /// The kind of the descriptor. + static const DescriptorKind kind; + static const DescriptorAccess descriptorAccess; +} +``` + The user can call `defaultGetDescriptorFromHandle` function from their implementation of `getDescriptorFromHandle` to dispatch to the default behavior. +The `kind` and `descriptorAccess` constants allows user code to fetch from different locations +depending on the type and access of the resource being requested. The `DescriptorKind` and +`DescriptorAccess` enums are defined as: + +```slang +enum DescriptorKind +{ + Unknown, /// Unknown descriptor kind. + Texture, /// A texture descriptor. + CombinedTextureSampler, /// A combined texture and sampler state descriptor. + Buffer, /// A buffer descriptor. + Sampler, /// A sampler state descriptor. + AccelerationStructure, /// A ray tracing acceleration structure descriptor. +} + +enum DescriptorAccess +{ + Unknown = -1, + Read = 0, + Write = 1, + ReadWrite = 2, + RasterizerOrdered = 3, + Feedback = 4, +} +``` + By default, the value of a `DescriptorHandle<T>` 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: diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index a6e1196e3..3d83e33c1 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -21966,6 +21966,16 @@ enum DescriptorKind AccelerationStructure, /// A ray tracing acceleration structure descriptor. } +enum DescriptorAccess +{ + Unknown = -1, + Read = $(kCoreModule_ResourceAccessReadOnly), + Write = $(kCoreModule_ResourceAccessWriteOnly), + ReadWrite = $(kCoreModule_ResourceAccessReadWrite), + RasterizerOrdered = $(kCoreModule_ResourceAccessRasterizerOrdered), + Feedback = $(kCoreModule_ResourceAccessFeedback), +} + /// Represents an opaque descriptor type, such as textures, samplers, and buffers etc, /// whose size may be undefined and can't be directly accessed as ordinary data. [sealed] @@ -21974,6 +21984,7 @@ interface IOpaqueDescriptor { /// The kind of the descriptor. static const DescriptorKind kind; + static const DescriptorAccess descriptorAccess; } __magic_type(DynamicResourceType) @@ -22005,7 +22016,8 @@ extension _Texture<T, Shape, isArray, isMS, sampleCount, access, isShadow, isCom typealias Handle = DescriptorHandle<This>; - static const DescriptorKind kind = isCombined!=0 ? DescriptorKind.CombinedTextureSampler : DescriptorKind.Texture; + static const DescriptorKind kind = isCombined != 0 ? DescriptorKind.CombinedTextureSampler : DescriptorKind.Texture; + static const DescriptorAccess descriptorAccess = (DescriptorAccess)access; __implicit_conversion($(kConversionCost_ImplicitDereference)) [ForceInline] @@ -22021,28 +22033,30 @@ struct DynamicResourceTypeInfo const char* name; const char* kind; const char* dynamicKind; + const char* access; }; const DynamicResourceTypeInfo kDynamicResourceCastableTypes[] = { - {"StructuredBuffer<T, L>", "Buffer", "General"}, - {"RWStructuredBuffer<T, L>", "Buffer", "General"}, - {"AppendStructuredBuffer<T, L>", "Buffer", "General"}, - {"ConsumeStructuredBuffer<T, L>", "Buffer", "General"}, - {"RasterizerOrderedStructuredBuffer<T, L>", "Buffer", "General"}, - {"ByteAddressBuffer", "Buffer", "General"}, - {"RWByteAddressBuffer", "Buffer", "General"}, - {"RasterizerOrderedByteAddressBuffer", "Buffer", "General"}, - {"SamplerState", "Sampler", "Sampler"}, - {"SamplerComparisonState", "Sampler", "Sampler"}, - {"ConstantBuffer<T, L>", "Buffer", "General"}, - {"TextureBuffer<T>", "Buffer", "General"}, - {"RaytracingAccelerationStructure", "AccelerationStructure", "General"}, + { "StructuredBuffer<T, L>", "Buffer", "General", "Read" }, + { "RWStructuredBuffer<T, L>", "Buffer", "General", "ReadWrite" }, + { "AppendStructuredBuffer<T, L>", "Buffer", "General", "ReadWrite" }, + { "ConsumeStructuredBuffer<T, L>", "Buffer", "General", "ReadWrite" }, + { "RasterizerOrderedStructuredBuffer<T, L>", "Buffer", "General", "ReadWrite" }, + { "ByteAddressBuffer", "Buffer", "General", "Read" }, + { "RWByteAddressBuffer", "Buffer", "General", "ReadWrite" }, + { "RasterizerOrderedByteAddressBuffer", "Buffer", "General", "ReadWrite" }, + { "SamplerState", "Sampler", "Sampler", "Unknown" }, + { "SamplerComparisonState", "Sampler", "Sampler", "Unknown" }, + { "ConstantBuffer<T, L>", "Buffer", "General", "Read"}, + { "TextureBuffer<T>", "Buffer", "General", "Read"}, + { "RaytracingAccelerationStructure", "AccelerationStructure", "General", "Read"}, }; for (auto type : kDynamicResourceCastableTypes) { auto dynamicKind = type.dynamicKind; auto kind = type.kind; auto typeName = type.name; + auto access = type.access; if (strstr(typeName, "<T, L>")) sb << "__generic<T, L : IBufferDataLayout>\n"; else if (strstr(typeName, "<T>")) @@ -22056,6 +22070,7 @@ extension $(typeName) : __IDynamicResourceCastable<__DynamicResourceKind.$(dynam __init(__DynamicResource res); static const DescriptorKind kind = DescriptorKind.$(kind); + static const DescriptorAccess descriptorAccess = DescriptorAccess.$(access); typealias Handle = DescriptorHandle<$(typeName)>; diff --git a/tests/language-feature/descriptor-handle/desc-handle-4.slang b/tests/language-feature/descriptor-handle/desc-handle-4.slang new file mode 100644 index 000000000..d04db3175 --- /dev/null +++ b/tests/language-feature/descriptor-handle/desc-handle-4.slang @@ -0,0 +1,34 @@ +//TEST:INTERPRET(filecheck=CHECK): + +#define CHECK(x) if (!(x)) return false + +DescriptorAccess getAccess<T : IOpaqueDescriptor>() +{ + return T.descriptorAccess; +} + +bool test() +{ + CHECK(getAccess<Texture2D>() == DescriptorAccess.Read); + CHECK(getAccess<SamplerState>() == DescriptorAccess.Unknown); + CHECK(getAccess<RasterizerOrderedStructuredBuffer<int>>() == DescriptorAccess.RasterizerOrdered); + CHECK(getAccess<RWStructuredBuffer<int>>() == DescriptorAccess.ReadWrite); + CHECK(getAccess<AppendStructuredBuffer<int>>() == DescriptorAccess.ReadWrite); + CHECK(getAccess<ConsumeStructuredBuffer<int>>() == DescriptorAccess.ReadWrite); + CHECK(getAccess<StructuredBuffer<int>>() == DescriptorAccess.Read); + CHECK(getAccess<ConstantBuffer<int>>() == DescriptorAccess.Read); + CHECK(getAccess<RWByteAddressBuffer>() == DescriptorAccess.ReadWrite); + CHECK(getAccess<ByteAddressBuffer>() == DescriptorAccess.Read); + CHECK(getAccess<RaytracingAccelerationStructure>() == DescriptorAccess.Read); + CHECK(getAccess<WTexture2DArray>() == DescriptorAccess.Write); + return true; +} + +void main() +{ + // CHECK: pass + if (test()) + printf("pass\n"); + else + printf("fail\n"); +}
\ No newline at end of file |
