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

View File

@ -23,12 +23,28 @@ Linked fragment stage:
Name 21 "low"
Name 26 "high"
Name 36 "Color"
Decorate 8(foo() RelaxedPrecision
Decorate 11(face1) RelaxedPrecision
Decorate 13(face2) RelaxedPrecision
Decorate 17(z) RelaxedPrecision
Decorate 21(low) RelaxedPrecision
Decorate 22 RelaxedPrecision
Decorate 23 RelaxedPrecision
Decorate 25 RelaxedPrecision
Decorate 26(high) RelaxedPrecision
Decorate 27 RelaxedPrecision
Decorate 32 RelaxedPrecision
Decorate 33 RelaxedPrecision
Decorate 36(Color) RelaxedPrecision
Decorate 37 RelaxedPrecision
Decorate 38 RelaxedPrecision
Decorate 39 RelaxedPrecision
Decorate 40 RelaxedPrecision
Decorate 41 RelaxedPrecision
Decorate 42 RelaxedPrecision
Decorate 43 RelaxedPrecision
Decorate 44 RelaxedPrecision
Decorate 45 RelaxedPrecision
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32

View File

@ -32,6 +32,10 @@ Linked vertex stage:
MemberDecorate 22(gl_PerVertex) 1 BuiltIn PointSize
Decorate 22(gl_PerVertex) Block
Decorate 27(ps) RelaxedPrecision
Decorate 28 RelaxedPrecision
Decorate 32 RelaxedPrecision
Decorate 39 RelaxedPrecision
Decorate 42 RelaxedPrecision
Decorate 48(gl_InstanceID) BuiltIn InstanceId
2: TypeVoid
3: TypeFunction 2

View File

@ -27,11 +27,17 @@ Linked fragment stage:
Decorate 9(c) RelaxedPrecision
Decorate 9(c) Location 7
Decorate 11(color) RelaxedPrecision
Decorate 12 RelaxedPrecision
MemberDecorate 13(S) 0 RelaxedPrecision
MemberDecorate 13(S) 1 RelaxedPrecision
Decorate 19 RelaxedPrecision
Decorate 20 RelaxedPrecision
Decorate 26(p) RelaxedPrecision
Decorate 26(p) Location 3
Decorate 29(pos) RelaxedPrecision
Decorate 30 RelaxedPrecision
Decorate 33 RelaxedPrecision
Decorate 34 RelaxedPrecision
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32

View File

@ -46,6 +46,8 @@ Linked vertex stage:
Name 247 "v4"
Name 268 "gl_VertexID"
Name 269 "gl_InstanceID"
Decorate 261 RelaxedPrecision
Decorate 265 RelaxedPrecision
Decorate 268(gl_VertexID) BuiltIn VertexId
Decorate 269(gl_InstanceID) BuiltIn InstanceId
2: TypeVoid

View File

@ -7,12 +7,12 @@ Linked fragment stage:
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 114
// Id's are bound by 127
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "main" 23 59 61 73
EntryPoint Fragment 4 "main" 23 59 61 73 116
ExecutionMode 4 OriginLowerLeft
Source ESSL 310
Name 4 "main"
@ -35,15 +35,58 @@ Linked fragment stage:
Name 73 "mediumfout"
Name 104 "ub2"
Name 105 "param"
Name 114 "S"
MemberName 114(S) 0 "a"
MemberName 114(S) 1 "b"
Name 116 "s"
Decorate 12(foo(vf3;) RelaxedPrecision
Decorate 11(mv3) RelaxedPrecision
Decorate 38(sum) RelaxedPrecision
Decorate 40(uniform_medium) RelaxedPrecision
Decorate 41 RelaxedPrecision
Decorate 46 RelaxedPrecision
Decorate 48(uniform_low) RelaxedPrecision
Decorate 49 RelaxedPrecision
Decorate 50 RelaxedPrecision
Decorate 51 RelaxedPrecision
Decorate 53(arg1) RelaxedPrecision
Decorate 55(arg2) RelaxedPrecision
Decorate 57(d) RelaxedPrecision
Decorate 59(lowfin) RelaxedPrecision
Decorate 60 RelaxedPrecision
Decorate 61(mediumfin) RelaxedPrecision
Decorate 62 RelaxedPrecision
Decorate 63 RelaxedPrecision
Decorate 73(mediumfout) RelaxedPrecision
Decorate 74 RelaxedPrecision
Decorate 75 RelaxedPrecision
Decorate 76 RelaxedPrecision
Decorate 77 RelaxedPrecision
Decorate 78 RelaxedPrecision
Decorate 79 RelaxedPrecision
Decorate 83 RelaxedPrecision
Decorate 85 RelaxedPrecision
Decorate 87 RelaxedPrecision
Decorate 88 RelaxedPrecision
Decorate 90 RelaxedPrecision
Decorate 91 RelaxedPrecision
Decorate 94 RelaxedPrecision
Decorate 95 RelaxedPrecision
Decorate 96 RelaxedPrecision
Decorate 97 RelaxedPrecision
Decorate 98 RelaxedPrecision
Decorate 99 RelaxedPrecision
Decorate 100 RelaxedPrecision
Decorate 101 RelaxedPrecision
Decorate 102 RelaxedPrecision
Decorate 110 RelaxedPrecision
Decorate 112 RelaxedPrecision
Decorate 113 RelaxedPrecision
MemberDecorate 114(S) 1 RelaxedPrecision
Decorate 120 RelaxedPrecision
Decorate 124 RelaxedPrecision
Decorate 125 RelaxedPrecision
Decorate 126 RelaxedPrecision
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32
@ -85,6 +128,11 @@ Linked fragment stage:
103: TypePointer UniformConstant 15(bvec2)
104(ub2): 103(ptr) Variable UniformConstant
111: 6(float) Constant 1065353216
114(S): TypeStruct 6(float) 6(float)
115: TypePointer Input 114(S)
116(s): 115(ptr) Variable Input
117: 36(int) Constant 0
122: 36(int) Constant 1
4(main): 2 Function None 3
5: Label
38(sum): 37(ptr) Variable Function
@ -157,6 +205,16 @@ Linked fragment stage:
Store 73(mediumfout) 113
Branch 109
109: Label
118: 58(ptr) AccessChain 116(s) 117
119: 6(float) Load 118
120: 21(fvec4) Load 73(mediumfout)
121: 21(fvec4) VectorTimesScalar 120 119
Store 73(mediumfout) 121
123: 58(ptr) AccessChain 116(s) 122
124: 6(float) Load 123
125: 21(fvec4) Load 73(mediumfout)
126: 21(fvec4) VectorTimesScalar 125 124
Store 73(mediumfout) 126
Return
FunctionEnd
12(foo(vf3;): 9(fvec2) Function None 10

View File

@ -42,15 +42,137 @@ Linked fragment stage:
Name 246 "param"
Name 248 "param"
Name 250 "param"
Decorate 15(foo1(vf4;vf4;i1;) RelaxedPrecision
Decorate 12(v1) RelaxedPrecision
Decorate 13(v2) RelaxedPrecision
Decorate 14(i1) RelaxedPrecision
Decorate 20(foo2(vf4;vf4;i1;) RelaxedPrecision
Decorate 17(v1) RelaxedPrecision
Decorate 18(v2) RelaxedPrecision
Decorate 19(i1) RelaxedPrecision
Decorate 22 RelaxedPrecision
Decorate 27 RelaxedPrecision
Decorate 29 RelaxedPrecision
Decorate 31 RelaxedPrecision
Decorate 32 RelaxedPrecision
Decorate 33 RelaxedPrecision
Decorate 40 RelaxedPrecision
Decorate 46 RelaxedPrecision
Decorate 51 RelaxedPrecision
Decorate 53 RelaxedPrecision
Decorate 54 RelaxedPrecision
Decorate 55 RelaxedPrecision
Decorate 60(local) RelaxedPrecision
Decorate 62(c) RelaxedPrecision
Decorate 63 RelaxedPrecision
Decorate 64 RelaxedPrecision
Decorate 66 RelaxedPrecision
Decorate 67 RelaxedPrecision
Decorate 73(f) RelaxedPrecision
Decorate 75(x) RelaxedPrecision
Decorate 76 RelaxedPrecision
Decorate 77 RelaxedPrecision
Decorate 79 RelaxedPrecision
Decorate 80 RelaxedPrecision
Decorate 82 RelaxedPrecision
Decorate 83 RelaxedPrecision
Decorate 85 RelaxedPrecision
Decorate 90 RelaxedPrecision
Decorate 91 RelaxedPrecision
Decorate 92 RelaxedPrecision
Decorate 93 RelaxedPrecision
Decorate 94 RelaxedPrecision
Decorate 95 RelaxedPrecision
Decorate 96 RelaxedPrecision
Decorate 97 RelaxedPrecision
Decorate 99 RelaxedPrecision
Decorate 100 RelaxedPrecision
Decorate 101 RelaxedPrecision
Decorate 102 RelaxedPrecision
Decorate 104 RelaxedPrecision
Decorate 108 RelaxedPrecision
Decorate 109 RelaxedPrecision
Decorate 110 RelaxedPrecision
Decorate 111 RelaxedPrecision
Decorate 113 RelaxedPrecision
Decorate 114 RelaxedPrecision
Decorate 115 RelaxedPrecision
Decorate 116 RelaxedPrecision
Decorate 119 RelaxedPrecision
Decorate 124 RelaxedPrecision
Decorate 125 RelaxedPrecision
Decorate 126 RelaxedPrecision
Decorate 127 RelaxedPrecision
Decorate 129(d) RelaxedPrecision
Decorate 130 RelaxedPrecision
Decorate 134 RelaxedPrecision
Decorate 135 RelaxedPrecision
Decorate 136 RelaxedPrecision
Decorate 137 RelaxedPrecision
Decorate 138 RelaxedPrecision
Decorate 139 RelaxedPrecision
Decorate 140 RelaxedPrecision
Decorate 142 RelaxedPrecision
Decorate 143 RelaxedPrecision
Decorate 144 RelaxedPrecision
Decorate 145 RelaxedPrecision
Decorate 146 RelaxedPrecision
Decorate 150 RelaxedPrecision
Decorate 151 RelaxedPrecision
Decorate 152 RelaxedPrecision
Decorate 153 RelaxedPrecision
Decorate 155(i) RelaxedPrecision
Decorate 162 RelaxedPrecision
Decorate 166 RelaxedPrecision
Decorate 171 RelaxedPrecision
Decorate 172 RelaxedPrecision
Decorate 173 RelaxedPrecision
Decorate 174 RelaxedPrecision
Decorate 175(j) RelaxedPrecision
Decorate 182 RelaxedPrecision
Decorate 185 RelaxedPrecision
Decorate 186 RelaxedPrecision
Decorate 187 RelaxedPrecision
Decorate 193 RelaxedPrecision
Decorate 194 RelaxedPrecision
Decorate 196 RelaxedPrecision
Decorate 197 RelaxedPrecision
Decorate 198 RelaxedPrecision
Decorate 199 RelaxedPrecision
Decorate 202 RelaxedPrecision
Decorate 203 RelaxedPrecision
Decorate 204 RelaxedPrecision
Decorate 205 RelaxedPrecision
Decorate 207 RelaxedPrecision
Decorate 213 RelaxedPrecision
Decorate 214 RelaxedPrecision
Decorate 215 RelaxedPrecision
Decorate 219 RelaxedPrecision
Decorate 220 RelaxedPrecision
Decorate 221 RelaxedPrecision
Decorate 222 RelaxedPrecision
Decorate 227(color) RelaxedPrecision
Decorate 228 RelaxedPrecision
Decorate 229 RelaxedPrecision
Decorate 230 RelaxedPrecision
Decorate 231 RelaxedPrecision
Decorate 233(v) RelaxedPrecision
Decorate 235 RelaxedPrecision
Decorate 237 RelaxedPrecision
Decorate 239 RelaxedPrecision
Decorate 240 RelaxedPrecision
Decorate 243 RelaxedPrecision
Decorate 244 RelaxedPrecision
Decorate 245 RelaxedPrecision
Decorate 247 RelaxedPrecision
Decorate 249 RelaxedPrecision
Decorate 251 RelaxedPrecision
Decorate 252 RelaxedPrecision
Decorate 254 RelaxedPrecision
Decorate 255 RelaxedPrecision
Decorate 256 RelaxedPrecision
Decorate 257 RelaxedPrecision
Decorate 264 RelaxedPrecision
2: TypeVoid
3: TypeFunction 2
6: TypeFloat 32

View File

@ -41,19 +41,102 @@ Linked fragment stage:
Decorate 12(u) RelaxedPrecision
Decorate 15(t) RelaxedPrecision
Decorate 15(t) Flat
Decorate 19 RelaxedPrecision
Decorate 21 RelaxedPrecision
Decorate 27 RelaxedPrecision
Decorate 28 RelaxedPrecision
Decorate 32 RelaxedPrecision
Decorate 33 RelaxedPrecision
Decorate 38 RelaxedPrecision
Decorate 39 RelaxedPrecision
Decorate 43 RelaxedPrecision
Decorate 44 RelaxedPrecision
Decorate 48 RelaxedPrecision
Decorate 49 RelaxedPrecision
Decorate 53 RelaxedPrecision
Decorate 54 RelaxedPrecision
Decorate 55(shiftedii) RelaxedPrecision
Decorate 57(shiftedui) RelaxedPrecision
Decorate 59(shiftediu) RelaxedPrecision
Decorate 60(shifteduu) RelaxedPrecision
Decorate 61 RelaxedPrecision
Decorate 62 RelaxedPrecision
Decorate 68(c) RelaxedPrecision
Decorate 72(usampler) RelaxedPrecision
Decorate 73 RelaxedPrecision
Decorate 77(tc) RelaxedPrecision
Decorate 78 RelaxedPrecision
Decorate 79 RelaxedPrecision
Decorate 80 RelaxedPrecision
Decorate 81 RelaxedPrecision
Decorate 85 RelaxedPrecision
Decorate 86 RelaxedPrecision
Decorate 88 RelaxedPrecision
Decorate 89 RelaxedPrecision
Decorate 90 RelaxedPrecision
Decorate 91 RelaxedPrecision
Decorate 92 RelaxedPrecision
Decorate 97 RelaxedPrecision
Decorate 98 RelaxedPrecision
Decorate 101 RelaxedPrecision
Decorate 102 RelaxedPrecision
Decorate 105 RelaxedPrecision
Decorate 111(af) RelaxedPrecision
Decorate 112 RelaxedPrecision
Decorate 113 RelaxedPrecision
Decorate 116 RelaxedPrecision
Decorate 118(ai) RelaxedPrecision
Decorate 119 RelaxedPrecision
Decorate 120 RelaxedPrecision
Decorate 121 RelaxedPrecision
Decorate 122 RelaxedPrecision
Decorate 124 RelaxedPrecision
Decorate 125 RelaxedPrecision
Decorate 126 RelaxedPrecision
Decorate 127 RelaxedPrecision
Decorate 128 RelaxedPrecision
Decorate 129 RelaxedPrecision
Decorate 130 RelaxedPrecision
Decorate 131 RelaxedPrecision
Decorate 135 RelaxedPrecision
Decorate 136 RelaxedPrecision
Decorate 140 RelaxedPrecision
Decorate 141 RelaxedPrecision
Decorate 145 RelaxedPrecision
Decorate 146 RelaxedPrecision
Decorate 150 RelaxedPrecision
Decorate 151 RelaxedPrecision
Decorate 152(mask1) RelaxedPrecision
Decorate 154(mask2) RelaxedPrecision
Decorate 156(mask3) RelaxedPrecision
Decorate 157 RelaxedPrecision
Decorate 159 RelaxedPrecision
Decorate 160(mask4) RelaxedPrecision
Decorate 162 RelaxedPrecision
Decorate 163 RelaxedPrecision
Decorate 167 RelaxedPrecision
Decorate 168 RelaxedPrecision
Decorate 169 RelaxedPrecision
Decorate 170 RelaxedPrecision
Decorate 171 RelaxedPrecision
Decorate 175 RelaxedPrecision
Decorate 176 RelaxedPrecision
Decorate 177 RelaxedPrecision
Decorate 178 RelaxedPrecision
Decorate 179 RelaxedPrecision
Decorate 180 RelaxedPrecision
Decorate 184 RelaxedPrecision
Decorate 185 RelaxedPrecision
Decorate 186 RelaxedPrecision
Decorate 187 RelaxedPrecision
Decorate 188 RelaxedPrecision
Decorate 192 RelaxedPrecision
Decorate 193 RelaxedPrecision
Decorate 194 RelaxedPrecision
Decorate 195 RelaxedPrecision
Decorate 196 RelaxedPrecision
Decorate 197 RelaxedPrecision
Decorate 198 RelaxedPrecision
Decorate 200(f) RelaxedPrecision
Decorate 202(v) RelaxedPrecision
Decorate 204(i) RelaxedPrecision

View File

@ -23,6 +23,13 @@ bool boolfun(bvec2 bv2)
return bv2 == bvec2(false, true);
}
struct S {
highp float a;
lowp float b;
};
in S s;
void main()
{
lowp int sum = uniform_medium + uniform_high;
@ -47,4 +54,7 @@ void main()
if (boolfun(ub2))
++mediumfout;
mediumfout *= s.a;
mediumfout *= s.b;
}