Backward incompatible: Turn on PureOperatorBuiltins: use only enum-based built-in functions in the AST.

If this breaks your AST consumer, best is to modify it to test
against the enum values instead of doing string comparisons on
built-in function names.  This is the reason the change was made.

If you need the old behavior, you should be able to get it back by changing
PureOperatorBuiltins to be false instead of true.  This path will work for
a while, but is marked deprecated.

Also, the old behavior is tagged as release 2.4.
This commit is contained in:
John Kessenich
2015-08-19 13:34:18 -06:00
parent a32d8f620d
commit fc51d284aa
41 changed files with 1092 additions and 967 deletions

View File

@@ -96,8 +96,8 @@ protected:
void visitFunctions(const glslang::TIntermSequence&);
void handleFunctionEntry(const glslang::TIntermAggregate* node);
void translateArguments(const glslang::TIntermSequence& glslangArguments, std::vector<spv::Id>& arguments);
spv::Id handleBuiltInFunctionCall(const glslang::TIntermAggregate*);
spv::Id handleTextureCall(spv::Decoration precision, glslang::TOperator, spv::Id typeId, glslang::TSampler, std::vector<spv::Id>& idArguments);
void translateArguments(glslang::TIntermUnary& node, std::vector<spv::Id>& arguments);
spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node);
spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*);
spv::Id createBinaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id left, spv::Id right, glslang::TBasicType typeProxy, bool reduceComparison = true);
@@ -664,6 +664,20 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node)
{
spv::Id result = spv::NoResult;
// try texturing first
result = createImageTextureFunctionCall(node);
if (result != spv::NoResult) {
builder.clearAccessChain();
builder.setAccessChainRValue(result);
return false; // done with this node
}
// Non-texturing.
// Start by evaluating the operand
builder.clearAccessChain();
node->getOperand()->traverse(this);
spv::Id operand = builder.accessChainLoad(TranslatePrecisionDecoration(node->getOperand()->getType()));
@@ -671,11 +685,13 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
// it could be a conversion
spv::Id result = createConversion(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operand);
if (! result)
result = createConversion(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operand);
// if not, then possibly an operation
if (! result)
result = createUnaryOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operand, node->getBasicType() == glslang::EbtFloat || node->getBasicType() == glslang::EbtDouble);
result = createUnaryOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operand,
node->getBasicType() == glslang::EbtFloat || node->getBasicType() == glslang::EbtDouble);
if (result) {
builder.clearAccessChain();
@@ -728,16 +744,6 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
builder.createNoResultOp(spv::OpEndStreamPrimitive, operand);
return false;
case glslang::EOpAtomicCounterIncrement:
case glslang::EOpAtomicCounterDecrement:
case glslang::EOpAtomicCounter:
{
// Handle all of the atomics in one place, in createAtomicOperation()
std::vector<spv::Id> operands;
operands.push_back(operand);
result = createAtomicOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands);
return false;
}
default:
spv::MissingFunctionality("glslang unary");
break;
@@ -748,7 +754,17 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TIntermAggregate* node)
{
spv::Id result;
spv::Id result = spv::NoResult;
// try texturing
result = createImageTextureFunctionCall(node);
if (result != spv::NoResult) {
builder.clearAccessChain();
builder.setAccessChainRValue(result);
return false;
}
glslang::TOperator binOp = glslang::EOpNull;
bool reduceComparison = true;
bool isMatrix = false;
@@ -830,8 +846,6 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
{
if (node->isUserDefined())
result = handleUserFunctionCall(node);
else
result = handleBuiltInFunctionCall(node);
if (! result) {
spv::MissingFunctionality("glslang function call");
@@ -984,6 +998,21 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
atomic = true;
break;
case glslang::EOpAddCarry:
case glslang::EOpSubBorrow:
case glslang::EOpUMulExtended:
case glslang::EOpIMulExtended:
case glslang::EOpBitfieldExtract:
case glslang::EOpBitfieldInsert:
spv::MissingFunctionality("integer aggregate");
break;
case glslang::EOpFma:
case glslang::EFrexp:
case glslang::ELdexp:
spv::MissingFunctionality("fma/frexp/ldexp aggregate");
break;
default:
break;
}
@@ -1578,123 +1607,123 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermSequence&
}
}
spv::Id TGlslangToSpvTraverser::handleBuiltInFunctionCall(const glslang::TIntermAggregate* node)
void TGlslangToSpvTraverser::translateArguments(glslang::TIntermUnary& node, std::vector<spv::Id>& arguments)
{
std::vector<spv::Id> arguments;
translateArguments(node->getSequence(), arguments);
spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
builder.clearAccessChain();
node.getOperand()->traverse(this);
arguments.push_back(builder.accessChainLoad(TranslatePrecisionDecoration(node.getAsTyped()->getType())));
}
if (node->getName() == "ftransform(") {
spv::MissingFunctionality("ftransform()");
//spv::Id vertex = builder.createVariable(spv::StorageShaderGlobal, spv::VectorType::get(spv::makeFloatType(), 4),
// "gl_Vertex_sim");
//spv::Id matrix = builder.createVariable(spv::StorageShaderGlobal, spv::VectorType::get(spv::makeFloatType(), 4),
// "gl_ModelViewProjectionMatrix_sim");
return 0;
spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermOperator* node)
{
if (node->isImage()) {
spv::MissingFunctionality("GLSL image function");
return spv::NoResult;
} else if (! node->isTexture()) {
return spv::NoResult;
}
if (node->getName().substr(0, 7) == "texture" || node->getName().substr(0, 5) == "texel" || node->getName().substr(0, 6) == "shadow") {
const glslang::TSampler sampler = node->getSequence()[0]->getAsTyped()->getType().getSampler();
spv::Builder::TextureParameters params = { };
params.sampler = arguments[0];
// Process a GLSL texturing op (will be SPV image)
// special case size query
if (node->getName().find("textureSize", 0) != std::string::npos) {
glslang::TCrackedTextureOp cracked;
node->crackTexture(cracked);
const glslang::TSampler sampler = node->getAsAggregate() ? node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType().getSampler()
: node->getAsUnaryNode()->getOperand()->getAsTyped()->getType().getSampler();
std::vector<spv::Id> arguments;
if (node->getAsAggregate())
translateArguments(node->getAsAggregate()->getSequence(), arguments);
else
translateArguments(*node->getAsUnaryNode(), arguments);
spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
spv::Builder::TextureParameters params = { };
params.sampler = arguments[0];
// Check for queries
if (cracked.query) {
switch (node->getOp()) {
case glslang::EOpImageQuerySize:
case glslang::EOpTextureQuerySize:
if (arguments.size() > 1) {
params.lod = arguments[1];
return builder.createTextureQueryCall(spv::OpImageQuerySizeLod, params);
} else
return builder.createTextureQueryCall(spv::OpImageQuerySize, params);
}
// special case the number of samples query
if (node->getName().find("textureSamples", 0) != std::string::npos)
case glslang::EOpImageQuerySamples:
case glslang::EOpTextureQuerySamples:
return builder.createTextureQueryCall(spv::OpImageQuerySamples, params);
// special case the other queries
if (node->getName().find("Query", 0) != std::string::npos) {
if (node->getName().find("Levels", 0) != std::string::npos)
return builder.createTextureQueryCall(spv::OpImageQueryLevels, params);
else if (node->getName().find("Lod", 0) != std::string::npos) {
params.coords = arguments[1];
return builder.createTextureQueryCall(spv::OpImageQueryLod, params);
} else
spv::MissingFunctionality("glslang texture query");
case glslang::EOpTextureQueryLod:
params.coords = arguments[1];
return builder.createTextureQueryCall(spv::OpImageQueryLod, params);
case glslang::EOpTextureQueryLevels:
return builder.createTextureQueryCall(spv::OpImageQueryLevels, params);
default:
assert(0);
break;
}
// This is no longer a query....
bool lod = node->getName().find("Lod", 0) != std::string::npos;
bool proj = node->getName().find("Proj", 0) != std::string::npos;
bool offsets = node->getName().find("Offsets", 0) != std::string::npos;
bool offset = ! offsets && node->getName().find("Offset", 0) != std::string::npos;
bool fetch = node->getName().find("Fetch", 0) != std::string::npos;
bool gather = node->getName().find("Gather", 0) != std::string::npos;
bool grad = node->getName().find("Grad", 0) != std::string::npos;
if (fetch)
spv::MissingFunctionality("texel fetch");
if (gather)
spv::MissingFunctionality("texture gather");
// check for bias argument
bool bias = false;
if (! lod && ! gather && ! grad && ! fetch) {
int nonBiasArgCount = 2;
if (offset)
++nonBiasArgCount;
if (grad)
nonBiasArgCount += 2;
if ((int)arguments.size() > nonBiasArgCount)
bias = true;
}
bool cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow;
// set the rest of the arguments
params.coords = arguments[1];
int extraArgs = 0;
if (cubeCompare)
params.Dref = arguments[2];
else if (sampler.shadow) {
std::vector<spv::Id> indexes;
int comp;
if (proj)
comp = 3;
else
comp = builder.getNumComponents(params.coords) - 1;
indexes.push_back(comp);
params.Dref = builder.createCompositeExtract(params.coords, builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes);
}
if (lod) {
params.lod = arguments[2];
++extraArgs;
}
if (grad) {
params.gradX = arguments[2 + extraArgs];
params.gradY = arguments[3 + extraArgs];
extraArgs += 2;
}
//if (gather && compare) {
// params.compare = arguments[2 + extraArgs];
// ++extraArgs;
//}
if (offset | offsets) {
params.offset = arguments[2 + extraArgs];
++extraArgs;
}
if (bias) {
params.bias = arguments[2 + extraArgs];
++extraArgs;
}
return builder.createTextureCall(precision, convertGlslangToSpvType(node->getType()), proj, params);
}
spv::MissingFunctionality("built-in function call");
// This is no longer a query....
return 0;
if (cracked.fetch)
spv::MissingFunctionality("texel fetch");
if (cracked.gather)
spv::MissingFunctionality("texture gather");
// check for bias argument
bool bias = false;
if (! cracked.lod && ! cracked.gather && ! cracked.grad && ! cracked.fetch) {
int nonBiasArgCount = 2;
if (cracked.offset)
++nonBiasArgCount;
if (cracked.grad)
nonBiasArgCount += 2;
if ((int)arguments.size() > nonBiasArgCount)
bias = true;
}
bool cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow;
// set the rest of the arguments
params.coords = arguments[1];
int extraArgs = 0;
if (cubeCompare)
params.Dref = arguments[2];
else if (sampler.shadow) {
std::vector<spv::Id> indexes;
int comp;
if (cracked.proj)
comp = 3;
else
comp = builder.getNumComponents(params.coords) - 1;
indexes.push_back(comp);
params.Dref = builder.createCompositeExtract(params.coords, builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes);
}
if (cracked.lod) {
params.lod = arguments[2];
++extraArgs;
}
if (cracked.grad) {
params.gradX = arguments[2 + extraArgs];
params.gradY = arguments[3 + extraArgs];
extraArgs += 2;
}
//if (gather && compare) {
// params.compare = arguments[2 + extraArgs];
// ++extraArgs;
//}
if (cracked.offset || cracked.offsets) {
params.offset = arguments[2 + extraArgs];
++extraArgs;
}
if (bias) {
params.bias = arguments[2 + extraArgs];
++extraArgs;
}
return builder.createTextureCall(precision, convertGlslangToSpvType(node->getType()), cracked.proj, params);
}
spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAggregate* node)
@@ -2172,6 +2201,24 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
case glslang::EOpUnpackHalf2x16:
libCall = spv::GLSLstd450UnpackHalf2x16;
break;
case glslang::EOpPackSnorm4x8:
libCall = spv::GLSLstd450PackSnorm4x8;
break;
case glslang::EOpUnpackSnorm4x8:
libCall = spv::GLSLstd450UnpackSnorm4x8;
break;
case glslang::EOpPackUnorm4x8:
libCall = spv::GLSLstd450PackUnorm4x8;
break;
case glslang::EOpUnpackUnorm4x8:
libCall = spv::GLSLstd450UnpackUnorm4x8;
break;
case glslang::EOpPackDouble2x32:
libCall = spv::GLSLstd450PackDouble2x32;
break;
case glslang::EOpUnpackDouble2x32:
libCall = spv::GLSLstd450UnpackDouble2x32;
break;
case glslang::EOpDPdx:
unaryOp = spv::OpDPdx;
@@ -2221,6 +2268,34 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
libCall = spv::GLSLstd450SSign;
break;
case glslang::EOpAtomicCounterIncrement:
case glslang::EOpAtomicCounterDecrement:
case glslang::EOpAtomicCounter:
{
// Handle all of the atomics in one place, in createAtomicOperation()
std::vector<spv::Id> operands;
operands.push_back(operand);
return createAtomicOperation(op, precision, typeId, operands);
}
case glslang::EOpImageLoad:
unaryOp = spv::OpImageRead;
break;
case glslang::EOpBitFieldReverse:
unaryOp = spv::OpBitReverse;
break;
case glslang::EOpBitCount:
unaryOp = spv::OpBitCount;
break;
case glslang::EOpFindLSB:
libCall = spv::GLSLstd450FindILSB;
break;
case glslang::EOpFindMSB:
spv::MissingFunctionality("signed vs. unsigned FindMSB");
libCall = spv::GLSLstd450FindSMSB;
break;
default:
return 0;
}