Front-end: Warn for likely missed change in default precisions.

This is part of the change to have desktop shaders respect precision
qualifiers on Vulkan, but since the defaults are all highp, and that's
different from ES fragment shaders, detect likely cases and warn about
them (but being careful to not be too noisy if it's unlikely to be a
problem).
This commit is contained in:
John Kessenich 2016-08-03 17:35:19 -06:00
parent 54571c2519
commit 32c169dbdf
10 changed files with 682 additions and 610 deletions

View File

@ -1,5 +1,7 @@
spv.aggOps.frag
Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
WARNING: 0:4: '' : all default precisions are highp; use precision statements to quiet warning, e.g.:
"precision mediump int; precision highp float;"
Linked fragment stage:

View File

@ -1,4 +1,7 @@
spv.structAssignment.frag
WARNING: 0:6: '' : all default precisions are highp; use precision statements to quiet warning, e.g.:
"precision mediump int; precision highp float;"
Linked fragment stage:
@ -33,6 +36,10 @@ Linked fragment stage:
Name 40 "samp2D"
Name 44 "coord"
Name 49 "foo"
MemberDecorate 8(lunarStruct1) 0 RelaxedPrecision
MemberDecorate 9(lunarStruct2) 0 RelaxedPrecision
MemberDecorate 10(lunarStruct3) 1 RelaxedPrecision
Decorate 16 RelaxedPrecision
Decorate 40(samp2D) DescriptorSet 0
Decorate 44(coord) RelaxedPrecision
Decorate 45 RelaxedPrecision

View File

@ -33,6 +33,8 @@ ERROR: 0:67: 'uniform' : no qualifiers allowed for function return
ERROR: 0:69: 'non-opaque uniforms outside a block' : not allowed when using GLSL for Vulkan
ERROR: 0:73: 'texture' : no matching overloaded function found
ERROR: 0:74: 'imageStore' : no matching overloaded function found
WARNING: 0:82: '' : all default precisions are highp; use precision statements to quiet warning, e.g.:
"precision mediump int; precision highp float;"
ERROR: 0:91: 'call argument' : sampler constructor must appear at point of use
ERROR: 0:92: 'call argument' : sampler constructor must appear at point of use
ERROR: 0:93: ',' : sampler constructor must appear at point of use

View File

@ -1,4 +1,5 @@
#version 450
precision mediump int; precision highp float;
layout(location=1) in highp vec4 v;
void main (void)
{

View File

@ -1,5 +1,7 @@
#version 140
precision mediump int;
uniform sampler2D samp2D;
in mediump vec2 coord;

View File

@ -2,5 +2,5 @@
// 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).
#define GLSLANG_REVISION "SPIRV99.1384"
#define GLSLANG_DATE "03-Aug-2016"
#define GLSLANG_REVISION "Overload400-PrecQual.1430"
#define GLSLANG_DATE "23-Aug-2016"

View File

@ -62,7 +62,12 @@ TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, b
linkage = new TIntermAggregate;
// decide whether precision qualifiers should be ignored or respected
obeyPrecisionQualifiers_ = profile == EEsProfile || spvVersion.vulkan > 0;
if (profile == EEsProfile || spvVersion.vulkan > 0) {
precisionManager.respectPrecisionQualifiers();
if (! parsingBuiltins && language == EShLangFragment && profile != EEsProfile && spvVersion.vulkan > 0)
precisionManager.warnAboutDefaults();
}
setPrecisionDefaults();
globalUniformDefaults.clear();
@ -1899,6 +1904,24 @@ TFunction* TParseContext::handleConstructorCall(const TSourceLoc& loc, const TPu
return new TFunction(&empty, type, op);
}
// Handle seeing a precision qualifier in the grammar.
void TParseContext::handlePrecisionQualifier(const TSourceLoc& loc, TQualifier& qualifier, TPrecisionQualifier precision)
{
if (obeyPrecisionQualifiers())
qualifier.precision = precision;
}
// Check for messages to give on seeing a precision qualifier used in a
// declaration in the grammar.
void TParseContext::checkPrecisionQualifier(const TSourceLoc& loc, TPrecisionQualifier)
{
if (precisionManager.shouldWarnAboutDefaults()) {
warn(loc, "all default precisions are highp; use precision statements to quiet warning, e.g.:\n"
" \"precision mediump int; precision highp float;\"", "", "");
precisionManager.defaultWarningGiven();
}
}
//
// Same error message for all places assignments don't work.
//
@ -2904,8 +2927,11 @@ void TParseContext::setDefaultPrecision(const TSourceLoc& loc, TPublicType& publ
if (basicType == EbtInt || basicType == EbtFloat) {
if (publicType.isScalar()) {
defaultPrecision[basicType] = qualifier;
if (basicType == EbtInt)
if (basicType == EbtInt) {
defaultPrecision[EbtUint] = qualifier;
precisionManager.explicitIntDefaultSeen();
} else
precisionManager.explicitFloatDefaultSeen();
return; // all is well
}

View File

@ -144,6 +144,40 @@ protected:
std::function<void(int, const char*)> errorCallback;
};
//
// Manage the state for when to respect precision qualifiers and when to warn about
// the defaults being different than might be expected.
//
class TPrecisionManager {
public:
TPrecisionManager() : obey(false), warn(false), explicitIntDefault(false), explicitFloatDefault(false){ }
virtual ~TPrecisionManager() {}
void respectPrecisionQualifiers() { obey = true; }
bool respectingPrecisionQualifiers() const { return obey; }
bool shouldWarnAboutDefaults() const { return warn; }
void defaultWarningGiven() { warn = false; }
void warnAboutDefaults() { warn = true; }
void explicitIntDefaultSeen()
{
explicitIntDefault = true;
if (explicitFloatDefault)
warn = false;
}
void explicitFloatDefaultSeen()
{
explicitFloatDefault = true;
if (explicitIntDefault)
warn = false;
}
protected:
bool obey; // respect precision qualifiers
bool warn; // need to give a warning about the defaults
bool explicitIntDefault; // user set the default for int/uint
bool explicitFloatDefault; // user set the default for float
};
//
// GLSL-specific parse helper. Should have GLSL in the name, but that's
// too big of a change for comparing branches at the moment, and perhaps
@ -155,7 +189,7 @@ public:
bool forwardCompatible = false, EShMessages messages = EShMsgDefault);
virtual ~TParseContext();
bool obeyPrecisionQualifiers() const { return obeyPrecisionQualifiers_; };
bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); };
void setPrecisionDefaults();
void setLimits(const TBuiltInResource&);
@ -212,6 +246,8 @@ public:
void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&);
void samplerConstructorLocationCheck(const TSourceLoc&, const char* token, TIntermNode*);
TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&);
void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier);
void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
bool parseVectorFields(const TSourceLoc&, const TString&, int vecSize, TVectorFields&);
void assignError(const TSourceLoc&, const char* op, TString left, TString right);
@ -344,6 +380,7 @@ protected:
const bool parsingBuiltins; // true if parsing built-in symbols/functions
static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2 * 2 * 2)); // see computeSamplerTypeIndex()
TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex];
TPrecisionManager precisionManager;
bool afterEOF;
TQualifier globalBufferDefaults;
TQualifier globalUniformDefaults;
@ -354,7 +391,6 @@ protected:
TIdSetType inductiveLoopIds;
bool anyIndexLimits;
TVector<TIntermTyped*> needsIndexLimitationChecking;
bool obeyPrecisionQualifiers_;
//
// Geometry shader input arrays:

View File

@ -1125,6 +1125,7 @@ single_type_qualifier
$$ = $1;
}
| precision_qualifier {
parseContext.checkPrecisionQualifier($1.loc, $1.qualifier.precision);
$$ = $1;
}
| interpolation_qualifier {
@ -2206,20 +2207,17 @@ precision_qualifier
: HIGH_PRECISION {
parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "highp precision qualifier");
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
if (parseContext.obeyPrecisionQualifiers())
$$.qualifier.precision = EpqHigh;
parseContext.handlePrecisionQualifier($1.loc, $$.qualifier, EpqHigh);
}
| MEDIUM_PRECISION {
parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "mediump precision qualifier");
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
if (parseContext.obeyPrecisionQualifiers())
$$.qualifier.precision = EpqMedium;
parseContext.handlePrecisionQualifier($1.loc, $$.qualifier, EpqMedium);
}
| LOW_PRECISION {
parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "lowp precision qualifier");
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
if (parseContext.obeyPrecisionQualifiers())
$$.qualifier.precision = EpqLow;
parseContext.handlePrecisionQualifier($1.loc, $$.qualifier, EpqLow);
}
;

File diff suppressed because it is too large Load Diff