Implement GL_EXT_null_initializer
Adds null initializer syntax (empty braces) Allows null initialization of shared variables
This commit is contained in:
parent
6abdde3ce5
commit
c739e03748
17 changed files with 2694 additions and 2355 deletions
|
|
@ -499,6 +499,7 @@ public:
|
|||
declaredBuiltIn = EbvNone;
|
||||
#ifndef GLSLANG_WEB
|
||||
noContraction = false;
|
||||
nullInit = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -512,6 +513,7 @@ public:
|
|||
clearMemory();
|
||||
specConstant = false;
|
||||
nonUniform = false;
|
||||
nullInit = false;
|
||||
clearLayout();
|
||||
}
|
||||
|
||||
|
|
@ -588,6 +590,8 @@ public:
|
|||
bool isNoContraction() const { return false; }
|
||||
void setNoContraction() { }
|
||||
bool isPervertexNV() const { return false; }
|
||||
void setNullInit() { }
|
||||
bool isNullInit() const { return false; }
|
||||
#else
|
||||
bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects
|
||||
bool nopersp : 1;
|
||||
|
|
@ -609,6 +613,7 @@ public:
|
|||
bool subgroupcoherent : 1;
|
||||
bool shadercallcoherent : 1;
|
||||
bool nonprivate : 1;
|
||||
bool nullInit : 1;
|
||||
bool isWriteOnly() const { return writeonly; }
|
||||
bool isReadOnly() const { return readonly; }
|
||||
bool isRestrict() const { return restrict; }
|
||||
|
|
@ -644,6 +649,8 @@ public:
|
|||
bool isNoContraction() const { return noContraction; }
|
||||
void setNoContraction() { noContraction = true; }
|
||||
bool isPervertexNV() const { return pervertexNV; }
|
||||
void setNullInit() { nullInit = true; }
|
||||
bool isNullInit() const { return nullInit; }
|
||||
#endif
|
||||
|
||||
bool isPipeInput() const
|
||||
|
|
@ -2164,6 +2171,8 @@ public:
|
|||
appendStr(" specialization-constant");
|
||||
if (qualifier.nonUniform)
|
||||
appendStr(" nonuniform");
|
||||
if (qualifier.isNullInit())
|
||||
appendStr(" null-init");
|
||||
appendStr(" ");
|
||||
appendStr(getStorageQualifierString());
|
||||
if (isArray()) {
|
||||
|
|
|
|||
|
|
@ -6815,6 +6815,11 @@ TVariable* TParseContext::declareNonArray(const TSourceLoc& loc, const TString&
|
|||
//
|
||||
TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable)
|
||||
{
|
||||
// A null initializer is an aggregate that hasn't had an op assigned yet
|
||||
// (still EOpNull, no relation to nullInit), and has no children.
|
||||
bool nullInit = initializer->getAsAggregate() && initializer->getAsAggregate()->getOp() == EOpNull &&
|
||||
initializer->getAsAggregate()->getSequence().size() == 0;
|
||||
|
||||
//
|
||||
// Identifier must be of type constant, a global, or a temporary, and
|
||||
// starting at version 120, desktop allows uniforms to have initializers.
|
||||
|
|
@ -6822,9 +6827,36 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
|
|||
TStorageQualifier qualifier = variable->getType().getQualifier().storage;
|
||||
if (! (qualifier == EvqTemporary || qualifier == EvqGlobal || qualifier == EvqConst ||
|
||||
(qualifier == EvqUniform && !isEsProfile() && version >= 120))) {
|
||||
error(loc, " cannot initialize this type of qualifier ", variable->getType().getStorageQualifierString(), "");
|
||||
if (qualifier == EvqShared) {
|
||||
// GL_EXT_null_initializer allows this for shared, if it's a null initializer
|
||||
if (nullInit) {
|
||||
const char* feature = "initialization with shared qualifier";
|
||||
profileRequires(loc, EEsProfile, 0, E_GL_EXT_null_initializer, feature);
|
||||
profileRequires(loc, ~EEsProfile, 0, E_GL_EXT_null_initializer, feature);
|
||||
} else {
|
||||
error(loc, "initializer can only be a null initializer ('{}')", "shared", "");
|
||||
}
|
||||
} else {
|
||||
error(loc, " cannot initialize this type of qualifier ",
|
||||
variable->getType().getStorageQualifierString(), "");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (nullInit) {
|
||||
// only some types can be null initialized
|
||||
if (variable->getType().containsUnsizedArray()) {
|
||||
error(loc, "null initializers can't size unsized arrays", "{}", "");
|
||||
return nullptr;
|
||||
}
|
||||
if (variable->getType().containsOpaque()) {
|
||||
error(loc, "null initializers can't be used on opaque values", "{}", "");
|
||||
return nullptr;
|
||||
}
|
||||
variable->getWritableType().getQualifier().setNullInit();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
arrayObjectCheck(loc, variable->getType(), "array initializer");
|
||||
|
||||
//
|
||||
|
|
@ -6868,13 +6900,15 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
|
|||
|
||||
// Uniforms require a compile-time constant initializer
|
||||
if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) {
|
||||
error(loc, "uniform initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str());
|
||||
error(loc, "uniform initializers must be constant", "=", "'%s'",
|
||||
variable->getType().getCompleteString().c_str());
|
||||
variable->getWritableType().getQualifier().makeTemporary();
|
||||
return nullptr;
|
||||
}
|
||||
// Global consts require a constant initializer (specialization constant is okay)
|
||||
if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
|
||||
error(loc, "global const initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str());
|
||||
error(loc, "global const initializers must be constant", "=", "'%s'",
|
||||
variable->getType().getCompleteString().c_str());
|
||||
variable->getWritableType().getQualifier().makeTemporary();
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -6894,7 +6928,8 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
|
|||
// "In declarations of global variables with no storage qualifier or with a const
|
||||
// qualifier any initializer must be a constant expression."
|
||||
if (symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) {
|
||||
const char* initFeature = "non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)";
|
||||
const char* initFeature =
|
||||
"non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)";
|
||||
if (isEsProfile()) {
|
||||
if (relaxedErrors() && ! extensionTurnedOn(E_GL_EXT_shader_non_constant_global_initializers))
|
||||
warn(loc, "not allowed in this version", initFeature, "");
|
||||
|
|
@ -6908,7 +6943,8 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
|
|||
// Compile-time tagging of the variable with its constant value...
|
||||
|
||||
initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer);
|
||||
if (! initializer || ! initializer->getType().getQualifier().isConstant() || variable->getType() != initializer->getType()) {
|
||||
if (! initializer || ! initializer->getType().getQualifier().isConstant() ||
|
||||
variable->getType() != initializer->getType()) {
|
||||
error(loc, "non-matching or non-convertible constant type for const initializer",
|
||||
variable->getType().getStorageQualifierString(), "");
|
||||
variable->getWritableType().getQualifier().makeTemporary();
|
||||
|
|
|
|||
|
|
@ -305,6 +305,7 @@ void TParseVersions::initializeExtensionBehavior()
|
|||
extensionBehavior[E_GL_EXT_tessellation_point_size] = EBhDisable;
|
||||
extensionBehavior[E_GL_EXT_texture_buffer] = EBhDisable;
|
||||
extensionBehavior[E_GL_EXT_texture_cube_map_array] = EBhDisable;
|
||||
extensionBehavior[E_GL_EXT_null_initializer] = EBhDisable;
|
||||
|
||||
// OES matching AEP
|
||||
extensionBehavior[E_GL_OES_geometry_shader] = EBhDisable;
|
||||
|
|
@ -408,9 +409,12 @@ void TParseVersions::getPreamble(std::string& preamble)
|
|||
"#define GL_EXT_shader_non_constant_global_initializers 1\n"
|
||||
;
|
||||
|
||||
if (isEsProfile() && version >= 300) {
|
||||
if (version >= 300) {
|
||||
preamble += "#define GL_NV_shader_noperspective_interpolation 1\n";
|
||||
}
|
||||
if (version >= 310) {
|
||||
preamble += "#define GL_EXT_null_initializer 1\n";
|
||||
}
|
||||
|
||||
} else { // !isEsProfile()
|
||||
preamble =
|
||||
|
|
@ -538,6 +542,9 @@ void TParseVersions::getPreamble(std::string& preamble)
|
|||
if (profile == ECompatibilityProfile)
|
||||
preamble += "#define GL_compatibility_profile 1\n";
|
||||
}
|
||||
if (version >= 140) {
|
||||
preamble += "#define GL_EXT_null_initializer 1\n";
|
||||
}
|
||||
#endif // GLSLANG_WEB
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -201,6 +201,7 @@ const char* const E_GL_EXT_blend_func_extended = "GL_EXT_blend_func
|
|||
const char* const E_GL_EXT_shader_implicit_conversions = "GL_EXT_shader_implicit_conversions";
|
||||
const char* const E_GL_EXT_fragment_shading_rate = "GL_EXT_fragment_shading_rate";
|
||||
const char* const E_GL_EXT_shader_image_int64 = "GL_EXT_shader_image_int64";
|
||||
const char* const E_GL_EXT_null_initializer = "GL_EXT_null_initializer";
|
||||
|
||||
// Arrays of extensions for the above viewportEXTs duplications
|
||||
|
||||
|
|
|
|||
|
|
@ -3575,6 +3575,12 @@ GLSLANG_WEB_EXCLUDE_ON
|
|||
parseContext.profileRequires($1.loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
|
||||
$$ = $2;
|
||||
}
|
||||
| LEFT_BRACE RIGHT_BRACE {
|
||||
const char* initFeature = "empty { } initializer";
|
||||
parseContext.profileRequires($1.loc, EEsProfile, 0, E_GL_EXT_null_initializer, initFeature);
|
||||
parseContext.profileRequires($1.loc, ~EEsProfile, 0, E_GL_EXT_null_initializer, initFeature);
|
||||
$$ = parseContext.intermediate.makeAggregate($1.loc);
|
||||
}
|
||||
GLSLANG_WEB_EXCLUDE_OFF
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -3575,6 +3575,12 @@ initializer
|
|||
parseContext.profileRequires($1.loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
|
||||
$$ = $2;
|
||||
}
|
||||
| LEFT_BRACE RIGHT_BRACE {
|
||||
const char* initFeature = "empty { } initializer";
|
||||
parseContext.profileRequires($1.loc, EEsProfile, 0, E_GL_EXT_null_initializer, initFeature);
|
||||
parseContext.profileRequires($1.loc, ~EEsProfile, 0, E_GL_EXT_null_initializer, initFeature);
|
||||
$$ = parseContext.intermediate.makeAggregate($1.loc);
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue