summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2025-04-30 16:38:57 -0700
committerGitHub <noreply@github.com>2025-04-30 16:38:57 -0700
commita8d7bb9f781fd77080f07bfaab54fbbcf3a3686d (patch)
tree3bda97cf2a0d9a7800e7201e948354962e13d2a4
parent7f1df9d0b31413e59846cc955d2a955d3f361e2a (diff)
Add `IOpaqueDescriptor::descriptorAccess`. (#6967)
* Add `IOpaqueHandle::descriptorAccess`. * Update doc. * fix.
-rw-r--r--docs/user-guide/03-convenience-features.md41
-rw-r--r--source/slang/hlsl.meta.slang43
-rw-r--r--tests/language-feature/descriptor-handle/desc-handle-4.slang34
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