summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2017-10-19 11:49:16 -0700
committerGitHub <noreply@github.com>2017-10-19 11:49:16 -0700
commit88023aea669f258d66e53eab10215337a7f72853 (patch)
tree630d2f89a201283307ebc3ae1ccd3ce3d28876bb
parent5995b7a47b2b65025410b9d558dfe1820e4c42e0 (diff)
Reflection: allow querying of semantics on varying input/output (#224)
This is functionality required to support a Falcor bug fix. Most of the code to compute the right semantic name/index for a parameter was already present. This change adds: - Storage for semantic name/index on every `VarLayout` - Note: this is wasteful and should be optimized later - A public API to query the semantic name/index - The contract is that this API returns `NULL` if the parameter had no semantic - A bit of work in `parameter-binding.cpp` to attach semantics to varying input/output when traversing varying parameters. - Note: this is intentionally set up so that it associates semantics even with non-leaf parameters, so that an API user can query the semantic of a `struct` parameter and know that its members will be assigned sequential semantic indices from its starting value. - Support for dumping this information in reflection tests One notable thing that I did *not* change here is that the reflection test fixture doesn't report information on the output of an entry point, even though it really should. That should be fixed in a separate change, though, because it would affect many of the expected outputs.
-rw-r--r--slang.h13
-rw-r--r--source/slang/lower.cpp2
-rw-r--r--source/slang/parameter-binding.cpp21
-rw-r--r--source/slang/reflection.cpp22
-rw-r--r--source/slang/type-layout.h8
-rw-r--r--tests/reflection/thread-group-size.hlsl.expected1
-rw-r--r--tests/reflection/vertex-input-semantics.hlsl33
-rw-r--r--tests/reflection/vertex-input-semantics.hlsl.expected152
-rw-r--r--tools/slang-reflection-test/main.cpp15
9 files changed, 267 insertions, 0 deletions
diff --git a/slang.h b/slang.h
index ff79d698b..11b34053c 100644
--- a/slang.h
+++ b/slang.h
@@ -627,6 +627,9 @@ extern "C"
SLANG_API size_t spReflectionVariableLayout_GetOffset(SlangReflectionVariableLayout* var, SlangParameterCategory category);
SLANG_API size_t spReflectionVariableLayout_GetSpace(SlangReflectionVariableLayout* var, SlangParameterCategory category);
+ SLANG_API char const* spReflectionVariableLayout_GetSemanticName(SlangReflectionVariableLayout* var);
+ SLANG_API size_t spReflectionVariableLayout_GetSemanticIndex(SlangReflectionVariableLayout* var);
+
// Shader Parameter Reflection
typedef SlangReflectionVariableLayout SlangReflectionParameter;
@@ -989,6 +992,16 @@ namespace slang
{
return spReflectionVariableLayout_GetSpace((SlangReflectionVariableLayout*) this, category);
}
+
+ char const* getSemanticName()
+ {
+ return spReflectionVariableLayout_GetSemanticName((SlangReflectionVariableLayout*) this);
+ }
+
+ size_t getSemanticIndex()
+ {
+ return spReflectionVariableLayout_GetSemanticIndex((SlangReflectionVariableLayout*) this);
+ }
};
struct EntryPointReflection
diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp
index 5708bab64..94738307b 100644
--- a/source/slang/lower.cpp
+++ b/source/slang/lower.cpp
@@ -3183,6 +3183,8 @@ struct LoweringVisitor
newFieldLayout->varDecl = fieldLayout->varDecl;
newFieldLayout->systemValueSemantic = fieldLayout->systemValueSemantic;
newFieldLayout->systemValueSemanticIndex = fieldLayout->systemValueSemanticIndex;
+ newFieldLayout->semanticName = fieldLayout->semanticName;
+ newFieldLayout->semanticIndex = fieldLayout->semanticIndex;
for (auto resInfo : fieldLayout->resourceInfos)
{
diff --git a/source/slang/parameter-binding.cpp b/source/slang/parameter-binding.cpp
index 4fbec5652..fed838e6b 100644
--- a/source/slang/parameter-binding.cpp
+++ b/source/slang/parameter-binding.cpp
@@ -1190,6 +1190,27 @@ static RefPtr<TypeLayout> processEntryPointParameter(
EntryPointParameterState const& state,
RefPtr<VarLayout> varLayout)
{
+ // If there is an available semantic name and index,
+ // then we should apply it to this parameter unconditionally
+ // (that is, not just if it is a leaf parameter).
+ auto optSemanticName = state.optSemanticName;
+ if (optSemanticName && varLayout)
+ {
+ // Always store semantics in upper-case for
+ // reflection information, since they are
+ // supposed to be case-insensitive and
+ // upper-case is the dominant convention.
+ String semanticName = *optSemanticName;
+ String sn = semanticName.ToUpper();
+
+ auto semanticIndex = *state.ioSemanticIndex;
+
+ varLayout->semanticName = sn;
+ varLayout->semanticIndex = semanticIndex;
+ varLayout->flags |= VarLayoutFlag::HasSemantic;
+ }
+
+
// Scalar and vector types are treated as outputs directly
if(auto basicType = type->As<BasicExpressionType>())
{
diff --git a/source/slang/reflection.cpp b/source/slang/reflection.cpp
index 435b4db3f..d7e8820c0 100644
--- a/source/slang/reflection.cpp
+++ b/source/slang/reflection.cpp
@@ -623,6 +623,28 @@ SLANG_API size_t spReflectionVariableLayout_GetSpace(SlangReflectionVariableLayo
return info->space;
}
+SLANG_API char const* spReflectionVariableLayout_GetSemanticName(SlangReflectionVariableLayout* inVarLayout)
+{
+ auto varLayout = convert(inVarLayout);
+ if(!varLayout) return 0;
+
+ if (!(varLayout->flags & Slang::VarLayoutFlag::HasSemantic))
+ return 0;
+
+ return varLayout->semanticName.Buffer();
+}
+
+SLANG_API size_t spReflectionVariableLayout_GetSemanticIndex(SlangReflectionVariableLayout* inVarLayout)
+{
+ auto varLayout = convert(inVarLayout);
+ if(!varLayout) return 0;
+
+ if (!(varLayout->flags & Slang::VarLayoutFlag::HasSemantic))
+ return 0;
+
+ return varLayout->semanticIndex;
+}
+
// Shader Parameter Reflection
diff --git a/source/slang/type-layout.h b/source/slang/type-layout.h
index 971088aac..d078d9554 100644
--- a/source/slang/type-layout.h
+++ b/source/slang/type-layout.h
@@ -218,6 +218,7 @@ typedef unsigned int VarLayoutFlags;
enum VarLayoutFlag : VarLayoutFlags
{
IsRedeclaration = 1 << 0, ///< This is a redeclaration of some shader parameter
+ HasSemantic = 1 << 1,
};
// A reified layout for a particular variable, field, etc.
@@ -241,6 +242,13 @@ public:
String systemValueSemantic;
int systemValueSemanticIndex;
+ // General cse semantic name and index
+ // TODO: this and the system-value field are redundant
+ // TODO: the `VarLayout` type is getting bloated; we need to not store this
+ // information unless actually required.
+ String semanticName;
+ int semanticIndex;
+
// The start register(s) for any resources
struct ResourceInfo
{
diff --git a/tests/reflection/thread-group-size.hlsl.expected b/tests/reflection/thread-group-size.hlsl.expected
index d139c5b64..a41c66248 100644
--- a/tests/reflection/thread-group-size.hlsl.expected
+++ b/tests/reflection/thread-group-size.hlsl.expected
@@ -24,6 +24,7 @@ standard output = {
"bindings": [
],
+ "semanticName": "SV_DISPATCHTHREADID",
"type": {
"kind": "vector",
"elementCount": 3,
diff --git a/tests/reflection/vertex-input-semantics.hlsl b/tests/reflection/vertex-input-semantics.hlsl
new file mode 100644
index 000000000..87a8431bc
--- /dev/null
+++ b/tests/reflection/vertex-input-semantics.hlsl
@@ -0,0 +1,33 @@
+//TEST:REFLECTION:-profile vs_4_0 -target hlsl
+
+// Confirm that we can generate reflection info for
+// vertex shader input parameters, including those
+// that have semantics, and including nesting
+// via struct types.
+
+struct X
+{
+ float4 x0;
+ float4 x1;
+};
+
+struct B
+{
+ int4 b0;
+ X b1;
+};
+
+struct C
+{
+ X c0 : CX;
+ int4 c1 : CY;
+};
+
+float4 main(
+ float4 a : A,
+ B b : B,
+ C c)
+ : SV_Position
+{
+ return 0.0;
+} \ No newline at end of file
diff --git a/tests/reflection/vertex-input-semantics.hlsl.expected b/tests/reflection/vertex-input-semantics.hlsl.expected
new file mode 100644
index 000000000..014533fdb
--- /dev/null
+++ b/tests/reflection/vertex-input-semantics.hlsl.expected
@@ -0,0 +1,152 @@
+result code = 0
+standard error = {
+}
+standard output = {
+{
+ "parameters": [
+
+ ],
+ "entryPoints": [
+ {
+ "name": "main",
+ "stage:": "vertex",
+ "parameters": [
+ {
+ "name": "a",
+ "binding": {"kind": "vertexInput", "index": 0},
+ "semanticName": "A",
+ "type": {
+ "kind": "vector",
+ "elementCount": 4,
+ "elementType": {
+ "kind": "scalar",
+ "scalarType": "float32"
+ }
+ }
+ },
+ {
+ "name": "b",
+ "binding": {"kind": "vertexInput", "index": 1, "count": 3},
+ "semanticName": "B",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "b0",
+ "type": {
+ "kind": "vector",
+ "elementCount": 4,
+ "elementType": {
+ "kind": "scalar",
+ "scalarType": "int32"
+ }
+ },
+ "binding": {"kind": "vertexInput", "index": 0},
+ "semanticName": "B"
+ },
+ {
+ "name": "b1",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "x0",
+ "type": {
+ "kind": "vector",
+ "elementCount": 4,
+ "elementType": {
+ "kind": "scalar",
+ "scalarType": "float32"
+ }
+ },
+ "binding": {"kind": "vertexInput", "index": 0},
+ "semanticName": "B",
+ "semanticIndex": 1
+ },
+ {
+ "name": "x1",
+ "type": {
+ "kind": "vector",
+ "elementCount": 4,
+ "elementType": {
+ "kind": "scalar",
+ "scalarType": "float32"
+ }
+ },
+ "binding": {"kind": "vertexInput", "index": 1},
+ "semanticName": "B",
+ "semanticIndex": 2
+ }
+ ]
+ },
+ "binding": {"kind": "vertexInput", "index": 1, "count": 2},
+ "semanticName": "B",
+ "semanticIndex": 1
+ }
+ ]
+ }
+ },
+ {
+ "name": "c",
+ "binding": {"kind": "vertexInput", "index": 4, "count": 3},
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "c0",
+ "type": {
+ "kind": "struct",
+ "fields": [
+ {
+ "name": "x0",
+ "type": {
+ "kind": "vector",
+ "elementCount": 4,
+ "elementType": {
+ "kind": "scalar",
+ "scalarType": "float32"
+ }
+ },
+ "binding": {"kind": "vertexInput", "index": 0},
+ "semanticName": "CX"
+ },
+ {
+ "name": "x1",
+ "type": {
+ "kind": "vector",
+ "elementCount": 4,
+ "elementType": {
+ "kind": "scalar",
+ "scalarType": "float32"
+ }
+ },
+ "binding": {"kind": "vertexInput", "index": 1},
+ "semanticName": "CX",
+ "semanticIndex": 1
+ }
+ ]
+ },
+ "binding": {"kind": "vertexInput", "index": 0, "count": 2},
+ "semanticName": "CX"
+ },
+ {
+ "name": "c1",
+ "type": {
+ "kind": "vector",
+ "elementCount": 4,
+ "elementType": {
+ "kind": "scalar",
+ "scalarType": "int32"
+ }
+ },
+ "binding": {"kind": "vertexInput", "index": 2},
+ "semanticName": "CY"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+}
+}
diff --git a/tools/slang-reflection-test/main.cpp b/tools/slang-reflection-test/main.cpp
index 9568dc3fe..f604ca1aa 100644
--- a/tools/slang-reflection-test/main.cpp
+++ b/tools/slang-reflection-test/main.cpp
@@ -183,6 +183,21 @@ static void emitReflectionVarBindingInfoJSON(
{
write(writer,"\n]");
}
+
+ if (auto semanticName = var->getSemanticName())
+ {
+ write(writer, ",\n");
+ write(writer,"\"semanticName\": \"");
+ write(writer, semanticName);
+ write(writer, "\"");
+
+ if (auto semanticIndex = var->getSemanticIndex())
+ {
+ write(writer, ",\n");
+ write(writer,"\"semanticIndex\": ");
+ write(writer, semanticIndex);
+ }
+ }
}
static void emitReflectionNameInfoJSON(