summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2018-08-22 11:36:02 -0400
committerTim Foley <tfoleyNV@users.noreply.github.com>2018-08-22 08:36:02 -0700
commit6a8ad6eb4cab72c18de48762768e04d08b60a21c (patch)
tree903863bf0154cb73e87c7a70a65c022649c096d3
parent0ce1131ba12f777fbaa40004e0e3e7af89ccf4f0 (diff)
Support for [[vk::push_constant]] (#629)
* Support for attributed [[vk::push_constant]] and [[push_constant]]. Can also use layout(push_constant). * Fix test so matches the expected output. * Add expected output to binding-push-constant-gl.hlsl * Trivial change to force travis rebuild to test the gcc linux build really has a problem.
-rw-r--r--source/slang/check.cpp5
-rw-r--r--source/slang/core.meta.slang5
-rw-r--r--source/slang/core.meta.slang.h5
-rw-r--r--source/slang/emit.cpp1
-rw-r--r--source/slang/modifier-defs.h4
-rw-r--r--source/slang/parameter-binding.cpp11
-rw-r--r--source/slang/parser.cpp55
-rw-r--r--tests/reflection/binding-push-constant-gl.hlsl57
-rw-r--r--tests/reflection/binding-push-constant-gl.hlsl.expected141
-rw-r--r--tools/slang-reflection-test/main.cpp1
10 files changed, 261 insertions, 24 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp
index c5ebf7f30..95a958495 100644
--- a/source/slang/check.cpp
+++ b/source/slang/check.cpp
@@ -1959,6 +1959,11 @@ namespace Slang
getSink()->diagnose(attr, Diagnostics::expectedSingleIntArg, attr->name);
}
}
+ else if (attr.As<PushConstantAttribute>())
+ {
+ // Has no args
+ SLANG_ASSERT(attr->args.Count() == 0);
+ }
else
{
if(attr->args.Count() == 0)
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index 9da424fba..31da44f3c 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -1122,6 +1122,11 @@ attribute_syntax [vk_binding(binding: int, set: int = 0)] : GLSLBindingAttribu
__attributeTarget(DeclBase)
attribute_syntax [gl_binding(binding: int, set: int = 0)] : GLSLBindingAttribute;
+__attributeTarget(DeclBase)
+attribute_syntax [vk_push_constant] : PushConstantAttribute;
+__attributeTarget(DeclBase)
+attribute_syntax [push_constant] : PushConstantAttribute;
+
// Statement Attributes
__attributeTarget(LoopStmt)
diff --git a/source/slang/core.meta.slang.h b/source/slang/core.meta.slang.h
index 0f69d0b5b..12c76d213 100644
--- a/source/slang/core.meta.slang.h
+++ b/source/slang/core.meta.slang.h
@@ -1140,6 +1140,11 @@ SLANG_RAW("\n")
SLANG_RAW("__attributeTarget(DeclBase)\n")
SLANG_RAW("attribute_syntax [gl_binding(binding: int, set: int = 0)]\t\t\t: GLSLBindingAttribute;\n")
SLANG_RAW("\n")
+SLANG_RAW("__attributeTarget(DeclBase)\n")
+SLANG_RAW("attribute_syntax [vk_push_constant]\t\t\t\t\t\t\t\t\t: PushConstantAttribute;\n")
+SLANG_RAW("__attributeTarget(DeclBase)\n")
+SLANG_RAW("attribute_syntax [push_constant]\t\t\t\t\t\t\t\t\t: PushConstantAttribute;\n")
+SLANG_RAW("\n")
SLANG_RAW("// Statement Attributes\n")
SLANG_RAW("\n")
SLANG_RAW("__attributeTarget(LoopStmt)\n")
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 8d31ca064..1d121d69b 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -5394,6 +5394,7 @@ struct EmitVisitor
}
emitGLSLLayoutQualifier(LayoutResourceKind::DescriptorTableSlot, &containerChain);
+ emitGLSLLayoutQualifier(LayoutResourceKind::PushConstantBuffer, &containerChain);
if(as<IRGLSLShaderStorageBufferType>(type))
{
diff --git a/source/slang/modifier-defs.h b/source/slang/modifier-defs.h
index 70c26568d..d53f8bc6c 100644
--- a/source/slang/modifier-defs.h
+++ b/source/slang/modifier-defs.h
@@ -129,7 +129,6 @@ SIMPLE_SYNTAX_CLASS(GLSLUnparsedLayoutModifier , GLSLLayoutModifier)
// Specific cases for known GLSL `layout` modifiers that we need to work with
SIMPLE_SYNTAX_CLASS(GLSLConstantIDLayoutModifier , GLSLParsedLayoutModifier)
SIMPLE_SYNTAX_CLASS(GLSLLocationLayoutModifier , GLSLParsedLayoutModifier)
-SIMPLE_SYNTAX_CLASS(GLSLPushConstantLayoutModifier, GLSLParsedLayoutModifier)
SIMPLE_SYNTAX_CLASS(GLSLLocalSizeLayoutModifier, GLSLUnparsedLayoutModifier)
SIMPLE_SYNTAX_CLASS(GLSLLocalSizeXLayoutModifier, GLSLLocalSizeLayoutModifier)
@@ -328,6 +327,9 @@ SIMPLE_SYNTAX_CLASS(FlattenAttribute, Attribute) // `[flatten]`
SIMPLE_SYNTAX_CLASS(ForceCaseAttribute, Attribute) // `[forcecase]`
SIMPLE_SYNTAX_CLASS(CallAttribute, Attribute) // `[call]`
+// [[vk_push_constant]] [[push_constant]]
+SIMPLE_SYNTAX_CLASS(PushConstantAttribute, Attribute)
+
// [[vk_binding]]
SYNTAX_CLASS(GLSLBindingAttribute, Attribute)
FIELD(int32_t, binding = 0)
diff --git a/source/slang/parameter-binding.cpp b/source/slang/parameter-binding.cpp
index ced8d7af2..40491c4df 100644
--- a/source/slang/parameter-binding.cpp
+++ b/source/slang/parameter-binding.cpp
@@ -977,7 +977,7 @@ getTypeLayoutForGlobalShaderParameter_GLSL(
// We want to check for a constant-buffer type with a `push_constant` layout
// qualifier before we move on to anything else.
- if( varDecl->HasModifier<GLSLPushConstantLayoutModifier>() && type->As<ConstantBufferType>() )
+ if( varDecl->HasModifier<PushConstantAttribute>() && type->As<ConstantBufferType>() )
{
return CreateTypeLayout(
layoutContext.with(rules->getPushConstantBufferRules()),
@@ -1043,6 +1043,15 @@ getTypeLayoutForGlobalShaderParameter_HLSL(
auto rules = layoutContext.getRulesFamily();
auto type = varDecl->getType();
+ // We want to check for a constant-buffer type with a `push_constant` layout
+ // qualifier before we move on to anything else.
+ if (varDecl->HasModifier<PushConstantAttribute>() && type->As<ConstantBufferType>())
+ {
+ return CreateTypeLayout(
+ layoutContext.with(rules->getPushConstantBufferRules()),
+ type);
+ }
+
// HLSL `static` modifier indicates "thread local"
if(varDecl->HasModifier<HLSLStaticModifier>())
return nullptr;
diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp
index 62fed75cc..e3982aee4 100644
--- a/source/slang/parser.cpp
+++ b/source/slang/parser.cpp
@@ -4511,35 +4511,46 @@ namespace Slang
}
else
{
- RefPtr<GLSLLayoutModifier> modifier;
-
- // TODO: better handling of this choice (e.g., lookup in scope)
- if(0) {}
- #define CASE(KEYWORD, CLASS) \
- else if(getText(nameAndLoc.name) == #KEYWORD) modifier = new CLASS()
+ if (nameText == "push_constant")
+ {
+ RefPtr<PushConstantAttribute> modifier(new PushConstantAttribute);
- CASE(constant_id, GLSLConstantIDLayoutModifier);
- CASE(location, GLSLLocationLayoutModifier);
- CASE(push_constant, GLSLPushConstantLayoutModifier);
- CASE(local_size_x, GLSLLocalSizeXLayoutModifier);
- CASE(local_size_y, GLSLLocalSizeYLayoutModifier);
- CASE(local_size_z, GLSLLocalSizeZLayoutModifier);
+ modifier->name = nameAndLoc.name;
+ modifier->loc = nameAndLoc.loc;
- #undef CASE
+ listBuilder.add(modifier);
+ }
else
{
- modifier = new GLSLUnparsedLayoutModifier();
- }
+ RefPtr<GLSLLayoutModifier> modifier;
- modifier->name = nameAndLoc.name;
- modifier->loc = nameAndLoc.loc;
+ // TODO: better handling of this choice (e.g., lookup in scope)
+ if(0) {}
+ #define CASE(KEYWORD, CLASS) \
+ else if(nameText == #KEYWORD) modifier = new CLASS()
- if(AdvanceIf(parser, TokenType::OpAssign))
- {
- modifier->valToken = parser->ReadToken(TokenType::IntegerLiteral);
- }
+ CASE(constant_id, GLSLConstantIDLayoutModifier);
+ CASE(location, GLSLLocationLayoutModifier);
+ CASE(local_size_x, GLSLLocalSizeXLayoutModifier);
+ CASE(local_size_y, GLSLLocalSizeYLayoutModifier);
+ CASE(local_size_z, GLSLLocalSizeZLayoutModifier);
- listBuilder.add(modifier);
+ #undef CASE
+ else
+ {
+ modifier = new GLSLUnparsedLayoutModifier();
+ }
+
+ modifier->name = nameAndLoc.name;
+ modifier->loc = nameAndLoc.loc;
+
+ if(AdvanceIf(parser, TokenType::OpAssign))
+ {
+ modifier->valToken = parser->ReadToken(TokenType::IntegerLiteral);
+ }
+
+ listBuilder.add(modifier);
+ }
}
if (AdvanceIf(parser, TokenType::RParent))
diff --git a/tests/reflection/binding-push-constant-gl.hlsl b/tests/reflection/binding-push-constant-gl.hlsl
new file mode 100644
index 000000000..f6bf13602
--- /dev/null
+++ b/tests/reflection/binding-push-constant-gl.hlsl
@@ -0,0 +1,57 @@
+//TEST:REFLECTION:-profile ps_4_0 -target spirv
+
+// Confirm that we can generate reflection info for arrays
+//
+// Note: just working with fixed-size arrays for now.
+// Unbounded arrays may require more work.
+
+layout(binding=0, set = 1) cbuffer MyConstantBuffer
+{
+ float x;
+
+ float a[10];
+
+ float y;
+}
+
+struct MyPushConstantStruct
+{
+ float pushX;
+ float pushY;
+};
+
+/* This style doesn't work
+[[vk::push_constant]] MyPushConstantStruct pushConstantBuffer;
+*/
+
+// This style does work
+[[vk::push_constant]]ConstantBuffer<MyPushConstantStruct> pushConstantBuffer;
+
+/* This style works too
+layout(push_constant)
+cbuffer MyPushConstantBuffer
+{
+ float pushX;
+ float pushY;
+}
+*/
+
+/* This works too
+[[vk::push_constant]] cbuffer MyPushConstantBuffer
+{
+ float pushX;
+ float pushY;
+}
+*/
+
+[[vk::binding(1,2)]] Texture2D tx;
+[gl::binding(2,3)] Texture2D ta;
+Texture2D ty;
+SamplerState sx;
+SamplerState sa[4];
+SamplerState sy;
+
+float4 main() : SV_Target
+{
+ return 0.0 + pushConstantBuffer.pushX;
+} \ No newline at end of file
diff --git a/tests/reflection/binding-push-constant-gl.hlsl.expected b/tests/reflection/binding-push-constant-gl.hlsl.expected
new file mode 100644
index 000000000..6dd9d0fdd
--- /dev/null
+++ b/tests/reflection/binding-push-constant-gl.hlsl.expected
@@ -0,0 +1,141 @@
+result code = 0
+standard error = {
+}
+standard output = {
+{
+ "parameters": [
+ {
+ "name": "MyConstantBuffer",
+ "binding": {"kind": "descriptorTableSlot", "space": 1, "index": 0},
+ "type": {
+ "kind": "constantBuffer",
+ "elementType": {
+ "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}
+ }
+ ]
+ }
+ }
+ },
+ {
+ "name": "pushConstantBuffer",
+ "binding": {"kind": "pushConstantBuffer", "index": 0},
+ "type": {
+ "kind": "constantBuffer",
+ "elementType": {
+ "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}
+ }
+ ]
+ }
+ }
+ },
+ {
+ "name": "tx",
+ "binding": {"kind": "descriptorTableSlot", "space": 2, "index": 1},
+ "type": {
+ "kind": "resource",
+ "baseShape": "texture2D"
+ }
+ },
+ {
+ "name": "ta",
+ "binding": {"kind": "descriptorTableSlot", "space": 3, "index": 2},
+ "type": {
+ "kind": "resource",
+ "baseShape": "texture2D"
+ }
+ },
+ {
+ "name": "ty",
+ "binding": {"kind": "descriptorTableSlot", "index": 0},
+ "type": {
+ "kind": "resource",
+ "baseShape": "texture2D"
+ }
+ },
+ {
+ "name": "sx",
+ "binding": {"kind": "descriptorTableSlot", "index": 1},
+ "type": {
+ "kind": "samplerState"
+ }
+ },
+ {
+ "name": "sa",
+ "binding": {"kind": "descriptorTableSlot", "index": 2},
+ "type": {
+ "kind": "array",
+ "elementCount": 4,
+ "elementType": {
+ "kind": "samplerState"
+ }
+ }
+ },
+ {
+ "name": "sy",
+ "binding": {"kind": "descriptorTableSlot", "index": 3},
+ "type": {
+ "kind": "samplerState"
+ }
+ },
+ {
+ "name": "SLANG_hack_samplerForTexelFetch",
+ "binding": {"kind": "descriptorTableSlot", "index": 4},
+ "type": {
+ "kind": "samplerState"
+ }
+ }
+ ],
+ "entryPoints": [
+ {
+ "name": "main",
+ "stage:": "fragment"
+ }
+ ]
+}
+}
diff --git a/tools/slang-reflection-test/main.cpp b/tools/slang-reflection-test/main.cpp
index 667a0ddf7..27ae20412 100644
--- a/tools/slang-reflection-test/main.cpp
+++ b/tools/slang-reflection-test/main.cpp
@@ -114,6 +114,7 @@ static void emitReflectionVarBindingInfoJSON(
CASE(VARYING_OUTPUT, varyingOutput);
CASE(SAMPLER_STATE, samplerState);
CASE(UNIFORM, uniform);
+ CASE(PUSH_CONSTANT_BUFFER, pushConstantBuffer);
CASE(DESCRIPTOR_TABLE_SLOT, descriptorTableSlot);
CASE(SPECIALIZATION_CONSTANT, specializationConstant);
CASE(MIXED, mixed);