Front-end "pure" built-in TOperator: Finish adding full support, but still turned off.
This is to avoid all need to do text comparison of built-in function names when consuming the AST. All built-in functions get enumerants. Will want to turn on soon. See PureOperatorBuiltins. See issue #8.
This commit is contained in:
parent
e88217b7d8
commit
ef676b0a59
8 changed files with 248 additions and 36 deletions
|
|
@ -59,7 +59,7 @@ void main()
|
||||||
v = textureLod(s2DArray, c3D, 1.2);
|
v = textureLod(s2DArray, c3D, 1.2);
|
||||||
f = textureOffset(s2DShadow, c3D, ic2D, c1D); // ERROR, offset argument not constant
|
f = textureOffset(s2DShadow, c3D, ic2D, c1D); // ERROR, offset argument not constant
|
||||||
v = texelFetch(s3D, ic3D, ic1D);
|
v = texelFetch(s3D, ic3D, ic1D);
|
||||||
v = texelFetchOffset(arrayedSampler[2], ic2D, 4, ic2D);
|
v = texelFetchOffset(arrayedSampler[2], ic2D, 4, ic2D); // ERROR, offset argument not constant
|
||||||
f = textureLodOffset(s2DShadow, c3D, c1D, ic2D);
|
f = textureLodOffset(s2DShadow, c3D, c1D, ic2D);
|
||||||
v = textureProjLodOffset(s2D, c3D, c1D, ic2D);
|
v = textureProjLodOffset(s2D, c3D, c1D, ic2D);
|
||||||
v = textureGrad(sCube, c3D, c3D, c3D);
|
v = textureGrad(sCube, c3D, c3D, c3D);
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,9 @@ Shader version: 430
|
||||||
0:43 'ic2D' (flat in 2-component vector of int)
|
0:43 'ic2D' (flat in 2-component vector of int)
|
||||||
0:43 Constant:
|
0:43 Constant:
|
||||||
0:43 4 (const int)
|
0:43 4 (const int)
|
||||||
0:43 'ic2D' (flat in 2-component vector of int)
|
0:43 Constant:
|
||||||
|
0:43 3 (const int)
|
||||||
|
0:43 3 (const int)
|
||||||
0:44 add second child into first child (temp float)
|
0:44 add second child into first child (temp float)
|
||||||
0:44 direct index (temp float)
|
0:44 direct index (temp float)
|
||||||
0:44 'v' (temp 4-component vector of float)
|
0:44 'v' (temp 4-component vector of float)
|
||||||
|
|
@ -301,7 +303,9 @@ Shader version: 430
|
||||||
0:43 'ic2D' (flat in 2-component vector of int)
|
0:43 'ic2D' (flat in 2-component vector of int)
|
||||||
0:43 Constant:
|
0:43 Constant:
|
||||||
0:43 4 (const int)
|
0:43 4 (const int)
|
||||||
0:43 'ic2D' (flat in 2-component vector of int)
|
0:43 Constant:
|
||||||
|
0:43 3 (const int)
|
||||||
|
0:43 3 (const int)
|
||||||
0:44 add second child into first child (temp float)
|
0:44 add second child into first child (temp float)
|
||||||
0:44 direct index (temp float)
|
0:44 direct index (temp float)
|
||||||
0:44 'v' (temp 4-component vector of float)
|
0:44 'v' (temp 4-component vector of float)
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ void main()
|
||||||
v += textureLod(s2DArray, c3D, 1.2);
|
v += textureLod(s2DArray, c3D, 1.2);
|
||||||
v.y += textureOffset(s2DShadow, c3D, ivec2(3), c1D);
|
v.y += textureOffset(s2DShadow, c3D, ivec2(3), c1D);
|
||||||
v += texelFetch(s3D, ic3D, ic1D);
|
v += texelFetch(s3D, ic3D, ic1D);
|
||||||
v += texelFetchOffset(s2D, ic2D, 4, ic2D);
|
v += texelFetchOffset(s2D, ic2D, 4, ivec2(3));
|
||||||
v.y += textureLodOffset(s2DShadow, c3D, c1D, ivec2(3));
|
v.y += textureLodOffset(s2DShadow, c3D, c1D, ivec2(3));
|
||||||
v += textureProjLodOffset(s2D, c3D, c1D, ivec2(3));
|
v += textureProjLodOffset(s2D, c3D, c1D, ivec2(3));
|
||||||
v += textureGrad(sCube, c3D, c3D, c3D);
|
v += textureGrad(sCube, c3D, c3D, c3D);
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ void main()
|
||||||
v += textureLod(s2DArray, c3D, 1.2);
|
v += textureLod(s2DArray, c3D, 1.2);
|
||||||
v.y += textureOffset(s2DShadow, c3D, ivec2(3), c1D);
|
v.y += textureOffset(s2DShadow, c3D, ivec2(3), c1D);
|
||||||
v += texelFetch(s3D, ic3D, ic1D);
|
v += texelFetch(s3D, ic3D, ic1D);
|
||||||
v += texelFetchOffset(s2D, ic2D, 4, ic2D);
|
v += texelFetchOffset(s2D, ic2D, 4, ivec2(3));
|
||||||
v.y += textureLodOffset(s2DShadow, c3D, c1D, ivec2(3));
|
v.y += textureLodOffset(s2DShadow, c3D, c1D, ivec2(3));
|
||||||
v += textureProjLodOffset(s2D, c3D, c1D, ivec2(3));
|
v += textureProjLodOffset(s2D, c3D, c1D, ivec2(3));
|
||||||
v += textureGrad(sCube, c3D, c3D, c3D);
|
v += textureGrad(sCube, c3D, c3D, c3D);
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,5 @@
|
||||||
// For the version, it uses the latest git tag followed by the number of commits.
|
// For the version, it uses the latest git tag followed by the number of commits.
|
||||||
// For the date, it uses the current date (when then script is run).
|
// For the date, it uses the current date (when then script is run).
|
||||||
|
|
||||||
#define GLSLANG_REVISION "2.3.723"
|
#define GLSLANG_REVISION "2.3.725"
|
||||||
#define GLSLANG_DATE "18-Aug-2015"
|
#define GLSLANG_DATE "18-Aug-2015"
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ bool ARBCompatibility = true;
|
||||||
const bool ForwardCompatibility = false;
|
const bool ForwardCompatibility = false;
|
||||||
|
|
||||||
// change this back to false if depending on textual spellings of texturing calls when consuming the AST
|
// change this back to false if depending on textual spellings of texturing calls when consuming the AST
|
||||||
const bool PureOperatorBuiltins = false;
|
bool PureOperatorBuiltins = false;
|
||||||
|
|
||||||
inline bool IncludeLegacy(int version, EProfile profile)
|
inline bool IncludeLegacy(int version, EProfile profile)
|
||||||
{
|
{
|
||||||
|
|
@ -3097,7 +3097,7 @@ void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymb
|
||||||
|
|
||||||
//
|
//
|
||||||
// Next, identify which built-ins have a mapping to an operator.
|
// Next, identify which built-ins have a mapping to an operator.
|
||||||
// Those that are not identified as such are
|
// If PureOperatorBuiltins is false, those that are not identified as such are
|
||||||
// expected to be resolved through a library of functions, versus as
|
// expected to be resolved through a library of functions, versus as
|
||||||
// operations.
|
// operations.
|
||||||
//
|
//
|
||||||
|
|
@ -3267,26 +3267,55 @@ void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymb
|
||||||
symbolTable.relateToOperator("textureGatherOffset", EOpTextureGatherOffset);
|
symbolTable.relateToOperator("textureGatherOffset", EOpTextureGatherOffset);
|
||||||
symbolTable.relateToOperator("textureGatherOffsets", EOpTextureGatherOffsets);
|
symbolTable.relateToOperator("textureGatherOffsets", EOpTextureGatherOffsets);
|
||||||
|
|
||||||
if (IncludeLegacy(version, profile)) {
|
if (IncludeLegacy(version, profile) || (profile == EEsProfile && version == 100)) {
|
||||||
// TBD: add ftransform(), any others?
|
symbolTable.relateToOperator("ftransform", EOpFtransform);
|
||||||
|
|
||||||
symbolTable.relateToOperator("texture1D", EOpTexture);
|
symbolTable.relateToOperator("texture1D", EOpTexture);
|
||||||
|
symbolTable.relateToOperator("texture1DGradARB", EOpTextureGrad);
|
||||||
symbolTable.relateToOperator("texture1DProj", EOpTextureProj);
|
symbolTable.relateToOperator("texture1DProj", EOpTextureProj);
|
||||||
|
symbolTable.relateToOperator("texture1DProjGradARB", EOpTextureProjGrad);
|
||||||
symbolTable.relateToOperator("texture1DLod", EOpTextureLod);
|
symbolTable.relateToOperator("texture1DLod", EOpTextureLod);
|
||||||
symbolTable.relateToOperator("texture1DProjLod", EOpTextureProjLod);
|
symbolTable.relateToOperator("texture1DProjLod", EOpTextureProjLod);
|
||||||
|
|
||||||
|
symbolTable.relateToOperator("texture2DRect", EOpTexture);
|
||||||
|
symbolTable.relateToOperator("texture2DRectProj", EOpTextureProj);
|
||||||
|
symbolTable.relateToOperator("texture2DRectGradARB", EOpTextureGrad);
|
||||||
|
symbolTable.relateToOperator("texture2DRectProjGradARB", EOpTextureProjGrad);
|
||||||
|
symbolTable.relateToOperator("shadow2DRect", EOpTexture);
|
||||||
|
symbolTable.relateToOperator("shadow2DRectProj", EOpTextureProj);
|
||||||
|
symbolTable.relateToOperator("shadow2DRectGradARB", EOpTextureGrad);
|
||||||
|
symbolTable.relateToOperator("shadow2DRectProjGradARB", EOpTextureProjGrad);
|
||||||
|
|
||||||
symbolTable.relateToOperator("texture2D", EOpTexture);
|
symbolTable.relateToOperator("texture2D", EOpTexture);
|
||||||
symbolTable.relateToOperator("texture2DProj", EOpTextureProj);
|
symbolTable.relateToOperator("texture2DProj", EOpTextureProj);
|
||||||
|
symbolTable.relateToOperator("texture2DGradEXT", EOpTextureGrad);
|
||||||
|
symbolTable.relateToOperator("texture2DGradARB", EOpTextureGrad);
|
||||||
|
symbolTable.relateToOperator("texture2DProjGradEXT", EOpTextureProjGrad);
|
||||||
|
symbolTable.relateToOperator("texture2DProjGradARB", EOpTextureProjGrad);
|
||||||
symbolTable.relateToOperator("texture2DLod", EOpTextureLod);
|
symbolTable.relateToOperator("texture2DLod", EOpTextureLod);
|
||||||
|
symbolTable.relateToOperator("texture2DLodEXT", EOpTextureLod);
|
||||||
symbolTable.relateToOperator("texture2DProjLod", EOpTextureProjLod);
|
symbolTable.relateToOperator("texture2DProjLod", EOpTextureProjLod);
|
||||||
|
symbolTable.relateToOperator("texture2DProjLodEXT", EOpTextureProjLod);
|
||||||
|
|
||||||
symbolTable.relateToOperator("texture3D", EOpTexture);
|
symbolTable.relateToOperator("texture3D", EOpTexture);
|
||||||
|
symbolTable.relateToOperator("texture3DGradARB", EOpTextureGrad);
|
||||||
symbolTable.relateToOperator("texture3DProj", EOpTextureProj);
|
symbolTable.relateToOperator("texture3DProj", EOpTextureProj);
|
||||||
|
symbolTable.relateToOperator("texture3DProjGradARB", EOpTextureProjGrad);
|
||||||
symbolTable.relateToOperator("texture3DLod", EOpTextureLod);
|
symbolTable.relateToOperator("texture3DLod", EOpTextureLod);
|
||||||
symbolTable.relateToOperator("texture3DProjLod", EOpTextureProjLod);
|
symbolTable.relateToOperator("texture3DProjLod", EOpTextureProjLod);
|
||||||
symbolTable.relateToOperator("textureCube", EOpTexture);
|
symbolTable.relateToOperator("textureCube", EOpTexture);
|
||||||
|
symbolTable.relateToOperator("textureCubeGradEXT", EOpTextureGrad);
|
||||||
|
symbolTable.relateToOperator("textureCubeGradARB", EOpTextureGrad);
|
||||||
symbolTable.relateToOperator("textureCubeLod", EOpTextureLod);
|
symbolTable.relateToOperator("textureCubeLod", EOpTextureLod);
|
||||||
|
symbolTable.relateToOperator("textureCubeLodEXT", EOpTextureLod);
|
||||||
symbolTable.relateToOperator("shadow1D", EOpTexture);
|
symbolTable.relateToOperator("shadow1D", EOpTexture);
|
||||||
|
symbolTable.relateToOperator("shadow1DGradARB", EOpTextureGrad);
|
||||||
symbolTable.relateToOperator("shadow2D", EOpTexture);
|
symbolTable.relateToOperator("shadow2D", EOpTexture);
|
||||||
|
symbolTable.relateToOperator("shadow2DGradARB", EOpTextureGrad);
|
||||||
symbolTable.relateToOperator("shadow1DProj", EOpTextureProj);
|
symbolTable.relateToOperator("shadow1DProj", EOpTextureProj);
|
||||||
symbolTable.relateToOperator("shadow2DProj", EOpTextureProj);
|
symbolTable.relateToOperator("shadow2DProj", EOpTextureProj);
|
||||||
|
symbolTable.relateToOperator("shadow1DProjGradARB", EOpTextureProjGrad);
|
||||||
|
symbolTable.relateToOperator("shadow2DProjGradARB", EOpTextureProjGrad);
|
||||||
symbolTable.relateToOperator("shadow1DLod", EOpTextureLod);
|
symbolTable.relateToOperator("shadow1DLod", EOpTextureLod);
|
||||||
symbolTable.relateToOperator("shadow2DLod", EOpTextureLod);
|
symbolTable.relateToOperator("shadow2DLod", EOpTextureLod);
|
||||||
symbolTable.relateToOperator("shadow1DProjLod", EOpTextureProjLod);
|
symbolTable.relateToOperator("shadow1DProjLod", EOpTextureProjLod);
|
||||||
|
|
|
||||||
|
|
@ -1109,9 +1109,12 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
|
||||||
error(arguments->getLoc(), " wrong operand type", "Internal Error",
|
error(arguments->getLoc(), " wrong operand type", "Internal Error",
|
||||||
"built in unary operator function. Type: %s",
|
"built in unary operator function. Type: %s",
|
||||||
static_cast<TIntermTyped*>(arguments)->getCompleteString().c_str());
|
static_cast<TIntermTyped*>(arguments)->getCompleteString().c_str());
|
||||||
|
} else if (result->getAsOperator()) {
|
||||||
|
builtInOpCheck(loc, *fnCandidate, *result->getAsOperator());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This is a function call not mapped to built-in operator, but it could still be a built-in function
|
// This is a function call not mapped to built-in operator.
|
||||||
|
// It could still be a built-in function, but only if PureOperatorBuiltins == false.
|
||||||
result = intermediate.setAggregateOperator(arguments, EOpFunctionCall, fnCandidate->getType(), loc);
|
result = intermediate.setAggregateOperator(arguments, EOpFunctionCall, fnCandidate->getType(), loc);
|
||||||
TIntermAggregate* call = result->getAsAggregate();
|
TIntermAggregate* call = result->getAsAggregate();
|
||||||
call->setName(fnCandidate->getMangledName());
|
call->setName(fnCandidate->getMangledName());
|
||||||
|
|
@ -1324,6 +1327,173 @@ TIntermTyped* TParseContext::addOutputArgumentConversions(const TFunction& funct
|
||||||
return conversionTree;
|
return conversionTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Do additional checking of built-in function calls that is not caught
|
||||||
|
// by normal semantic checks on argument type, extension tagging, etc.
|
||||||
|
//
|
||||||
|
// Assumes there has been a semantically correct match to a built-in function prototype.
|
||||||
|
//
|
||||||
|
void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermOperator& callNode)
|
||||||
|
{
|
||||||
|
// Set up convenience accessors to the argument(s). There is almost always
|
||||||
|
// multiple arguments for the cases below, but when there might be one,
|
||||||
|
// check the unaryArg first.
|
||||||
|
const TIntermSequence* argp = nullptr; // confusing to use [] syntax on a pointer, so this is to help get a reference
|
||||||
|
const TIntermTyped* unaryArg = nullptr;
|
||||||
|
const TIntermTyped* arg0 = nullptr;
|
||||||
|
if (callNode.getAsAggregate()) {
|
||||||
|
argp = &callNode.getAsAggregate()->getSequence();
|
||||||
|
if (argp->size() > 0)
|
||||||
|
arg0 = (*argp)[0]->getAsTyped();
|
||||||
|
} else {
|
||||||
|
assert(callNode.getAsUnaryNode());
|
||||||
|
unaryArg = callNode.getAsUnaryNode()->getOperand();
|
||||||
|
arg0 = unaryArg;
|
||||||
|
}
|
||||||
|
const TIntermSequence& aggArgs = *argp; // only valid when unaryArg is nullptr
|
||||||
|
|
||||||
|
// built-in texturing functions get their return value precision from the precision of the sampler
|
||||||
|
if (fnCandidate.getType().getQualifier().precision == EpqNone &&
|
||||||
|
fnCandidate.getParamCount() > 0 && fnCandidate[0].type->getBasicType() == EbtSampler)
|
||||||
|
callNode.getQualifier().precision = arg0->getQualifier().precision;
|
||||||
|
|
||||||
|
switch (callNode.getOp()) {
|
||||||
|
case EOpTextureGather:
|
||||||
|
case EOpTextureGatherOffset:
|
||||||
|
case EOpTextureGatherOffsets:
|
||||||
|
{
|
||||||
|
// Figure out which variants are allowed by what extensions,
|
||||||
|
// and what arguments must be constant for which situations.
|
||||||
|
|
||||||
|
TString featureString = fnCandidate.getName() + "(...)";
|
||||||
|
const char* feature = featureString.c_str();
|
||||||
|
profileRequires(loc, EEsProfile, 310, nullptr, feature);
|
||||||
|
int compArg = -1; // track which argument, if any, is the constant component argument
|
||||||
|
switch (callNode.getOp()) {
|
||||||
|
case EOpTextureGather:
|
||||||
|
// More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5,
|
||||||
|
// otherwise, need GL_ARB_texture_gather.
|
||||||
|
if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || fnCandidate[0].type->getSampler().shadow) {
|
||||||
|
profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
|
||||||
|
if (! fnCandidate[0].type->getSampler().shadow)
|
||||||
|
compArg = 2;
|
||||||
|
} else
|
||||||
|
profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature);
|
||||||
|
break;
|
||||||
|
case EOpTextureGatherOffset:
|
||||||
|
// GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument
|
||||||
|
if (fnCandidate[0].type->getSampler().dim == Esd2D && ! fnCandidate[0].type->getSampler().shadow && fnCandidate.getParamCount() == 3)
|
||||||
|
profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature);
|
||||||
|
else
|
||||||
|
profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
|
||||||
|
if (! aggArgs[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion())
|
||||||
|
profileRequires(loc, EEsProfile, 0, Num_AEP_gpu_shader5, AEP_gpu_shader5, "non-constant offset argument");
|
||||||
|
if (! fnCandidate[0].type->getSampler().shadow)
|
||||||
|
compArg = 3;
|
||||||
|
break;
|
||||||
|
case EOpTextureGatherOffsets:
|
||||||
|
profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature);
|
||||||
|
if (! fnCandidate[0].type->getSampler().shadow)
|
||||||
|
compArg = 3;
|
||||||
|
// check for constant offsets
|
||||||
|
if (! aggArgs[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion())
|
||||||
|
error(loc, "must be a compile-time constant:", feature, "offsets argument");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compArg > 0 && compArg < fnCandidate.getParamCount()) {
|
||||||
|
if (aggArgs[compArg]->getAsConstantUnion()) {
|
||||||
|
int value = aggArgs[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst();
|
||||||
|
if (value < 0 || value > 3)
|
||||||
|
error(loc, "must be 0, 1, 2, or 3:", feature, "component argument");
|
||||||
|
} else
|
||||||
|
error(loc, "must be a compile-time constant:", feature, "component argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case EOpTextureOffset:
|
||||||
|
case EOpTextureFetchOffset:
|
||||||
|
case EOpTextureProjOffset:
|
||||||
|
case EOpTextureLodOffset:
|
||||||
|
case EOpTextureProjLodOffset:
|
||||||
|
case EOpTextureGradOffset:
|
||||||
|
case EOpTextureProjGradOffset:
|
||||||
|
{
|
||||||
|
// Handle texture-offset limits checking
|
||||||
|
// Pick which argument has to hold constant offsets
|
||||||
|
int arg = -1;
|
||||||
|
switch (callNode.getOp()) {
|
||||||
|
case EOpTextureOffset: arg = 2; break;
|
||||||
|
case EOpTextureFetchOffset: arg = 3; break;
|
||||||
|
case EOpTextureProjOffset: arg = 2; break;
|
||||||
|
case EOpTextureLodOffset: arg = 3; break;
|
||||||
|
case EOpTextureProjLodOffset: arg = 3; break;
|
||||||
|
case EOpTextureGradOffset: arg = 4; break;
|
||||||
|
case EOpTextureProjGradOffset: arg = 4; break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg > 0) {
|
||||||
|
if (! aggArgs[arg]->getAsConstantUnion())
|
||||||
|
error(loc, "argument must be compile-time constant", "texel offset", "");
|
||||||
|
else {
|
||||||
|
const TType& type = aggArgs[arg]->getAsTyped()->getType();
|
||||||
|
for (int c = 0; c < type.getVectorSize(); ++c) {
|
||||||
|
int offset = aggArgs[arg]->getAsConstantUnion()->getConstArray()[c].getIConst();
|
||||||
|
if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset)
|
||||||
|
error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case EOpTextureQuerySamples:
|
||||||
|
case EOpImageQuerySamples:
|
||||||
|
// GL_ARB_shader_texture_image_samples
|
||||||
|
profileRequires(loc, ~EEsProfile, 450, E_GL_ARB_shader_texture_image_samples, "textureSamples and imageSamples");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EOpImageAtomicAdd:
|
||||||
|
case EOpImageAtomicMin:
|
||||||
|
case EOpImageAtomicMax:
|
||||||
|
case EOpImageAtomicAnd:
|
||||||
|
case EOpImageAtomicOr:
|
||||||
|
case EOpImageAtomicXor:
|
||||||
|
case EOpImageAtomicExchange:
|
||||||
|
case EOpImageAtomicCompSwap:
|
||||||
|
{
|
||||||
|
// Make sure the image types have the correct layout() format and correct argument types
|
||||||
|
const TType& imageType = arg0->getType();
|
||||||
|
if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) {
|
||||||
|
if (imageType.getQualifier().layoutFormat != ElfR32i && imageType.getQualifier().layoutFormat != ElfR32ui)
|
||||||
|
error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), "");
|
||||||
|
} else {
|
||||||
|
if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0)
|
||||||
|
error(loc, "only supported on integer images", fnCandidate.getName().c_str(), "");
|
||||||
|
else if (imageType.getQualifier().layoutFormat != ElfR32f && profile == EEsProfile)
|
||||||
|
error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern bool PureOperatorBuiltins;
|
||||||
|
|
||||||
|
// Deprecated! Use PureOperatorBuiltins == true instead, in which case this
|
||||||
|
// functionality is handled in builtInOpCheck() instead of here.
|
||||||
//
|
//
|
||||||
// Do additional checking of built-in function calls that were not mapped
|
// Do additional checking of built-in function calls that were not mapped
|
||||||
// to built-in operations (e.g., texturing functions).
|
// to built-in operations (e.g., texturing functions).
|
||||||
|
|
@ -1332,10 +1502,18 @@ TIntermTyped* TParseContext::addOutputArgumentConversions(const TFunction& funct
|
||||||
//
|
//
|
||||||
void TParseContext::nonOpBuiltInCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermAggregate& callNode)
|
void TParseContext::nonOpBuiltInCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermAggregate& callNode)
|
||||||
{
|
{
|
||||||
|
// Further maintainance of this function is deprecated, because the "correct"
|
||||||
|
// future-oriented design is to not have to do string compares on function names.
|
||||||
|
|
||||||
|
// If PureOperatorBuiltins == true, then all built-ins should be mapped
|
||||||
|
// to a TOperator, and this function would then never get called.
|
||||||
|
|
||||||
|
assert(PureOperatorBuiltins == false);
|
||||||
|
|
||||||
// built-in texturing functions get their return value precision from the precision of the sampler
|
// built-in texturing functions get their return value precision from the precision of the sampler
|
||||||
if (fnCandidate.getType().getQualifier().precision == EpqNone &&
|
if (fnCandidate.getType().getQualifier().precision == EpqNone &&
|
||||||
fnCandidate.getParamCount() > 0 && fnCandidate[0].type->getBasicType() == EbtSampler)
|
fnCandidate.getParamCount() > 0 && fnCandidate[0].type->getBasicType() == EbtSampler)
|
||||||
callNode.getQualifier().precision = callNode.getAsAggregate()->getSequence()[0]->getAsTyped()->getQualifier().precision;
|
callNode.getQualifier().precision = callNode.getSequence()[0]->getAsTyped()->getQualifier().precision;
|
||||||
|
|
||||||
if (fnCandidate.getName().compare(0, 7, "texture") == 0) {
|
if (fnCandidate.getName().compare(0, 7, "texture") == 0) {
|
||||||
if (fnCandidate.getName().compare(0, 13, "textureGather") == 0) {
|
if (fnCandidate.getName().compare(0, 13, "textureGather") == 0) {
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,7 @@ public:
|
||||||
TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
|
TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
|
||||||
void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
|
void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
|
||||||
TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
|
TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
|
||||||
|
void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
|
||||||
void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&);
|
void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&);
|
||||||
TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&);
|
TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue