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
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue