--- /dev/null
+hlsl.attributeC11.frag
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:16 Function Definition: @main(vf4; ( temp 4-component vector of float)
+0:16 Function Parameters:
+0:16 'input' ( in 4-component vector of float)
+0:? Sequence
+0:17 Branch: Return with expression
+0:17 add ( temp 4-component vector of float)
+0:17 'input' ( in 4-component vector of float)
+0:17 textureFetch ( temp 4-component vector of float)
+0:17 'attach' ( uniform texture2D)
+0:17 vector swizzle ( temp int)
+0:17 Constant:
+0:17 0 (const int)
+0:17 0 (const int)
+0:17 Sequence
+0:17 Constant:
+0:17 0 (const int)
+0:17 direct index ( temp int)
+0:17 Constant:
+0:17 0 (const int)
+0:17 0 (const int)
+0:17 Constant:
+0:17 1 (const int)
+0:16 Function Definition: main( ( temp void)
+0:16 Function Parameters:
+0:? Sequence
+0:16 move second child to first child ( temp 4-component vector of float)
+0:? 'input' ( temp 4-component vector of float)
+0:? 'input' (layout( location=8) in 4-component vector of float)
+0:16 move second child to first child ( temp 4-component vector of float)
+0:? '@entryPointOutput' (layout( location=7) out 4-component vector of float)
+0:16 Function Call: @main(vf4; ( temp 4-component vector of float)
+0:? 'input' ( temp 4-component vector of float)
+0:? Linker Objects
+0:? 'buffer1' (layout( set=0 binding=1 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of structure{ temp 2-component vector of float f} @data})
+0:? 'buffer3' (layout( set=2 binding=3 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of structure{ temp 2-component vector of float f} @data})
+0:? 'attach' ( uniform texture2D)
+0:? '@entryPointOutput' (layout( location=7) out 4-component vector of float)
+0:? 'input' (layout( location=8) in 4-component vector of float)
+
+
+Linked fragment stage:
+
+
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:16 Function Definition: @main(vf4; ( temp 4-component vector of float)
+0:16 Function Parameters:
+0:16 'input' ( in 4-component vector of float)
+0:? Sequence
+0:17 Branch: Return with expression
+0:17 add ( temp 4-component vector of float)
+0:17 'input' ( in 4-component vector of float)
+0:17 textureFetch ( temp 4-component vector of float)
+0:17 'attach' ( uniform texture2D)
+0:17 vector swizzle ( temp int)
+0:17 Constant:
+0:17 0 (const int)
+0:17 0 (const int)
+0:17 Sequence
+0:17 Constant:
+0:17 0 (const int)
+0:17 direct index ( temp int)
+0:17 Constant:
+0:17 0 (const int)
+0:17 0 (const int)
+0:17 Constant:
+0:17 1 (const int)
+0:16 Function Definition: main( ( temp void)
+0:16 Function Parameters:
+0:? Sequence
+0:16 move second child to first child ( temp 4-component vector of float)
+0:? 'input' ( temp 4-component vector of float)
+0:? 'input' (layout( location=8) in 4-component vector of float)
+0:16 move second child to first child ( temp 4-component vector of float)
+0:? '@entryPointOutput' (layout( location=7) out 4-component vector of float)
+0:16 Function Call: @main(vf4; ( temp 4-component vector of float)
+0:? 'input' ( temp 4-component vector of float)
+0:? Linker Objects
+0:? 'buffer1' (layout( set=0 binding=1 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of structure{ temp 2-component vector of float f} @data})
+0:? 'buffer3' (layout( set=2 binding=3 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of structure{ temp 2-component vector of float f} @data})
+0:? 'attach' ( uniform texture2D)
+0:? '@entryPointOutput' (layout( location=7) out 4-component vector of float)
+0:? 'input' (layout( location=8) in 4-component vector of float)
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 47
+
+ Capability Shader
+ 1: ExtInstImport "GLSL.std.450"
+ MemoryModel Logical GLSL450
+ EntryPoint Fragment 4 "main" 33 36
+ ExecutionMode 4 OriginUpperLeft
+ Source HLSL 500
+ Name 4 "main"
+ Name 11 "@main(vf4;"
+ Name 10 "input"
+ Name 16 "attach"
+ Name 31 "input"
+ Name 33 "input"
+ Name 36 "@entryPointOutput"
+ Name 37 "param"
+ Name 41 "S"
+ MemberName 41(S) 0 "f"
+ Name 43 "buffer1"
+ MemberName 43(buffer1) 0 "@data"
+ Name 45 "buffer1"
+ Name 46 "buffer3"
+ Decorate 16(attach) DescriptorSet 0
+ Decorate 16(attach) InputAttachmentIndex 4
+ Decorate 33(input) Location 8
+ Decorate 36(@entryPointOutput) Location 7
+ MemberDecorate 41(S) 0 Offset 0
+ Decorate 42 ArrayStride 8
+ MemberDecorate 43(buffer1) 0 NonWritable
+ MemberDecorate 43(buffer1) 0 Offset 0
+ Decorate 43(buffer1) BufferBlock
+ Decorate 45(buffer1) DescriptorSet 0
+ Decorate 45(buffer1) Binding 1
+ Decorate 46(buffer3) DescriptorSet 2
+ Decorate 46(buffer3) Binding 3
+ 2: TypeVoid
+ 3: TypeFunction 2
+ 6: TypeFloat 32
+ 7: TypeVector 6(float) 4
+ 8: TypePointer Function 7(fvec4)
+ 9: TypeFunction 7(fvec4) 8(ptr)
+ 14: TypeImage 6(float) 2D sampled format:Unknown
+ 15: TypePointer UniformConstant 14
+ 16(attach): 15(ptr) Variable UniformConstant
+ 18: TypeInt 32 1
+ 19: TypeVector 18(int) 2
+ 20: 18(int) Constant 0
+ 21: 19(ivec2) ConstantComposite 20 20
+ 22: TypeInt 32 0
+ 23: 22(int) Constant 0
+ 25: 22(int) Constant 1
+ 32: TypePointer Input 7(fvec4)
+ 33(input): 32(ptr) Variable Input
+ 35: TypePointer Output 7(fvec4)
+36(@entryPointOutput): 35(ptr) Variable Output
+ 40: TypeVector 6(float) 2
+ 41(S): TypeStruct 40(fvec2)
+ 42: TypeRuntimeArray 41(S)
+ 43(buffer1): TypeStruct 42
+ 44: TypePointer Uniform 43(buffer1)
+ 45(buffer1): 44(ptr) Variable Uniform
+ 46(buffer3): 44(ptr) Variable Uniform
+ 4(main): 2 Function None 3
+ 5: Label
+ 31(input): 8(ptr) Variable Function
+ 37(param): 8(ptr) Variable Function
+ 34: 7(fvec4) Load 33(input)
+ Store 31(input) 34
+ 38: 7(fvec4) Load 31(input)
+ Store 37(param) 38
+ 39: 7(fvec4) FunctionCall 11(@main(vf4;) 37(param)
+ Store 36(@entryPointOutput) 39
+ Return
+ FunctionEnd
+ 11(@main(vf4;): 7(fvec4) Function None 9
+ 10(input): 8(ptr) FunctionParameter
+ 12: Label
+ 13: 7(fvec4) Load 10(input)
+ 17: 14 Load 16(attach)
+ 24: 18(int) CompositeExtract 21 0
+ 26: 18(int) CompositeExtract 21 1
+ 27: 7(fvec4) ImageFetch 17 24 Lod 26
+ 28: 7(fvec4) FAdd 13 27
+ ReturnValue 28
+ FunctionEnd
--- /dev/null
+struct S {\r
+ float2 f;\r
+};\r
+\r
+[[vk::binding(1)]]\r
+StructuredBuffer<S> buffer1;\r
+\r
+[[vk::binding(3, 2)]]\r
+StructuredBuffer<S> buffer3;\r
+\r
+[[vk::input_attachment_index(4)]]\r
+Texture2D<float4> attach;\r
+\r
+[[vk::location(7)]] float4\r
+main([[vk::location(8)]] float4 input: A) : B\r
+{\r
+ return input + attach.Load(float2(0.5));\r
+}\r
{"hlsl.assoc.frag", "PixelShaderFunction"},
{"hlsl.attribute.frag", "PixelShaderFunction"},
{"hlsl.attribute.expression.comp", "main"},
+ {"hlsl.attributeC11.frag", "main"},
{"hlsl.basic.comp", "main"},
{"hlsl.basic.geom", "main"},
{"hlsl.boolConv.vert", "main"},
namespace glslang {
// Map the given string to an attribute enum from TAttributeType,
// or EatNone if invalid.
- TAttributeType TAttributeMap::attributeFromName(const TString& name)
+ TAttributeType TAttributeMap::attributeFromName(const TString& nameSpace, const TString& name)
{
// These are case insensitive.
TString lowername(name);
std::transform(lowername.begin(), lowername.end(), lowername.begin(), ::tolower);
+ TString lowernameSpace(nameSpace);
+ std::transform(lowernameSpace.begin(), lowernameSpace.end(), lowernameSpace.begin(), ::tolower);
+
+ // handle names within a namespace
+
+ if (lowernameSpace == "vk") {
+ if (lowername == "input_attachment_index")
+ return EatInputAttachment;
+ else if (lowername == "location")
+ return EatLocation;
+ else if (lowername == "binding")
+ return EatBinding;
+ } else if (lowernameSpace.size() > 0)
+ return EatNone;
+
+ // handle names with no namespace
if (lowername == "allow_uav_condition")
return EatAllow_uav_condition;
// Look up entry, inserting if it's not there, and if name is a valid attribute name
// as known by attributeFromName.
- TAttributeType TAttributeMap::setAttribute(const TString* name, TIntermAggregate* value)
+ TAttributeType TAttributeMap::setAttribute(const TString& nameSpace, const TString* name, TIntermAggregate* value)
{
if (name == nullptr)
return EatNone;
- const TAttributeType attr = attributeFromName(*name);
+ const TAttributeType attr = attributeFromName(nameSpace, *name);
if (attr != EatNone)
attributes[attr] = value;
EatPatchSize,
EatUnroll,
EatLoop,
+ EatBinding,
+ EatLocation,
+ EatInputAttachment
};
}
public:
// Search for and potentially add the attribute into the map. Return the
// attribute type enum for it, if found, else EatNone.
- TAttributeType setAttribute(const TString* name, TIntermAggregate* value);
+ TAttributeType setAttribute(const TString& nameSpace, const TString* name, TIntermAggregate* value);
// Const lookup: search for (but do not modify) the attribute in the map.
const TIntermAggregate* operator[](TAttributeType) const;
protected:
// Find an attribute enum given its name.
- static TAttributeType attributeFromName(const TString&);
+ static TAttributeType attributeFromName(const TString& nameSpace, const TString& name);
std::unordered_map<TAttributeType, TIntermAggregate*> attributes;
};
}
// declaration
+// : attributes attributed_declaration
+// | NAMESPACE IDENTIFIER LEFT_BRACE declaration_list RIGHT_BRACE
+//
+// attributed_declaration
// : sampler_declaration_dx9 post_decls SEMICOLON
// | fully_specified_type // for cbuffer/tbuffer
// | fully_specified_type declarator_list SEMICOLON // for non cbuffer/tbuffer
// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition
// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition
// | typedef declaration
-// | NAMESPACE IDENTIFIER LEFT_BRACE declaration_list RIGHT_BRACE
//
// declarator_list
// : declarator COMMA declarator COMMA declarator... // zero or more declarators
if (! acceptFullySpecifiedType(declaredType, nodeList))
return false;
+ parseContext.transferTypeAttributes(declarator.attributes, declaredType);
+
// cbuffer and tbuffer end with the closing '}'.
// No semicolon is included.
if (forbidDeclarators)
}
// parameter_declaration
+// : attributes attributed_declaration
+//
+// attributed_declaration
// : fully_specified_type post_decls [ = default_parameter_declaration ]
// | fully_specified_type identifier array_specifier post_decls [ = default_parameter_declaration ]
//
bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
{
+ // attributes
+ TAttributeMap attributes;
+ acceptAttributes(attributes);
+
// fully_specified_type
TType* type = new TType;
if (! acceptFullySpecifiedType(*type))
return false;
+ parseContext.transferTypeAttributes(attributes, *type);
+
// identifier
HlslToken idToken;
acceptIdentifier(idToken);
}
// attributes
-// : list of zero or more of: LEFT_BRACKET attribute RIGHT_BRACKET
+// : [zero or more:] bracketed-attribute
+//
+// bracketed-attribute:
+// : LEFT_BRACKET scoped-attribute RIGHT_BRACKET
+// : LEFT_BRACKET LEFT_BRACKET scoped-attribute RIGHT_BRACKET RIGHT_BRACKET
+//
+// scoped-attribute:
+// : attribute
+// | namespace COLON COLON attribute
//
// attribute:
// : UNROLL
// numthreads, which is used to set the CS local size.
// TODO: subset to correct set? Pass on?
do {
- HlslToken idToken;
+ HlslToken attributeToken;
// LEFT_BRACKET?
if (! acceptTokenClass(EHTokLeftBracket))
return;
+ // another LEFT_BRACKET?
+ bool doubleBrackets = false;
+ if (acceptTokenClass(EHTokLeftBracket))
+ doubleBrackets = true;
+
+ // attribute? (could be namespace; will adjust later)
+ if (!acceptIdentifier(attributeToken)) {
+ if (!peekTokenClass(EHTokRightBracket)) {
+ expected("namespace or attribute identifier");
+ advanceToken();
+ }
+ }
- // attribute
- if (acceptIdentifier(idToken)) {
- // 'idToken.string' is the attribute
- } else if (! peekTokenClass(EHTokRightBracket)) {
- expected("identifier");
- advanceToken();
+ TString nameSpace;
+ if (acceptTokenClass(EHTokColonColon)) {
+ // namespace COLON COLON
+ nameSpace = *attributeToken.string;
+ // attribute
+ if (!acceptIdentifier(attributeToken)) {
+ expected("attribute identifier");
+ return;
+ }
}
TIntermAggregate* expressions = nullptr;
expected("]");
return;
}
+ // another RIGHT_BRACKET?
+ if (doubleBrackets && !acceptTokenClass(EHTokRightBracket)) {
+ expected("]]");
+ return;
+ }
// Add any values we found into the attribute map. This accepts
// (and ignores) values not mapping to a known TAttributeType;
- attributes.setAttribute(idToken.string, expressions);
+ attributes.setAttribute(nameSpace, attributeToken.string, expressions);
} while (true);
}
return paramNodes;
}
-
// Handle all [attrib] attribute for the shader entry point
void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const TAttributeMap& attributes)
{
}
}
+// Update the given type with any type-like attribute information in the
+// attributes.
+void HlslParseContext::transferTypeAttributes(const TAttributeMap& attributes, TType& type)
+{
+ // extract integers out of attribute arguments stored in attribute aggregate
+ const auto getInt = [&](TAttributeType attr, int argNum, int& value) -> bool {
+ const TIntermAggregate* attrAgg = attributes[attr];
+ if (attrAgg == nullptr)
+ return false;
+ if (argNum >= attrAgg->getSequence().size())
+ return false;
+ const TConstUnion& intConst = attrAgg->getSequence()[argNum]->getAsConstantUnion()->getConstArray()[0];
+ if (intConst == nullptr)
+ return false;
+ value = intConst.getIConst();
+ return true;
+ };
+
+ // location
+ int value;
+ if (getInt(EatLocation, 0, value))
+ type.getQualifier().layoutLocation = value;
+
+ // binding
+ if (getInt(EatBinding, 0, value)) {
+ type.getQualifier().layoutBinding = value;
+ type.getQualifier().layoutSet = 0;
+ }
+
+ // set
+ if (getInt(EatBinding, 1, value))
+ type.getQualifier().layoutSet = value;
+
+ // input attachment
+ if (getInt(EatInputAttachment, 0, value))
+ type.getQualifier().layoutAttachment = value;
+}
+
//
// Do all special handling for the entry point, including wrapping
// the shader's entry point with the official entry point that will call it.
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributeMap&, TIntermNode*& entryPointTree);
TIntermNode* transformEntryPoint(const TSourceLoc&, TFunction&, const TAttributeMap&);
void handleEntryPointAttributes(const TSourceLoc&, const TAttributeMap&);
+ void transferTypeAttributes(const TAttributeMap&, TType&);
void handleFunctionBody(const TSourceLoc&, TFunction&, TIntermNode* functionBody, TIntermNode*& node);
void remapEntryPointIO(TFunction& function, TVariable*& returnValue, TVector<TVariable*>& inputs, TVector<TVariable*>& outputs);
void remapNonEntryPointIO(TFunction& function);