mirror of
https://github.com/KhronosGroup/glslang
synced 2024-11-09 20:10:06 +00:00
HLSL: Refactor attribute implementation.
- make it sharable with GLSL - correct the case insensitivity - remove the map; queries are not needed, all entries need processing - make it easier to build bottom up (will help GLSL parsing) - support semantic checking and reporting - allow front-end dependent semantics and attribute name mapping
This commit is contained in:
parent
e349af7e20
commit
e18fd20d5c
@ -129,8 +129,9 @@ protected:
|
|||||||
spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
|
spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
|
||||||
spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration);
|
spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration);
|
||||||
spv::ImageFormat TranslateImageFormat(const glslang::TType& type);
|
spv::ImageFormat TranslateImageFormat(const glslang::TType& type);
|
||||||
spv::SelectionControlMask TranslateSelectionControl(glslang::TSelectionControl) const;
|
spv::SelectionControlMask TranslateSelectionControl(const glslang::TIntermSelection&) const;
|
||||||
spv::LoopControlMask TranslateLoopControl(glslang::TLoopControl) const;
|
spv::SelectionControlMask TranslateSwitchControl(const glslang::TIntermSwitch&) const;
|
||||||
|
spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&) const;
|
||||||
spv::StorageClass TranslateStorageClass(const glslang::TType&);
|
spv::StorageClass TranslateStorageClass(const glslang::TType&);
|
||||||
spv::Id createSpvVariable(const glslang::TIntermSymbol*);
|
spv::Id createSpvVariable(const glslang::TIntermSymbol*);
|
||||||
spv::Id getSampledType(const glslang::TSampler&);
|
spv::Id getSampledType(const glslang::TSampler&);
|
||||||
@ -748,26 +749,34 @@ spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TTy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(glslang::TSelectionControl selectionControl) const
|
spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(const glslang::TIntermSelection& selectionNode) const
|
||||||
{
|
{
|
||||||
switch (selectionControl) {
|
if (selectionNode.getFlatten())
|
||||||
case glslang::ESelectionControlNone: return spv::SelectionControlMaskNone;
|
return spv::SelectionControlFlattenMask;
|
||||||
case glslang::ESelectionControlFlatten: return spv::SelectionControlFlattenMask;
|
if (selectionNode.getDontFlatten())
|
||||||
case glslang::ESelectionControlDontFlatten: return spv::SelectionControlDontFlattenMask;
|
return spv::SelectionControlDontFlattenMask;
|
||||||
default: return spv::SelectionControlMaskNone;
|
return spv::SelectionControlMaskNone;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(glslang::TLoopControl loopControl) const
|
spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode) const
|
||||||
{
|
{
|
||||||
switch (loopControl) {
|
if (switchNode.getFlatten())
|
||||||
case glslang::ELoopControlNone: return spv::LoopControlMaskNone;
|
return spv::SelectionControlFlattenMask;
|
||||||
case glslang::ELoopControlUnroll: return spv::LoopControlUnrollMask;
|
if (switchNode.getDontFlatten())
|
||||||
case glslang::ELoopControlDontUnroll: return spv::LoopControlDontUnrollMask;
|
return spv::SelectionControlDontFlattenMask;
|
||||||
// TODO: DependencyInfinite
|
return spv::SelectionControlMaskNone;
|
||||||
// TODO: DependencyLength
|
|
||||||
default: return spv::LoopControlMaskNone;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(const glslang::TIntermLoop& loopNode) const
|
||||||
|
{
|
||||||
|
spv::LoopControlMask control = spv::LoopControlMaskNone;
|
||||||
|
|
||||||
|
if (loopNode.getDontUnroll())
|
||||||
|
control = control | spv::LoopControlDontUnrollMask;
|
||||||
|
if (loopNode.getUnroll())
|
||||||
|
control = control | spv::LoopControlUnrollMask;
|
||||||
|
|
||||||
|
return control;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate glslang type to SPIR-V storage class.
|
// Translate glslang type to SPIR-V storage class.
|
||||||
@ -2026,7 +2035,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
|
|||||||
node->getCondition()->traverse(this);
|
node->getCondition()->traverse(this);
|
||||||
|
|
||||||
// Selection control:
|
// Selection control:
|
||||||
const spv::SelectionControlMask control = TranslateSelectionControl(node->getSelectionControl());
|
const spv::SelectionControlMask control = TranslateSelectionControl(*node);
|
||||||
|
|
||||||
// make an "if" based on the value created by the condition
|
// make an "if" based on the value created by the condition
|
||||||
spv::Builder::If ifBuilder(accessChainLoad(node->getCondition()->getType()), control, builder);
|
spv::Builder::If ifBuilder(accessChainLoad(node->getCondition()->getType()), control, builder);
|
||||||
@ -2068,7 +2077,7 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T
|
|||||||
spv::Id selector = accessChainLoad(node->getCondition()->getAsTyped()->getType());
|
spv::Id selector = accessChainLoad(node->getCondition()->getAsTyped()->getType());
|
||||||
|
|
||||||
// Selection control:
|
// Selection control:
|
||||||
const spv::SelectionControlMask control = TranslateSelectionControl(node->getSelectionControl());
|
const spv::SelectionControlMask control = TranslateSwitchControl(*node);
|
||||||
|
|
||||||
// browse the children to sort out code segments
|
// browse the children to sort out code segments
|
||||||
int defaultSegment = -1;
|
int defaultSegment = -1;
|
||||||
@ -2128,7 +2137,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
|
|||||||
builder.createBranch(&blocks.head);
|
builder.createBranch(&blocks.head);
|
||||||
|
|
||||||
// Loop control:
|
// Loop control:
|
||||||
const spv::LoopControlMask control = TranslateLoopControl(node->getLoopControl());
|
const spv::LoopControlMask control = TranslateLoopControl(*node);
|
||||||
|
|
||||||
// TODO: dependency length
|
// TODO: dependency length
|
||||||
|
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
hlsl.numthreads.comp
|
hlsl.numthreads.comp
|
||||||
Shader version: 500
|
Shader version: 500
|
||||||
local_size = (4, 4, 2)
|
local_size = (1, 4, 8)
|
||||||
0:? Sequence
|
0:? Sequence
|
||||||
0:4 Function Definition: main(vu3; ( temp void)
|
0:4 Function Definition: main(vu3; ( temp void)
|
||||||
0:4 Function Parameters:
|
0:4 Function Parameters:
|
||||||
0:4 'tid' ( in 3-component vector of uint)
|
0:4 'tid' ( in 3-component vector of uint)
|
||||||
0:9 Function Definition: @main_aux1(vu3; ( temp void)
|
0:9 Function Definition: @main_aux2(vu3; ( temp void)
|
||||||
0:9 Function Parameters:
|
0:9 Function Parameters:
|
||||||
0:9 'tid' ( in 3-component vector of uint)
|
0:9 'tid' ( in 3-component vector of uint)
|
||||||
0:9 Function Definition: main_aux1( ( temp void)
|
0:9 Function Definition: main_aux2( ( temp void)
|
||||||
0:9 Function Parameters:
|
0:9 Function Parameters:
|
||||||
0:? Sequence
|
0:? Sequence
|
||||||
0:9 move second child to first child ( temp 3-component vector of uint)
|
0:9 move second child to first child ( temp 3-component vector of uint)
|
||||||
0:? 'tid' ( temp 3-component vector of uint)
|
0:? 'tid' ( temp 3-component vector of uint)
|
||||||
0:? 'tid' ( in 3-component vector of uint GlobalInvocationID)
|
0:? 'tid' ( in 3-component vector of uint GlobalInvocationID)
|
||||||
0:9 Function Call: @main_aux1(vu3; ( temp void)
|
0:9 Function Call: @main_aux2(vu3; ( temp void)
|
||||||
0:? 'tid' ( temp 3-component vector of uint)
|
0:? 'tid' ( temp 3-component vector of uint)
|
||||||
0:? Linker Objects
|
0:? Linker Objects
|
||||||
0:? 'tid' ( in 3-component vector of uint GlobalInvocationID)
|
0:? 'tid' ( in 3-component vector of uint GlobalInvocationID)
|
||||||
@ -24,21 +24,21 @@ Linked compute stage:
|
|||||||
|
|
||||||
|
|
||||||
Shader version: 500
|
Shader version: 500
|
||||||
local_size = (4, 4, 2)
|
local_size = (1, 4, 8)
|
||||||
0:? Sequence
|
0:? Sequence
|
||||||
0:4 Function Definition: main(vu3; ( temp void)
|
0:4 Function Definition: main(vu3; ( temp void)
|
||||||
0:4 Function Parameters:
|
0:4 Function Parameters:
|
||||||
0:4 'tid' ( in 3-component vector of uint)
|
0:4 'tid' ( in 3-component vector of uint)
|
||||||
0:9 Function Definition: @main_aux1(vu3; ( temp void)
|
0:9 Function Definition: @main_aux2(vu3; ( temp void)
|
||||||
0:9 Function Parameters:
|
0:9 Function Parameters:
|
||||||
0:9 'tid' ( in 3-component vector of uint)
|
0:9 'tid' ( in 3-component vector of uint)
|
||||||
0:9 Function Definition: main_aux1( ( temp void)
|
0:9 Function Definition: main_aux2( ( temp void)
|
||||||
0:9 Function Parameters:
|
0:9 Function Parameters:
|
||||||
0:? Sequence
|
0:? Sequence
|
||||||
0:9 move second child to first child ( temp 3-component vector of uint)
|
0:9 move second child to first child ( temp 3-component vector of uint)
|
||||||
0:? 'tid' ( temp 3-component vector of uint)
|
0:? 'tid' ( temp 3-component vector of uint)
|
||||||
0:? 'tid' ( in 3-component vector of uint GlobalInvocationID)
|
0:? 'tid' ( in 3-component vector of uint GlobalInvocationID)
|
||||||
0:9 Function Call: @main_aux1(vu3; ( temp void)
|
0:9 Function Call: @main_aux2(vu3; ( temp void)
|
||||||
0:? 'tid' ( temp 3-component vector of uint)
|
0:? 'tid' ( temp 3-component vector of uint)
|
||||||
0:? Linker Objects
|
0:? Linker Objects
|
||||||
0:? 'tid' ( in 3-component vector of uint GlobalInvocationID)
|
0:? 'tid' ( in 3-component vector of uint GlobalInvocationID)
|
||||||
@ -50,13 +50,13 @@ local_size = (4, 4, 2)
|
|||||||
Capability Shader
|
Capability Shader
|
||||||
1: ExtInstImport "GLSL.std.450"
|
1: ExtInstImport "GLSL.std.450"
|
||||||
MemoryModel Logical GLSL450
|
MemoryModel Logical GLSL450
|
||||||
EntryPoint GLCompute 4 "main_aux1" 18
|
EntryPoint GLCompute 4 "main_aux2" 18
|
||||||
ExecutionMode 4 LocalSize 4 4 2
|
ExecutionMode 4 LocalSize 1 4 8
|
||||||
Source HLSL 500
|
Source HLSL 500
|
||||||
Name 4 "main_aux1"
|
Name 4 "main_aux2"
|
||||||
Name 11 "main(vu3;"
|
Name 11 "main(vu3;"
|
||||||
Name 10 "tid"
|
Name 10 "tid"
|
||||||
Name 14 "@main_aux1(vu3;"
|
Name 14 "@main_aux2(vu3;"
|
||||||
Name 13 "tid"
|
Name 13 "tid"
|
||||||
Name 16 "tid"
|
Name 16 "tid"
|
||||||
Name 18 "tid"
|
Name 18 "tid"
|
||||||
@ -70,7 +70,7 @@ local_size = (4, 4, 2)
|
|||||||
9: TypeFunction 2 8(ptr)
|
9: TypeFunction 2 8(ptr)
|
||||||
17: TypePointer Input 7(ivec3)
|
17: TypePointer Input 7(ivec3)
|
||||||
18(tid): 17(ptr) Variable Input
|
18(tid): 17(ptr) Variable Input
|
||||||
4(main_aux1): 2 Function None 3
|
4(main_aux2): 2 Function None 3
|
||||||
5: Label
|
5: Label
|
||||||
16(tid): 8(ptr) Variable Function
|
16(tid): 8(ptr) Variable Function
|
||||||
20(param): 8(ptr) Variable Function
|
20(param): 8(ptr) Variable Function
|
||||||
@ -78,7 +78,7 @@ local_size = (4, 4, 2)
|
|||||||
Store 16(tid) 19
|
Store 16(tid) 19
|
||||||
21: 7(ivec3) Load 16(tid)
|
21: 7(ivec3) Load 16(tid)
|
||||||
Store 20(param) 21
|
Store 20(param) 21
|
||||||
22: 2 FunctionCall 14(@main_aux1(vu3;) 20(param)
|
22: 2 FunctionCall 14(@main_aux2(vu3;) 20(param)
|
||||||
Return
|
Return
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
11(main(vu3;): 2 Function None 9
|
11(main(vu3;): 2 Function None 9
|
||||||
@ -86,7 +86,7 @@ local_size = (4, 4, 2)
|
|||||||
12: Label
|
12: Label
|
||||||
Return
|
Return
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
14(@main_aux1(vu3;): 2 Function None 9
|
14(@main_aux2(vu3;): 2 Function None 9
|
||||||
13(tid): 8(ptr) FunctionParameter
|
13(tid): 8(ptr) FunctionParameter
|
||||||
15: Label
|
15: Label
|
||||||
Return
|
Return
|
||||||
|
@ -4,11 +4,8 @@ void main(uint3 tid : SV_DispatchThreadID )
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[numTHreaDs(4,4,2)] // case insensitive
|
[numthreads(1,4,8)]
|
||||||
void main_aux1(uint3 tid : SV_DispatchThreadID )
|
void main_aux2(uint3 tid : SV_DispatchThreadID )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[numthreads(1,4,8)]
|
|
||||||
void main_aux2(uint3 tid : SV_DispatchThreadID );
|
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ endif(WIN32)
|
|||||||
set(SOURCES
|
set(SOURCES
|
||||||
MachineIndependent/glslang.y
|
MachineIndependent/glslang.y
|
||||||
MachineIndependent/glslang_tab.cpp
|
MachineIndependent/glslang_tab.cpp
|
||||||
|
MachineIndependent/attribute.cpp
|
||||||
MachineIndependent/Constant.cpp
|
MachineIndependent/Constant.cpp
|
||||||
MachineIndependent/iomapper.cpp
|
MachineIndependent/iomapper.cpp
|
||||||
MachineIndependent/InfoSink.cpp
|
MachineIndependent/InfoSink.cpp
|
||||||
@ -51,6 +52,7 @@ set(HEADERS
|
|||||||
Include/revision.h
|
Include/revision.h
|
||||||
Include/ShHandle.h
|
Include/ShHandle.h
|
||||||
Include/Types.h
|
Include/Types.h
|
||||||
|
MachineIndependent/attribute.h
|
||||||
MachineIndependent/glslang_tab.cpp.h
|
MachineIndependent/glslang_tab.cpp.h
|
||||||
MachineIndependent/gl_types.h
|
MachineIndependent/gl_types.h
|
||||||
MachineIndependent/Initialize.h
|
MachineIndependent/Initialize.h
|
||||||
|
@ -37,6 +37,9 @@
|
|||||||
#ifndef _CONSTANT_UNION_INCLUDED_
|
#ifndef _CONSTANT_UNION_INCLUDED_
|
||||||
#define _CONSTANT_UNION_INCLUDED_
|
#define _CONSTANT_UNION_INCLUDED_
|
||||||
|
|
||||||
|
#include "../Include/Common.h"
|
||||||
|
#include "../Include/BaseTypes.h"
|
||||||
|
|
||||||
namespace glslang {
|
namespace glslang {
|
||||||
|
|
||||||
class TConstUnion {
|
class TConstUnion {
|
||||||
|
@ -885,24 +885,6 @@ protected:
|
|||||||
TType type;
|
TType type;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
|
||||||
// Selection control hints
|
|
||||||
//
|
|
||||||
enum TSelectionControl {
|
|
||||||
ESelectionControlNone,
|
|
||||||
ESelectionControlFlatten,
|
|
||||||
ESelectionControlDontFlatten,
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Loop control hints
|
|
||||||
//
|
|
||||||
enum TLoopControl {
|
|
||||||
ELoopControlNone,
|
|
||||||
ELoopControlUnroll,
|
|
||||||
ELoopControlDontUnroll,
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handle for, do-while, and while loops.
|
// Handle for, do-while, and while loops.
|
||||||
//
|
//
|
||||||
@ -913,7 +895,8 @@ public:
|
|||||||
test(aTest),
|
test(aTest),
|
||||||
terminal(aTerminal),
|
terminal(aTerminal),
|
||||||
first(testFirst),
|
first(testFirst),
|
||||||
control(ELoopControlNone)
|
unroll(false),
|
||||||
|
dontUnroll(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual TIntermLoop* getAsLoopNode() { return this; }
|
virtual TIntermLoop* getAsLoopNode() { return this; }
|
||||||
@ -924,15 +907,18 @@ public:
|
|||||||
TIntermTyped* getTerminal() const { return terminal; }
|
TIntermTyped* getTerminal() const { return terminal; }
|
||||||
bool testFirst() const { return first; }
|
bool testFirst() const { return first; }
|
||||||
|
|
||||||
void setLoopControl(TLoopControl c) { control = c; }
|
void setUnroll() { unroll = true; }
|
||||||
TLoopControl getLoopControl() const { return control; }
|
void setDontUnroll() { dontUnroll = true; }
|
||||||
|
bool getUnroll() const { return unroll; }
|
||||||
|
bool getDontUnroll() const { return dontUnroll; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TIntermNode* body; // code to loop over
|
TIntermNode* body; // code to loop over
|
||||||
TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops
|
TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops
|
||||||
TIntermTyped* terminal; // exists for for-loops
|
TIntermTyped* terminal; // exists for for-loops
|
||||||
bool first; // true for while and for, not for do-while
|
bool first; // true for while and for, not for do-while
|
||||||
TLoopControl control; // loop control hint
|
bool unroll; // true if unroll requested
|
||||||
|
bool dontUnroll; // true if request to not unroll
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1343,22 +1329,29 @@ protected:
|
|||||||
class TIntermSelection : public TIntermTyped {
|
class TIntermSelection : public TIntermTyped {
|
||||||
public:
|
public:
|
||||||
TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
|
TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
|
||||||
TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB), control(ESelectionControlNone) {}
|
TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB),
|
||||||
|
flatten(false), dontFlatten(false) {}
|
||||||
TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
|
TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
|
||||||
TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB), control(ESelectionControlNone) {}
|
TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB),
|
||||||
|
flatten(false), dontFlatten(false) {}
|
||||||
virtual void traverse(TIntermTraverser*);
|
virtual void traverse(TIntermTraverser*);
|
||||||
virtual TIntermTyped* getCondition() const { return condition; }
|
virtual TIntermTyped* getCondition() const { return condition; }
|
||||||
virtual TIntermNode* getTrueBlock() const { return trueBlock; }
|
virtual TIntermNode* getTrueBlock() const { return trueBlock; }
|
||||||
virtual TIntermNode* getFalseBlock() const { return falseBlock; }
|
virtual TIntermNode* getFalseBlock() const { return falseBlock; }
|
||||||
virtual TIntermSelection* getAsSelectionNode() { return this; }
|
virtual TIntermSelection* getAsSelectionNode() { return this; }
|
||||||
virtual const TIntermSelection* getAsSelectionNode() const { return this; }
|
virtual const TIntermSelection* getAsSelectionNode() const { return this; }
|
||||||
void setSelectionControl(TSelectionControl c) { control = c; }
|
|
||||||
TSelectionControl getSelectionControl() const { return control; }
|
void setFlatten() { flatten = true; }
|
||||||
|
void setDontFlatten() { dontFlatten = true; }
|
||||||
|
bool getFlatten() const { return flatten; }
|
||||||
|
bool getDontFlatten() const { return dontFlatten; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TIntermTyped* condition;
|
TIntermTyped* condition;
|
||||||
TIntermNode* trueBlock;
|
TIntermNode* trueBlock;
|
||||||
TIntermNode* falseBlock;
|
TIntermNode* falseBlock;
|
||||||
TSelectionControl control; // selection control hint
|
bool flatten; // true if flatten requested
|
||||||
|
bool dontFlatten; // true if requested to not flatten
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1369,18 +1362,24 @@ protected:
|
|||||||
//
|
//
|
||||||
class TIntermSwitch : public TIntermNode {
|
class TIntermSwitch : public TIntermNode {
|
||||||
public:
|
public:
|
||||||
TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b), control(ESelectionControlNone) { }
|
TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b),
|
||||||
|
flatten(false), dontFlatten(false) {}
|
||||||
virtual void traverse(TIntermTraverser*);
|
virtual void traverse(TIntermTraverser*);
|
||||||
virtual TIntermNode* getCondition() const { return condition; }
|
virtual TIntermNode* getCondition() const { return condition; }
|
||||||
virtual TIntermAggregate* getBody() const { return body; }
|
virtual TIntermAggregate* getBody() const { return body; }
|
||||||
virtual TIntermSwitch* getAsSwitchNode() { return this; }
|
virtual TIntermSwitch* getAsSwitchNode() { return this; }
|
||||||
virtual const TIntermSwitch* getAsSwitchNode() const { return this; }
|
virtual const TIntermSwitch* getAsSwitchNode() const { return this; }
|
||||||
void setSelectionControl(TSelectionControl c) { control = c; }
|
|
||||||
TSelectionControl getSelectionControl() const { return control; }
|
void setFlatten() { flatten = true; }
|
||||||
|
void setDontFlatten() { dontFlatten = true; }
|
||||||
|
bool getFlatten() const { return flatten; }
|
||||||
|
bool getDontFlatten() const { return dontFlatten; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TIntermTyped* condition;
|
TIntermTyped* condition;
|
||||||
TIntermAggregate* body;
|
TIntermAggregate* body;
|
||||||
TSelectionControl control; // selection control hint
|
bool flatten; // true if flatten requested
|
||||||
|
bool dontFlatten; // true if requested to not flatten
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TVisit
|
enum TVisit
|
||||||
|
@ -1614,7 +1614,7 @@ TIntermAggregate* TIntermediate::makeAggregate(const TSourceLoc& loc)
|
|||||||
//
|
//
|
||||||
// Returns the selection node created.
|
// Returns the selection node created.
|
||||||
//
|
//
|
||||||
TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& loc, TSelectionControl control)
|
TIntermSelection* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& loc)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Don't prune the false path for compile-time constants; it's needed
|
// Don't prune the false path for compile-time constants; it's needed
|
||||||
@ -1623,7 +1623,6 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair no
|
|||||||
|
|
||||||
TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
|
TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
|
||||||
node->setLoc(loc);
|
node->setLoc(loc);
|
||||||
node->setSelectionControl(control);
|
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@ -1666,12 +1665,13 @@ TIntermTyped* TIntermediate::addMethod(TIntermTyped* object, const TType& type,
|
|||||||
//
|
//
|
||||||
// Returns the selection node created, or nullptr if one could not be.
|
// Returns the selection node created, or nullptr if one could not be.
|
||||||
//
|
//
|
||||||
TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& loc, TSelectionControl control)
|
TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock,
|
||||||
|
const TSourceLoc& loc)
|
||||||
{
|
{
|
||||||
// If it's void, go to the if-then-else selection()
|
// If it's void, go to the if-then-else selection()
|
||||||
if (trueBlock->getBasicType() == EbtVoid && falseBlock->getBasicType() == EbtVoid) {
|
if (trueBlock->getBasicType() == EbtVoid && falseBlock->getBasicType() == EbtVoid) {
|
||||||
TIntermNodePair pair = { trueBlock, falseBlock };
|
TIntermNodePair pair = { trueBlock, falseBlock };
|
||||||
return addSelection(cond, pair, loc, control);
|
return addSelection(cond, pair, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1909,11 +1909,11 @@ const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool
|
|||||||
//
|
//
|
||||||
// Create while and do-while loop nodes.
|
// Create while and do-while loop nodes.
|
||||||
//
|
//
|
||||||
TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TLoopControl control)
|
TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst,
|
||||||
|
const TSourceLoc& loc)
|
||||||
{
|
{
|
||||||
TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
|
TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
|
||||||
node->setLoc(loc);
|
node->setLoc(loc);
|
||||||
node->setLoopControl(control);
|
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@ -1921,11 +1921,11 @@ TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TInte
|
|||||||
//
|
//
|
||||||
// Create a for-loop sequence.
|
// Create a for-loop sequence.
|
||||||
//
|
//
|
||||||
TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TLoopControl control)
|
TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test,
|
||||||
|
TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TIntermLoop*& node)
|
||||||
{
|
{
|
||||||
TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
|
node = new TIntermLoop(body, test, terminal, testFirst);
|
||||||
node->setLoc(loc);
|
node->setLoc(loc);
|
||||||
node->setLoopControl(control);
|
|
||||||
|
|
||||||
// make a sequence of the initializer and statement, but try to reuse the
|
// make a sequence of the initializer and statement, but try to reuse the
|
||||||
// aggregate already created for whatever is in the initializer, if there is one
|
// aggregate already created for whatever is in the initializer, if there is one
|
||||||
|
86
glslang/MachineIndependent/attribute.cpp
Normal file
86
glslang/MachineIndependent/attribute.cpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2017 LunarG, Inc.
|
||||||
|
// Copyright (C) 2018 Google, Inc.
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions
|
||||||
|
// are met:
|
||||||
|
//
|
||||||
|
// Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following
|
||||||
|
// disclaimer in the documentation and/or other materials provided
|
||||||
|
// with the distribution.
|
||||||
|
//
|
||||||
|
// Neither the name of Google, Inc., nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived
|
||||||
|
// from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "attribute.h"
|
||||||
|
#include "../Include/intermediate.h"
|
||||||
|
#include "ParseHelper.h"
|
||||||
|
|
||||||
|
namespace glslang {
|
||||||
|
|
||||||
|
// extract integers out of attribute arguments stored in attribute aggregate
|
||||||
|
bool TAttributeArgs::getInt(int& value, int argNum) const
|
||||||
|
{
|
||||||
|
const TConstUnion* intConst = getConstUnion(EbtInt, argNum);
|
||||||
|
|
||||||
|
if (intConst == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
value = intConst->getIConst();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// extract strings out of attribute arguments stored in attribute aggregate.
|
||||||
|
// convert to lower case if converToLower is true (for case-insensitive compare convenience)
|
||||||
|
bool TAttributeArgs::getString(TString& value, int argNum, bool convertToLower) const
|
||||||
|
{
|
||||||
|
const TConstUnion* stringConst = getConstUnion(EbtString, argNum);
|
||||||
|
|
||||||
|
if (stringConst == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
value = *stringConst->getSConst();
|
||||||
|
|
||||||
|
// Convenience.
|
||||||
|
if (convertToLower)
|
||||||
|
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper to get attribute const union. Returns nullptr on failure.
|
||||||
|
const TConstUnion* TAttributeArgs::getConstUnion(TBasicType basicType, int argNum) const
|
||||||
|
{
|
||||||
|
if (argNum >= args->getSequence().size())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
const TConstUnion* constVal = &args->getSequence()[argNum]->getAsConstantUnion()->getConstArray()[0];
|
||||||
|
if (constVal == nullptr || constVal->getType() != basicType)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return constVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end namespace glslang
|
97
glslang/MachineIndependent/attribute.h
Normal file
97
glslang/MachineIndependent/attribute.h
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2017 LunarG, Inc.
|
||||||
|
// Copyright (C) 2018 Google, Inc.
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions
|
||||||
|
// are met:
|
||||||
|
//
|
||||||
|
// Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following
|
||||||
|
// disclaimer in the documentation and/or other materials provided
|
||||||
|
// with the distribution.
|
||||||
|
//
|
||||||
|
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived
|
||||||
|
// from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef _ATTRIBUTE_INCLUDED_
|
||||||
|
#define _ATTRIBUTE_INCLUDED_
|
||||||
|
|
||||||
|
#include "../Include/Common.h"
|
||||||
|
#include "../Include/ConstantUnion.h"
|
||||||
|
|
||||||
|
namespace glslang {
|
||||||
|
|
||||||
|
enum TAttributeType {
|
||||||
|
EatNone,
|
||||||
|
EatAllow_uav_condition,
|
||||||
|
EatBranch,
|
||||||
|
EatCall,
|
||||||
|
EatDomain,
|
||||||
|
EatEarlyDepthStencil,
|
||||||
|
EatFastOpt,
|
||||||
|
EatFlatten,
|
||||||
|
EatForceCase,
|
||||||
|
EatInstance,
|
||||||
|
EatMaxTessFactor,
|
||||||
|
EatNumThreads,
|
||||||
|
EatMaxVertexCount,
|
||||||
|
EatOutputControlPoints,
|
||||||
|
EatOutputTopology,
|
||||||
|
EatPartitioning,
|
||||||
|
EatPatchConstantFunc,
|
||||||
|
EatPatchSize,
|
||||||
|
EatUnroll,
|
||||||
|
EatLoop,
|
||||||
|
EatBinding,
|
||||||
|
EatGlobalBinding,
|
||||||
|
EatLocation,
|
||||||
|
EatInputAttachment,
|
||||||
|
EatBuiltIn,
|
||||||
|
EatPushConstant,
|
||||||
|
EatConstantId
|
||||||
|
};
|
||||||
|
|
||||||
|
class TIntermAggregate;
|
||||||
|
|
||||||
|
struct TAttributeArgs {
|
||||||
|
TAttributeType name;
|
||||||
|
TIntermAggregate* args;
|
||||||
|
|
||||||
|
// Obtain attribute as integer
|
||||||
|
// Return false if it cannot be obtained
|
||||||
|
bool getInt(int& value, int argNum = 0) const;
|
||||||
|
|
||||||
|
// Obtain attribute as string, with optional to-lower transform
|
||||||
|
// Return false if it cannot be obtained
|
||||||
|
bool getString(TString& value, int argNum = 0, bool convertToLower = true) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const TConstUnion* getConstUnion(TBasicType basicType, int argNum) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef TList<TAttributeArgs> TAttributes;
|
||||||
|
|
||||||
|
} // end namespace glslang
|
||||||
|
|
||||||
|
#endif // _ATTRIBUTE_INCLUDED_
|
@ -420,8 +420,8 @@ public:
|
|||||||
TIntermAggregate* makeAggregate(const TSourceLoc&);
|
TIntermAggregate* makeAggregate(const TSourceLoc&);
|
||||||
TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc);
|
TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc);
|
||||||
bool areAllChildConst(TIntermAggregate* aggrNode);
|
bool areAllChildConst(TIntermAggregate* aggrNode);
|
||||||
TIntermTyped* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&, TSelectionControl = ESelectionControlNone);
|
TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
|
||||||
TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&, TSelectionControl = ESelectionControlNone);
|
TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
|
||||||
TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
|
TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
|
||||||
TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&);
|
TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&);
|
||||||
TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const;
|
TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const;
|
||||||
@ -439,8 +439,9 @@ public:
|
|||||||
TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const;
|
TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const;
|
||||||
TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
|
TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
|
||||||
bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
|
bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
|
||||||
TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&, TLoopControl = ELoopControlNone);
|
TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
|
||||||
TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&, TLoopControl = ELoopControlNone);
|
TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst,
|
||||||
|
const TSourceLoc&, TIntermLoop*&);
|
||||||
TIntermBranch* addBranch(TOperator, const TSourceLoc&);
|
TIntermBranch* addBranch(TOperator, const TSourceLoc&);
|
||||||
TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
|
TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
|
||||||
template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&);
|
template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&);
|
||||||
|
@ -247,7 +247,7 @@ INSTANTIATE_TEST_CASE_P(
|
|||||||
{"hlsl.matrixindex.frag", "main"},
|
{"hlsl.matrixindex.frag", "main"},
|
||||||
{"hlsl.nonstaticMemberFunction.frag", "main"},
|
{"hlsl.nonstaticMemberFunction.frag", "main"},
|
||||||
{"hlsl.numericsuffixes.frag", "main"},
|
{"hlsl.numericsuffixes.frag", "main"},
|
||||||
{"hlsl.numthreads.comp", "main_aux1"},
|
{"hlsl.numthreads.comp", "main_aux2"},
|
||||||
{"hlsl.overload.frag", "PixelShaderFunction"},
|
{"hlsl.overload.frag", "PixelShaderFunction"},
|
||||||
{"hlsl.opaque-type-bug.frag", "main"},
|
{"hlsl.opaque-type-bug.frag", "main"},
|
||||||
{"hlsl.params.default.frag", "main"},
|
{"hlsl.params.default.frag", "main"},
|
||||||
|
@ -34,157 +34,73 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "hlslAttributes.h"
|
#include "hlslAttributes.h"
|
||||||
#include <cstdlib>
|
#include "hlslParseHelper.h"
|
||||||
#include <cctype>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace glslang {
|
namespace glslang {
|
||||||
// Map the given string to an attribute enum from TAttributeType,
|
// Map the given string to an attribute enum from TAttributeType,
|
||||||
// or EatNone if invalid.
|
// or EatNone if invalid.
|
||||||
TAttributeType TAttributeMap::attributeFromName(const TString& nameSpace, const TString& name)
|
TAttributeType HlslParseContext::attributeFromName(const TString& nameSpace, const TString& name) const
|
||||||
{
|
{
|
||||||
// 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
|
// handle names within a namespace
|
||||||
|
|
||||||
if (lowernameSpace == "vk") {
|
if (nameSpace == "vk") {
|
||||||
if (lowername == "input_attachment_index")
|
if (name == "input_attachment_index")
|
||||||
return EatInputAttachment;
|
return EatInputAttachment;
|
||||||
else if (lowername == "location")
|
else if (name == "location")
|
||||||
return EatLocation;
|
return EatLocation;
|
||||||
else if (lowername == "binding")
|
else if (name == "binding")
|
||||||
return EatBinding;
|
return EatBinding;
|
||||||
else if (lowername == "global_cbuffer_binding")
|
else if (name == "global_cbuffer_binding")
|
||||||
return EatGlobalBinding;
|
return EatGlobalBinding;
|
||||||
else if (lowername == "builtin")
|
else if (name == "builtin")
|
||||||
return EatBuiltIn;
|
return EatBuiltIn;
|
||||||
else if (lowername == "constant_id")
|
else if (name == "constant_id")
|
||||||
return EatConstantId;
|
return EatConstantId;
|
||||||
else if (lowername == "push_constant")
|
else if (name == "push_constant")
|
||||||
return EatPushConstant;
|
return EatPushConstant;
|
||||||
} else if (lowernameSpace.size() > 0)
|
} else if (nameSpace.size() > 0)
|
||||||
return EatNone;
|
return EatNone;
|
||||||
|
|
||||||
// handle names with no namespace
|
// handle names with no namespace
|
||||||
|
|
||||||
if (lowername == "allow_uav_condition")
|
if (name == "allow_uav_condition")
|
||||||
return EatAllow_uav_condition;
|
return EatAllow_uav_condition;
|
||||||
else if (lowername == "branch")
|
else if (name == "branch")
|
||||||
return EatBranch;
|
return EatBranch;
|
||||||
else if (lowername == "call")
|
else if (name == "call")
|
||||||
return EatCall;
|
return EatCall;
|
||||||
else if (lowername == "domain")
|
else if (name == "domain")
|
||||||
return EatDomain;
|
return EatDomain;
|
||||||
else if (lowername == "earlydepthstencil")
|
else if (name == "earlydepthstencil")
|
||||||
return EatEarlyDepthStencil;
|
return EatEarlyDepthStencil;
|
||||||
else if (lowername == "fastopt")
|
else if (name == "fastopt")
|
||||||
return EatFastOpt;
|
return EatFastOpt;
|
||||||
else if (lowername == "flatten")
|
else if (name == "flatten")
|
||||||
return EatFlatten;
|
return EatFlatten;
|
||||||
else if (lowername == "forcecase")
|
else if (name == "forcecase")
|
||||||
return EatForceCase;
|
return EatForceCase;
|
||||||
else if (lowername == "instance")
|
else if (name == "instance")
|
||||||
return EatInstance;
|
return EatInstance;
|
||||||
else if (lowername == "maxtessfactor")
|
else if (name == "maxtessfactor")
|
||||||
return EatMaxTessFactor;
|
return EatMaxTessFactor;
|
||||||
else if (lowername == "maxvertexcount")
|
else if (name == "maxvertexcount")
|
||||||
return EatMaxVertexCount;
|
return EatMaxVertexCount;
|
||||||
else if (lowername == "numthreads")
|
else if (name == "numthreads")
|
||||||
return EatNumThreads;
|
return EatNumThreads;
|
||||||
else if (lowername == "outputcontrolpoints")
|
else if (name == "outputcontrolpoints")
|
||||||
return EatOutputControlPoints;
|
return EatOutputControlPoints;
|
||||||
else if (lowername == "outputtopology")
|
else if (name == "outputtopology")
|
||||||
return EatOutputTopology;
|
return EatOutputTopology;
|
||||||
else if (lowername == "partitioning")
|
else if (name == "partitioning")
|
||||||
return EatPartitioning;
|
return EatPartitioning;
|
||||||
else if (lowername == "patchconstantfunc")
|
else if (name == "patchconstantfunc")
|
||||||
return EatPatchConstantFunc;
|
return EatPatchConstantFunc;
|
||||||
else if (lowername == "unroll")
|
else if (name == "unroll")
|
||||||
return EatUnroll;
|
return EatUnroll;
|
||||||
else if (lowername == "loop")
|
else if (name == "loop")
|
||||||
return EatLoop;
|
return EatLoop;
|
||||||
else
|
else
|
||||||
return EatNone;
|
return EatNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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& nameSpace, const TString* name, TIntermAggregate* value)
|
|
||||||
{
|
|
||||||
if (name == nullptr)
|
|
||||||
return EatNone;
|
|
||||||
|
|
||||||
const TAttributeType attr = attributeFromName(nameSpace, *name);
|
|
||||||
|
|
||||||
if (attr != EatNone)
|
|
||||||
attributes[attr] = value;
|
|
||||||
|
|
||||||
return attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look up entry (const version), and return aggregate node. This cannot change the map.
|
|
||||||
const TIntermAggregate* TAttributeMap::operator[](TAttributeType attr) const
|
|
||||||
{
|
|
||||||
const auto entry = attributes.find(attr);
|
|
||||||
|
|
||||||
return (entry == attributes.end()) ? nullptr : entry->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// True if entry exists in map (even if value is nullptr)
|
|
||||||
bool TAttributeMap::contains(TAttributeType attr) const
|
|
||||||
{
|
|
||||||
return attributes.find(attr) != attributes.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
// extract integers out of attribute arguments stored in attribute aggregate
|
|
||||||
bool TAttributeMap::getInt(TAttributeType attr, int& value, int argNum) const
|
|
||||||
{
|
|
||||||
const TConstUnion* intConst = getConstUnion(attr, EbtInt, argNum);
|
|
||||||
|
|
||||||
if (intConst == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
value = intConst->getIConst();
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// extract strings out of attribute arguments stored in attribute aggregate.
|
|
||||||
// convert to lower case if converToLower is true (for case-insensitive compare convenience)
|
|
||||||
bool TAttributeMap::getString(TAttributeType attr, TString& value, int argNum, bool convertToLower) const
|
|
||||||
{
|
|
||||||
const TConstUnion* stringConst = getConstUnion(attr, EbtString, argNum);
|
|
||||||
|
|
||||||
if (stringConst == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
value = *stringConst->getSConst();
|
|
||||||
|
|
||||||
// Convenience.
|
|
||||||
if (convertToLower)
|
|
||||||
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper to get attribute const union. Returns nullptr on failure.
|
|
||||||
const TConstUnion* TAttributeMap::getConstUnion(TAttributeType attr, TBasicType basicType, int argNum) const
|
|
||||||
{
|
|
||||||
const TIntermAggregate* attrAgg = (*this)[attr];
|
|
||||||
if (attrAgg == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (argNum >= int(attrAgg->getSequence().size()))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
const TConstUnion* constVal = &attrAgg->getSequence()[argNum]->getAsConstantUnion()->getConstArray()[0];
|
|
||||||
if (constVal == nullptr || constVal->getType() != basicType)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return constVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace glslang
|
} // end namespace glslang
|
||||||
|
@ -38,93 +38,22 @@
|
|||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
#include "../glslang/MachineIndependent/attribute.h"
|
||||||
|
#include "../glslang/MachineIndependent/SymbolTable.h"
|
||||||
#include "hlslScanContext.h"
|
#include "hlslScanContext.h"
|
||||||
#include "../glslang/Include/Common.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
namespace glslang {
|
||||||
enum TAttributeType {
|
|
||||||
EatNone,
|
|
||||||
EatAllow_uav_condition,
|
|
||||||
EatBranch,
|
|
||||||
EatCall,
|
|
||||||
EatDomain,
|
|
||||||
EatEarlyDepthStencil,
|
|
||||||
EatFastOpt,
|
|
||||||
EatFlatten,
|
|
||||||
EatForceCase,
|
|
||||||
EatInstance,
|
|
||||||
EatMaxTessFactor,
|
|
||||||
EatNumThreads,
|
|
||||||
EatMaxVertexCount,
|
|
||||||
EatOutputControlPoints,
|
|
||||||
EatOutputTopology,
|
|
||||||
EatPartitioning,
|
|
||||||
EatPatchConstantFunc,
|
|
||||||
EatPatchSize,
|
|
||||||
EatUnroll,
|
|
||||||
EatLoop,
|
|
||||||
EatBinding,
|
|
||||||
EatGlobalBinding,
|
|
||||||
EatLocation,
|
|
||||||
EatInputAttachment,
|
|
||||||
EatBuiltIn,
|
|
||||||
EatPushConstant,
|
|
||||||
EatConstantId
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
// Allow use of TAttributeType enum in hash_map without calling code having to cast.
|
|
||||||
template <> struct hash<glslang::TAttributeType> {
|
|
||||||
std::size_t operator()(glslang::TAttributeType attr) const {
|
|
||||||
return std::hash<int>()(int(attr));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // end namespace std
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
class TIntermAggregate;
|
|
||||||
|
|
||||||
class TAttributeMap {
|
|
||||||
public:
|
|
||||||
int size() const { return (int)attributes.size(); }
|
|
||||||
|
|
||||||
// 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& nameSpace, const TString* name, TIntermAggregate* value);
|
|
||||||
|
|
||||||
// Const lookup: search for (but do not modify) the attribute in the map.
|
|
||||||
const TIntermAggregate* operator[](TAttributeType) const;
|
|
||||||
|
|
||||||
// True if entry exists in map (even if value is nullptr)
|
|
||||||
bool contains(TAttributeType) const;
|
|
||||||
|
|
||||||
// Obtain attribute as integer
|
|
||||||
bool getInt(TAttributeType attr, int& value, int argNum = 0) const;
|
|
||||||
|
|
||||||
// Obtain attribute as string, with optional to-lower transform
|
|
||||||
bool getString(TAttributeType attr, TString& value, int argNum = 0, bool convertToLower = true) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Helper to get attribute const union
|
|
||||||
const TConstUnion* getConstUnion(TAttributeType attr, TBasicType, int argNum) const;
|
|
||||||
|
|
||||||
// Find an attribute enum given its name.
|
|
||||||
static TAttributeType attributeFromName(const TString& nameSpace, const TString& name);
|
|
||||||
|
|
||||||
std::unordered_map<TAttributeType, TIntermAggregate*> attributes;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TFunctionDeclarator {
|
class TFunctionDeclarator {
|
||||||
public:
|
public:
|
||||||
TFunctionDeclarator() : function(nullptr), body(nullptr) { }
|
TFunctionDeclarator() : function(nullptr), body(nullptr) { }
|
||||||
TSourceLoc loc;
|
TSourceLoc loc;
|
||||||
TFunction* function;
|
TFunction* function;
|
||||||
TAttributeMap attributes;
|
TAttributes attributes;
|
||||||
TVector<HlslToken>* body;
|
TVector<HlslToken>* body;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace glslang
|
} // end namespace glslang
|
||||||
|
|
||||||
|
|
||||||
#endif // HLSLATTRIBUTES_H_
|
#endif // HLSLATTRIBUTES_H_
|
||||||
|
@ -396,6 +396,9 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
|
|||||||
if (peekTokenClass(EHTokLeftParen)) {
|
if (peekTokenClass(EHTokLeftParen)) {
|
||||||
// looks like function parameters
|
// looks like function parameters
|
||||||
|
|
||||||
|
// merge in the attributes into the return type
|
||||||
|
parseContext.transferTypeAttributes(token.loc, declarator.attributes, declaredType, true);
|
||||||
|
|
||||||
// Potentially rename shader entry point function. No-op most of the time.
|
// Potentially rename shader entry point function. No-op most of the time.
|
||||||
parseContext.renameShaderFunction(fullName);
|
parseContext.renameShaderFunction(fullName);
|
||||||
|
|
||||||
@ -423,7 +426,13 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
|
|||||||
parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, true);
|
parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// A variable declaration. Fix the storage qualifier if it's a global.
|
// A variable declaration.
|
||||||
|
|
||||||
|
// merge in the attributes, the first time around, into the shared type
|
||||||
|
if (! declarator_list)
|
||||||
|
parseContext.transferTypeAttributes(token.loc, declarator.attributes, declaredType);
|
||||||
|
|
||||||
|
// Fix the storage qualifier if it's a global.
|
||||||
if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
|
if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
|
||||||
declaredType.getQualifier().storage = EvqUniform;
|
declaredType.getQualifier().storage = EvqUniform;
|
||||||
|
|
||||||
@ -536,13 +545,16 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
|
|||||||
bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
|
bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
|
||||||
{
|
{
|
||||||
node = nullptr;
|
node = nullptr;
|
||||||
TAttributeMap attributes;
|
TAttributes attributes;
|
||||||
|
|
||||||
// fully_specified_type
|
// fully_specified_type
|
||||||
TType type;
|
TType type;
|
||||||
if (! acceptFullySpecifiedType(type, attributes))
|
if (! acceptFullySpecifiedType(type, attributes))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (attributes.size() > 0)
|
||||||
|
parseContext.warn(token.loc, "attributes don't apply to control declaration", "", "");
|
||||||
|
|
||||||
// filter out type casts
|
// filter out type casts
|
||||||
if (peekTokenClass(EHTokLeftParen)) {
|
if (peekTokenClass(EHTokLeftParen)) {
|
||||||
recedeToken();
|
recedeToken();
|
||||||
@ -578,12 +590,12 @@ bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
|
|||||||
// : type_specifier
|
// : type_specifier
|
||||||
// | type_qualifier type_specifier
|
// | type_qualifier type_specifier
|
||||||
//
|
//
|
||||||
bool HlslGrammar::acceptFullySpecifiedType(TType& type, const TAttributeMap& attributes)
|
bool HlslGrammar::acceptFullySpecifiedType(TType& type, const TAttributes& attributes)
|
||||||
{
|
{
|
||||||
TIntermNode* nodeList = nullptr;
|
TIntermNode* nodeList = nullptr;
|
||||||
return acceptFullySpecifiedType(type, nodeList, attributes);
|
return acceptFullySpecifiedType(type, nodeList, attributes);
|
||||||
}
|
}
|
||||||
bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList, const TAttributeMap& attributes, bool forbidDeclarators)
|
bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList, const TAttributes& attributes, bool forbidDeclarators)
|
||||||
{
|
{
|
||||||
// type_qualifier
|
// type_qualifier
|
||||||
TQualifier qualifier;
|
TQualifier qualifier;
|
||||||
@ -608,7 +620,7 @@ bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList,
|
|||||||
parseContext.mergeQualifiers(type.getQualifier(), qualifier);
|
parseContext.mergeQualifiers(type.getQualifier(), qualifier);
|
||||||
|
|
||||||
// merge in the attributes
|
// merge in the attributes
|
||||||
parseContext.transferTypeAttributes(attributes, type);
|
parseContext.transferTypeAttributes(token.loc, attributes, type);
|
||||||
|
|
||||||
// further, it can create an anonymous instance of the block
|
// further, it can create an anonymous instance of the block
|
||||||
// (cbuffer and tbuffer don't consume the next identifier, and
|
// (cbuffer and tbuffer don't consume the next identifier, and
|
||||||
@ -633,9 +645,6 @@ bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList,
|
|||||||
qualifier.builtIn = type.getQualifier().builtIn;
|
qualifier.builtIn = type.getQualifier().builtIn;
|
||||||
|
|
||||||
type.getQualifier() = qualifier;
|
type.getQualifier() = qualifier;
|
||||||
|
|
||||||
// merge in the attributes
|
|
||||||
parseContext.transferTypeAttributes(attributes, type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -2335,7 +2344,7 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*
|
|||||||
// struct_declaration
|
// struct_declaration
|
||||||
|
|
||||||
// attributes
|
// attributes
|
||||||
TAttributeMap attributes;
|
TAttributes attributes;
|
||||||
acceptAttributes(attributes);
|
acceptAttributes(attributes);
|
||||||
|
|
||||||
bool declarator_list = false;
|
bool declarator_list = false;
|
||||||
@ -2347,6 +2356,9 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// merge in the attributes
|
||||||
|
parseContext.transferTypeAttributes(token.loc, attributes, memberType);
|
||||||
|
|
||||||
// struct_declarator COMMA struct_declarator ...
|
// struct_declarator COMMA struct_declarator ...
|
||||||
bool functionDefinitionAccepted = false;
|
bool functionDefinitionAccepted = false;
|
||||||
do {
|
do {
|
||||||
@ -2542,7 +2554,7 @@ bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTy
|
|||||||
bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
|
bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
|
||||||
{
|
{
|
||||||
// attributes
|
// attributes
|
||||||
TAttributeMap attributes;
|
TAttributes attributes;
|
||||||
acceptAttributes(attributes);
|
acceptAttributes(attributes);
|
||||||
|
|
||||||
// fully_specified_type
|
// fully_specified_type
|
||||||
@ -2550,6 +2562,9 @@ bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
|
|||||||
if (! acceptFullySpecifiedType(*type, attributes))
|
if (! acceptFullySpecifiedType(*type, attributes))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// merge in the attributes
|
||||||
|
parseContext.transferTypeAttributes(token.loc, attributes, *type);
|
||||||
|
|
||||||
// identifier
|
// identifier
|
||||||
HlslToken idToken;
|
HlslToken idToken;
|
||||||
acceptIdentifier(idToken);
|
acceptIdentifier(idToken);
|
||||||
@ -3386,7 +3401,7 @@ bool HlslGrammar::acceptStatement(TIntermNode*& statement)
|
|||||||
statement = nullptr;
|
statement = nullptr;
|
||||||
|
|
||||||
// attributes
|
// attributes
|
||||||
TAttributeMap attributes;
|
TAttributes attributes;
|
||||||
acceptAttributes(attributes);
|
acceptAttributes(attributes);
|
||||||
|
|
||||||
// attributed_statement
|
// attributed_statement
|
||||||
@ -3458,7 +3473,7 @@ bool HlslGrammar::acceptStatement(TIntermNode*& statement)
|
|||||||
// | PATCHCONSTANTFUNC
|
// | PATCHCONSTANTFUNC
|
||||||
// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
|
// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
|
||||||
//
|
//
|
||||||
void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
|
void HlslGrammar::acceptAttributes(TAttributes& attributes)
|
||||||
{
|
{
|
||||||
// For now, accept the [ XXX(X) ] syntax, but drop all but
|
// For now, accept the [ XXX(X) ] syntax, but drop all but
|
||||||
// numthreads, which is used to set the CS local size.
|
// numthreads, which is used to set the CS local size.
|
||||||
@ -3529,9 +3544,16 @@ void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add any values we found into the attribute map. This accepts
|
// Add any values we found into the attribute map.
|
||||||
// (and ignores) values not mapping to a known TAttributeType;
|
if (attributeToken.string != nullptr) {
|
||||||
attributes.setAttribute(nameSpace, attributeToken.string, expressions);
|
TAttributeType attributeType = parseContext.attributeFromName(nameSpace, *attributeToken.string);
|
||||||
|
if (attributeType == EatNone)
|
||||||
|
parseContext.warn(attributeToken.loc, "unrecognized attribute", attributeToken.string->c_str(), "");
|
||||||
|
else {
|
||||||
|
TAttributeArgs attributeArgs = { attributeType, expressions };
|
||||||
|
attributes.push_back(attributeArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3539,12 +3561,10 @@ void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
|
|||||||
// : IF LEFT_PAREN expression RIGHT_PAREN statement
|
// : IF LEFT_PAREN expression RIGHT_PAREN statement
|
||||||
// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
|
// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
|
||||||
//
|
//
|
||||||
bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttributeMap& attributes)
|
bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttributes& attributes)
|
||||||
{
|
{
|
||||||
TSourceLoc loc = token.loc;
|
TSourceLoc loc = token.loc;
|
||||||
|
|
||||||
const TSelectionControl control = parseContext.handleSelectionControl(attributes);
|
|
||||||
|
|
||||||
// IF
|
// IF
|
||||||
if (! acceptTokenClass(EHTokIf))
|
if (! acceptTokenClass(EHTokIf))
|
||||||
return false;
|
return false;
|
||||||
@ -3582,7 +3602,9 @@ bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Put the pieces together
|
// Put the pieces together
|
||||||
statement = intermediate.addSelection(condition, thenElse, loc, control);
|
statement = intermediate.addSelection(condition, thenElse, loc);
|
||||||
|
parseContext.handleSelectionAttributes(loc, statement->getAsSelectionNode(), attributes);
|
||||||
|
|
||||||
parseContext.popScope();
|
parseContext.popScope();
|
||||||
--parseContext.controlFlowNestingLevel;
|
--parseContext.controlFlowNestingLevel;
|
||||||
|
|
||||||
@ -3592,13 +3614,11 @@ bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttri
|
|||||||
// switch_statement
|
// switch_statement
|
||||||
// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
|
// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
|
||||||
//
|
//
|
||||||
bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttributeMap& attributes)
|
bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttributes& attributes)
|
||||||
{
|
{
|
||||||
// SWITCH
|
// SWITCH
|
||||||
TSourceLoc loc = token.loc;
|
TSourceLoc loc = token.loc;
|
||||||
|
|
||||||
const TSelectionControl control = parseContext.handleSelectionControl(attributes);
|
|
||||||
|
|
||||||
if (! acceptTokenClass(EHTokSwitch))
|
if (! acceptTokenClass(EHTokSwitch))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -3618,7 +3638,8 @@ bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttribut
|
|||||||
--parseContext.controlFlowNestingLevel;
|
--parseContext.controlFlowNestingLevel;
|
||||||
|
|
||||||
if (statementOkay)
|
if (statementOkay)
|
||||||
statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr, control);
|
statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr,
|
||||||
|
attributes);
|
||||||
|
|
||||||
parseContext.popSwitchSequence();
|
parseContext.popSwitchSequence();
|
||||||
parseContext.popScope();
|
parseContext.popScope();
|
||||||
@ -3632,7 +3653,7 @@ bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttribut
|
|||||||
// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
|
// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
|
||||||
//
|
//
|
||||||
// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
|
// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
|
||||||
bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributeMap& attributes)
|
bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributes& attributes)
|
||||||
{
|
{
|
||||||
TSourceLoc loc = token.loc;
|
TSourceLoc loc = token.loc;
|
||||||
TIntermTyped* condition = nullptr;
|
TIntermTyped* condition = nullptr;
|
||||||
@ -3643,8 +3664,7 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttri
|
|||||||
// WHILE or DO or FOR
|
// WHILE or DO or FOR
|
||||||
advanceToken();
|
advanceToken();
|
||||||
|
|
||||||
const TLoopControl control = parseContext.handleLoopControl(attributes);
|
TIntermLoop* loopNode = nullptr;
|
||||||
|
|
||||||
switch (loop) {
|
switch (loop) {
|
||||||
case EHTokWhile:
|
case EHTokWhile:
|
||||||
// so that something declared in the condition is scoped to the lifetime
|
// so that something declared in the condition is scoped to the lifetime
|
||||||
@ -3670,9 +3690,9 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttri
|
|||||||
parseContext.popScope();
|
parseContext.popScope();
|
||||||
--parseContext.controlFlowNestingLevel;
|
--parseContext.controlFlowNestingLevel;
|
||||||
|
|
||||||
statement = intermediate.addLoop(statement, condition, nullptr, true, loc, control);
|
loopNode = intermediate.addLoop(statement, condition, nullptr, true, loc);
|
||||||
|
statement = loopNode;
|
||||||
return true;
|
break;
|
||||||
|
|
||||||
case EHTokDo:
|
case EHTokDo:
|
||||||
parseContext.nestLooping(); // this only needs to work right if no errors
|
parseContext.nestLooping(); // this only needs to work right if no errors
|
||||||
@ -3703,9 +3723,9 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttri
|
|||||||
parseContext.unnestLooping();
|
parseContext.unnestLooping();
|
||||||
--parseContext.controlFlowNestingLevel;
|
--parseContext.controlFlowNestingLevel;
|
||||||
|
|
||||||
statement = intermediate.addLoop(statement, condition, 0, false, loc, control);
|
loopNode = intermediate.addLoop(statement, condition, 0, false, loc);
|
||||||
|
statement = loopNode;
|
||||||
return true;
|
break;
|
||||||
|
|
||||||
case EHTokFor:
|
case EHTokFor:
|
||||||
{
|
{
|
||||||
@ -3747,18 +3767,21 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttri
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, control);
|
statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, loopNode);
|
||||||
|
|
||||||
parseContext.popScope();
|
parseContext.popScope();
|
||||||
parseContext.unnestLooping();
|
parseContext.unnestLooping();
|
||||||
--parseContext.controlFlowNestingLevel;
|
--parseContext.controlFlowNestingLevel;
|
||||||
|
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parseContext.handleLoopAttributes(loc, loopNode, attributes);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// jump_statement
|
// jump_statement
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
|
|
||||||
namespace glslang {
|
namespace glslang {
|
||||||
|
|
||||||
class TAttributeMap;
|
|
||||||
class TFunctionDeclarator;
|
class TFunctionDeclarator;
|
||||||
|
|
||||||
// Should just be the grammar aspect of HLSL.
|
// Should just be the grammar aspect of HLSL.
|
||||||
@ -71,8 +70,8 @@ namespace glslang {
|
|||||||
bool acceptControlDeclaration(TIntermNode*& node);
|
bool acceptControlDeclaration(TIntermNode*& node);
|
||||||
bool acceptSamplerDeclarationDX9(TType&);
|
bool acceptSamplerDeclarationDX9(TType&);
|
||||||
bool acceptSamplerState();
|
bool acceptSamplerState();
|
||||||
bool acceptFullySpecifiedType(TType&, const TAttributeMap&);
|
bool acceptFullySpecifiedType(TType&, const TAttributes&);
|
||||||
bool acceptFullySpecifiedType(TType&, TIntermNode*& nodeList, const TAttributeMap&, bool forbidDeclarators = false);
|
bool acceptFullySpecifiedType(TType&, TIntermNode*& nodeList, const TAttributes&, bool forbidDeclarators = false);
|
||||||
bool acceptQualifier(TQualifier&);
|
bool acceptQualifier(TQualifier&);
|
||||||
bool acceptLayoutQualifierList(TQualifier&);
|
bool acceptLayoutQualifierList(TQualifier&);
|
||||||
bool acceptType(TType&);
|
bool acceptType(TType&);
|
||||||
@ -117,10 +116,10 @@ namespace glslang {
|
|||||||
bool acceptScopedCompoundStatement(TIntermNode*&);
|
bool acceptScopedCompoundStatement(TIntermNode*&);
|
||||||
bool acceptStatement(TIntermNode*&);
|
bool acceptStatement(TIntermNode*&);
|
||||||
bool acceptNestedStatement(TIntermNode*&);
|
bool acceptNestedStatement(TIntermNode*&);
|
||||||
void acceptAttributes(TAttributeMap&);
|
void acceptAttributes(TAttributes&);
|
||||||
bool acceptSelectionStatement(TIntermNode*&, const TAttributeMap&);
|
bool acceptSelectionStatement(TIntermNode*&, const TAttributes&);
|
||||||
bool acceptSwitchStatement(TIntermNode*&, const TAttributeMap&);
|
bool acceptSwitchStatement(TIntermNode*&, const TAttributes&);
|
||||||
bool acceptIterationStatement(TIntermNode*&, const TAttributeMap&);
|
bool acceptIterationStatement(TIntermNode*&, const TAttributes&);
|
||||||
bool acceptJumpStatement(TIntermNode*&);
|
bool acceptJumpStatement(TIntermNode*&);
|
||||||
bool acceptCaseLabel(TIntermNode*&);
|
bool acceptCaseLabel(TIntermNode*&);
|
||||||
bool acceptDefaultLabel(TIntermNode*&);
|
bool acceptDefaultLabel(TIntermNode*&);
|
||||||
|
@ -1620,7 +1620,7 @@ void HlslParseContext::addStructBufferHiddenCounterParam(const TSourceLoc& loc,
|
|||||||
// Returns an aggregate of parameter-symbol nodes.
|
// Returns an aggregate of parameter-symbol nodes.
|
||||||
//
|
//
|
||||||
TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& loc, TFunction& function,
|
TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& loc, TFunction& function,
|
||||||
const TAttributeMap& attributes,
|
const TAttributes& attributes,
|
||||||
TIntermNode*& entryPointTree)
|
TIntermNode*& entryPointTree)
|
||||||
{
|
{
|
||||||
currentCaller = function.getMangledName();
|
currentCaller = function.getMangledName();
|
||||||
@ -1717,43 +1717,44 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle all [attrib] attribute for the shader entry point
|
// Handle all [attrib] attribute for the shader entry point
|
||||||
void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const TAttributeMap& attributes)
|
void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const TAttributes& attributes)
|
||||||
{
|
{
|
||||||
// Handle entry-point function attributes
|
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
|
||||||
const TIntermAggregate* numThreads = attributes[EatNumThreads];
|
switch (it->name) {
|
||||||
if (numThreads != nullptr) {
|
case EatNumThreads:
|
||||||
const TIntermSequence& sequence = numThreads->getSequence();
|
{
|
||||||
|
const TIntermSequence& sequence = it->args->getSequence();
|
||||||
for (int lid = 0; lid < int(sequence.size()); ++lid)
|
for (int lid = 0; lid < int(sequence.size()); ++lid)
|
||||||
intermediate.setLocalSize(lid, sequence[lid]->getAsConstantUnion()->getConstArray()[0].getIConst());
|
intermediate.setLocalSize(lid, sequence[lid]->getAsConstantUnion()->getConstArray()[0].getIConst());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case EatMaxVertexCount:
|
||||||
// MaxVertexCount
|
{
|
||||||
if (attributes.contains(EatMaxVertexCount)) {
|
|
||||||
int maxVertexCount;
|
int maxVertexCount;
|
||||||
|
|
||||||
if (! attributes.getInt(EatMaxVertexCount, maxVertexCount)) {
|
if (! it->getInt(maxVertexCount)) {
|
||||||
error(loc, "invalid maxvertexcount", "", "");
|
error(loc, "invalid maxvertexcount", "", "");
|
||||||
} else {
|
} else {
|
||||||
if (! intermediate.setVertices(maxVertexCount))
|
if (! intermediate.setVertices(maxVertexCount))
|
||||||
error(loc, "cannot change previously set maxvertexcount attribute", "", "");
|
error(loc, "cannot change previously set maxvertexcount attribute", "", "");
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case EatPatchConstantFunc:
|
||||||
// Handle [patchconstantfunction("...")]
|
{
|
||||||
if (attributes.contains(EatPatchConstantFunc)) {
|
|
||||||
TString pcfName;
|
TString pcfName;
|
||||||
if (! attributes.getString(EatPatchConstantFunc, pcfName, 0, false)) {
|
if (! it->getString(pcfName, 0, false)) {
|
||||||
error(loc, "invalid patch constant function", "", "");
|
error(loc, "invalid patch constant function", "", "");
|
||||||
} else {
|
} else {
|
||||||
patchConstantFunctionName = pcfName;
|
patchConstantFunctionName = pcfName;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case EatDomain:
|
||||||
|
{
|
||||||
// Handle [domain("...")]
|
// Handle [domain("...")]
|
||||||
if (attributes.contains(EatDomain)) {
|
|
||||||
TString domainStr;
|
TString domainStr;
|
||||||
if (! attributes.getString(EatDomain, domainStr)) {
|
if (! it->getString(domainStr)) {
|
||||||
error(loc, "invalid domain", "", "");
|
error(loc, "invalid domain", "", "");
|
||||||
} else {
|
} else {
|
||||||
TLayoutGeometry domain = ElgNone;
|
TLayoutGeometry domain = ElgNone;
|
||||||
@ -1776,12 +1777,13 @@ void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const T
|
|||||||
error(loc, "cannot change previously set domain", TQualifier::getGeometryString(domain), "");
|
error(loc, "cannot change previously set domain", TQualifier::getGeometryString(domain), "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case EatOutputTopology:
|
||||||
|
{
|
||||||
// Handle [outputtopology("...")]
|
// Handle [outputtopology("...")]
|
||||||
if (attributes.contains(EatOutputTopology)) {
|
|
||||||
TString topologyStr;
|
TString topologyStr;
|
||||||
if (! attributes.getString(EatOutputTopology, topologyStr)) {
|
if (! it->getString(topologyStr)) {
|
||||||
error(loc, "invalid outputtopology", "", "");
|
error(loc, "invalid outputtopology", "", "");
|
||||||
} else {
|
} else {
|
||||||
TVertexOrder vertexOrder = EvoNone;
|
TVertexOrder vertexOrder = EvoNone;
|
||||||
@ -1810,12 +1812,13 @@ void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const T
|
|||||||
if (primitive != ElgNone)
|
if (primitive != ElgNone)
|
||||||
intermediate.setOutputPrimitive(primitive);
|
intermediate.setOutputPrimitive(primitive);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case EatPartitioning:
|
||||||
|
{
|
||||||
// Handle [partitioning("...")]
|
// Handle [partitioning("...")]
|
||||||
if (attributes.contains(EatPartitioning)) {
|
|
||||||
TString partitionStr;
|
TString partitionStr;
|
||||||
if (! attributes.getString(EatPartitioning, partitionStr)) {
|
if (! it->getString(partitionStr)) {
|
||||||
error(loc, "invalid partitioning", "", "");
|
error(loc, "invalid partitioning", "", "");
|
||||||
} else {
|
} else {
|
||||||
TVertexSpacing partitioning = EvsNone;
|
TVertexSpacing partitioning = EvsNone;
|
||||||
@ -1835,72 +1838,97 @@ void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const T
|
|||||||
error(loc, "cannot change previously set partitioning",
|
error(loc, "cannot change previously set partitioning",
|
||||||
TQualifier::getVertexSpacingString(partitioning), "");
|
TQualifier::getVertexSpacingString(partitioning), "");
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case EatOutputControlPoints:
|
||||||
|
{
|
||||||
// Handle [outputcontrolpoints("...")]
|
// Handle [outputcontrolpoints("...")]
|
||||||
if (attributes.contains(EatOutputControlPoints)) {
|
|
||||||
int ctrlPoints;
|
int ctrlPoints;
|
||||||
if (! attributes.getInt(EatOutputControlPoints, ctrlPoints)) {
|
if (! it->getInt(ctrlPoints)) {
|
||||||
error(loc, "invalid outputcontrolpoints", "", "");
|
error(loc, "invalid outputcontrolpoints", "", "");
|
||||||
} else {
|
} else {
|
||||||
if (! intermediate.setVertices(ctrlPoints)) {
|
if (! intermediate.setVertices(ctrlPoints)) {
|
||||||
error(loc, "cannot change previously set outputcontrolpoints attribute", "", "");
|
error(loc, "cannot change previously set outputcontrolpoints attribute", "", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EatBuiltIn:
|
||||||
|
case EatLocation:
|
||||||
|
// tolerate these because of dual use of entrypoint and type attributes
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
warn(loc, "attribute does not apply to entry point", "", "");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the given type with any type-like attribute information in the
|
// Update the given type with any type-like attribute information in the
|
||||||
// attributes.
|
// attributes.
|
||||||
void HlslParseContext::transferTypeAttributes(const TAttributeMap& attributes, TType& type)
|
void HlslParseContext::transferTypeAttributes(const TSourceLoc& loc, const TAttributes& attributes, TType& type,
|
||||||
|
bool allowEntry)
|
||||||
{
|
{
|
||||||
if (attributes.size() == 0)
|
if (attributes.size() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// location
|
|
||||||
int value;
|
int value;
|
||||||
if (attributes.getInt(EatLocation, value))
|
TString builtInString;
|
||||||
|
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
|
||||||
|
switch (it->name) {
|
||||||
|
case EatLocation:
|
||||||
|
// location
|
||||||
|
if (it->getInt(value))
|
||||||
type.getQualifier().layoutLocation = value;
|
type.getQualifier().layoutLocation = value;
|
||||||
|
break;
|
||||||
|
case EatBinding:
|
||||||
// binding
|
// binding
|
||||||
if (attributes.getInt(EatBinding, value)) {
|
if (it->getInt(value)) {
|
||||||
type.getQualifier().layoutBinding = value;
|
type.getQualifier().layoutBinding = value;
|
||||||
type.getQualifier().layoutSet = 0;
|
type.getQualifier().layoutSet = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set
|
// set
|
||||||
if (attributes.getInt(EatBinding, value, 1))
|
if (it->getInt(value, 1))
|
||||||
type.getQualifier().layoutSet = value;
|
type.getQualifier().layoutSet = value;
|
||||||
|
break;
|
||||||
|
case EatGlobalBinding:
|
||||||
// global cbuffer binding
|
// global cbuffer binding
|
||||||
if (attributes.getInt(EatGlobalBinding, value))
|
if (it->getInt(value))
|
||||||
globalUniformBinding = value;
|
globalUniformBinding = value;
|
||||||
|
|
||||||
// global cbuffer binding
|
// global cbuffer binding
|
||||||
if (attributes.getInt(EatGlobalBinding, value, 1))
|
if (it->getInt(value, 1))
|
||||||
globalUniformSet = value;
|
globalUniformSet = value;
|
||||||
|
break;
|
||||||
|
case EatInputAttachment:
|
||||||
// input attachment
|
// input attachment
|
||||||
if (attributes.getInt(EatInputAttachment, value))
|
if (it->getInt(value))
|
||||||
type.getQualifier().layoutAttachment = value;
|
type.getQualifier().layoutAttachment = value;
|
||||||
|
break;
|
||||||
|
case EatBuiltIn:
|
||||||
// PointSize built-in
|
// PointSize built-in
|
||||||
TString builtInString;
|
if (it->getString(builtInString, 0, false)) {
|
||||||
if (attributes.getString(EatBuiltIn, builtInString, 0, false)) {
|
|
||||||
if (builtInString == "PointSize")
|
if (builtInString == "PointSize")
|
||||||
type.getQualifier().builtIn = EbvPointSize;
|
type.getQualifier().builtIn = EbvPointSize;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case EatPushConstant:
|
||||||
// push_constant
|
// push_constant
|
||||||
if (attributes.contains(EatPushConstant))
|
|
||||||
type.getQualifier().layoutPushConstant = true;
|
type.getQualifier().layoutPushConstant = true;
|
||||||
|
break;
|
||||||
|
case EatConstantId:
|
||||||
// specialization constant
|
// specialization constant
|
||||||
if (attributes.getInt(EatConstantId, value)) {
|
if (it->getInt(value)) {
|
||||||
TSourceLoc loc;
|
TSourceLoc loc;
|
||||||
loc.init();
|
loc.init();
|
||||||
setSpecConstantId(loc, type.getQualifier(), value);
|
setSpecConstantId(loc, type.getQualifier(), value);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (! allowEntry)
|
||||||
|
warn(loc, "attribute does not apply to a type", "", "");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1936,7 +1964,7 @@ void HlslParseContext::transferTypeAttributes(const TAttributeMap& attributes, T
|
|||||||
// a subtree that creates the entry point.
|
// a subtree that creates the entry point.
|
||||||
//
|
//
|
||||||
TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunction& userFunction,
|
TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunction& userFunction,
|
||||||
const TAttributeMap& attributes)
|
const TAttributes& attributes)
|
||||||
{
|
{
|
||||||
// Return true if this is a tessellation patch constant function input to a domain shader.
|
// Return true if this is a tessellation patch constant function input to a domain shader.
|
||||||
const auto isDsPcfInput = [this](const TType& type) {
|
const auto isDsPcfInput = [this](const TType& type) {
|
||||||
@ -8792,29 +8820,75 @@ bool HlslParseContext::handleOutputGeometry(const TSourceLoc& loc, const TLayout
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Selection hints
|
// Selection attributes
|
||||||
//
|
//
|
||||||
TSelectionControl HlslParseContext::handleSelectionControl(const TAttributeMap& attributes) const
|
void HlslParseContext::handleSelectionAttributes(const TSourceLoc& loc, TIntermSelection* selection,
|
||||||
|
const TAttributes& attributes)
|
||||||
{
|
{
|
||||||
if (attributes.contains(EatFlatten))
|
if (selection == nullptr)
|
||||||
return ESelectionControlFlatten;
|
return;
|
||||||
else if (attributes.contains(EatBranch))
|
|
||||||
return ESelectionControlDontFlatten;
|
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
|
||||||
else
|
switch (it->name) {
|
||||||
return ESelectionControlNone;
|
case EatFlatten:
|
||||||
|
selection->setFlatten();
|
||||||
|
break;
|
||||||
|
case EatBranch:
|
||||||
|
selection->setDontFlatten();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
warn(loc, "attribute does not apply to a selection", "", "");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Switch attributes
|
||||||
|
//
|
||||||
|
void HlslParseContext::handleSwitchAttributes(const TSourceLoc& loc, TIntermSwitch* selection,
|
||||||
|
const TAttributes& attributes)
|
||||||
|
{
|
||||||
|
if (selection == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
|
||||||
|
switch (it->name) {
|
||||||
|
case EatFlatten:
|
||||||
|
selection->setFlatten();
|
||||||
|
break;
|
||||||
|
case EatBranch:
|
||||||
|
selection->setDontFlatten();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
warn(loc, "attribute does not apply to a switch", "", "");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop hints
|
// Loop hints
|
||||||
//
|
//
|
||||||
TLoopControl HlslParseContext::handleLoopControl(const TAttributeMap& attributes) const
|
void HlslParseContext::handleLoopAttributes(const TSourceLoc& loc, TIntermLoop* loop,
|
||||||
|
const TAttributes& attributes)
|
||||||
{
|
{
|
||||||
if (attributes.contains(EatUnroll))
|
if (loop == nullptr)
|
||||||
return ELoopControlUnroll;
|
return;
|
||||||
else if (attributes.contains(EatLoop))
|
|
||||||
return ELoopControlDontUnroll;
|
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
|
||||||
else
|
switch (it->name) {
|
||||||
return ELoopControlNone;
|
case EatUnroll:
|
||||||
|
loop->setUnroll();
|
||||||
|
break;
|
||||||
|
case EatLoop:
|
||||||
|
loop->setDontUnroll();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
warn(loc, "attribute does not apply to a loop", "", "");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -8959,7 +9033,7 @@ void HlslParseContext::wrapupSwitchSubsequence(TIntermAggregate* statements, TIn
|
|||||||
// into a switch node.
|
// into a switch node.
|
||||||
//
|
//
|
||||||
TIntermNode* HlslParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expression,
|
TIntermNode* HlslParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expression,
|
||||||
TIntermAggregate* lastStatements, TSelectionControl control)
|
TIntermAggregate* lastStatements, const TAttributes& attributes)
|
||||||
{
|
{
|
||||||
wrapupSwitchSubsequence(lastStatements, nullptr);
|
wrapupSwitchSubsequence(lastStatements, nullptr);
|
||||||
|
|
||||||
@ -8986,7 +9060,7 @@ TIntermNode* HlslParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* ex
|
|||||||
|
|
||||||
TIntermSwitch* switchNode = new TIntermSwitch(expression, body);
|
TIntermSwitch* switchNode = new TIntermSwitch(expression, body);
|
||||||
switchNode->setLoc(loc);
|
switchNode->setLoc(loc);
|
||||||
switchNode->setSelectionControl(control);
|
handleSwitchAttributes(loc, switchNode, attributes);
|
||||||
|
|
||||||
return switchNode;
|
return switchNode;
|
||||||
}
|
}
|
||||||
|
@ -38,12 +38,12 @@
|
|||||||
|
|
||||||
#include "../glslang/MachineIndependent/parseVersions.h"
|
#include "../glslang/MachineIndependent/parseVersions.h"
|
||||||
#include "../glslang/MachineIndependent/ParseHelper.h"
|
#include "../glslang/MachineIndependent/ParseHelper.h"
|
||||||
|
#include "../glslang/MachineIndependent/attribute.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
namespace glslang {
|
namespace glslang {
|
||||||
|
|
||||||
class TAttributeMap; // forward declare
|
|
||||||
class TFunctionDeclarator;
|
class TFunctionDeclarator;
|
||||||
|
|
||||||
class HlslParseContext : public TParseContextBase {
|
class HlslParseContext : public TParseContextBase {
|
||||||
@ -80,10 +80,10 @@ public:
|
|||||||
bool isBuiltInMethod(const TSourceLoc&, TIntermTyped* base, const TString& field);
|
bool isBuiltInMethod(const TSourceLoc&, TIntermTyped* base, const TString& field);
|
||||||
void assignToInterface(TVariable& variable);
|
void assignToInterface(TVariable& variable);
|
||||||
void handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
|
void handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
|
||||||
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributeMap&, TIntermNode*& entryPointTree);
|
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributes&, TIntermNode*& entryPointTree);
|
||||||
TIntermNode* transformEntryPoint(const TSourceLoc&, TFunction&, const TAttributeMap&);
|
TIntermNode* transformEntryPoint(const TSourceLoc&, TFunction&, const TAttributes&);
|
||||||
void handleEntryPointAttributes(const TSourceLoc&, const TAttributeMap&);
|
void handleEntryPointAttributes(const TSourceLoc&, const TAttributes&);
|
||||||
void transferTypeAttributes(const TAttributeMap&, TType&);
|
void transferTypeAttributes(const TSourceLoc&, const TAttributes&, TType&, bool allowEntry = false);
|
||||||
void handleFunctionBody(const TSourceLoc&, TFunction&, TIntermNode* functionBody, TIntermNode*& node);
|
void handleFunctionBody(const TSourceLoc&, TFunction&, TIntermNode* functionBody, TIntermNode*& node);
|
||||||
void remapEntryPointIO(TFunction& function, TVariable*& returnValue, TVector<TVariable*>& inputs, TVector<TVariable*>& outputs);
|
void remapEntryPointIO(TFunction& function, TVariable*& returnValue, TVector<TVariable*>& inputs, TVector<TVariable*>& outputs);
|
||||||
void remapNonEntryPointIO(TFunction& function);
|
void remapNonEntryPointIO(TFunction& function);
|
||||||
@ -163,7 +163,7 @@ public:
|
|||||||
void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
|
void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
|
||||||
void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
|
void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
|
||||||
void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
|
void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
|
||||||
TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body, TSelectionControl control);
|
TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body, const TAttributes&);
|
||||||
|
|
||||||
void updateImplicitArraySize(const TSourceLoc&, TIntermNode*, int index);
|
void updateImplicitArraySize(const TSourceLoc&, TIntermNode*, int index);
|
||||||
|
|
||||||
@ -203,10 +203,11 @@ public:
|
|||||||
bool handleInputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry);
|
bool handleInputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry);
|
||||||
|
|
||||||
// Determine selection control from attributes
|
// Determine selection control from attributes
|
||||||
TSelectionControl handleSelectionControl(const TAttributeMap& attributes) const;
|
void handleSelectionAttributes(const TSourceLoc& loc, TIntermSelection*, const TAttributes& attributes);
|
||||||
|
void handleSwitchAttributes(const TSourceLoc& loc, TIntermSwitch*, const TAttributes& attributes);
|
||||||
|
|
||||||
// Determine loop control from attributes
|
// Determine loop control from attributes
|
||||||
TLoopControl handleLoopControl(const TAttributeMap& attributes) const;
|
void handleLoopAttributes(const TSourceLoc& loc, TIntermLoop*, const TAttributes& attributes);
|
||||||
|
|
||||||
// Share struct buffer deep types
|
// Share struct buffer deep types
|
||||||
void shareStructBufferType(TType&);
|
void shareStructBufferType(TType&);
|
||||||
@ -217,6 +218,8 @@ public:
|
|||||||
// Obtain the sampler return type of the given sampler in retType.
|
// Obtain the sampler return type of the given sampler in retType.
|
||||||
void getTextureReturnType(const TSampler& sampler, TType& retType) const;
|
void getTextureReturnType(const TSampler& sampler, TType& retType) const;
|
||||||
|
|
||||||
|
TAttributeType attributeFromName(const TString& nameSpace, const TString& name) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct TFlattenData {
|
struct TFlattenData {
|
||||||
TFlattenData() : nextBinding(TQualifier::layoutBindingEnd),
|
TFlattenData() : nextBinding(TQualifier::layoutBindingEnd),
|
||||||
|
Loading…
Reference in New Issue
Block a user