SPV: RelaxedPrecision: Plumb this through the full AST->SPV translator.

This commit is contained in:
John Kessenich 2016-02-02 12:37:46 -07:00
parent 26bd6a313d
commit 32cfd49b68
11 changed files with 411 additions and 109 deletions

View file

@ -93,6 +93,7 @@ protected:
spv::Id getSampledType(const glslang::TSampler&);
spv::Id convertGlslangToSpvType(const glslang::TType& type);
spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&);
spv::Id accessChainLoad(const glslang::TType& type);
glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const;
int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
@ -234,7 +235,6 @@ spv::Decoration TranslatePrecisionDecoration(const glslang::TType& type)
switch (type.getQualifier().precision) {
case glslang::EpqLow: return spv::DecorationRelaxedPrecision;
case glslang::EpqMedium: return spv::DecorationRelaxedPrecision;
case glslang::EpqHigh: return spv::NoPrecision;
default:
return spv::NoPrecision;
}
@ -709,12 +709,12 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
// evaluate the right
builder.clearAccessChain();
node->getRight()->traverse(this);
spv::Id rValue = builder.accessChainLoad(convertGlslangToSpvType(node->getRight()->getType()));
spv::Id rValue = accessChainLoad(node->getRight()->getType());
if (node->getOp() != glslang::EOpAssign) {
// the left is also an r-value
builder.setAccessChain(lValue);
spv::Id leftRValue = builder.accessChainLoad(convertGlslangToSpvType(node->getLeft()->getType()));
spv::Id leftRValue = accessChainLoad(node->getLeft()->getType());
// do the operation
rValue = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getType()),
@ -782,7 +782,7 @@ 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(convertGlslangToSpvType(node->getRight()->getType()));
spv::Id index = accessChainLoad(node->getRight()->getType());
// restore the saved access chain
builder.setAccessChain(partial);
@ -824,21 +824,20 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
// Assume generic binary op...
// Get the operands
// get right operand
builder.clearAccessChain();
node->getLeft()->traverse(this);
spv::Id left = builder.accessChainLoad(convertGlslangToSpvType(node->getLeft()->getType()));
spv::Id left = accessChainLoad(node->getLeft()->getType());
// get left operand
builder.clearAccessChain();
node->getRight()->traverse(this);
spv::Id right = builder.accessChainLoad(convertGlslangToSpvType(node->getRight()->getType()));
spv::Id right = accessChainLoad(node->getRight()->getType());
spv::Id result;
spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
result = createBinaryOperation(node->getOp(), precision,
convertGlslangToSpvType(node->getType()), left, right,
node->getLeft()->getType().getBasicType());
// get result
spv::Id result = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getType()),
convertGlslangToSpvType(node->getType()), left, right,
node->getLeft()->getType().getBasicType());
builder.clearAccessChain();
if (! result) {
@ -896,7 +895,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
node->getOp() == glslang::EOpInterpolateAtCentroid)
operand = builder.accessChainGetLValue(); // Special case l-value operands
else
operand = builder.accessChainLoad(convertGlslangToSpvType(node->getOperand()->getType()));
operand = accessChainLoad(node->getOperand()->getType());
spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
@ -1208,11 +1207,11 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
builder.clearAccessChain();
left->traverse(this);
spv::Id leftId = builder.accessChainLoad(convertGlslangToSpvType(left->getType()));
spv::Id leftId = accessChainLoad(left->getType());
builder.clearAccessChain();
right->traverse(this);
spv::Id rightId = builder.accessChainLoad(convertGlslangToSpvType(right->getType()));
spv::Id rightId = accessChainLoad(right->getType());
result = createBinaryOperation(binOp, precision,
convertGlslangToSpvType(node->getType()), leftId, rightId,
@ -1275,7 +1274,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
if (lvalue)
operands.push_back(builder.accessChainGetLValue());
else
operands.push_back(builder.accessChainLoad(convertGlslangToSpvType(glslangOperands[arg]->getAsTyped()->getType())));
operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
}
if (atomic) {
@ -1325,13 +1324,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(convertGlslangToSpvType(node->getCondition()->getType())), builder);
spv::Builder::If ifBuilder(accessChainLoad(node->getCondition()->getType()), builder);
if (node->getTrueBlock()) {
// emit the "then" statement
node->getTrueBlock()->traverse(this);
if (result)
builder.createStore(builder.accessChainLoad(convertGlslangToSpvType(node->getTrueBlock()->getAsTyped()->getType())), result);
builder.createStore(accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()), result);
}
if (node->getFalseBlock()) {
@ -1339,7 +1338,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
// emit the "else" statement
node->getFalseBlock()->traverse(this);
if (result)
builder.createStore(builder.accessChainLoad(convertGlslangToSpvType(node->getFalseBlock()->getAsTyped()->getType())), result);
builder.createStore(accessChainLoad(node->getFalseBlock()->getAsTyped()->getType()), result);
}
ifBuilder.makeEndIf();
@ -1360,7 +1359,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(convertGlslangToSpvType(node->getCondition()->getAsTyped()->getType()));
spv::Id selector = accessChainLoad(node->getCondition()->getAsTyped()->getType());
// browse the children to sort out code segments
int defaultSegment = -1;
@ -1433,7 +1432,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
builder.setBuildPoint(&test);
node->getTest()->traverse(this);
spv::Id condition =
builder.accessChainLoad(convertGlslangToSpvType(node->getTest()->getType()));
accessChainLoad(node->getTest()->getType());
builder.createConditionalBranch(condition, &blocks.body, &blocks.merge);
builder.setBuildPoint(&blocks.body);
@ -1463,7 +1462,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
if (node->getTest()) {
node->getTest()->traverse(this);
spv::Id condition =
builder.accessChainLoad(convertGlslangToSpvType(node->getTest()->getType()));
accessChainLoad(node->getTest()->getType());
builder.createConditionalBranch(condition, &blocks.head, &blocks.merge);
} else {
// TODO: unless there was a break/return/discard instruction
@ -1497,7 +1496,7 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
break;
case glslang::EOpReturn:
if (node->getExpression())
builder.makeReturn(false, builder.accessChainLoad(convertGlslangToSpvType(node->getExpression()->getType())));
builder.makeReturn(false, accessChainLoad(node->getExpression()->getType()));
else
builder.makeReturn(false);
@ -1765,6 +1764,11 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
return spvType;
}
spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
{
return builder.accessChainLoad(TranslatePrecisionDecoration(type), convertGlslangToSpvType(type));
}
// Decide whether or not this type should be
// decorated with offsets and strides, and if so
// whether std140 or std430 rules should be applied.
@ -1885,6 +1889,7 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
// copy-in/copy-out semantics. They can be handled though with a pointer to a copy.
std::vector<spv::Id> paramTypes;
std::vector<spv::Decoration> paramPrecisions;
glslang::TIntermSequence& parameters = glslFunction->getSequence()[0]->getAsAggregate()->getSequence();
for (int p = 0; p < (int)parameters.size(); ++p) {
@ -1894,12 +1899,14 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
typeId = builder.makePointer(spv::StorageClassFunction, typeId);
else
constReadOnlyParameters.insert(parameters[p]->getAsSymbolNode()->getId());
paramPrecisions.push_back(TranslatePrecisionDecoration(paramType));
paramTypes.push_back(typeId);
}
spv::Block* functionBlock;
spv::Function *function = builder.makeFunctionEntry(convertGlslangToSpvType(glslFunction->getType()), glslFunction->getName().c_str(),
paramTypes, &functionBlock);
spv::Function *function = builder.makeFunctionEntry(TranslatePrecisionDecoration(glslFunction->getType()),
convertGlslangToSpvType(glslFunction->getType()),
glslFunction->getName().c_str(), paramTypes, paramPrecisions, &functionBlock);
// Track function to emit/call later
functionMap[glslFunction->getName().c_str()] = function;
@ -2028,7 +2035,7 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate&
if (lvalue)
arguments.push_back(builder.accessChainGetLValue());
else
arguments.push_back(builder.accessChainLoad(convertGlslangToSpvType(glslangArguments[i]->getAsTyped()->getType())));
arguments.push_back(accessChainLoad(glslangArguments[i]->getAsTyped()->getType()));
}
}
@ -2036,7 +2043,7 @@ void TGlslangToSpvTraverser::translateArguments(glslang::TIntermUnary& node, std
{
builder.clearAccessChain();
node.getOperand()->traverse(this);
arguments.push_back(builder.accessChainLoad(convertGlslangToSpvType(node.getOperand()->getType())));
arguments.push_back(accessChainLoad(node.getOperand()->getType()));
}
spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermOperator* node)
@ -2241,19 +2248,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;
std::vector<const glslang::TType*> 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()));
argTypes.push_back(&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(argTypes.back()));
rValues.push_back(accessChainLoad(*argTypes.back()));
}
}
@ -2273,7 +2280,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(argTypes[a]);
spv::Id copy = accessChainLoad(*argTypes[a]);
builder.createStore(copy, arg);
}
++lValueCount;
@ -2286,6 +2293,7 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
// 3. Make the call.
spv::Id result = builder.createFunctionCall(function, spvArgs);
builder.setPrecision(result, TranslatePrecisionDecoration(node->getType()));
// 4. Copy back out an "out" arguments.
lValueCount = 0;
@ -2446,10 +2454,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
if (needMatchingVectors)
builder.promoteScalar(precision, left, right);
spv::Id id = builder.createBinOp(binOp, typeId, left, right);
builder.setPrecision(id, precision);
return id;
return builder.setPrecision(builder.createBinOp(binOp, typeId, left, right), precision);
}
if (! comparison)
@ -2514,12 +2519,8 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
break;
}
if (binOp != spv::OpNop) {
spv::Id id = builder.createBinOp(binOp, typeId, left, right);
builder.setPrecision(id, precision);
return id;
}
if (binOp != spv::OpNop)
return builder.setPrecision(builder.createBinOp(binOp, typeId, left, right), precision);
return 0;
}
@ -2574,12 +2575,8 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Dec
break;
}
if (firstClass) {
spv::Id id = builder.createBinOp(op, typeId, left, right);
builder.setPrecision(id, precision);
return id;
}
if (firstClass)
return builder.setPrecision(builder.createBinOp(op, typeId, left, right), precision);
// Handle component-wise +, -, *, and / for all combinations of type.
// The result type of all of them is the same type as the (a) matrix operand.
@ -2619,9 +2616,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Dec
}
// put the pieces together
spv::Id id = builder.createCompositeConstruct(typeId, results);
builder.setPrecision(id, precision);
return id;
return builder.setPrecision(builder.createCompositeConstruct(typeId, results), precision);
}
default:
assert(0);
@ -2899,13 +2894,11 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
if (libCall >= 0) {
std::vector<spv::Id> args;
args.push_back(operand);
id = builder.createBuiltinCall(precision, typeId, stdBuiltins, libCall, args);
id = builder.createBuiltinCall(typeId, stdBuiltins, libCall, args);
} else
id = builder.createUnaryOp(unaryOp, typeId, operand);
builder.setPrecision(id, precision);
return id;
return builder.setPrecision(id, precision);
}
// Create a unary operation on a matrix
@ -2935,10 +2928,7 @@ spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, spv::Deco
}
// put the pieces together
spv::Id id = builder.createCompositeConstruct(typeId, results);
builder.setPrecision(id, precision);
return id;
return builder.setPrecision(builder.createCompositeConstruct(typeId, results), precision);
}
spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, spv::Decoration precision, spv::Id destType, spv::Id operand)
@ -3031,9 +3021,7 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, spv::Dec
} else
result = builder.createUnaryOp(convOp, destType, operand);
builder.setPrecision(result, precision);
return result;
return builder.setPrecision(result, precision);
}
spv::Id TGlslangToSpvTraverser::makeSmearedConstant(spv::Id constant, int vectorSize)
@ -3277,7 +3265,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
// Construct the call arguments, without modifying the original operands vector.
// We might need the remaining arguments, e.g. in the EOpFrexp case.
std::vector<spv::Id> callArguments(operands.begin(), operands.begin() + consumedOperands);
id = builder.createBuiltinCall(precision, typeId, stdBuiltins, libCall, callArguments);
id = builder.createBuiltinCall(typeId, stdBuiltins, libCall, callArguments);
} else {
switch (consumedOperands) {
case 0:
@ -3320,9 +3308,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
break;
}
builder.setPrecision(id, precision);
return id;
return builder.setPrecision(id, precision);
}
// Intrinsics with no arguments, no return value, and no precision.
@ -3644,7 +3630,7 @@ spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslan
// emit left operand
builder.clearAccessChain();
left.traverse(this);
spv::Id leftId = builder.accessChainLoad(boolTypeId);
spv::Id leftId = builder.accessChainLoad(spv::NoPrecision, boolTypeId);
// Operands to accumulate OpPhi operands
std::vector<spv::Id> phiOperands;
@ -3667,7 +3653,7 @@ spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslan
// emit right operand as the "then" part of the "if"
builder.clearAccessChain();
right.traverse(this);
spv::Id rightId = builder.accessChainLoad(boolTypeId);
spv::Id rightId = builder.accessChainLoad(spv::NoPrecision, boolTypeId);
// accumulate left operand's phi information
phiOperands.push_back(rightId);

View file

@ -192,7 +192,7 @@ Id Builder::makeFloatType(int width)
// See makeStructResultType() for non-decorated structs
// needed as the result of some instructions, which does
// check for duplicates.
Id Builder::makeStructType(std::vector<Id>& members, const char* name)
Id Builder::makeStructType(const std::vector<Id>& members, const char* name)
{
// Don't look for previous one, because in the general case,
// structs can be duplicated except for decorations.
@ -321,7 +321,7 @@ Id Builder::makeRuntimeArray(Id element)
return type->getResultId();
}
Id Builder::makeFunctionType(Id returnType, std::vector<Id>& paramTypes)
Id Builder::makeFunctionType(Id returnType, const std::vector<Id>& paramTypes)
{
// try to find it
Instruction* type;
@ -805,19 +805,28 @@ Function* Builder::makeMain()
Block* entry;
std::vector<Id> params;
std::vector<Decoration> precisions;
mainFunction = makeFunctionEntry(makeVoidType(), "main", params, &entry);
mainFunction = makeFunctionEntry(NoPrecision, makeVoidType(), "main", params, precisions, &entry);
return mainFunction;
}
// Comments in header
Function* Builder::makeFunctionEntry(Id returnType, const char* name, std::vector<Id>& paramTypes, Block **entry)
Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name,
const std::vector<Id>& paramTypes, const std::vector<Decoration>& precisions, Block **entry)
{
// Make the function and initial instructions in it
Id typeId = makeFunctionType(returnType, paramTypes);
Id firstParamId = paramTypes.size() == 0 ? 0 : getUniqueIds((int)paramTypes.size());
Function* function = new Function(getUniqueId(), returnType, typeId, firstParamId, module);
// Set up the precisions
setPrecision(function->getId(), precision);
for (unsigned p = 0; p < (unsigned)precisions.size(); ++p)
setPrecision(firstParamId + p, precisions[p]);
// CFG
if (entry) {
*entry = new Block(getUniqueId(), *function);
function->addBlock(*entry);
@ -1117,10 +1126,10 @@ Id Builder::createFunctionCall(spv::Function* function, std::vector<spv::Id>& ar
}
// Comments in header
Id Builder::createRvalueSwizzle(Id typeId, Id source, std::vector<unsigned>& channels)
Id Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source, std::vector<unsigned>& channels)
{
if (channels.size() == 1)
return createCompositeExtract(source, typeId, channels.front());
return setPrecision(createCompositeExtract(source, typeId, channels.front()), precision);
Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
assert(isVector(source));
@ -1130,7 +1139,7 @@ Id Builder::createRvalueSwizzle(Id typeId, Id source, std::vector<unsigned>& cha
swizzle->addImmediateOperand(channels[i]);
buildPoint->addInstruction(std::unique_ptr<Instruction>(swizzle));
return swizzle->getResultId();
return setPrecision(swizzle->getResultId(), precision);
}
// Comments in header
@ -1178,7 +1187,7 @@ void Builder::promoteScalar(Decoration precision, Id& left, Id& right)
}
// Comments in header
Id Builder::smearScalar(Decoration /*precision*/, Id scalar, Id vectorType)
Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType)
{
assert(getNumComponents(scalar) == 1);
assert(getTypeId(scalar) == getScalarTypeId(vectorType));
@ -1192,11 +1201,11 @@ Id Builder::smearScalar(Decoration /*precision*/, Id scalar, Id vectorType)
smear->addIdOperand(scalar);
buildPoint->addInstruction(std::unique_ptr<Instruction>(smear));
return smear->getResultId();
return setPrecision(smear->getResultId(), precision);
}
// Comments in header
Id Builder::createBuiltinCall(Decoration /*precision*/, Id resultType, Id builtins, int entryPoint, std::vector<Id>& args)
Id Builder::createBuiltinCall(Id resultType, Id builtins, int entryPoint, std::vector<Id>& args)
{
Instruction* inst = new Instruction(getUniqueId(), resultType, OpExtInst);
inst->addIdOperand(builtins);
@ -1205,6 +1214,7 @@ Id Builder::createBuiltinCall(Decoration /*precision*/, Id resultType, Id builti
inst->addIdOperand(args[arg]);
buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
return inst->getResultId();
}
@ -1386,6 +1396,7 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse,
// Decode the return type that was a special structure
createStore(createCompositeExtract(resultId, typeId1, 1), parameters.texelOut);
resultId = createCompositeExtract(resultId, typeId0, 0);
setPrecision(resultId, precision);
} else {
// When a smear is needed, do it, as per what was computed
// above when resultType was changed to a scalar type.
@ -1492,7 +1503,6 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
if (isScalarType(valueType)) {
// scalar
resultId = createBinOp(op, boolType, value1, value2);
setPrecision(resultId, precision);
} else {
// vector
resultId = createBinOp(op, makeVectorType(boolType, numConstituents), value1, value2);
@ -1501,7 +1511,7 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
resultId = createUnaryOp(equal ? OpAll : OpAny, boolType, resultId);
}
return resultId;
return setPrecision(resultId, precision);
}
// Only structs, arrays, and matrices should be left.
@ -1521,7 +1531,7 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
if (constituent == 0)
resultId = subResultId;
else
resultId = createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId);
resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), precision);
}
return resultId;
@ -1543,7 +1553,7 @@ Id Builder::createCompositeConstruct(Id typeId, std::vector<Id>& constituents)
// Vector or scalar constructor
Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId)
{
Id result = 0;
Id result = NoResult;
unsigned int numTargetComponents = getNumTypeComponents(resultTypeId);
unsigned int targetComponent = 0;
@ -1566,7 +1576,7 @@ Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sourc
if (sourceSize > 1) {
std::vector<unsigned> swiz;
swiz.push_back(s);
arg = createRvalueSwizzle(scalarTypeId, arg, swiz);
arg = createRvalueSwizzle(precision, scalarTypeId, arg, swiz);
}
if (numTargetComponents > 1)
@ -1583,9 +1593,7 @@ Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sourc
if (constituents.size() > 0)
result = createCompositeConstruct(resultTypeId, constituents);
setPrecision(result, precision);
return result;
return setPrecision(result, precision);
}
// Comments in header
@ -1666,11 +1674,13 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
std::vector<Id> vectorComponents;
for (int row = 0; row < numRows; ++row)
vectorComponents.push_back(ids[col][row]);
matrixColumns.push_back(createCompositeConstruct(columnTypeId, vectorComponents));
Id column = createCompositeConstruct(columnTypeId, vectorComponents);
setPrecision(column, precision);
matrixColumns.push_back(column);
}
// make the matrix
return createCompositeConstruct(resultTypeId, matrixColumns);
return setPrecision(createCompositeConstruct(resultTypeId, matrixColumns), precision);
}
// Comments in header
@ -1895,7 +1905,7 @@ void Builder::accessChainStore(Id rvalue)
}
// Comments in header
Id Builder::accessChainLoad(Id resultType)
Id Builder::accessChainLoad(Decoration precision, Id resultType)
{
Id id;
@ -1904,7 +1914,7 @@ Id Builder::accessChainLoad(Id resultType)
transferAccessChainSwizzle(false);
if (accessChain.indexChain.size() > 0) {
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;
@ -1933,12 +1943,14 @@ Id Builder::accessChainLoad(Id resultType)
// load through the access chain
id = createLoad(collapseAccessChain());
}
setPrecision(id, precision);
} else
id = accessChain.base;
id = accessChain.base; // no precision, it was set when this was defined
} else {
transferAccessChainSwizzle(true);
// load through the access chain
id = createLoad(collapseAccessChain());
setPrecision(id, precision);
}
// Done, unless there are swizzles to do
@ -1952,12 +1964,12 @@ Id Builder::accessChainLoad(Id resultType)
Id swizzledType = getScalarTypeId(getTypeId(id));
if (accessChain.swizzle.size() > 1)
swizzledType = makeVectorType(swizzledType, (int)accessChain.swizzle.size());
id = createRvalueSwizzle(swizzledType, id, accessChain.swizzle);
id = createRvalueSwizzle(precision, swizzledType, id, accessChain.swizzle);
}
// dynamic single-component selection
if (accessChain.component != NoResult)
id = createVectorExtractDynamic(id, resultType, accessChain.component);
id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision);
return id;
}

View file

@ -100,13 +100,13 @@ public:
Id makeIntType(int width) { return makeIntegerType(width, true); }
Id makeUintType(int width) { return makeIntegerType(width, false); }
Id makeFloatType(int width);
Id makeStructType(std::vector<Id>& members, const char*);
Id makeStructType(const std::vector<Id>& members, const char*);
Id makeStructResultType(Id type0, Id type1);
Id makeVectorType(Id component, int size);
Id makeMatrixType(Id component, int cols, int rows);
Id makeArrayType(Id element, unsigned size, int stride); // 0 means no stride decoration
Id makeRuntimeArray(Id element);
Id makeFunctionType(Id returnType, std::vector<Id>& paramTypes);
Id makeFunctionType(Id returnType, const std::vector<Id>& paramTypes);
Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format);
Id makeSamplerType();
Id makeSampledImageType(Id imageType);
@ -210,7 +210,8 @@ public:
// Make a shader-style function, and create its entry block if entry is non-zero.
// Return the function, pass back the entry.
// The returned pointer is only valid for the lifetime of this builder.
Function* makeFunctionEntry(Id returnType, const char* name, std::vector<Id>& paramTypes, Block **entry = 0);
Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, const std::vector<Id>& paramTypes,
const std::vector<Decoration>& precisions, Block **entry = 0);
// Create a return. An 'implicit' return is one not appearing in the source
// code. In the case of an implicit return, no post-return block is inserted.
@ -225,7 +226,7 @@ public:
// Create a global or function local or IO variable.
Id createVariable(StorageClass, Id type, const char* name = 0);
// Create an imtermediate with an undefined value.
// Create an intermediate with an undefined value.
Id createUndefined(Id type);
// Store into an Id and return the l-value
@ -262,7 +263,7 @@ public:
// Take an rvalue (source) and a set of channels to extract from it to
// make a new rvalue, which is returned.
Id createRvalueSwizzle(Id typeId, Id source, std::vector<unsigned>& channels);
Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, std::vector<unsigned>& channels);
// Take a copy of an lvalue (target) and a source of components, and set the
// source components into the lvalue where the 'channels' say to put them.
@ -270,13 +271,15 @@ public:
// (No true lvalue or stores are used.)
Id createLvalueSwizzle(Id typeId, Id target, Id source, std::vector<unsigned>& channels);
// If the value passed in is an instruction and the precision is not NoPrecision,
// it gets tagged with the requested precision.
void setPrecision(Id /* value */, Decoration precision)
// If both the id and precision are valid, the id
// gets tagged with the requested precision.
// The passed in id is always the returned id, to simplify use patterns.
Id setPrecision(Id id, Decoration precision)
{
if (precision != NoPrecision) {
;// TODO
}
if (precision != NoPrecision && id != NoResult)
addDecoration(id, precision);
return id;
}
// Can smear a scalar to a vector for the following forms:
@ -299,7 +302,7 @@ public:
Id smearScalar(Decoration precision, Id scalarVal, Id vectorType);
// Create a call to a built-in function.
Id createBuiltinCall(Decoration precision, Id resultType, Id builtins, int entryPoint, std::vector<Id>& args);
Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, std::vector<Id>& args);
// List of parameters used to create a texture operation
struct TextureParameters {
@ -330,7 +333,7 @@ public:
Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned);
Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id);
// Reduction comparision for composites: For equal and not-equal resulting in a scalar.
// Reduction comparison for composites: For equal and not-equal resulting in a scalar.
Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */);
// OpCompositeConstruct
@ -498,7 +501,7 @@ public:
void accessChainStore(Id rvalue);
// use accessChain and swizzle to load an r-value
Id accessChainLoad(Id ResultType);
Id accessChainLoad(Decoration precision, Id ResultType);
// get the direct pointer for an l-value
Id accessChainGetLValue();