Merge master branch from upstream

This commit is contained in:
Rex Xu 2015-09-14 10:38:56 +08:00
commit 30f9258d5e
43 changed files with 1992 additions and 174 deletions

View file

@ -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;

View file

@ -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();
}

View file

@ -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();