summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/slang/parameter-binding.cpp34
-rw-r--r--tests/reflection/default-space.slang23
-rw-r--r--tests/reflection/default-space.slang.expected44
3 files changed, 94 insertions, 7 deletions
diff --git a/source/slang/parameter-binding.cpp b/source/slang/parameter-binding.cpp
index a74e4639f..e5057828f 100644
--- a/source/slang/parameter-binding.cpp
+++ b/source/slang/parameter-binding.cpp
@@ -2298,23 +2298,43 @@ RefPtr<ProgramLayout> generateParameterBindings(
// As a starting point, we will definitely need a "default" space if
// we are creating a default constant buffer, since it should get
// a binding in that "default" space.
+ //
bool needDefaultSpace = needDefaultConstantBuffer;
if (!needDefaultSpace)
{
+ // Next we will look at the global-scope parameters and see if
+ // any of them requires a `register` or `binding` that will
+ // thus need to land in a default space.
+ //
for (auto& parameterInfo : sharedContext.parameters)
{
SLANG_RELEASE_ASSERT(parameterInfo->varLayouts.Count() != 0);
auto firstVarLayout = parameterInfo->varLayouts.First();
- // Does the parameter have any resource usage that isn't just
- // allocating a whole register space?
+ // For each parameter, we will look at each resource it consumes.
+ //
for (auto resInfo : firstVarLayout->typeLayout->resourceInfos)
{
- if (resInfo.kind != LayoutResourceKind::RegisterSpace)
- {
- needDefaultSpace = true;
- break;
- }
+ // We don't care about whole register spaces/sets, since
+ // we don't need to allocate a default space/set for a parameter
+ // that itself consumes a whole space/set.
+ //
+ if( resInfo.kind == LayoutResourceKind::RegisterSpace )
+ continue;
+
+ // We also don't want to consider resource kinds for which
+ // the variable already has an (explicit) binding, since
+ // the space from the explicit binding will be used, so
+ // that a default space isn't needed.
+ //
+ if( parameterInfo->bindingInfo[resInfo.kind].count != 0 )
+ continue;
+
+ // Otherwise, we have a shader parameter that will need
+ // a default space or set to live in.
+ //
+ needDefaultSpace = true;
+ break;
}
}
}
diff --git a/tests/reflection/default-space.slang b/tests/reflection/default-space.slang
new file mode 100644
index 000000000..666714b79
--- /dev/null
+++ b/tests/reflection/default-space.slang
@@ -0,0 +1,23 @@
+//TEST:REFLECTION:-profile sm_5_1 -stage fragment -target hlsl
+
+// This test is to confirm that we do not allocate a "default"
+// space/set for global shader parameters unless it is
+// really required. In particular, if there are global-scope
+// resource parameters *but* they are all explicitly bound,
+// then a default space isn't needed.
+
+
+// An explicitly-bound global texture.
+Texture2D a : register(t0, space99);
+
+// An implicitly-bound global parameter block.
+//
+// This parameter should be given `space0`, because
+// it is the first available space after all explicitly-bound
+// parameters have claimed their registers/spaces.
+//
+struct B { Texture2D b; }
+ParameterBlock<B> b;
+
+float4 main() : SV_Target
+{ return 0.0; }
diff --git a/tests/reflection/default-space.slang.expected b/tests/reflection/default-space.slang.expected
new file mode 100644
index 000000000..548de2be0
--- /dev/null
+++ b/tests/reflection/default-space.slang.expected
@@ -0,0 +1,44 @@
+result code = 0
+standard error = {
+}
+standard output = {
+{
+ "parameters": [
+ {
+ "name": "a",
+ "binding": {"kind": "shaderResource", "space": 99, "index": 0},
+ "type": {
+ "kind": "resource",
+ "baseShape": "texture2D"
+ }
+ },
+ {
+ "name": "b",
+ "binding": {"kind": "registerSpace", "index": 0},
+ "type": {
+ "kind": "parameterBlock",
+ "elementType": {
+ "kind": "struct",
+ "name": "B",
+ "fields": [
+ {
+ "name": "b",
+ "type": {
+ "kind": "resource",
+ "baseShape": "texture2D"
+ },
+ "binding": {"kind": "shaderResource", "index": 0}
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "entryPoints": [
+ {
+ "name": "main",
+ "stage:": "fragment"
+ }
+ ]
+}
+}