Implement GL_EXT_null_initializer

Adds null initializer syntax (empty braces)
Allows null initialization of shared variables
This commit is contained in:
John Kessenich 2020-06-11 08:30:03 -06:00 committed by Alan Baker
parent 6abdde3ce5
commit c739e03748
17 changed files with 2694 additions and 2355 deletions

View file

@ -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()) {

View file

@ -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();

View file

@ -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
}

View file

@ -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

View file

@ -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
;

View file

@ -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