diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2018-08-22 11:36:02 -0400 |
|---|---|---|
| committer | Tim Foley <tfoleyNV@users.noreply.github.com> | 2018-08-22 08:36:02 -0700 |
| commit | 6a8ad6eb4cab72c18de48762768e04d08b60a21c (patch) | |
| tree | 903863bf0154cb73e87c7a70a65c022649c096d3 | |
| parent | 0ce1131ba12f777fbaa40004e0e3e7af89ccf4f0 (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.cpp | 5 | ||||
| -rw-r--r-- | source/slang/core.meta.slang | 5 | ||||
| -rw-r--r-- | source/slang/core.meta.slang.h | 5 | ||||
| -rw-r--r-- | source/slang/emit.cpp | 1 | ||||
| -rw-r--r-- | source/slang/modifier-defs.h | 4 | ||||
| -rw-r--r-- | source/slang/parameter-binding.cpp | 11 | ||||
| -rw-r--r-- | source/slang/parser.cpp | 55 | ||||
| -rw-r--r-- | tests/reflection/binding-push-constant-gl.hlsl | 57 | ||||
| -rw-r--r-- | tests/reflection/binding-push-constant-gl.hlsl.expected | 141 | ||||
| -rw-r--r-- | tools/slang-reflection-test/main.cpp | 1 |
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); |
