diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2020-01-08 14:45:06 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-01-08 14:45:06 -0800 |
| commit | 0a856f458ff9f17d76bc646d008602713c6c66d1 (patch) | |
| tree | 8b4642a374fb5b4d06411f2a9c383a6079a7426e | |
| parent | cae5ddd4a2c9343ec7367c9049c5cc0c8628a9c4 (diff) | |
Cover a few corner cases in reflection API (#1163)
This change adds some new entry points to the reflection API to cover corner cases that a majority of applications won't care about.
These are most likely to come up for users who want to make a complete copy of the Slang reflection information into a data format of their own design.
All of the information is stuff that we already computed as part of layout, and just hadn't exposed:
* Alignment information for type layouts. This is only useful for ordinary/uniform data; in all other cases alignment is always one. Even for uniform/ordinary data, it is unlikely that any application would actually make use of it.
* Layout information for the result of an entry point function. This would be useful for applications that need to enumerate the varying outputs (user- or system-defined) of a shader. Having information available for `out` parameters but not the function result was inconsistent.
* The "element type" of a parameter block type (e.g., going from `ParameterBlock<X>` to `X`). This seems to have been an oversight since `ConstantBuffer<X>` appears to have been implemented, and the case for a type *layout* was handled.
* The "container" variable layout for a parameter block or constant buffer. It took a while for us to arrive at the current representation of layout for parameter groups, and most client code continues to use the original API that requires us to generated kludged "do what I mean" data. However, if we don't expose the more useful new representation fully, there is no way for users to take advantage of it!
The reflection test tool has been updated to print the new information where it makes sense, which provides us some level of coverage for the new code.
Unfortunately, this led to some cascading changes:
* First, a bunch of the tests had their output changed since they include new information. That's the easy bit.
* Next, the "container" and "element" var layouts don't actually have names (because there is no actual variable underlying them), which means that the code to emit variable names in the JSON dump needed to be condition.
* Making the `"name"` output conditional messed up a lot of the delicate logic that had been dealing with when to emit commas for the output JSON (JSON uses commas as separators, and doesn't allow trailing commas). I added a bit of new infrastructure to make it simple(-ish) to track when a comma actually needs to be output.
30 files changed, 1843 insertions, 84 deletions
@@ -1986,12 +1986,14 @@ extern "C" SLANG_API SlangReflectionType* spReflectionTypeLayout_GetType(SlangReflectionTypeLayout* type); SLANG_API size_t spReflectionTypeLayout_GetSize(SlangReflectionTypeLayout* type, SlangParameterCategory category); + SLANG_API int32_t spReflectionTypeLayout_getAlignment(SlangReflectionTypeLayout* type, SlangParameterCategory category); SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_GetFieldByIndex(SlangReflectionTypeLayout* type, unsigned index); SLANG_API size_t spReflectionTypeLayout_GetElementStride(SlangReflectionTypeLayout* type, SlangParameterCategory category); SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_GetElementTypeLayout(SlangReflectionTypeLayout* type); SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_GetElementVarLayout(SlangReflectionTypeLayout* type); + SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_getContainerVarLayout(SlangReflectionTypeLayout* type); SLANG_API SlangParameterCategory spReflectionTypeLayout_GetParameterCategory(SlangReflectionTypeLayout* type); @@ -2072,6 +2074,9 @@ extern "C" SLANG_API SlangReflectionVariableLayout* spReflectionEntryPoint_getVarLayout( SlangReflectionEntryPoint* entryPoint); + SLANG_API SlangReflectionVariableLayout* spReflectionEntryPoint_getResultVarLayout( + SlangReflectionEntryPoint* entryPoint); + SLANG_API int spReflectionEntryPoint_hasDefaultConstantBuffer( SlangReflectionEntryPoint* entryPoint); @@ -2346,6 +2351,11 @@ namespace slang return spReflectionTypeLayout_GetSize((SlangReflectionTypeLayout*) this, category); } + int32_t getAlignment(SlangParameterCategory category = SLANG_PARAMETER_CATEGORY_UNIFORM) + { + return spReflectionTypeLayout_getAlignment((SlangReflectionTypeLayout*) this, category); + } + unsigned int getFieldCount() { return getType()->getFieldCount(); @@ -2394,6 +2404,11 @@ namespace slang return (VariableLayoutReflection*)spReflectionTypeLayout_GetElementVarLayout((SlangReflectionTypeLayout*) this); } + VariableLayoutReflection* getContainerVarLayout() + { + return (VariableLayoutReflection*)spReflectionTypeLayout_getContainerVarLayout((SlangReflectionTypeLayout*) this); + } + // How is this type supposed to be bound? ParameterCategory getParameterCategory() { @@ -2636,6 +2651,11 @@ namespace slang return getVarLayout()->getTypeLayout(); } + VariableLayoutReflection* getResultVarLayout() + { + return (VariableLayoutReflection*) spReflectionEntryPoint_getResultVarLayout((SlangReflectionEntryPoint*) this); + } + bool hasDefaultConstantBuffer() { return spReflectionEntryPoint_hasDefaultConstantBuffer((SlangReflectionEntryPoint*) this) != 0; diff --git a/source/slang/slang-reflection.cpp b/source/slang/slang-reflection.cpp index 8901f6bdd..c0c5bd72f 100644 --- a/source/slang/slang-reflection.cpp +++ b/source/slang/slang-reflection.cpp @@ -357,9 +357,9 @@ SLANG_API SlangReflectionType* spReflectionType_GetElementType(SlangReflectionTy { return (SlangReflectionType*) arrayType->baseType.Ptr(); } - else if( auto constantBufferType = as<ConstantBufferType>(type)) + else if( auto parameterGroupType = as<ParameterGroupType>(type)) { - return convert(constantBufferType->elementType.Ptr()); + return convert(parameterGroupType->elementType.Ptr()); } else if( auto vectorType = as<VectorExpressionType>(type)) { @@ -680,6 +680,21 @@ SLANG_API size_t spReflectionTypeLayout_GetSize(SlangReflectionTypeLayout* inTyp return getReflectionSize(info->count); } +SLANG_API int32_t spReflectionTypeLayout_getAlignment(SlangReflectionTypeLayout* inTypeLayout, SlangParameterCategory category) +{ + auto typeLayout = convert(inTypeLayout); + if(!typeLayout) return 0; + + if( category == SLANG_PARAMETER_CATEGORY_UNIFORM ) + { + return int32_t(typeLayout->uniformAlignment); + } + else + { + return 1; + } +} + SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_GetFieldByIndex(SlangReflectionTypeLayout* inTypeLayout, unsigned index) { auto typeLayout = convert(inTypeLayout); @@ -758,9 +773,22 @@ SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_GetElementVarLay auto typeLayout = convert(inTypeLayout); if(!typeLayout) return nullptr; - if( auto constantBufferTypeLayout = as<ParameterGroupTypeLayout>(typeLayout)) + if( auto parameterGroupTypeLayout = as<ParameterGroupTypeLayout>(typeLayout)) { - return convert(constantBufferTypeLayout->elementVarLayout.Ptr()); + return convert(parameterGroupTypeLayout->elementVarLayout.Ptr()); + } + + return nullptr; +} + +SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_getContainerVarLayout(SlangReflectionTypeLayout* inTypeLayout) +{ + auto typeLayout = convert(inTypeLayout); + if(!typeLayout) return nullptr; + + if( auto parameterGroupTypeLayout = as<ParameterGroupTypeLayout>(typeLayout)) + { + return convert(parameterGroupTypeLayout->containerVarLayout.Ptr()); } return nullptr; @@ -1300,6 +1328,17 @@ SLANG_API SlangReflectionVariableLayout* spReflectionEntryPoint_getVarLayout( return convert(entryPointLayout->parametersLayout); } +SLANG_API SlangReflectionVariableLayout* spReflectionEntryPoint_getResultVarLayout( + SlangReflectionEntryPoint* inEntryPoint) +{ + auto entryPointLayout = convert(inEntryPoint); + if(!entryPointLayout) + return nullptr; + + return convert(entryPointLayout->resultLayout); +} + + static bool hasDefaultConstantBuffer(ScopeLayout* layout) { auto typeLayout = layout->parametersLayout->getTypeLayout(); diff --git a/tests/cross-compile/cpp-resource-reflection.slang.32.expected b/tests/cross-compile/cpp-resource-reflection.slang.32.expected index 7f88c134e..f40cc0fcc 100644 --- a/tests/cross-compile/cpp-resource-reflection.slang.32.expected +++ b/tests/cross-compile/cpp-resource-reflection.slang.32.expected @@ -38,6 +38,42 @@ standard output = { "binding": {"kind": "uniform", "offset": 8, "size": 4} } ] + }, + "containerVarLayout": { + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "name": "Thing", + "fields": [ + { + "name": "a", + "type": { + "kind": "scalar", + "scalarType": "int32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + { + "name": "b", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 4, "size": 4} + }, + { + "name": "c", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 8, "size": 4} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 12} } } }, diff --git a/tests/cross-compile/cpp-resource-reflection.slang.64.expected b/tests/cross-compile/cpp-resource-reflection.slang.64.expected index a0e5241f0..2a03aaa91 100644 --- a/tests/cross-compile/cpp-resource-reflection.slang.64.expected +++ b/tests/cross-compile/cpp-resource-reflection.slang.64.expected @@ -38,6 +38,42 @@ standard output = { "binding": {"kind": "uniform", "offset": 8, "size": 4} } ] + }, + "containerVarLayout": { + "binding": {"kind": "uniform", "offset": 0, "size": 8} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "name": "Thing", + "fields": [ + { + "name": "a", + "type": { + "kind": "scalar", + "scalarType": "int32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + { + "name": "b", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 4, "size": 4} + }, + { + "name": "c", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 8, "size": 4} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 12} } } }, diff --git a/tests/reflection/arrays.hlsl.expected b/tests/reflection/arrays.hlsl.expected index f815ea88c..2152ed0df 100644 --- a/tests/reflection/arrays.hlsl.expected +++ b/tests/reflection/arrays.hlsl.expected @@ -42,6 +42,46 @@ standard output = { "binding": {"kind": "uniform", "offset": 164, "size": 4} } ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "fields": [ + { + "name": "x", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + { + "name": "a", + "type": { + "kind": "array", + "elementCount": 10, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + }, + "uniformStride": 16 + }, + "binding": {"kind": "uniform", "offset": 16, "size": 148} + }, + { + "name": "y", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 164, "size": 4} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 168} } } }, @@ -102,7 +142,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/attribute.slang.expected b/tests/reflection/attribute.slang.expected index 4348b898f..b15c87df8 100644 --- a/tests/reflection/attribute.slang.expected +++ b/tests/reflection/attribute.slang.expected @@ -45,6 +45,49 @@ standard output = { ] } ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "name": "A", + "fields": [ + { + "name": "x", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + { + "name": "y", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 4, "size": 4}, + "userAttribs": [{ + "name": "DefaultValue", + "arguments": [ + 1 + ] + } + ] + } + ], + "userAttribs": [{ + "name": "MyStruct", + "arguments": [ + 0, + 1.000000 + ] + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 8} } } }, @@ -89,6 +132,49 @@ standard output = { ] } ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "name": "B", + "fields": [ + { + "name": "x", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + { + "name": "z", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 4, "size": 4}, + "userAttribs": [{ + "name": "DefaultValue", + "arguments": [ + 2 + ] + } + ] + } + ], + "userAttribs": [{ + "name": "MyStruct", + "arguments": [ + 0, + 2.000000 + ] + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 8} } } } diff --git a/tests/reflection/binding-gl.hlsl.expected b/tests/reflection/binding-gl.hlsl.expected index 1b5e7354f..8c2e761b5 100644 --- a/tests/reflection/binding-gl.hlsl.expected +++ b/tests/reflection/binding-gl.hlsl.expected @@ -42,6 +42,46 @@ standard output = { "binding": {"kind": "uniform", "offset": 176, "size": 4} } ] + }, + "containerVarLayout": { + "binding": {"kind": "descriptorTableSlot", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "fields": [ + { + "name": "x", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + { + "name": "a", + "type": { + "kind": "array", + "elementCount": 10, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + }, + "uniformStride": 16 + }, + "binding": {"kind": "uniform", "offset": 16, "size": 160} + }, + { + "name": "y", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 176, "size": 4} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 192} } } }, @@ -98,7 +138,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/binding-push-constant-gl.hlsl.expected b/tests/reflection/binding-push-constant-gl.hlsl.expected index ed6983364..13dfe2fcd 100644 --- a/tests/reflection/binding-push-constant-gl.hlsl.expected +++ b/tests/reflection/binding-push-constant-gl.hlsl.expected @@ -42,6 +42,46 @@ standard output = { "binding": {"kind": "uniform", "offset": 176, "size": 4} } ] + }, + "containerVarLayout": { + "binding": {"kind": "descriptorTableSlot", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "fields": [ + { + "name": "x", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + { + "name": "a", + "type": { + "kind": "array", + "elementCount": 10, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + }, + "uniformStride": 16 + }, + "binding": {"kind": "uniform", "offset": 16, "size": 160} + }, + { + "name": "y", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 176, "size": 4} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 192} } } }, @@ -71,6 +111,34 @@ standard output = { "binding": {"kind": "uniform", "offset": 4, "size": 4} } ] + }, + "containerVarLayout": { + "binding": {"kind": "pushConstantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "name": "MyPushConstantStruct", + "fields": [ + { + "name": "pushX", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + { + "name": "pushY", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 4, "size": 4} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 16} } } }, @@ -127,7 +195,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/buffer-layout.slang.1.expected b/tests/reflection/buffer-layout.slang.1.expected index 890f31481..0b01f54a1 100644 --- a/tests/reflection/buffer-layout.slang.1.expected +++ b/tests/reflection/buffer-layout.slang.1.expected @@ -81,6 +81,85 @@ standard output = { "binding": {"kind": "uniform", "offset": 80, "size": 4} } ] + }, + "containerVarLayout": { + "binding": {"kind": "descriptorTableSlot", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "name": "S", + "fields": [ + { + "name": "z", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + { + "name": "a", + "type": { + "kind": "struct", + "name": "A", + "fields": [ + { + "name": "x", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + { + "name": "y", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 4, "size": 4} + } + ] + }, + "binding": {"kind": "uniform", "offset": 16, "size": 16} + }, + { + "name": "b", + "type": { + "kind": "scalar", + "scalarType": "int32" + }, + "binding": {"kind": "uniform", "offset": 32, "size": 4} + }, + { + "name": "c", + "type": { + "kind": "array", + "elementCount": 2, + "elementType": { + "kind": "vector", + "elementCount": 2, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "uniformStride": 16 + }, + "binding": {"kind": "uniform", "offset": 48, "size": 32} + }, + { + "name": "d", + "type": { + "kind": "scalar", + "scalarType": "int32" + }, + "binding": {"kind": "uniform", "offset": 80, "size": 4} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 96} } } }, diff --git a/tests/reflection/buffer-layout.slang.expected b/tests/reflection/buffer-layout.slang.expected index 25a41bc6d..4fc7b2381 100644 --- a/tests/reflection/buffer-layout.slang.expected +++ b/tests/reflection/buffer-layout.slang.expected @@ -81,6 +81,85 @@ standard output = { "binding": {"kind": "uniform", "offset": 56, "size": 4} } ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "name": "S", + "fields": [ + { + "name": "z", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + { + "name": "a", + "type": { + "kind": "struct", + "name": "A", + "fields": [ + { + "name": "x", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + }, + { + "name": "y", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 4, "size": 4} + } + ] + }, + "binding": {"kind": "uniform", "offset": 16, "size": 8} + }, + { + "name": "b", + "type": { + "kind": "scalar", + "scalarType": "int32" + }, + "binding": {"kind": "uniform", "offset": 24, "size": 4} + }, + { + "name": "c", + "type": { + "kind": "array", + "elementCount": 2, + "elementType": { + "kind": "vector", + "elementCount": 2, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "uniformStride": 16 + }, + "binding": {"kind": "uniform", "offset": 32, "size": 24} + }, + { + "name": "d", + "type": { + "kind": "scalar", + "scalarType": "int32" + }, + "binding": {"kind": "uniform", "offset": 56, "size": 4} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 60} } } }, diff --git a/tests/reflection/cross-compile.slang.expected b/tests/reflection/cross-compile.slang.expected index a54598d08..e3dd63095 100644 --- a/tests/reflection/cross-compile.slang.expected +++ b/tests/reflection/cross-compile.slang.expected @@ -40,6 +40,29 @@ standard output = { "binding": {"kind": "uniform", "offset": 0, "size": 12} } ] + }, + "containerVarLayout": { + "binding": {"kind": "descriptorTableSlot", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "fields": [ + { + "name": "c", + "type": { + "kind": "vector", + "elementCount": 3, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 0, "size": 12} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 16} } } } @@ -47,7 +70,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/default-space.slang.expected b/tests/reflection/default-space.slang.expected index 548de2be0..5ba17790c 100644 --- a/tests/reflection/default-space.slang.expected +++ b/tests/reflection/default-space.slang.expected @@ -30,6 +30,26 @@ standard output = { "binding": {"kind": "shaderResource", "index": 0} } ] + }, + "containerVarLayout": { + "binding": {"kind": "registerSpace", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "name": "B", + "fields": [ + { + "name": "b", + "type": { + "kind": "resource", + "baseShape": "texture2D" + }, + "binding": {"kind": "shaderResource", "index": 0} + } + ] + }, + "binding": {"kind": "shaderResource", "index": 0} } } } @@ -37,7 +57,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/explicit-register-space.slang.expected b/tests/reflection/explicit-register-space.slang.expected index c9e32c4f5..0c282f5f9 100644 --- a/tests/reflection/explicit-register-space.slang.expected +++ b/tests/reflection/explicit-register-space.slang.expected @@ -16,7 +16,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/global-type-params.slang.expected b/tests/reflection/global-type-params.slang.expected index 8f6ba2838..4fb7d0279 100644 --- a/tests/reflection/global-type-params.slang.expected +++ b/tests/reflection/global-type-params.slang.expected @@ -22,6 +22,26 @@ standard output = { "binding": {"kind": "generic", "index": 0} } ] + }, + "containerVarLayout": { + + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "name": "S", + "fields": [ + { + "name": "p", + "type": { + "kind": "GenericTypeParameter", + "name": "TParam2" + }, + "binding": {"kind": "generic", "index": 0} + } + ] + }, + "binding": {"kind": "generic", "index": 0} } } }, @@ -33,6 +53,16 @@ standard output = { "elementType": { "kind": "GenericTypeParameter", "name": "TParam" + }, + "containerVarLayout": { + + }, + "elementVarLayout": { + "type": { + "kind": "GenericTypeParameter", + "name": "TParam" + }, + "binding": {"kind": "generic", "index": 0} } } }, @@ -96,6 +126,53 @@ standard output = { "binding": {"kind": "uniform", "offset": 32, "size": 16} } ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "fields": [ + { + "name": "u", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 0, "size": 16} + }, + { + "name": "v", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 16, "size": 16} + }, + { + "name": "w", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 32, "size": 16} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 48} } } } @@ -103,7 +180,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ], "typeParams": diff --git a/tests/reflection/matrix-layout.slang.1.expected b/tests/reflection/matrix-layout.slang.1.expected index 57fd29c6d..0683a6edc 100644 --- a/tests/reflection/matrix-layout.slang.1.expected +++ b/tests/reflection/matrix-layout.slang.1.expected @@ -52,6 +52,56 @@ standard output = { "binding": {"kind": "uniform", "offset": 96, "size": 60} } ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "fields": [ + { + "name": "aa", + "type": { + "kind": "matrix", + "rowCount": 3, + "columnCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 0, "size": 48} + }, + { + "name": "ab", + "type": { + "kind": "matrix", + "rowCount": 3, + "columnCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 48, "size": 48} + }, + { + "name": "ac", + "type": { + "kind": "matrix", + "rowCount": 3, + "columnCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 96, "size": 60} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 156} } } }, @@ -113,6 +163,66 @@ standard output = { "binding": {"kind": "uniform", "offset": 0, "size": 156} } ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "fields": [ + { + "name": "b", + "type": { + "kind": "struct", + "name": "SB", + "fields": [ + { + "name": "ba", + "type": { + "kind": "matrix", + "rowCount": 3, + "columnCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 0, "size": 48} + }, + { + "name": "bb", + "type": { + "kind": "matrix", + "rowCount": 3, + "columnCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 48, "size": 48} + }, + { + "name": "bc", + "type": { + "kind": "matrix", + "rowCount": 3, + "columnCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 96, "size": 60} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 156} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 156} } } } @@ -120,7 +230,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/matrix-layout.slang.expected b/tests/reflection/matrix-layout.slang.expected index c8aeb2ae1..c81207216 100644 --- a/tests/reflection/matrix-layout.slang.expected +++ b/tests/reflection/matrix-layout.slang.expected @@ -52,6 +52,56 @@ standard output = { "binding": {"kind": "uniform", "offset": 112, "size": 60} } ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "fields": [ + { + "name": "aa", + "type": { + "kind": "matrix", + "rowCount": 3, + "columnCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 0, "size": 60} + }, + { + "name": "ab", + "type": { + "kind": "matrix", + "rowCount": 3, + "columnCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 64, "size": 48} + }, + { + "name": "ac", + "type": { + "kind": "matrix", + "rowCount": 3, + "columnCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 112, "size": 60} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 172} } } }, @@ -113,6 +163,66 @@ standard output = { "binding": {"kind": "uniform", "offset": 0, "size": 172} } ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "fields": [ + { + "name": "b", + "type": { + "kind": "struct", + "name": "SB", + "fields": [ + { + "name": "ba", + "type": { + "kind": "matrix", + "rowCount": 3, + "columnCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 0, "size": 60} + }, + { + "name": "bb", + "type": { + "kind": "matrix", + "rowCount": 3, + "columnCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 64, "size": 48} + }, + { + "name": "bc", + "type": { + "kind": "matrix", + "rowCount": 3, + "columnCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 112, "size": 60} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 172} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 172} } } } @@ -120,7 +230,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/multi-file.hlsl.expected b/tests/reflection/multi-file.hlsl.expected index 814c648e0..1cbc73f5c 100644 --- a/tests/reflection/multi-file.hlsl.expected +++ b/tests/reflection/multi-file.hlsl.expected @@ -72,6 +72,61 @@ standard output = { "binding": {"kind": "uniform", "offset": 32, "size": 8} } ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "fields": [ + { + "name": "vertexCA", + "type": { + "kind": "vector", + "elementCount": 3, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 0, "size": 12} + }, + { + "name": "vertexCB", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 12, "size": 4} + }, + { + "name": "vertexCC", + "type": { + "kind": "vector", + "elementCount": 3, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 16, "size": 12} + }, + { + "name": "vertexCD", + "type": { + "kind": "vector", + "elementCount": 2, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 32, "size": 8} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 40} } } }, @@ -143,6 +198,61 @@ standard output = { "binding": {"kind": "uniform", "offset": 32, "size": 8} } ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "fields": [ + { + "name": "fragmentCA", + "type": { + "kind": "vector", + "elementCount": 3, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 0, "size": 12} + }, + { + "name": "fragmentCB", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 12, "size": 4} + }, + { + "name": "fragmentCC", + "type": { + "kind": "vector", + "elementCount": 3, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 16, "size": 12} + }, + { + "name": "fragmentCD", + "type": { + "kind": "vector", + "elementCount": 2, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 32, "size": 8} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 40} } } }, @@ -214,6 +324,61 @@ standard output = { "binding": {"kind": "uniform", "offset": 32, "size": 8} } ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "fields": [ + { + "name": "sharedCA", + "type": { + "kind": "vector", + "elementCount": 3, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 0, "size": 12} + }, + { + "name": "sharedCB", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 12, "size": 4} + }, + { + "name": "sharedCC", + "type": { + "kind": "vector", + "elementCount": 3, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 16, "size": 12} + }, + { + "name": "sharedCD", + "type": { + "kind": "vector", + "elementCount": 2, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 32, "size": 8} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 40} } } }, @@ -237,11 +402,35 @@ standard output = { "entryPoints": [ { "name": "mainVS", - "stage:": "vertex" + "stage:": "vertex", + "result:": { + "semanticName": "SV_POSITION", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } }, { "name": "mainFS", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/parameter-block-explicit-space.slang.expected b/tests/reflection/parameter-block-explicit-space.slang.expected index f7944c644..a96f95961 100644 --- a/tests/reflection/parameter-block-explicit-space.slang.expected +++ b/tests/reflection/parameter-block-explicit-space.slang.expected @@ -52,6 +52,60 @@ standard output = { "binding": {"kind": "samplerState", "index": 0} } ] + }, + "containerVarLayout": { + "bindings": [ + {"kind": "constantBuffer", "index": 0}, + {"kind": "registerSpace", "index": 0} + ] + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "name": "A", + "fields": [ + { + "name": "au", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 0, "size": 16} + }, + { + "name": "at1", + "type": { + "kind": "resource", + "baseShape": "texture2D" + }, + "binding": {"kind": "shaderResource", "index": 0} + }, + { + "name": "at2", + "type": { + "kind": "resource", + "baseShape": "texture2D" + }, + "binding": {"kind": "shaderResource", "index": 1} + }, + { + "name": "as", + "type": { + "kind": "samplerState" + }, + "binding": {"kind": "samplerState", "index": 0} + } + ] + }, + "bindings": [ + {"kind": "shaderResource", "index": 0, "count": 2}, + {"kind": "samplerState", "index": 0}, + {"kind": "uniform", "offset": 0, "size": 16} + ] } } }, @@ -95,6 +149,52 @@ standard output = { "binding": {"kind": "samplerState", "index": 0} } ] + }, + "containerVarLayout": { + "bindings": [ + {"kind": "constantBuffer", "index": 0}, + {"kind": "registerSpace", "index": 0} + ] + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "name": "B", + "fields": [ + { + "name": "bu", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 0, "size": 16} + }, + { + "name": "bt", + "type": { + "kind": "resource", + "baseShape": "texture2D" + }, + "binding": {"kind": "shaderResource", "index": 0} + }, + { + "name": "bs", + "type": { + "kind": "samplerState" + }, + "binding": {"kind": "samplerState", "index": 0} + } + ] + }, + "bindings": [ + {"kind": "shaderResource", "index": 0}, + {"kind": "samplerState", "index": 0}, + {"kind": "uniform", "offset": 0, "size": 16} + ] } } } @@ -102,7 +202,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/parameter-block.slang.1.expected b/tests/reflection/parameter-block.slang.1.expected index bbd52a784..b8f462e60 100644 --- a/tests/reflection/parameter-block.slang.1.expected +++ b/tests/reflection/parameter-block.slang.1.expected @@ -32,6 +32,36 @@ standard output = { "binding": {"kind": "samplerState", "index": 0} } ] + }, + "containerVarLayout": { + + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "name": "Helper", + "fields": [ + { + "name": "t", + "type": { + "kind": "resource", + "baseShape": "texture2D" + }, + "binding": {"kind": "shaderResource", "index": 0} + }, + { + "name": "s", + "type": { + "kind": "samplerState" + }, + "binding": {"kind": "samplerState", "index": 0} + } + ] + }, + "bindings": [ + {"kind": "shaderResource", "index": 0}, + {"kind": "samplerState", "index": 0} + ] } } }, @@ -47,7 +77,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/parameter-block.slang.2.expected b/tests/reflection/parameter-block.slang.2.expected index e692718e8..e4bf9b6cb 100644 --- a/tests/reflection/parameter-block.slang.2.expected +++ b/tests/reflection/parameter-block.slang.2.expected @@ -29,6 +29,36 @@ standard output = { "binding": {"kind": "samplerState", "index": 0} } ] + }, + "containerVarLayout": { + "binding": {"kind": "registerSpace", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "name": "Helper", + "fields": [ + { + "name": "t", + "type": { + "kind": "resource", + "baseShape": "texture2D" + }, + "binding": {"kind": "shaderResource", "index": 0} + }, + { + "name": "s", + "type": { + "kind": "samplerState" + }, + "binding": {"kind": "samplerState", "index": 0} + } + ] + }, + "bindings": [ + {"kind": "shaderResource", "index": 0}, + {"kind": "samplerState", "index": 0} + ] } } }, @@ -44,7 +74,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/parameter-block.slang.expected b/tests/reflection/parameter-block.slang.expected index 58344bc12..0909dc8cf 100644 --- a/tests/reflection/parameter-block.slang.expected +++ b/tests/reflection/parameter-block.slang.expected @@ -29,6 +29,33 @@ standard output = { "binding": {"kind": "descriptorTableSlot", "index": 1} } ] + }, + "containerVarLayout": { + "binding": {"kind": "registerSpace", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "name": "Helper", + "fields": [ + { + "name": "t", + "type": { + "kind": "resource", + "baseShape": "texture2D" + }, + "binding": {"kind": "descriptorTableSlot", "index": 0} + }, + { + "name": "s", + "type": { + "kind": "samplerState" + }, + "binding": {"kind": "descriptorTableSlot", "index": 1} + } + ] + }, + "binding": {"kind": "descriptorTableSlot", "index": 0, "count": 2} } } }, @@ -44,7 +71,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/reflect-imported-code.hlsl.expected b/tests/reflection/reflect-imported-code.hlsl.expected index 78e7ce195..5d51ddb5c 100644 --- a/tests/reflection/reflect-imported-code.hlsl.expected +++ b/tests/reflection/reflect-imported-code.hlsl.expected @@ -36,6 +36,25 @@ standard output = { "binding": {"kind": "uniform", "offset": 0, "size": 4} } ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "fields": [ + { + "name": "c", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} } } }, @@ -71,6 +90,25 @@ standard output = { "binding": {"kind": "uniform", "offset": 0, "size": 4} } ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "fields": [ + { + "name": "c_i", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} } } } @@ -78,7 +116,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/reflection0.hlsl.expected b/tests/reflection/reflection0.hlsl.expected index e4d6070ca..64b8fcd85 100644 --- a/tests/reflection/reflection0.hlsl.expected +++ b/tests/reflection/reflection0.hlsl.expected @@ -36,6 +36,25 @@ standard output = { "binding": {"kind": "uniform", "offset": 0, "size": 4} } ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "fields": [ + { + "name": "c", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} + } + ] + }, + "binding": {"kind": "uniform", "offset": 0, "size": 4} } } } @@ -43,7 +62,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/resource-in-cbuffer.hlsl.expected b/tests/reflection/resource-in-cbuffer.hlsl.expected index d14fbe577..03299a8e0 100644 --- a/tests/reflection/resource-in-cbuffer.hlsl.expected +++ b/tests/reflection/resource-in-cbuffer.hlsl.expected @@ -48,6 +48,56 @@ standard output = { "binding": {"kind": "samplerState", "index": 0} } ] + }, + "containerVarLayout": { + "binding": {"kind": "constantBuffer", "index": 0} + }, + "elementVarLayout": { + "type": { + "kind": "struct", + "fields": [ + { + "name": "v", + "type": { + "kind": "vector", + "elementCount": 3, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + }, + "binding": {"kind": "uniform", "offset": 0, "size": 12} + }, + { + "name": "myTexture", + "type": { + "kind": "resource", + "baseShape": "texture2D" + }, + "binding": {"kind": "shaderResource", "index": 0} + }, + { + "name": "c", + "type": { + "kind": "scalar", + "scalarType": "float32" + }, + "binding": {"kind": "uniform", "offset": 12, "size": 4} + }, + { + "name": "mySampler", + "type": { + "kind": "samplerState" + }, + "binding": {"kind": "samplerState", "index": 0} + } + ] + }, + "bindings": [ + {"kind": "shaderResource", "index": 0}, + {"kind": "samplerState", "index": 0}, + {"kind": "uniform", "offset": 0, "size": 16} + ] } } } @@ -55,7 +105,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/sample-index-input.hlsl.expected b/tests/reflection/sample-index-input.hlsl.expected index 5bf5f297e..d0bc3c1b9 100644 --- a/tests/reflection/sample-index-input.hlsl.expected +++ b/tests/reflection/sample-index-input.hlsl.expected @@ -45,7 +45,20 @@ standard output = { } } ], - "usesAnySampleRateInput": true + "usesAnySampleRateInput": true, + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/sample-rate-input.hlsl.expected b/tests/reflection/sample-rate-input.hlsl.expected index 0c86ebecb..485594fae 100644 --- a/tests/reflection/sample-rate-input.hlsl.expected +++ b/tests/reflection/sample-rate-input.hlsl.expected @@ -51,7 +51,20 @@ standard output = { } } ], - "usesAnySampleRateInput": true + "usesAnySampleRateInput": true, + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/shared-modifier.hlsl.expected b/tests/reflection/shared-modifier.hlsl.expected index ddb982177..782e038de 100644 --- a/tests/reflection/shared-modifier.hlsl.expected +++ b/tests/reflection/shared-modifier.hlsl.expected @@ -40,7 +40,20 @@ standard output = { } } } - ] + ], + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/structured-buffer.slang.expected b/tests/reflection/structured-buffer.slang.expected index 3e79fd1c5..d0cb3e501 100644 --- a/tests/reflection/structured-buffer.slang.expected +++ b/tests/reflection/structured-buffer.slang.expected @@ -78,7 +78,20 @@ standard output = { "entryPoints": [ { "name": "main", - "stage:": "fragment" + "stage:": "fragment", + "result:": { + "stage": "fragment", + "binding": {"kind": "varyingOutput", "index": 0}, + "semanticName": "SV_TARGET", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tests/reflection/vertex-input-semantics.hlsl.expected b/tests/reflection/vertex-input-semantics.hlsl.expected index 06b7bc95a..e15a3a258 100644 --- a/tests/reflection/vertex-input-semantics.hlsl.expected +++ b/tests/reflection/vertex-input-semantics.hlsl.expected @@ -160,7 +160,18 @@ standard output = { ] } } - ] + ], + "result:": { + "semanticName": "SV_POSITION", + "type": { + "kind": "vector", + "elementCount": 4, + "elementType": { + "kind": "scalar", + "scalarType": "float32" + } + } + } } ] } diff --git a/tools/slang-reflection-test/slang-reflection-test-main.cpp b/tools/slang-reflection-test/slang-reflection-test-main.cpp index 7480b6ae9..6537362d7 100644 --- a/tools/slang-reflection-test/slang-reflection-test-main.cpp +++ b/tools/slang-reflection-test/slang-reflection-test-main.cpp @@ -12,8 +12,14 @@ struct PrettyWriter { + struct CommaState + { + bool needComma = false; + }; + bool startOfLine = true; int indent = 0; + CommaState* commaState = nullptr; }; static void writeRaw(PrettyWriter& writer, char const* begin, char const* end) @@ -154,6 +160,44 @@ static void write(PrettyWriter& writer, float val) Slang::StdWriters::getOut().print("%f", val); } + /// Type for tracking whether a comma is needed in a comma-separated JSON list +struct CommaTrackerRAII +{ + CommaTrackerRAII(PrettyWriter& writer) + : m_writer(&writer) + , m_previousState(writer.commaState) + { + writer.commaState = &m_state; + } + + ~CommaTrackerRAII() + { + m_writer->commaState = m_previousState; + } + +private: + PrettyWriter::CommaState m_state; + + PrettyWriter* m_writer; + PrettyWriter::CommaState* m_previousState; +}; + + /// Call before items in a comma-separated JSON list to emit the comma if/when needed +static void comma(PrettyWriter& writer) +{ + if( auto state = writer.commaState ) + { + if( !state->needComma ) + { + state->needComma = true; + return; + } + } + + write(writer, ",\n"); +} + + static void emitReflectionVarInfoJSON(PrettyWriter& writer, slang::VariableReflection* var); static void emitReflectionTypeLayoutJSON(PrettyWriter& writer, slang::TypeLayoutReflection* type); static void emitReflectionTypeJSON(PrettyWriter& writer, slang::TypeReflection* type); @@ -234,7 +278,7 @@ static void emitReflectionVarBindingInfoJSON( auto stage = var->getStage(); if (stage != SLANG_STAGE_NONE) { - write(writer, ",\n"); + comma(writer); char const* stageName = "UNKNOWN"; switch (stage) { @@ -259,7 +303,7 @@ static void emitReflectionVarBindingInfoJSON( if (categoryCount) { - write(writer, ",\n"); + comma(writer); if( categoryCount != 1 ) { write(writer,"\"bindings\": [\n"); @@ -298,14 +342,14 @@ static void emitReflectionVarBindingInfoJSON( if (auto semanticName = var->getSemanticName()) { - write(writer, ",\n"); + comma(writer); write(writer,"\"semanticName\": \""); write(writer, semanticName); write(writer, "\""); if (auto semanticIndex = var->getSemanticIndex()) { - write(writer, ",\n"); + comma(writer); write(writer,"\"semanticIndex\": "); write(writer, int(semanticIndex)); } @@ -328,7 +372,8 @@ static void emitReflectionModifierInfoJSON( { if( var->findModifier(slang::Modifier::Shared) ) { - write(writer, ",\n\"shared\": true"); + comma(writer); + write(writer, "\"shared\": true"); } } @@ -409,9 +454,15 @@ static void emitReflectionVarLayoutJSON( write(writer, "{\n"); indent(writer); - emitReflectionNameInfoJSON(writer, var->getName()); - write(writer, ",\n"); + CommaTrackerRAII commaTracker(writer); + if( auto name = var->getName() ) + { + comma(writer); + emitReflectionNameInfoJSON(writer, name); + } + + comma(writer); write(writer, "\"type\": "); emitReflectionTypeLayoutJSON(writer, var->getTypeLayout()); @@ -456,8 +507,9 @@ static void emitReflectionResourceTypeBaseInfoJSON( { auto shape = type->getResourceShape(); auto access = type->getResourceAccess(); + comma(writer); write(writer, "\"kind\": \"resource\""); - write(writer, ",\n"); + comma(writer); write(writer, "\"baseShape\": \""); switch (shape & SLANG_RESOURCE_BASE_SHAPE_MASK) { @@ -479,18 +531,19 @@ static void emitReflectionResourceTypeBaseInfoJSON( write(writer, "\""); if (shape & SLANG_TEXTURE_ARRAY_FLAG) { - write(writer, ",\n"); + comma(writer); write(writer, "\"array\": true"); } if (shape & SLANG_TEXTURE_MULTISAMPLE_FLAG) { - write(writer, ",\n"); + comma(writer); write(writer, "\"multisample\": true"); } if( access != SLANG_RESOURCE_ACCESS_READ ) { - write(writer, ",\n\"access\": \""); + comma(writer); + write(writer, "\"access\": \""); switch(access) { default: @@ -519,6 +572,7 @@ static void emitReflectionTypeInfoJSON( switch(kind) { case slang::TypeReflection::Kind::SamplerState: + comma(writer); write(writer, "\"kind\": \"samplerState\""); break; @@ -539,7 +593,7 @@ static void emitReflectionTypeInfoJSON( case SLANG_STRUCTURED_BUFFER: if( auto resultType = type->getResourceResultType() ) { - write(writer, ",\n"); + comma(writer); write(writer, "\"resultType\": "); emitReflectionTypeJSON( writer, @@ -551,8 +605,9 @@ static void emitReflectionTypeInfoJSON( break; case slang::TypeReflection::Kind::ConstantBuffer: + comma(writer); write(writer, "\"kind\": \"constantBuffer\""); - write(writer, ",\n"); + comma(writer); write(writer, "\"elementType\": "); emitReflectionTypeJSON( writer, @@ -560,8 +615,9 @@ static void emitReflectionTypeInfoJSON( break; case slang::TypeReflection::Kind::ParameterBlock: + comma(writer); write(writer, "\"kind\": \"parameterBlock\""); - write(writer, ",\n"); + comma(writer); write(writer, "\"elementType\": "); emitReflectionTypeJSON( writer, @@ -569,8 +625,9 @@ static void emitReflectionTypeInfoJSON( break; case slang::TypeReflection::Kind::TextureBuffer: + comma(writer); write(writer, "\"kind\": \"textureBuffer\""); - write(writer, ",\n"); + comma(writer); write(writer, "\"elementType\": "); emitReflectionTypeJSON( writer, @@ -578,8 +635,9 @@ static void emitReflectionTypeInfoJSON( break; case slang::TypeReflection::Kind::ShaderStorageBuffer: + comma(writer); write(writer, "\"kind\": \"shaderStorageBuffer\""); - write(writer, ",\n"); + comma(writer); write(writer, "\"elementType\": "); emitReflectionTypeJSON( writer, @@ -587,19 +645,21 @@ static void emitReflectionTypeInfoJSON( break; case slang::TypeReflection::Kind::Scalar: + comma(writer); write(writer, "\"kind\": \"scalar\""); - write(writer, ",\n"); + comma(writer); emitReflectionScalarTypeInfoJSON( writer, type->getScalarType()); break; case slang::TypeReflection::Kind::Vector: + comma(writer); write(writer, "\"kind\": \"vector\""); - write(writer, ",\n"); + comma(writer); write(writer, "\"elementCount\": "); write(writer, int(type->getElementCount())); - write(writer, ",\n"); + comma(writer); write(writer, "\"elementType\": "); emitReflectionTypeJSON( writer, @@ -607,14 +667,15 @@ static void emitReflectionTypeInfoJSON( break; case slang::TypeReflection::Kind::Matrix: + comma(writer); write(writer, "\"kind\": \"matrix\""); - write(writer, ",\n"); + comma(writer); write(writer, "\"rowCount\": "); write(writer, type->getRowCount()); - write(writer, ",\n"); + comma(writer); write(writer, "\"columnCount\": "); write(writer, type->getColumnCount()); - write(writer, ",\n"); + comma(writer); write(writer, "\"elementType\": "); emitReflectionTypeJSON( writer, @@ -624,11 +685,12 @@ static void emitReflectionTypeInfoJSON( case slang::TypeReflection::Kind::Array: { auto arrayType = type; + comma(writer); write(writer, "\"kind\": \"array\""); - write(writer, ",\n"); + comma(writer); write(writer, "\"elementCount\": "); write(writer, int(arrayType->getElementCount())); - write(writer, ",\n"); + comma(writer); write(writer, "\"elementType\": "); emitReflectionTypeJSON(writer, arrayType->getElementType()); } @@ -636,7 +698,9 @@ static void emitReflectionTypeInfoJSON( case slang::TypeReflection::Kind::Struct: { - write(writer, "\"kind\": \"struct\",\n"); + comma(writer); + write(writer, "\"kind\": \"struct\""); + comma(writer); write(writer, "\"fields\": [\n"); indent(writer); @@ -655,11 +719,15 @@ static void emitReflectionTypeInfoJSON( break; case slang::TypeReflection::Kind::GenericTypeParameter: - write(writer, "\"kind\": \"GenericTypeParameter\",\n"); + comma(writer); + write(writer, "\"kind\": \"GenericTypeParameter\""); + comma(writer); emitReflectionNameInfoJSON(writer, type->getName()); break; case slang::TypeReflection::Kind::Interface: - write(writer, "\"kind\": \"Interface\",\n"); + comma(writer); + write(writer, "\"kind\": \"Interface\""); + comma(writer); emitReflectionNameInfoJSON(writer, type->getName()); break; default: @@ -669,6 +737,66 @@ static void emitReflectionTypeInfoJSON( emitUserAttributes(writer, type); } +static void emitReflectionParameterGroupTypeLayoutInfoJSON( + PrettyWriter& writer, + slang::TypeLayoutReflection* typeLayout, + const char* kind) +{ + write(writer, "\"kind\": \""); + write(writer, kind); + write(writer, "\""); + + write(writer, ",\n\"elementType\": "); + emitReflectionTypeLayoutJSON( + writer, + typeLayout->getElementTypeLayout()); + + // Note: There is a subtle detail below when it comes to the + // container/element variable layouts that get nested inside + // a parameter group type layout. + // + // A top-level parameter group type layout like `ConstantBuffer<Foo>` + // needs to store both information about the `ConstantBuffer` part of + // things (e.g., it might consume 1 `binding`), as well as the `Foo` + // part (e.g., it might consume 4 bytes plus 1 `binding`), and there + // is offset information for each. + // + // The "element" part is easy: it is a variable layout for a variable + // of type `Foo`. The actual variable will be null, but everything else + // will be filled in as a client would expect. + // + // The "container" part is thornier: what should the type and type + // layout of the "container" variable be? The obvious answer (which + // the Slang reflection implementation uses today) is that the type + // is the type of the parameter group itself (e.g., `ConstantBuffer<Foo>`), + // and the layout is a dummy `TypeLayout` that just reflects the + // resource usage of the "container" part of things. + // + // That means that at runtime the "container var layout" will have + // a parameter group type (e.g., `TYPE_KIND_CONSTANT_BUFFER`) + // but its type layotu will be a base `TypeLayout` and not a + // `ParameterGroupLayout` (since that would introduce infinite regress). + // + // We thus have to guard here against the recursive path where + // we are emitting reflection info for the "container" part of things. + // + // TODO: We should probably + + { + CommaTrackerRAII commaTracker(writer); + + write(writer, ",\n\"containerVarLayout\": {\n"); + indent(writer); + emitReflectionVarBindingInfoJSON(writer, typeLayout->getContainerVarLayout()); + dedent(writer); + write(writer, "\n}"); + } + + write(writer, ",\n\"elementVarLayout\": "); + emitReflectionVarLayoutJSON( + writer, + typeLayout->getElementVarLayout()); +} static void emitReflectionTypeLayoutInfoJSON( PrettyWriter& writer, @@ -684,18 +812,22 @@ static void emitReflectionTypeLayoutInfoJSON( { auto arrayTypeLayout = typeLayout; auto elementTypeLayout = arrayTypeLayout->getElementTypeLayout(); + comma(writer); write(writer, "\"kind\": \"array\""); - write(writer, ",\n"); + + comma(writer); write(writer, "\"elementCount\": "); write(writer, int(arrayTypeLayout->getElementCount())); - write(writer, ",\n"); + + comma(writer); write(writer, "\"elementType\": "); emitReflectionTypeLayoutJSON( writer, elementTypeLayout); + if (arrayTypeLayout->getSize(SLANG_PARAMETER_CATEGORY_UNIFORM) != 0) { - write(writer, ",\n"); + comma(writer); write(writer, "\"uniformStride\": "); write(writer, int(arrayTypeLayout->getElementStride(SLANG_PARAMETER_CATEGORY_UNIFORM))); } @@ -706,12 +838,14 @@ static void emitReflectionTypeLayoutInfoJSON( { auto structTypeLayout = typeLayout; - write(writer, "\"kind\": \"struct\",\n"); + comma(writer); + write(writer, "\"kind\": \"struct\""); if( auto name = structTypeLayout->getName() ) { + comma(writer); emitReflectionNameInfoJSON(writer, structTypeLayout->getName()); - write(writer, ",\n"); } + comma(writer); write(writer, "\"fields\": [\n"); indent(writer); @@ -731,48 +865,39 @@ static void emitReflectionTypeLayoutInfoJSON( break; case slang::TypeReflection::Kind::ConstantBuffer: - write(writer, "\"kind\": \"constantBuffer\""); - write(writer, ",\n"); - write(writer, "\"elementType\": "); - emitReflectionTypeLayoutJSON( - writer, - typeLayout->getElementTypeLayout()); + emitReflectionParameterGroupTypeLayoutInfoJSON(writer, typeLayout, "constantBuffer"); break; case slang::TypeReflection::Kind::ParameterBlock: - write(writer, "\"kind\": \"parameterBlock\""); - write(writer, ",\n"); - write(writer, "\"elementType\": "); - emitReflectionTypeLayoutJSON( - writer, - typeLayout->getElementTypeLayout()); + emitReflectionParameterGroupTypeLayoutInfoJSON(writer, typeLayout, "parameterBlock"); break; case slang::TypeReflection::Kind::TextureBuffer: - write(writer, "\"kind\": \"textureBuffer\""); - write(writer, ",\n"); - write(writer, "\"elementType\": "); - emitReflectionTypeLayoutJSON( - writer, - typeLayout->getElementTypeLayout()); + emitReflectionParameterGroupTypeLayoutInfoJSON(writer, typeLayout, "textureBuffer"); break; case slang::TypeReflection::Kind::ShaderStorageBuffer: + comma(writer); write(writer, "\"kind\": \"shaderStorageBuffer\""); - write(writer, ",\n"); + + comma(writer); write(writer, "\"elementType\": "); emitReflectionTypeLayoutJSON( writer, typeLayout->getElementTypeLayout()); break; case slang::TypeReflection::Kind::GenericTypeParameter: + comma(writer); write(writer, "\"kind\": \"GenericTypeParameter\""); - write(writer, ",\n"); + + comma(writer); emitReflectionNameInfoJSON(writer, typeLayout->getName()); break; case slang::TypeReflection::Kind::Interface: - write(writer, "\"kind\": \"Interface\",\n"); - write(writer, ",\n"); + comma(writer); + write(writer, "\"kind\": \"Interface\""); + + comma(writer); emitReflectionNameInfoJSON(writer, typeLayout->getName()); break; @@ -792,7 +917,7 @@ static void emitReflectionTypeLayoutInfoJSON( if( auto resultTypeLayout = typeLayout->getElementTypeLayout() ) { - write(writer, ",\n"); + comma(writer); write(writer, "\"resultType\": "); emitReflectionTypeLayoutJSON( writer, @@ -812,6 +937,7 @@ static void emitReflectionTypeLayoutJSON( PrettyWriter& writer, slang::TypeLayoutReflection* typeLayout) { + CommaTrackerRAII commaTracker(writer); write(writer, "{\n"); indent(writer); emitReflectionTypeLayoutInfoJSON(writer, typeLayout); @@ -823,6 +949,7 @@ static void emitReflectionTypeJSON( PrettyWriter& writer, slang::TypeReflection* type) { + CommaTrackerRAII commaTracker(writer); write(writer, "{\n"); indent(writer); emitReflectionTypeInfoJSON(writer, type); @@ -847,16 +974,25 @@ static void emitReflectionParamJSON( PrettyWriter& writer, slang::VariableLayoutReflection* param) { + // TODO: This function is likely redundant with `emitReflectionVarLayoutJSON` + // and we should try to collapse them into one. + write(writer, "{\n"); indent(writer); - emitReflectionNameInfoJSON(writer, param->getName()); + CommaTrackerRAII commaTracker(writer); + + if( auto name = param->getName() ) + { + comma(writer); + emitReflectionNameInfoJSON(writer, name); + } emitReflectionModifierInfoJSON(writer, param->getVariable()); emitReflectionVarBindingInfoJSON(writer, param); - write(writer, ",\n"); + comma(writer); write(writer, "\"type\": "); emitReflectionTypeLayoutJSON(writer, param->getTypeLayout()); @@ -931,6 +1067,7 @@ static void emitReflectionTypeParamJSON( if (ee != 0) write(writer, ",\n"); write(writer, "{\n"); indent(writer); + CommaTrackerRAII commaTracker(writer); emitReflectionTypeInfoJSON(writer, typeParam->getConstraintByIndex(ee)); dedent(writer); write(writer, "\n}"); @@ -983,6 +1120,11 @@ static void emitReflectionEntryPointJSON( { write(writer, ",\n\"usesAnySampleRateInput\": true"); } + if( auto resultVarLayout = entryPoint->getResultVarLayout() ) + { + write(writer, ",\n\"result:\": "); + emitReflectionParamJSON(writer, resultVarLayout); + } if (entryPoint->getStage() == SLANG_STAGE_COMPUTE) { |
