Merge branch 'master' of github.com:KhronosGroup/glslang into clang-format
This commit is contained in:
commit
5797975686
34 changed files with 934 additions and 150 deletions
|
|
@ -128,8 +128,9 @@ protected:
|
|||
void addDecoration(spv::Id id, spv::Decoration dec, unsigned value);
|
||||
void addMemberDecoration(spv::Id id, int member, spv::Decoration dec);
|
||||
void addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value);
|
||||
spv::Id createSpvSpecConstant(const glslang::TIntermTyped&);
|
||||
spv::Id createSpvConstant(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant);
|
||||
spv::Id createSpvConstant(const glslang::TIntermTyped&);
|
||||
spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant);
|
||||
spv::Id createSpvConstantFromConstSubTree(const glslang::TIntermTyped* subTree);
|
||||
bool isTrivialLeaf(const glslang::TIntermTyped* node);
|
||||
bool isTrivial(const glslang::TIntermTyped* node);
|
||||
spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right);
|
||||
|
|
@ -719,6 +720,7 @@ void TGlslangToSpvTraverser::dumpSpv(std::vector<unsigned int>& out)
|
|||
for (auto it = iOSet.cbegin(); it != iOSet.cend(); ++it)
|
||||
entryPoint->addIdOperand(*it);
|
||||
|
||||
builder.eliminateDeadDecorations();
|
||||
builder.dump(out);
|
||||
}
|
||||
|
||||
|
|
@ -1519,7 +1521,7 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T
|
|||
void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node)
|
||||
{
|
||||
int nextConst = 0;
|
||||
spv::Id constant = createSpvConstant(node->getType(), node->getConstArray(), nextConst, false);
|
||||
spv::Id constant = createSpvConstantFromConstUnionArray(node->getType(), node->getConstArray(), nextConst, false);
|
||||
|
||||
builder.clearAccessChain();
|
||||
builder.setAccessChainRValue(constant);
|
||||
|
|
@ -1628,8 +1630,8 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol*
|
|||
// First, steer off constants, which are not SPIR-V variables, but
|
||||
// can still have a mapping to a SPIR-V Id.
|
||||
// This includes specialization constants.
|
||||
if (node->getQualifier().storage == glslang::EvqConst) {
|
||||
return createSpvSpecConstant(*node);
|
||||
if (node->getQualifier().isConstant()) {
|
||||
return createSpvConstant(*node);
|
||||
}
|
||||
|
||||
// Now, handle actual variables
|
||||
|
|
@ -3434,11 +3436,12 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
|
|||
builder.promoteScalar(precision, operands.front(), operands[2]);
|
||||
break;
|
||||
case glslang::EOpMix:
|
||||
if (isFloat)
|
||||
if (! builder.isBoolType(builder.getScalarTypeId(builder.getTypeId(operands.back())))) {
|
||||
assert(isFloat);
|
||||
libCall = spv::GLSLstd450FMix;
|
||||
else {
|
||||
} else {
|
||||
opCode = spv::OpSelect;
|
||||
spv::MissingFunctionality("translating integer mix to OpSelect");
|
||||
std::swap(operands.front(), operands.back());
|
||||
}
|
||||
builder.promoteScalar(precision, operands.front(), operands.back());
|
||||
break;
|
||||
|
|
@ -3728,15 +3731,15 @@ void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::De
|
|||
// recursively walks. So, this function walks the "top" of the tree:
|
||||
// - emit specialization constant-building instructions for specConstant
|
||||
// - when running into a non-spec-constant, switch to createSpvConstant()
|
||||
spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermTyped& node)
|
||||
spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& node)
|
||||
{
|
||||
assert(node.getQualifier().storage == glslang::EvqConst);
|
||||
assert(node.getQualifier().isConstant());
|
||||
|
||||
if (! node.getQualifier().specConstant) {
|
||||
// hand off to the non-spec-constant path
|
||||
assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr);
|
||||
int nextConst = 0;
|
||||
return createSpvConstant(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
|
||||
return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
|
||||
nextConst, false);
|
||||
}
|
||||
|
||||
|
|
@ -3745,7 +3748,7 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType
|
|||
if (node.getAsSymbolNode() && node.getQualifier().hasSpecConstantId()) {
|
||||
// this is a direct literal assigned to a layout(constant_id=) declaration
|
||||
int nextConst = 0;
|
||||
return createSpvConstant(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
|
||||
return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
|
||||
nextConst, true);
|
||||
} else {
|
||||
// gl_WorkgroupSize is a special case until the front-end handles hierarchical specialization constants,
|
||||
|
|
@ -3759,8 +3762,11 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType
|
|||
addDecoration(dimConstId.back(), spv::DecorationSpecId, glslangIntermediate->getLocalSizeSpecId(dim));
|
||||
}
|
||||
return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true);
|
||||
} else if (auto* sn = node.getAsSymbolNode()){
|
||||
return createSpvConstantFromConstSubTree(sn->getConstSubtree());
|
||||
} else {
|
||||
spv::MissingFunctionality("specialization-constant expression trees");
|
||||
spv::MissingFunctionality("Neither a front-end constant nor a spec constant.");
|
||||
exit(1);
|
||||
return spv::NoResult;
|
||||
}
|
||||
}
|
||||
|
|
@ -3772,7 +3778,7 @@ spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermType
|
|||
// If there are not enough elements present in 'consts', 0 will be substituted;
|
||||
// an empty 'consts' can be used to create a fully zeroed SPIR-V constant.
|
||||
//
|
||||
spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant)
|
||||
spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant)
|
||||
{
|
||||
// vector of constants for SPIR-V
|
||||
std::vector<spv::Id> spvConsts;
|
||||
|
|
@ -3783,15 +3789,15 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangT
|
|||
if (glslangType.isArray()) {
|
||||
glslang::TType elementType(glslangType, 0);
|
||||
for (int i = 0; i < glslangType.getOuterArraySize(); ++i)
|
||||
spvConsts.push_back(createSpvConstant(elementType, consts, nextConst, false));
|
||||
spvConsts.push_back(createSpvConstantFromConstUnionArray(elementType, consts, nextConst, false));
|
||||
} else if (glslangType.isMatrix()) {
|
||||
glslang::TType vectorType(glslangType, 0);
|
||||
for (int col = 0; col < glslangType.getMatrixCols(); ++col)
|
||||
spvConsts.push_back(createSpvConstant(vectorType, consts, nextConst, false));
|
||||
spvConsts.push_back(createSpvConstantFromConstUnionArray(vectorType, consts, nextConst, false));
|
||||
} else if (glslangType.getStruct()) {
|
||||
glslang::TVector<glslang::TTypeLoc>::const_iterator iter;
|
||||
for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter)
|
||||
spvConsts.push_back(createSpvConstant(*iter->type, consts, nextConst, false));
|
||||
spvConsts.push_back(createSpvConstantFromConstUnionArray(*iter->type, consts, nextConst, false));
|
||||
} else if (glslangType.isVector()) {
|
||||
for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) {
|
||||
bool zero = nextConst >= consts.size();
|
||||
|
|
@ -3848,6 +3854,66 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangT
|
|||
return builder.makeCompositeConstant(typeId, spvConsts);
|
||||
}
|
||||
|
||||
// Create constant ID from const initializer sub tree.
|
||||
spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstSubTree(
|
||||
const glslang::TIntermTyped* subTree) {
|
||||
const glslang::TType& glslangType = subTree->getType();
|
||||
spv::Id typeId = convertGlslangToSpvType(glslangType);
|
||||
bool is_spec_const = subTree->getType().getQualifier().isSpecConstant();
|
||||
if (const glslang::TIntermAggregate* an = subTree->getAsAggregate()) {
|
||||
// Aggregate node, we should generate OpConstantComposite or
|
||||
// OpSpecConstantComposite instruction.
|
||||
std::vector<spv::Id> const_constituents;
|
||||
for (auto NI = an->getSequence().begin(); NI != an->getSequence().end();
|
||||
NI++) {
|
||||
const_constituents.push_back(
|
||||
createSpvConstantFromConstSubTree((*NI)->getAsTyped()));
|
||||
}
|
||||
// Note that constructors are aggregate nodes, so expressions like:
|
||||
// float x = float(y) will become an aggregate node. If 'x' is declared
|
||||
// as a constant, the aggregate node representing 'float(y)' will be
|
||||
// processed here.
|
||||
if (builder.isVectorType(typeId) || builder.isMatrixType(typeId) ||
|
||||
builder.isAggregateType(typeId)) {
|
||||
return builder.makeCompositeConstant(typeId, const_constituents, is_spec_const);
|
||||
} else {
|
||||
assert(builder.isScalarType(typeId) && const_constituents.size() == 1);
|
||||
return const_constituents.front();
|
||||
}
|
||||
|
||||
} else if (const glslang::TIntermBinary* bn = subTree->getAsBinaryNode()) {
|
||||
// Binary operation node, we should generate OpSpecConstantOp <binary op>
|
||||
// This case should only happen when Specialization Constants are involved.
|
||||
spv::MissingFunctionality("OpSpecConstantOp <binary op> not implemented");
|
||||
return spv::NoResult;
|
||||
|
||||
} else if (const glslang::TIntermUnary* un = subTree->getAsUnaryNode()) {
|
||||
// Unary operation node, similar to binary operation node, should only
|
||||
// happen when specialization constants are involved.
|
||||
spv::MissingFunctionality("OpSpecConstantOp <unary op> not implemented");
|
||||
return spv::NoResult;
|
||||
|
||||
} else if (const glslang::TIntermConstantUnion* cn = subTree->getAsConstantUnion()) {
|
||||
// ConstantUnion node, should redirect to
|
||||
// createSpvConstantFromConstUnionArray
|
||||
int nextConst = 0;
|
||||
return createSpvConstantFromConstUnionArray(
|
||||
glslangType, cn->getConstArray(), nextConst, is_spec_const);
|
||||
|
||||
} else if (const glslang::TIntermSymbol* sn = subTree->getAsSymbolNode()) {
|
||||
// Symbol node. Call getSymbolId(). This should cover both cases 1) the
|
||||
// symbol has already been assigned an ID, 2) need a new ID for this
|
||||
// symbol.
|
||||
return getSymbolId(sn);
|
||||
|
||||
} else {
|
||||
spv::MissingFunctionality(
|
||||
"createSpvConstantFromConstSubTree() not covered TIntermTyped* const "
|
||||
"initializer subtree.");
|
||||
return spv::NoResult;
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if the node is a constant or symbol whose reading has no
|
||||
// non-trivial observable cost or effect.
|
||||
bool TGlslangToSpvTraverser::isTrivialLeaf(const glslang::TIntermTyped* node)
|
||||
|
|
|
|||
|
|
@ -2234,6 +2234,45 @@ Id Builder::accessChainGetInferredType()
|
|||
return type;
|
||||
}
|
||||
|
||||
// comment in header
|
||||
void Builder::eliminateDeadDecorations()
|
||||
{
|
||||
std::unordered_set<const Block*> reachable_blocks;
|
||||
std::unordered_set<Id> unreachable_definitions;
|
||||
// Collect IDs defined in unreachable blocks. For each function, label the
|
||||
// reachable blocks first. Then for each unreachable block, collect the
|
||||
// result IDs of the instructions in it.
|
||||
for (std::vector<Function*>::const_iterator fi = module.getFunctions().cbegin();
|
||||
fi != module.getFunctions().cend(); fi++)
|
||||
{
|
||||
Function* f = *fi;
|
||||
Block* entry = f->getEntryBlock();
|
||||
inReadableOrder(entry, [&reachable_blocks](const Block* b) { reachable_blocks.insert(b); });
|
||||
for (std::vector<Block*>::const_iterator bi = f->getBlocks().cbegin();
|
||||
bi != f->getBlocks().cend(); bi++)
|
||||
{
|
||||
Block* b = *bi;
|
||||
if (!reachable_blocks.count(b))
|
||||
{
|
||||
for (std::vector<std::unique_ptr<Instruction> >::const_iterator ii =
|
||||
b->getInstructions().cbegin();
|
||||
ii != b->getInstructions().cend(); ii++)
|
||||
{
|
||||
Instruction* i = ii->get();
|
||||
unreachable_definitions.insert(i->getResultId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
decorations.erase(std::remove_if(decorations.begin(), decorations.end(),
|
||||
[&unreachable_definitions](std::unique_ptr<Instruction>& I) {
|
||||
Instruction* inst = I.get();
|
||||
Id decoration_id = inst->getIdOperand(0);
|
||||
return unreachable_definitions.count(decoration_id) != 0;
|
||||
}),
|
||||
decorations.end());
|
||||
}
|
||||
|
||||
void Builder::dump(std::vector<unsigned int>& out) const
|
||||
{
|
||||
// Header, before first instructions:
|
||||
|
|
|
|||
|
|
@ -535,6 +535,9 @@ public:
|
|||
// based on the type of the base and the chain of dereferences.
|
||||
Id accessChainGetInferredType();
|
||||
|
||||
// Remove OpDecorate instructions whose operands are defined in unreachable
|
||||
// blocks.
|
||||
void eliminateDeadDecorations();
|
||||
void dump(std::vector<unsigned int>&) const;
|
||||
|
||||
void createBranch(Block* block);
|
||||
|
|
|
|||
|
|
@ -182,6 +182,9 @@ public:
|
|||
void addLocalVariable(std::unique_ptr<Instruction> inst) { localVariables.push_back(std::move(inst)); }
|
||||
const std::vector<Block*>& getPredecessors() const { return predecessors; }
|
||||
const std::vector<Block*>& getSuccessors() const { return successors; }
|
||||
const std::vector<std::unique_ptr<Instruction> >& getInstructions() const {
|
||||
return instructions;
|
||||
}
|
||||
void setUnreachable() { unreachable = true; }
|
||||
bool isUnreachable() const { return unreachable; }
|
||||
// Returns the block's merge instruction, if one exists (otherwise null).
|
||||
|
|
@ -275,6 +278,7 @@ public:
|
|||
Module& getParent() const { return parent; }
|
||||
Block* getEntryBlock() const { return blocks.front(); }
|
||||
Block* getLastBlock() const { return blocks.back(); }
|
||||
const std::vector<Block*>& getBlocks() const { return blocks; }
|
||||
void addLocalVariable(std::unique_ptr<Instruction> inst);
|
||||
Id getReturnType() const { return functionInstruction.getTypeId(); }
|
||||
void dump(std::vector<unsigned int>& out) const
|
||||
|
|
@ -326,6 +330,7 @@ public:
|
|||
}
|
||||
|
||||
Instruction* getInstruction(Id id) const { return idToInstruction[id]; }
|
||||
const std::vector<Function*>& getFunctions() const { return functions; }
|
||||
spv::Id getTypeId(Id resultId) const { return idToInstruction[resultId]->getTypeId(); }
|
||||
StorageClass getStorageClass(Id typeId) const
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue