diff options
| -rw-r--r-- | source/slang/parameter-binding.cpp | 34 | ||||
| -rw-r--r-- | tests/reflection/default-space.slang | 23 | ||||
| -rw-r--r-- | tests/reflection/default-space.slang.expected | 44 |
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" + } + ] +} +} |
