Commit e18fd20d by John Kessenich

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
parent e349af7e
......@@ -129,8 +129,9 @@ protected:
spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier);
spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration);
spv::ImageFormat TranslateImageFormat(const glslang::TType& type);
spv::SelectionControlMask TranslateSelectionControl(glslang::TSelectionControl) const;
spv::LoopControlMask TranslateLoopControl(glslang::TLoopControl) const;
spv::SelectionControlMask TranslateSelectionControl(const glslang::TIntermSelection&) const;
spv::SelectionControlMask TranslateSwitchControl(const glslang::TIntermSwitch&) const;
spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&) const;
spv::StorageClass TranslateStorageClass(const glslang::TType&);
spv::Id createSpvVariable(const glslang::TIntermSymbol*);
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) {
case glslang::ESelectionControlNone: return spv::SelectionControlMaskNone;
case glslang::ESelectionControlFlatten: return spv::SelectionControlFlattenMask;
case glslang::ESelectionControlDontFlatten: return spv::SelectionControlDontFlattenMask;
default: return spv::SelectionControlMaskNone;
}
if (selectionNode.getFlatten())
return spv::SelectionControlFlattenMask;
if (selectionNode.getDontFlatten())
return spv::SelectionControlDontFlattenMask;
return spv::SelectionControlMaskNone;
}
spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(glslang::TLoopControl loopControl) const
spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode) const
{
switch (loopControl) {
case glslang::ELoopControlNone: return spv::LoopControlMaskNone;
case glslang::ELoopControlUnroll: return spv::LoopControlUnrollMask;
case glslang::ELoopControlDontUnroll: return spv::LoopControlDontUnrollMask;
// TODO: DependencyInfinite
// TODO: DependencyLength
default: return spv::LoopControlMaskNone;
}
if (switchNode.getFlatten())
return spv::SelectionControlFlattenMask;
if (switchNode.getDontFlatten())
return spv::SelectionControlDontFlattenMask;
return spv::SelectionControlMaskNone;
}
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.
......@@ -2026,7 +2035,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
node->getCondition()->traverse(this);
// 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
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());
// Selection control:
const spv::SelectionControlMask control = TranslateSelectionControl(node->getSelectionControl());
const spv::SelectionControlMask control = TranslateSwitchControl(*node);
// browse the children to sort out code segments
int defaultSegment = -1;
......@@ -2128,7 +2137,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
builder.createBranch(&blocks.head);
// Loop control:
const spv::LoopControlMask control = TranslateLoopControl(node->getLoopControl());
const spv::LoopControlMask control = TranslateLoopControl(*node);
// TODO: dependency length
......
hlsl.numthreads.comp
Shader version: 500
local_size = (4, 4, 2)
local_size = (1, 4, 8)
0:? Sequence
0:4 Function Definition: main(vu3; ( temp void)
0:4 Function Parameters:
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 '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:? Sequence
0:9 move second child to first child ( temp 3-component vector of uint)
0:? 'tid' ( temp 3-component vector of uint)
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:? Linker Objects
0:? 'tid' ( in 3-component vector of uint GlobalInvocationID)
......@@ -24,21 +24,21 @@ Linked compute stage:
Shader version: 500
local_size = (4, 4, 2)
local_size = (1, 4, 8)
0:? Sequence
0:4 Function Definition: main(vu3; ( temp void)
0:4 Function Parameters:
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 '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:? Sequence
0:9 move second child to first child ( temp 3-component vector of uint)
0:? 'tid' ( temp 3-component vector of uint)
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:? Linker Objects
0:? 'tid' ( in 3-component vector of uint GlobalInvocationID)
......@@ -50,13 +50,13 @@ local_size = (4, 4, 2)
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint GLCompute 4 "main_aux1" 18
ExecutionMode 4 LocalSize 4 4 2
EntryPoint GLCompute 4 "main_aux2" 18
ExecutionMode 4 LocalSize 1 4 8
Source HLSL 500
Name 4 "main_aux1"
Name 4 "main_aux2"
Name 11 "main(vu3;"
Name 10 "tid"
Name 14 "@main_aux1(vu3;"
Name 14 "@main_aux2(vu3;"
Name 13 "tid"
Name 16 "tid"
Name 18 "tid"
......@@ -70,7 +70,7 @@ local_size = (4, 4, 2)
9: TypeFunction 2 8(ptr)
17: TypePointer Input 7(ivec3)
18(tid): 17(ptr) Variable Input
4(main_aux1): 2 Function None 3
4(main_aux2): 2 Function None 3
5: Label
16(tid): 8(ptr) Variable Function
20(param): 8(ptr) Variable Function
......@@ -78,7 +78,7 @@ local_size = (4, 4, 2)
Store 16(tid) 19
21: 7(ivec3) Load 16(tid)
Store 20(param) 21
22: 2 FunctionCall 14(@main_aux1(vu3;) 20(param)
22: 2 FunctionCall 14(@main_aux2(vu3;) 20(param)
Return
FunctionEnd
11(main(vu3;): 2 Function None 9
......@@ -86,7 +86,7 @@ local_size = (4, 4, 2)
12: Label
Return
FunctionEnd
14(@main_aux1(vu3;): 2 Function None 9
14(@main_aux2(vu3;): 2 Function None 9
13(tid): 8(ptr) FunctionParameter
15: Label
Return
......
......@@ -4,11 +4,8 @@ void main(uint3 tid : SV_DispatchThreadID )
{
}
[numTHreaDs(4,4,2)] // case insensitive
void main_aux1(uint3 tid : SV_DispatchThreadID )
[numthreads(1,4,8)]
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
MachineIndependent/glslang.y
MachineIndependent/glslang_tab.cpp
MachineIndependent/attribute.cpp
MachineIndependent/Constant.cpp
MachineIndependent/iomapper.cpp
MachineIndependent/InfoSink.cpp
......@@ -51,6 +52,7 @@ set(HEADERS
Include/revision.h
Include/ShHandle.h
Include/Types.h
MachineIndependent/attribute.h
MachineIndependent/glslang_tab.cpp.h
MachineIndependent/gl_types.h
MachineIndependent/Initialize.h
......
......@@ -37,6 +37,9 @@
#ifndef _CONSTANT_UNION_INCLUDED_
#define _CONSTANT_UNION_INCLUDED_
#include "../Include/Common.h"
#include "../Include/BaseTypes.h"
namespace glslang {
class TConstUnion {
......
......@@ -819,7 +819,7 @@ public:
virtual glslang::TIntermMethod* getAsMethodNode() { return 0; }
virtual glslang::TIntermSymbol* getAsSymbolNode() { return 0; }
virtual glslang::TIntermBranch* getAsBranchNode() { return 0; }
virtual glslang::TIntermLoop* getAsLoopNode() { return 0; }
virtual glslang::TIntermLoop* getAsLoopNode() { return 0; }
virtual const glslang::TIntermTyped* getAsTyped() const { return 0; }
virtual const glslang::TIntermOperator* getAsOperator() const { return 0; }
......@@ -832,7 +832,7 @@ public:
virtual const glslang::TIntermMethod* getAsMethodNode() const { return 0; }
virtual const glslang::TIntermSymbol* getAsSymbolNode() const { return 0; }
virtual const glslang::TIntermBranch* getAsBranchNode() const { return 0; }
virtual const glslang::TIntermLoop* getAsLoopNode() const { return 0; }
virtual const glslang::TIntermLoop* getAsLoopNode() const { return 0; }
virtual ~TIntermNode() { }
protected:
......@@ -886,24 +886,6 @@ protected:
};
//
// Selection control hints
//
enum TSelectionControl {
ESelectionControlNone,
ESelectionControlFlatten,
ESelectionControlDontFlatten,
};
//
// Loop control hints
//
enum TLoopControl {
ELoopControlNone,
ELoopControlUnroll,
ELoopControlDontUnroll,
};
//
// Handle for, do-while, and while loops.
//
class TIntermLoop : public TIntermNode {
......@@ -913,26 +895,30 @@ public:
test(aTest),
terminal(aTerminal),
first(testFirst),
control(ELoopControlNone)
unroll(false),
dontUnroll(false)
{ }
virtual TIntermLoop* getAsLoopNode() { return this; }
virtual const TIntermLoop* getAsLoopNode() const { return this; }
virtual TIntermLoop* getAsLoopNode() { return this; }
virtual const TIntermLoop* getAsLoopNode() const { return this; }
virtual void traverse(TIntermTraverser*);
TIntermNode* getBody() const { return body; }
TIntermTyped* getTest() const { return test; }
TIntermTyped* getTerminal() const { return terminal; }
bool testFirst() const { return first; }
void setLoopControl(TLoopControl c) { control = c; }
TLoopControl getLoopControl() const { return control; }
void setUnroll() { unroll = true; }
void setDontUnroll() { dontUnroll = true; }
bool getUnroll() const { return unroll; }
bool getDontUnroll() const { return dontUnroll; }
protected:
TIntermNode* body; // code to loop over
TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops
TIntermTyped* terminal; // exists for for-loops
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 {
public:
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) :
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 TIntermTyped* getCondition() const { return condition; }
virtual TIntermNode* getTrueBlock() const { return trueBlock; }
virtual TIntermNode* getFalseBlock() const { return falseBlock; }
virtual TIntermSelection* getAsSelectionNode() { 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:
TIntermTyped* condition;
TIntermNode* trueBlock;
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 {
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 TIntermNode* getCondition() const { return condition; }
virtual TIntermAggregate* getBody() const { return body; }
virtual TIntermSwitch* getAsSwitchNode() { 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:
TIntermTyped* condition;
TIntermAggregate* body;
TSelectionControl control; // selection control hint
bool flatten; // true if flatten requested
bool dontFlatten; // true if requested to not flatten
};
enum TVisit
......
......@@ -1614,7 +1614,7 @@ TIntermAggregate* TIntermediate::makeAggregate(const TSourceLoc& loc)
//
// 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
......@@ -1623,7 +1623,6 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair no
TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
node->setLoc(loc);
node->setSelectionControl(control);
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.
//
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 (trueBlock->getBasicType() == EbtVoid && falseBlock->getBasicType() == EbtVoid) {
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.
//
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);
node->setLoc(loc);
node->setLoopControl(control);
return node;
}
......@@ -1921,11 +1921,11 @@ TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TInte
//
// 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->setLoopControl(control);
// 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
......
//
// 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
//
// 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&);
TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc);
bool areAllChildConst(TIntermAggregate* aggrNode);
TIntermTyped* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&, TSelectionControl = ESelectionControlNone);
TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&, TSelectionControl = ESelectionControlNone);
TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&);
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;
TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&, TLoopControl = ELoopControlNone);
TIntermAggregate* addForLoop(TIntermNode*, 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&, TIntermLoop*&);
TIntermBranch* addBranch(TOperator, const TSourceLoc&);
TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&);
......
......@@ -247,7 +247,7 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.matrixindex.frag", "main"},
{"hlsl.nonstaticMemberFunction.frag", "main"},
{"hlsl.numericsuffixes.frag", "main"},
{"hlsl.numthreads.comp", "main_aux1"},
{"hlsl.numthreads.comp", "main_aux2"},
{"hlsl.overload.frag", "PixelShaderFunction"},
{"hlsl.opaque-type-bug.frag", "main"},
{"hlsl.params.default.frag", "main"},
......
......@@ -34,157 +34,73 @@
//
#include "hlslAttributes.h"
#include <cstdlib>
#include <cctype>
#include <algorithm>
#include "hlslParseHelper.h"
namespace glslang {
// Map the given string to an attribute enum from TAttributeType,
// 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
if (lowernameSpace == "vk") {
if (lowername == "input_attachment_index")
if (nameSpace == "vk") {
if (name == "input_attachment_index")
return EatInputAttachment;
else if (lowername == "location")
else if (name == "location")
return EatLocation;
else if (lowername == "binding")
else if (name == "binding")
return EatBinding;
else if (lowername == "global_cbuffer_binding")
else if (name == "global_cbuffer_binding")
return EatGlobalBinding;
else if (lowername == "builtin")
else if (name == "builtin")
return EatBuiltIn;
else if (lowername == "constant_id")
else if (name == "constant_id")
return EatConstantId;
else if (lowername == "push_constant")
else if (name == "push_constant")
return EatPushConstant;
} else if (lowernameSpace.size() > 0)
} else if (nameSpace.size() > 0)
return EatNone;
// handle names with no namespace
if (lowername == "allow_uav_condition")
if (name == "allow_uav_condition")
return EatAllow_uav_condition;
else if (lowername == "branch")
else if (name == "branch")
return EatBranch;
else if (lowername == "call")
else if (name == "call")
return EatCall;
else if (lowername == "domain")
else if (name == "domain")
return EatDomain;
else if (lowername == "earlydepthstencil")
else if (name == "earlydepthstencil")
return EatEarlyDepthStencil;
else if (lowername == "fastopt")
else if (name == "fastopt")
return EatFastOpt;
else if (lowername == "flatten")
else if (name == "flatten")
return EatFlatten;
else if (lowername == "forcecase")
else if (name == "forcecase")
return EatForceCase;
else if (lowername == "instance")
else if (name == "instance")
return EatInstance;
else if (lowername == "maxtessfactor")
else if (name == "maxtessfactor")
return EatMaxTessFactor;
else if (lowername == "maxvertexcount")
else if (name == "maxvertexcount")
return EatMaxVertexCount;
else if (lowername == "numthreads")
else if (name == "numthreads")
return EatNumThreads;
else if (lowername == "outputcontrolpoints")
else if (name == "outputcontrolpoints")
return EatOutputControlPoints;
else if (lowername == "outputtopology")
else if (name == "outputtopology")
return EatOutputTopology;
else if (lowername == "partitioning")
else if (name == "partitioning")
return EatPartitioning;
else if (lowername == "patchconstantfunc")
else if (name == "patchconstantfunc")
return EatPatchConstantFunc;
else if (lowername == "unroll")
else if (name == "unroll")
return EatUnroll;
else if (lowername == "loop")
else if (name == "loop")
return EatLoop;
else
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
......@@ -38,93 +38,22 @@
#include <unordered_map>
#include <functional>
#include "hlslScanContext.h"
#include "../glslang/Include/Common.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
};
}
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
#include "../glslang/MachineIndependent/attribute.h"
#include "../glslang/MachineIndependent/SymbolTable.h"
#include "hlslScanContext.h"
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 {
public:
TFunctionDeclarator() : function(nullptr), body(nullptr) { }
TSourceLoc loc;
TFunction* function;
TAttributeMap attributes;
TAttributes attributes;
TVector<HlslToken>* body;
};
} // end namespace glslang
#endif // HLSLATTRIBUTES_H_
......@@ -43,7 +43,6 @@
namespace glslang {
class TAttributeMap;
class TFunctionDeclarator;
// Should just be the grammar aspect of HLSL.
......@@ -71,8 +70,8 @@ namespace glslang {
bool acceptControlDeclaration(TIntermNode*& node);
bool acceptSamplerDeclarationDX9(TType&);
bool acceptSamplerState();
bool acceptFullySpecifiedType(TType&, const TAttributeMap&);
bool acceptFullySpecifiedType(TType&, TIntermNode*& nodeList, const TAttributeMap&, bool forbidDeclarators = false);
bool acceptFullySpecifiedType(TType&, const TAttributes&);
bool acceptFullySpecifiedType(TType&, TIntermNode*& nodeList, const TAttributes&, bool forbidDeclarators = false);
bool acceptQualifier(TQualifier&);
bool acceptLayoutQualifierList(TQualifier&);
bool acceptType(TType&);
......@@ -117,10 +116,10 @@ namespace glslang {
bool acceptScopedCompoundStatement(TIntermNode*&);
bool acceptStatement(TIntermNode*&);
bool acceptNestedStatement(TIntermNode*&);
void acceptAttributes(TAttributeMap&);
bool acceptSelectionStatement(TIntermNode*&, const TAttributeMap&);
bool acceptSwitchStatement(TIntermNode*&, const TAttributeMap&);
bool acceptIterationStatement(TIntermNode*&, const TAttributeMap&);
void acceptAttributes(TAttributes&);
bool acceptSelectionStatement(TIntermNode*&, const TAttributes&);
bool acceptSwitchStatement(TIntermNode*&, const TAttributes&);
bool acceptIterationStatement(TIntermNode*&, const TAttributes&);
bool acceptJumpStatement(TIntermNode*&);
bool acceptCaseLabel(TIntermNode*&);
bool acceptDefaultLabel(TIntermNode*&);
......
......@@ -38,12 +38,12 @@
#include "../glslang/MachineIndependent/parseVersions.h"
#include "../glslang/MachineIndependent/ParseHelper.h"
#include "../glslang/MachineIndependent/attribute.h"
#include <array>
namespace glslang {
class TAttributeMap; // forward declare
class TFunctionDeclarator;
class HlslParseContext : public TParseContextBase {
......@@ -80,10 +80,10 @@ public:
bool isBuiltInMethod(const TSourceLoc&, TIntermTyped* base, const TString& field);
void assignToInterface(TVariable& variable);
void handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
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&);
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributes&, TIntermNode*& entryPointTree);
TIntermNode* transformEntryPoint(const TSourceLoc&, TFunction&, const TAttributes&);
void handleEntryPointAttributes(const TSourceLoc&, const TAttributes&);
void transferTypeAttributes(const TSourceLoc&, const TAttributes&, TType&, bool allowEntry = false);
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);
......@@ -163,7 +163,7 @@ public:
void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
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);
......@@ -203,10 +203,11 @@ public:
bool handleInputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry);
// 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
TLoopControl handleLoopControl(const TAttributeMap& attributes) const;
void handleLoopAttributes(const TSourceLoc& loc, TIntermLoop*, const TAttributes& attributes);
// Share struct buffer deep types
void shareStructBufferType(TType&);
......@@ -217,6 +218,8 @@ public:
// Obtain the sampler return type of the given sampler in retType.
void getTextureReturnType(const TSampler& sampler, TType& retType) const;
TAttributeType attributeFromName(const TString& nameSpace, const TString& name) const;
protected:
struct TFlattenData {
TFlattenData() : nextBinding(TQualifier::layoutBindingEnd),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment