SPV: RelaxedPrecision: Generalize fix #2293 to cover more operations.

This simplifies and enforces use of precision in many more places,
to help avoid accidental loss of RelaxedPrecision through intermediate
operations. Known fixes are:
- ?:
- function return values with mis-matched precision
- precision of function return values when a copy was needed to fix types
This commit is contained in:
John Kessenich
2020-06-30 01:27:08 -06:00
parent 27e915ed4f
commit 435dd8028b
10 changed files with 835 additions and 670 deletions

View File

@@ -1297,11 +1297,11 @@ Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const
// Set up the precisions
setPrecision(function->getId(), precision);
function->setReturnPrecision(precision);
for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) {
for (int d = 0; d < (int)decorations[p].size(); ++d) {
addDecoration(firstParamId + p, decorations[p][d]);
if (decorations[p][d] == DecorationRelaxedPrecision)
function->addReducedPrecisionParam(p);
function->addParamPrecision(p, decorations[p][d]);
}
}
@@ -1359,7 +1359,7 @@ void Builder::makeDiscard()
}
// Comments in header
Id Builder::createVariable(StorageClass storageClass, Id type, const char* name, Id initializer)
Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name, Id initializer)
{
Id pointerType = makePointer(storageClass, type);
Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable);
@@ -1381,6 +1381,7 @@ Id Builder::createVariable(StorageClass storageClass, Id type, const char* name,
if (name)
addName(inst->getResultId(), name);
setPrecision(inst->getResultId(), precision);
return inst->getResultId();
}
@@ -1437,7 +1438,8 @@ void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAcce
}
// Comments in header
Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
Id Builder::createLoad(Id lValue, spv::Decoration precision, spv::MemoryAccessMask memoryAccess,
spv::Scope scope, unsigned int alignment)
{
Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad);
load->addIdOperand(lValue);
@@ -1455,6 +1457,7 @@ Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope
}
buildPoint->addInstruction(std::unique_ptr<Instruction>(load));
setPrecision(load->getResultId(), precision);
return load->getResultId();
}
@@ -2677,7 +2680,7 @@ void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, sp
// If swizzle still exists, it is out-of-order or not full, we must load the target vector,
// extract and insert elements to perform writeMask and/or swizzle.
if (accessChain.swizzle.size() > 0) {
Id tempBaseId = createLoad(base);
Id tempBaseId = createLoad(base, spv::NoPrecision);
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
}
@@ -2716,17 +2719,17 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
if (constant) {
id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
setPrecision(id, precision);
} else {
Id lValue = NoResult;
if (spvVersion >= Spv_1_4) {
// make a new function variable for this r-value, using an initializer,
// and mark it as NonWritable so that downstream it can be detected as a lookup
// table
lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable",
accessChain.base);
lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base), "indexable", accessChain.base);
addDecoration(lValue, DecorationNonWritable);
} else {
lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base), "indexable");
// store into it
createStore(accessChain.base, lValue);
}
@@ -2735,9 +2738,8 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
accessChain.isRValue = false;
// load through the access chain
id = createLoad(collapseAccessChain());
id = createLoad(collapseAccessChain(), precision);
}
setPrecision(id, precision);
} else
id = accessChain.base; // no precision, it was set when this was defined
} else {
@@ -2756,8 +2758,7 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
// loaded image types get decorated. TODO: This should maybe move to
// createImageTextureFunctionCall.
addDecoration(id, nonUniform);
id = createLoad(id, memoryAccess, scope, alignment);
setPrecision(id, precision);
id = createLoad(id, precision, memoryAccess, scope, alignment);
addDecoration(id, nonUniform);
}