Merge master branch from upstream
This commit is contained in:
commit
30f9258d5e
43 changed files with 1992 additions and 174 deletions
|
|
@ -88,6 +88,10 @@ protected:
|
|||
spv::Id createSpvVariable(const glslang::TIntermSymbol*);
|
||||
spv::Id getSampledType(const glslang::TSampler&);
|
||||
spv::Id convertGlslangToSpvType(const glslang::TType& type);
|
||||
spv::Id convertGlslangToSpvType(const glslang::TType& type, bool explicitLayout);
|
||||
bool requiresExplicitLayout(const glslang::TType& type) const;
|
||||
int getArrayStride(const glslang::TType& arrayType);
|
||||
int getMatrixStride(const glslang::TType& matrixType);
|
||||
void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset);
|
||||
|
||||
bool isShaderEntrypoint(const glslang::TIntermAggregate* node);
|
||||
|
|
@ -578,12 +582,12 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
|||
// evaluate the right
|
||||
builder.clearAccessChain();
|
||||
node->getRight()->traverse(this);
|
||||
spv::Id rValue = builder.accessChainLoad(TranslatePrecisionDecoration(node->getRight()->getType()));
|
||||
spv::Id rValue = builder.accessChainLoad(convertGlslangToSpvType(node->getRight()->getType()));
|
||||
|
||||
if (node->getOp() != glslang::EOpAssign) {
|
||||
// the left is also an r-value
|
||||
builder.setAccessChain(lValue);
|
||||
spv::Id leftRValue = builder.accessChainLoad(TranslatePrecisionDecoration(node->getLeft()->getType()));
|
||||
spv::Id leftRValue = builder.accessChainLoad(convertGlslangToSpvType(node->getLeft()->getType()));
|
||||
|
||||
// do the operation
|
||||
rValue = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getType()),
|
||||
|
|
@ -635,10 +639,10 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
|||
// so short circuit the access-chain stuff with a swizzle.
|
||||
std::vector<unsigned> swizzle;
|
||||
swizzle.push_back(node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst());
|
||||
builder.accessChainPushSwizzle(swizzle);
|
||||
builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()));
|
||||
} else {
|
||||
// normal case for indexing array or structure or block
|
||||
builder.accessChainPush(builder.makeIntConstant(index), convertGlslangToSpvType(node->getType()));
|
||||
builder.accessChainPush(builder.makeIntConstant(index));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -659,15 +663,15 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
|||
// compute the next index in the chain
|
||||
builder.clearAccessChain();
|
||||
node->getRight()->traverse(this);
|
||||
spv::Id index = builder.accessChainLoad(TranslatePrecisionDecoration(node->getRight()->getType()));
|
||||
spv::Id index = builder.accessChainLoad(convertGlslangToSpvType(node->getRight()->getType()));
|
||||
|
||||
// restore the saved access chain
|
||||
builder.setAccessChain(partial);
|
||||
|
||||
if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector())
|
||||
builder.accessChainPushComponent(index);
|
||||
builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType()));
|
||||
else
|
||||
builder.accessChainPush(index, convertGlslangToSpvType(node->getType()));
|
||||
builder.accessChainPush(index);
|
||||
}
|
||||
return false;
|
||||
case glslang::EOpVectorSwizzle:
|
||||
|
|
@ -677,7 +681,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
|||
std::vector<unsigned> swizzle;
|
||||
for (int i = 0; i < (int)swizzleSequence.size(); ++i)
|
||||
swizzle.push_back(swizzleSequence[i]->getAsConstantUnion()->getConstArray()[0].getIConst());
|
||||
builder.accessChainPushSwizzle(swizzle);
|
||||
builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()));
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
|
|
@ -689,11 +693,11 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
|
|||
// Get the operands
|
||||
builder.clearAccessChain();
|
||||
node->getLeft()->traverse(this);
|
||||
spv::Id left = builder.accessChainLoad(TranslatePrecisionDecoration(node->getLeft()->getType()));
|
||||
spv::Id left = builder.accessChainLoad(convertGlslangToSpvType(node->getLeft()->getType()));
|
||||
|
||||
builder.clearAccessChain();
|
||||
node->getRight()->traverse(this);
|
||||
spv::Id right = builder.accessChainLoad(TranslatePrecisionDecoration(node->getRight()->getType()));
|
||||
spv::Id right = builder.accessChainLoad(convertGlslangToSpvType(node->getRight()->getType()));
|
||||
|
||||
spv::Id result;
|
||||
spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
|
||||
|
|
@ -728,10 +732,29 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
|
|||
}
|
||||
|
||||
// Non-texturing.
|
||||
|
||||
if (node->getOp() == glslang::EOpArrayLength) {
|
||||
// Quite special; won't want to evaluate the operand.
|
||||
|
||||
// Normal .length() would have been constant folded by the front-end.
|
||||
// So, this has to be block.lastMember.length().
|
||||
// SPV wants "block" as the operand, go get it.
|
||||
assert(node->getOperand()->getType().isRuntimeSizedArray());
|
||||
glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft();
|
||||
block->traverse(this);
|
||||
spv::Id length = builder.createUnaryOp(spv::OpArrayLength, builder.makeIntType(32), builder.accessChainGetLValue());
|
||||
|
||||
builder.clearAccessChain();
|
||||
builder.setAccessChainRValue(length);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start by evaluating the operand
|
||||
|
||||
builder.clearAccessChain();
|
||||
node->getOperand()->traverse(this);
|
||||
|
||||
spv::Id operand = spv::NoResult;
|
||||
|
||||
if (node->getOp() == glslang::EOpAtomicCounterIncrement ||
|
||||
|
|
@ -739,7 +762,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
|
|||
node->getOp() == glslang::EOpAtomicCounter)
|
||||
operand = builder.accessChainGetLValue(); // Special case l-value operands
|
||||
else
|
||||
operand = builder.accessChainLoad(TranslatePrecisionDecoration(node->getOperand()->getType()));
|
||||
operand = builder.accessChainLoad(convertGlslangToSpvType(node->getOperand()->getType()));
|
||||
|
||||
spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
|
||||
|
||||
|
|
@ -1027,17 +1050,6 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||
// which can be emitted by the one in createBinaryOperation()
|
||||
binOp = glslang::EOpMod;
|
||||
break;
|
||||
case glslang::EOpArrayLength:
|
||||
{
|
||||
glslang::TIntermTyped* typedNode = node->getSequence()[0]->getAsTyped();
|
||||
assert(typedNode);
|
||||
spv::Id length = builder.makeIntConstant(typedNode->getType().getOuterArraySize());
|
||||
|
||||
builder.clearAccessChain();
|
||||
builder.setAccessChainRValue(length);
|
||||
|
||||
return false;
|
||||
}
|
||||
case glslang::EOpEmitVertex:
|
||||
case glslang::EOpEndPrimitive:
|
||||
case glslang::EOpBarrier:
|
||||
|
|
@ -1091,11 +1103,11 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||
|
||||
builder.clearAccessChain();
|
||||
left->traverse(this);
|
||||
spv::Id leftId = builder.accessChainLoad(TranslatePrecisionDecoration(left->getType()));
|
||||
spv::Id leftId = builder.accessChainLoad(convertGlslangToSpvType(left->getType()));
|
||||
|
||||
builder.clearAccessChain();
|
||||
right->traverse(this);
|
||||
spv::Id rightId = builder.accessChainLoad(TranslatePrecisionDecoration(right->getType()));
|
||||
spv::Id rightId = builder.accessChainLoad(convertGlslangToSpvType(right->getType()));
|
||||
|
||||
result = createBinaryOperation(binOp, precision,
|
||||
convertGlslangToSpvType(node->getType()), leftId, rightId,
|
||||
|
|
@ -1148,7 +1160,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||
if (lvalue)
|
||||
operands.push_back(builder.accessChainGetLValue());
|
||||
else
|
||||
operands.push_back(builder.accessChainLoad(TranslatePrecisionDecoration(glslangOperands[arg]->getAsTyped()->getType())));
|
||||
operands.push_back(builder.accessChainLoad(convertGlslangToSpvType(glslangOperands[arg]->getAsTyped()->getType())));
|
||||
}
|
||||
|
||||
if (atomic) {
|
||||
|
|
@ -1198,13 +1210,13 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
|
|||
node->getCondition()->traverse(this);
|
||||
|
||||
// make an "if" based on the value created by the condition
|
||||
spv::Builder::If ifBuilder(builder.accessChainLoad(spv::NoPrecision), builder);
|
||||
spv::Builder::If ifBuilder(builder.accessChainLoad(convertGlslangToSpvType(node->getCondition()->getType())), builder);
|
||||
|
||||
if (node->getTrueBlock()) {
|
||||
// emit the "then" statement
|
||||
node->getTrueBlock()->traverse(this);
|
||||
if (result)
|
||||
builder.createStore(builder.accessChainLoad(TranslatePrecisionDecoration(node->getTrueBlock()->getAsTyped()->getType())), result);
|
||||
builder.createStore(builder.accessChainLoad(convertGlslangToSpvType(node->getTrueBlock()->getAsTyped()->getType())), result);
|
||||
}
|
||||
|
||||
if (node->getFalseBlock()) {
|
||||
|
|
@ -1212,7 +1224,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
|
|||
// emit the "else" statement
|
||||
node->getFalseBlock()->traverse(this);
|
||||
if (result)
|
||||
builder.createStore(builder.accessChainLoad(TranslatePrecisionDecoration(node->getFalseBlock()->getAsTyped()->getType())), result);
|
||||
builder.createStore(builder.accessChainLoad(convertGlslangToSpvType(node->getFalseBlock()->getAsTyped()->getType())), result);
|
||||
}
|
||||
|
||||
ifBuilder.makeEndIf();
|
||||
|
|
@ -1233,7 +1245,7 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T
|
|||
{
|
||||
// emit and get the condition before doing anything with switch
|
||||
node->getCondition()->traverse(this);
|
||||
spv::Id selector = builder.accessChainLoad(TranslatePrecisionDecoration(node->getCondition()->getAsTyped()->getType()));
|
||||
spv::Id selector = builder.accessChainLoad(convertGlslangToSpvType(node->getCondition()->getAsTyped()->getType()));
|
||||
|
||||
// browse the children to sort out code segments
|
||||
int defaultSegment = -1;
|
||||
|
|
@ -1297,7 +1309,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
|
|||
if (node->getTest()) {
|
||||
node->getTest()->traverse(this);
|
||||
// the AST only contained the test computation, not the branch, we have to add it
|
||||
spv::Id condition = builder.accessChainLoad(TranslatePrecisionDecoration(node->getTest()->getType()));
|
||||
spv::Id condition = builder.accessChainLoad(convertGlslangToSpvType(node->getTest()->getType()));
|
||||
builder.createLoopTestBranch(condition);
|
||||
} else {
|
||||
builder.createBranchToBody();
|
||||
|
|
@ -1343,7 +1355,7 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
|
|||
if (inMain)
|
||||
builder.makeMainReturn();
|
||||
else if (node->getExpression())
|
||||
builder.makeReturn(false, builder.accessChainLoad(TranslatePrecisionDecoration(node->getExpression()->getType())));
|
||||
builder.makeReturn(false, builder.accessChainLoad(convertGlslangToSpvType(node->getExpression()->getType())));
|
||||
else
|
||||
builder.makeReturn();
|
||||
|
||||
|
|
@ -1391,8 +1403,16 @@ spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler)
|
|||
}
|
||||
}
|
||||
|
||||
// Do full recursive conversion of an arbitrary glslang type to a SPIR-V Id.
|
||||
// Convert from a glslang type to an SPV type, by calling into
|
||||
// recursive version of this function.
|
||||
spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type)
|
||||
{
|
||||
return convertGlslangToSpvType(type, requiresExplicitLayout(type));
|
||||
}
|
||||
|
||||
// Do full recursive conversion of an arbitrary glslang type to a SPIR-V Id.
|
||||
// explicitLayout can be kept the same throughout the heirarchical recursive walk.
|
||||
spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, bool explicitLayout)
|
||||
{
|
||||
spv::Id spvType = 0;
|
||||
|
||||
|
|
@ -1456,7 +1476,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
|||
} else {
|
||||
if (type.getBasicType() == glslang::EbtBlock)
|
||||
memberRemapper[glslangStruct][i] = i - memberDelta;
|
||||
structFields.push_back(convertGlslangToSpvType(glslangType));
|
||||
structFields.push_back(convertGlslangToSpvType(glslangType, explicitLayout));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1484,15 +1504,19 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
|||
builder.addMemberDecoration(spvType, member, spv::DecorationComponent, glslangType.getQualifier().layoutComponent);
|
||||
if (glslangType.getQualifier().hasXfbOffset())
|
||||
builder.addMemberDecoration(spvType, member, spv::DecorationOffset, glslangType.getQualifier().layoutXfbOffset);
|
||||
else {
|
||||
else if (explicitLayout) {
|
||||
// figure out what to do with offset, which is accumulating
|
||||
int nextOffset;
|
||||
updateMemberOffset(type, glslangType, offset, nextOffset);
|
||||
if (offset >= 0)
|
||||
builder.addMemberDecoration(spvType, member, spv::DecorationOffset, glslangType.getQualifier().layoutOffset);
|
||||
builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset);
|
||||
offset = nextOffset;
|
||||
}
|
||||
|
||||
if (glslangType.isMatrix() && explicitLayout) {
|
||||
builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, getMatrixStride(glslangType));
|
||||
}
|
||||
|
||||
// built-in variable decorations
|
||||
spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangType.getQualifier().builtIn);
|
||||
if (builtIn != spv::BadValue)
|
||||
|
|
@ -1527,18 +1551,56 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
|||
}
|
||||
|
||||
if (type.isArray()) {
|
||||
unsigned arraySize;
|
||||
if (! type.isExplicitlySizedArray()) {
|
||||
spv::MissingFunctionality("Unsized array");
|
||||
arraySize = 8;
|
||||
} else
|
||||
arraySize = type.getOuterArraySize();
|
||||
spvType = builder.makeArrayType(spvType, arraySize);
|
||||
// Do all but the outer dimension
|
||||
for (int dim = type.getArraySizes()->getNumDims() - 1; dim > 0; --dim) {
|
||||
assert(type.getArraySizes()->getDimSize(dim) > 0);
|
||||
spvType = builder.makeArrayType(spvType, type.getArraySizes()->getDimSize(dim));
|
||||
}
|
||||
|
||||
// Do the outer dimension, which might not be known for a runtime-sized array
|
||||
if (type.isRuntimeSizedArray()) {
|
||||
spvType = builder.makeRuntimeArray(spvType);
|
||||
} else {
|
||||
assert(type.getOuterArraySize() > 0);
|
||||
spvType = builder.makeArrayType(spvType, type.getOuterArraySize());
|
||||
}
|
||||
|
||||
// TODO: layout still needs to be done hierarchically for arrays of arrays, which
|
||||
// may still require additional "link time" support from the front-end
|
||||
// for arrays of arrays
|
||||
if (explicitLayout)
|
||||
builder.addDecoration(spvType, spv::DecorationArrayStride, getArrayStride(type));
|
||||
}
|
||||
|
||||
return spvType;
|
||||
}
|
||||
|
||||
bool TGlslangToSpvTraverser::requiresExplicitLayout(const glslang::TType& type) const
|
||||
{
|
||||
return type.getBasicType() == glslang::EbtBlock &&
|
||||
type.getQualifier().layoutPacking != glslang::ElpShared &&
|
||||
type.getQualifier().layoutPacking != glslang::ElpPacked &&
|
||||
(type.getQualifier().storage == glslang::EvqUniform ||
|
||||
type.getQualifier().storage == glslang::EvqBuffer);
|
||||
}
|
||||
|
||||
// Given an array type, returns the integer stride required for that array
|
||||
int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType)
|
||||
{
|
||||
glslang::TType derefType(arrayType, 0);
|
||||
int size;
|
||||
glslangIntermediate->getBaseAlignment(derefType, size, true);
|
||||
return size;
|
||||
}
|
||||
|
||||
// Given a matrix type, returns the integer stride required for that matrix
|
||||
// when used as a member of an interface block
|
||||
int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType)
|
||||
{
|
||||
int size;
|
||||
return glslangIntermediate->getBaseAlignment(matrixType, size, true);
|
||||
}
|
||||
|
||||
// Given a member type of a struct, realign the current offset for it, and compute
|
||||
// the next (not yet aligned) offset for the next member, which will get aligned
|
||||
// on the next call.
|
||||
|
|
@ -1700,9 +1762,8 @@ void TGlslangToSpvTraverser::translateArguments(glslang::TIntermAggregate& node,
|
|||
|
||||
if (lvalue) {
|
||||
arguments.push_back(builder.accessChainGetLValue());
|
||||
}
|
||||
else {
|
||||
arguments.push_back(builder.accessChainLoad(TranslatePrecisionDecoration(glslangArguments[i]->getAsTyped()->getType())));
|
||||
} else {
|
||||
arguments.push_back(builder.accessChainLoad(convertGlslangToSpvType(glslangArguments[i]->getAsTyped()->getType())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1711,7 +1772,7 @@ void TGlslangToSpvTraverser::translateArguments(glslang::TIntermUnary& node, std
|
|||
{
|
||||
builder.clearAccessChain();
|
||||
node.getOperand()->traverse(this);
|
||||
arguments.push_back(builder.accessChainLoad(TranslatePrecisionDecoration(node.getAsTyped()->getType())));
|
||||
arguments.push_back(builder.accessChainLoad(convertGlslangToSpvType(node.getOperand()->getType())));
|
||||
}
|
||||
|
||||
spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermOperator* node)
|
||||
|
|
@ -1792,8 +1853,6 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
|
|||
}
|
||||
|
||||
// Check for texture functions other than queries
|
||||
if (cracked.fetch)
|
||||
spv::MissingFunctionality("texel fetch");
|
||||
if (cracked.gather)
|
||||
spv::MissingFunctionality("texture gather");
|
||||
|
||||
|
|
@ -1849,7 +1908,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
|
|||
++extraArgs;
|
||||
}
|
||||
|
||||
return builder.createTextureCall(precision, convertGlslangToSpvType(node->getType()), cracked.proj, params);
|
||||
return builder.createTextureCall(precision, convertGlslangToSpvType(node->getType()), cracked.fetch, cracked.proj, params);
|
||||
}
|
||||
|
||||
spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAggregate* node)
|
||||
|
|
@ -1873,17 +1932,19 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
|
|||
// 1. Evaluate the arguments
|
||||
std::vector<spv::Builder::AccessChain> lValues;
|
||||
std::vector<spv::Id> rValues;
|
||||
std::vector<spv::Id> argTypes;
|
||||
for (int a = 0; a < (int)glslangArgs.size(); ++a) {
|
||||
// build l-value
|
||||
builder.clearAccessChain();
|
||||
glslangArgs[a]->traverse(this);
|
||||
argTypes.push_back(convertGlslangToSpvType(glslangArgs[a]->getAsTyped()->getType()));
|
||||
// keep outputs as l-values, evaluate input-only as r-values
|
||||
if (qualifiers[a] != glslang::EvqConstReadOnly) {
|
||||
// save l-value
|
||||
lValues.push_back(builder.getAccessChain());
|
||||
} else {
|
||||
// process r-value
|
||||
rValues.push_back(builder.accessChainLoad(TranslatePrecisionDecoration(glslangArgs[a]->getAsTyped()->getType())));
|
||||
rValues.push_back(builder.accessChainLoad(argTypes.back()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1903,7 +1964,7 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
|
|||
if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) {
|
||||
// need to copy the input into output space
|
||||
builder.setAccessChain(lValues[lValueCount]);
|
||||
spv::Id copy = builder.accessChainLoad(spv::NoPrecision); // TODO: get precision
|
||||
spv::Id copy = builder.accessChainLoad(argTypes[a]);
|
||||
builder.createStore(copy, arg);
|
||||
}
|
||||
++lValueCount;
|
||||
|
|
|
|||
|
|
@ -264,6 +264,16 @@ Id Builder::makeArrayType(Id element, unsigned size)
|
|||
return type->getResultId();
|
||||
}
|
||||
|
||||
Id Builder::makeRuntimeArray(Id element)
|
||||
{
|
||||
Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeRuntimeArray);
|
||||
type->addIdOperand(element);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
module.mapInstruction(type);
|
||||
|
||||
return type->getResultId();
|
||||
}
|
||||
|
||||
Id Builder::makeFunctionType(Id returnType, std::vector<Id>& paramTypes)
|
||||
{
|
||||
// try to find it
|
||||
|
|
@ -280,7 +290,7 @@ Id Builder::makeFunctionType(Id returnType, std::vector<Id>& paramTypes)
|
|||
}
|
||||
}
|
||||
if (! mismatch)
|
||||
return type->getResultId();
|
||||
return type->getResultId();
|
||||
}
|
||||
|
||||
// not found, make it
|
||||
|
|
@ -1147,7 +1157,7 @@ Id Builder::createBuiltinCall(Decoration /*precision*/, Id resultType, Id builti
|
|||
|
||||
// Accept all parameters needed to create a texture instruction.
|
||||
// Create the correct instruction based on the inputs, and make the call.
|
||||
Id Builder::createTextureCall(Decoration precision, Id resultType, bool proj, const TextureParameters& parameters)
|
||||
Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, bool proj, const TextureParameters& parameters)
|
||||
{
|
||||
static const int maxTextureArgs = 10;
|
||||
Id texArgs[maxTextureArgs] = {};
|
||||
|
|
@ -1206,7 +1216,9 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool proj, co
|
|||
//
|
||||
Op opCode;
|
||||
opCode = OpImageSampleImplicitLod;
|
||||
if (xplicit) {
|
||||
if (fetch) {
|
||||
opCode = OpImageFetch;
|
||||
} else if (xplicit) {
|
||||
if (parameters.Dref) {
|
||||
if (proj)
|
||||
opCode = OpImageSampleProjDrefExplicitLod;
|
||||
|
|
@ -1955,18 +1967,23 @@ void Builder::createBranchToLoopHeaderFromInside(const Loop& loop)
|
|||
|
||||
void Builder::clearAccessChain()
|
||||
{
|
||||
accessChain.base = 0;
|
||||
accessChain.base = NoResult;
|
||||
accessChain.indexChain.clear();
|
||||
accessChain.instr = 0;
|
||||
accessChain.instr = NoResult;
|
||||
accessChain.swizzle.clear();
|
||||
accessChain.component = 0;
|
||||
accessChain.resultType = NoType;
|
||||
accessChain.component = NoResult;
|
||||
accessChain.preSwizzleBaseType = NoType;
|
||||
accessChain.isRValue = false;
|
||||
}
|
||||
|
||||
// Comments in header
|
||||
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle)
|
||||
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType)
|
||||
{
|
||||
// swizzles can be stacked in GLSL, but simplified to a single
|
||||
// one here; the base type doesn't change
|
||||
if (accessChain.preSwizzleBaseType == NoType)
|
||||
accessChain.preSwizzleBaseType = preSwizzleBaseType;
|
||||
|
||||
// if needed, propagate the swizzle for the current access chain
|
||||
if (accessChain.swizzle.size()) {
|
||||
std::vector<unsigned> oldSwizzle = accessChain.swizzle;
|
||||
|
|
@ -1988,7 +2005,7 @@ void Builder::accessChainStore(Id rvalue)
|
|||
|
||||
Id base = collapseAccessChain();
|
||||
|
||||
if (accessChain.swizzle.size() && accessChain.component)
|
||||
if (accessChain.swizzle.size() && accessChain.component != NoResult)
|
||||
MissingFunctionality("simultaneous l-value swizzle and dynamic component selection");
|
||||
|
||||
// If swizzle exists, it is out-of-order or not full, we must load the target vector,
|
||||
|
|
@ -2000,7 +2017,7 @@ void Builder::accessChainStore(Id rvalue)
|
|||
}
|
||||
|
||||
// dynamic component selection
|
||||
if (accessChain.component) {
|
||||
if (accessChain.component != NoResult) {
|
||||
Id tempBaseId = (source == NoResult) ? createLoad(base) : source;
|
||||
source = createVectorInsertDynamic(tempBaseId, getTypeId(tempBaseId), rvalue, accessChain.component);
|
||||
}
|
||||
|
|
@ -2012,13 +2029,15 @@ void Builder::accessChainStore(Id rvalue)
|
|||
}
|
||||
|
||||
// Comments in header
|
||||
Id Builder::accessChainLoad(Decoration /*precision*/)
|
||||
Id Builder::accessChainLoad(Id resultType)
|
||||
{
|
||||
Id id;
|
||||
|
||||
if (accessChain.isRValue) {
|
||||
if (accessChain.indexChain.size() > 0) {
|
||||
mergeAccessChainSwizzle(); // TODO: optimization: look at applying this optimization more widely
|
||||
Id swizzleBase = accessChain.preSwizzleBaseType != NoType ? accessChain.preSwizzleBaseType : resultType;
|
||||
|
||||
// if all the accesses are constants, we can use OpCompositeExtract
|
||||
std::vector<unsigned> indexes;
|
||||
bool constant = true;
|
||||
|
|
@ -2032,7 +2051,7 @@ Id Builder::accessChainLoad(Decoration /*precision*/)
|
|||
}
|
||||
|
||||
if (constant)
|
||||
id = createCompositeExtract(accessChain.base, accessChain.resultType, indexes);
|
||||
id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
|
||||
else {
|
||||
// make a new function variable for this r-value
|
||||
Id lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
|
||||
|
|
@ -2055,24 +2074,22 @@ Id Builder::accessChainLoad(Decoration /*precision*/)
|
|||
}
|
||||
|
||||
// Done, unless there are swizzles to do
|
||||
if (accessChain.swizzle.size() == 0 && accessChain.component == 0)
|
||||
if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult)
|
||||
return id;
|
||||
|
||||
Id componentType = getScalarTypeId(accessChain.resultType);
|
||||
|
||||
// Do remaining swizzling
|
||||
// First, static swizzling
|
||||
if (accessChain.swizzle.size()) {
|
||||
// static swizzle
|
||||
Id resultType = componentType;
|
||||
Id swizzledType = getScalarTypeId(getTypeId(id));
|
||||
if (accessChain.swizzle.size() > 1)
|
||||
resultType = makeVectorType(componentType, (int)accessChain.swizzle.size());
|
||||
id = createRvalueSwizzle(resultType, id, accessChain.swizzle);
|
||||
swizzledType = makeVectorType(swizzledType, (int)accessChain.swizzle.size());
|
||||
id = createRvalueSwizzle(swizzledType, id, accessChain.swizzle);
|
||||
}
|
||||
|
||||
// dynamic single-component selection
|
||||
if (accessChain.component)
|
||||
id = createVectorExtractDynamic(id, componentType, accessChain.component);
|
||||
if (accessChain.component != NoResult)
|
||||
id = createVectorExtractDynamic(id, resultType, accessChain.component);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
|
@ -2087,7 +2104,7 @@ Id Builder::accessChainGetLValue()
|
|||
// extract and insert elements to perform writeMask and/or swizzle. This does not
|
||||
// go with getting a direct l-value pointer.
|
||||
assert(accessChain.swizzle.size() == 0);
|
||||
assert(accessChain.component == spv::NoResult);
|
||||
assert(accessChain.component == NoResult);
|
||||
|
||||
return lvalue;
|
||||
}
|
||||
|
|
@ -2168,7 +2185,7 @@ void Builder::simplifyAccessChainSwizzle()
|
|||
{
|
||||
// If the swizzle has fewer components than the vector, it is subsetting, and must stay
|
||||
// to preserve that fact.
|
||||
if (getNumTypeComponents(accessChain.resultType) > (int)accessChain.swizzle.size())
|
||||
if (getNumTypeComponents(accessChain.preSwizzleBaseType) > (int)accessChain.swizzle.size())
|
||||
return;
|
||||
|
||||
// if components are out of order, it is a swizzle
|
||||
|
|
@ -2179,6 +2196,8 @@ void Builder::simplifyAccessChainSwizzle()
|
|||
|
||||
// otherwise, there is no need to track this swizzle
|
||||
accessChain.swizzle.clear();
|
||||
if (accessChain.component == NoResult)
|
||||
accessChain.preSwizzleBaseType = NoType;
|
||||
}
|
||||
|
||||
// clear out swizzle if it can become part of the indexes
|
||||
|
|
@ -2186,12 +2205,12 @@ void Builder::mergeAccessChainSwizzle()
|
|||
{
|
||||
// is there even a chance of doing something? Need a single-component swizzle
|
||||
if ((accessChain.swizzle.size() > 1) ||
|
||||
(accessChain.swizzle.size() == 0 && accessChain.component == 0))
|
||||
(accessChain.swizzle.size() == 0 && accessChain.component == NoResult))
|
||||
return;
|
||||
|
||||
// TODO: optimization: remove this, but for now confine this to non-dynamic accesses
|
||||
// (the above test is correct when this is removed.)
|
||||
if (accessChain.component)
|
||||
if (accessChain.component != NoResult)
|
||||
return;
|
||||
|
||||
// move the swizzle over to the indexes
|
||||
|
|
@ -2199,10 +2218,10 @@ void Builder::mergeAccessChainSwizzle()
|
|||
accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front()));
|
||||
else
|
||||
accessChain.indexChain.push_back(accessChain.component);
|
||||
accessChain.resultType = getScalarTypeId(accessChain.resultType);
|
||||
|
||||
// now there is no need to track this swizzle
|
||||
accessChain.component = NoResult;
|
||||
accessChain.preSwizzleBaseType = NoType;
|
||||
accessChain.swizzle.clear();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ public:
|
|||
Id makeVectorType(Id component, int size);
|
||||
Id makeMatrixType(Id component, int cols, int rows);
|
||||
Id makeArrayType(Id element, unsigned size);
|
||||
Id makeRuntimeArray(Id element);
|
||||
Id makeFunctionType(Id returnType, std::vector<Id>& paramTypes);
|
||||
Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format);
|
||||
Id makeSampledImageType(Id imageType);
|
||||
|
|
@ -304,7 +305,7 @@ public:
|
|||
};
|
||||
|
||||
// Select the correct texture operation based on all inputs, and emit the correct instruction
|
||||
Id createTextureCall(Decoration precision, Id resultType, bool proj, const TextureParameters&);
|
||||
Id createTextureCall(Decoration precision, Id resultType, bool fetch, bool proj, const TextureParameters&);
|
||||
|
||||
// Emit the OpTextureQuery* instruction that was passed in.
|
||||
// Figure out the right return value and type, and return it.
|
||||
|
|
@ -436,7 +437,7 @@ public:
|
|||
Id instr; // the instruction that generates this access chain
|
||||
std::vector<unsigned> swizzle;
|
||||
Id component; // a dynamic component index, can coexist with a swizzle, done after the swizzle
|
||||
Id resultType; // dereferenced type, to be exclusive of swizzles
|
||||
Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present
|
||||
bool isRValue;
|
||||
};
|
||||
|
||||
|
|
@ -457,7 +458,6 @@ public:
|
|||
{
|
||||
assert(isPointer(lValue));
|
||||
accessChain.base = lValue;
|
||||
accessChain.resultType = getContainedTypeId(getTypeId(lValue));
|
||||
}
|
||||
|
||||
// set new base value as an r-value
|
||||
|
|
@ -465,27 +465,30 @@ public:
|
|||
{
|
||||
accessChain.isRValue = true;
|
||||
accessChain.base = rValue;
|
||||
accessChain.resultType = getTypeId(rValue);
|
||||
}
|
||||
|
||||
// push offset onto the end of the chain
|
||||
void accessChainPush(Id offset, Id newType)
|
||||
void accessChainPush(Id offset)
|
||||
{
|
||||
accessChain.indexChain.push_back(offset);
|
||||
accessChain.resultType = newType;
|
||||
}
|
||||
|
||||
// push new swizzle onto the end of any existing swizzle, merging into a single swizzle
|
||||
void accessChainPushSwizzle(std::vector<unsigned>& swizzle);
|
||||
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType);
|
||||
|
||||
// push a variable component selection onto the access chain; supporting only one, so unsided
|
||||
void accessChainPushComponent(Id component) { accessChain.component = component; }
|
||||
void accessChainPushComponent(Id component, Id preSwizzleBaseType)
|
||||
{
|
||||
accessChain.component = component;
|
||||
if (accessChain.preSwizzleBaseType == NoType)
|
||||
accessChain.preSwizzleBaseType = preSwizzleBaseType;
|
||||
}
|
||||
|
||||
// use accessChain and swizzle to store value
|
||||
void accessChainStore(Id rvalue);
|
||||
|
||||
// use accessChain and swizzle to load an r-value
|
||||
Id accessChainLoad(Decoration precision);
|
||||
Id accessChainLoad(Id ResultType);
|
||||
|
||||
// get the direct pointer for an l-value
|
||||
Id accessChainGetLValue();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue