Implement relaxed rule for opaque struct members
This commit is contained in:
parent
a3069e1df4
commit
c59b876ca0
9 changed files with 2787 additions and 2187 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -7,10 +7,17 @@ uniform vec4 a;
|
||||||
uniform vec2 b = vec2(0, 0); // initializer will be ignored
|
uniform vec2 b = vec2(0, 0); // initializer will be ignored
|
||||||
layout(location = 0) uniform vec2 c; // location qualifier will be ignored
|
layout(location = 0) uniform vec2 c; // location qualifier will be ignored
|
||||||
uniform vec4 d[10];
|
uniform vec4 d[10];
|
||||||
|
|
||||||
|
struct SamplerArray{
|
||||||
|
sampler2D tn[4];
|
||||||
|
};
|
||||||
|
|
||||||
uniform struct e {
|
uniform struct e {
|
||||||
vec2 x;
|
vec2 x;
|
||||||
float y;
|
float y;
|
||||||
uint z;
|
uint z;
|
||||||
|
sampler2D t0;
|
||||||
|
SamplerArray samplers;
|
||||||
} structUniform;
|
} structUniform;
|
||||||
|
|
||||||
// opaque types will not be grouped into uniform block
|
// opaque types will not be grouped into uniform block
|
||||||
|
|
@ -64,11 +71,15 @@ uint bar() {
|
||||||
vec4 foo() {
|
vec4 foo() {
|
||||||
float f = j + bufferInstance.j + structUniform.y + structUniform.z;
|
float f = j + bufferInstance.j + structUniform.y + structUniform.z;
|
||||||
vec2 v2 = b + c + structUniform.x;
|
vec2 v2 = b + c + structUniform.x;
|
||||||
vec4 v4 = a + d[0] + d[1] + d[2] + k + bufferInstance.k + texture(t1, vec2(0, 0));
|
vec4 v4 = a + d[0] + d[1] + d[2] + k + bufferInstance.k + texture(t1, vec2(0, 0)) + texture(structUniform.t0, vec2(0, 0));
|
||||||
return vec4(f) * vec4(v2, 1, 1) * v4;
|
return vec4(f) * vec4(v2, 1, 1) * v4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec4 baz(SamplerArray samplers) {
|
||||||
|
return texture(samplers.tn[0], vec2(0, 0)) + texture(samplers.tn[1], vec2(0, 0)) + texture(samplers.tn[2], vec2(0, 0)) + texture(samplers.tn[3], vec2(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
float j = float(bar());
|
float j = float(bar());
|
||||||
o = j * foo();
|
o = j * foo() + baz(structUniform.samplers);
|
||||||
}
|
}
|
||||||
|
|
@ -2317,6 +2317,40 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r
|
||||||
return aggNode;
|
return aggNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TIntermAggregate* TIntermediate::mergeAggregate(TIntermNode* left, TIntermNode* right)
|
||||||
|
{
|
||||||
|
if (left == nullptr && right == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
TIntermAggregate* aggNode = nullptr;
|
||||||
|
if (left != nullptr)
|
||||||
|
aggNode = left->getAsAggregate();
|
||||||
|
if (aggNode == nullptr || aggNode->getOp() != EOpNull) {
|
||||||
|
aggNode = new TIntermAggregate;
|
||||||
|
if (left != nullptr)
|
||||||
|
aggNode->getSequence().push_back(left);
|
||||||
|
}
|
||||||
|
|
||||||
|
TIntermAggregate* rhsagg = right->getAsAggregate();
|
||||||
|
if (rhsagg == nullptr || rhsagg->getOp() != EOpNull)
|
||||||
|
aggNode->getSequence().push_back(right);
|
||||||
|
else
|
||||||
|
aggNode->getSequence().insert(aggNode->getSequence().end(),
|
||||||
|
rhsagg->getSequence().begin(),
|
||||||
|
rhsagg->getSequence().end());
|
||||||
|
|
||||||
|
return aggNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
TIntermAggregate* TIntermediate::mergeAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& loc)
|
||||||
|
{
|
||||||
|
TIntermAggregate* aggNode = mergeAggregate(left, right);
|
||||||
|
if (aggNode)
|
||||||
|
aggNode->setLoc(loc);
|
||||||
|
|
||||||
|
return aggNode;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Turn an existing node into an aggregate.
|
// Turn an existing node into an aggregate.
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -722,6 +722,24 @@ void TParseContextBase::finish()
|
||||||
if (parsingBuiltins)
|
if (parsingBuiltins)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
for (const TString& relaxedSymbol : relaxedSymbols)
|
||||||
|
{
|
||||||
|
TSymbol* symbol = symbolTable.find(relaxedSymbol);
|
||||||
|
TType& type = symbol->getWritableType();
|
||||||
|
for (const TTypeLoc& typeLoc : *type.getStruct())
|
||||||
|
{
|
||||||
|
if (typeLoc.type->isOpaque())
|
||||||
|
{
|
||||||
|
typeLoc.type->getSampler() = TSampler{};
|
||||||
|
typeLoc.type->setBasicType(EbtInt);
|
||||||
|
TString fieldName("/*");
|
||||||
|
fieldName.append(typeLoc.type->getFieldName());
|
||||||
|
fieldName.append("*/");
|
||||||
|
typeLoc.type->setFieldName(fieldName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Transfer the linkage symbols to AST nodes, preserving order.
|
// Transfer the linkage symbols to AST nodes, preserving order.
|
||||||
TIntermAggregate* linkage = new TIntermAggregate;
|
TIntermAggregate* linkage = new TIntermAggregate;
|
||||||
for (auto i = linkageSymbols.begin(); i != linkageSymbols.end(); ++i)
|
for (auto i = linkageSymbols.begin(); i != linkageSymbols.end(); ++i)
|
||||||
|
|
|
||||||
|
|
@ -993,7 +993,13 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldFound) {
|
if (fieldFound) {
|
||||||
|
if (spvVersion.vulkan != 0 && spvVersion.vulkanRelaxed)
|
||||||
|
result = vkRelaxedRemapDotDereference(loc, *base, *(*fields)[member].type, field);
|
||||||
|
|
||||||
|
if (result == base)
|
||||||
|
{
|
||||||
if (base->getType().getQualifier().isFrontEndConstant())
|
if (base->getType().getQualifier().isFrontEndConstant())
|
||||||
result = intermediate.foldDereference(base, member, loc);
|
result = intermediate.foldDereference(base, member, loc);
|
||||||
else {
|
else {
|
||||||
|
|
@ -1004,6 +1010,8 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
|
||||||
if ((*fields)[member].type->getQualifier().isIo())
|
if ((*fields)[member].type->getQualifier().isIo())
|
||||||
intermediate.addIoAccessed(field);
|
intermediate.addIoAccessed(field);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inheritMemoryQualifiers(base->getQualifier(), result->getWritableType().getQualifier());
|
inheritMemoryQualifiers(base->getQualifier(), result->getWritableType().getQualifier());
|
||||||
} else {
|
} else {
|
||||||
auto baseSymbol = base;
|
auto baseSymbol = base;
|
||||||
|
|
@ -7357,12 +7365,14 @@ void TParseContext::coopMatTypeParametersCheck(const TSourceLoc& loc, const TPub
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TParseContext::vkRelaxedRemapUniformVariable(const TSourceLoc& loc, TString& identifier, const TPublicType&,
|
bool TParseContext::vkRelaxedRemapUniformVariable(const TSourceLoc& loc, TString& identifier, const TPublicType& publicType,
|
||||||
TArraySizes*, TIntermTyped* initializer, TType& type)
|
TArraySizes*, TIntermTyped* initializer, TType& type)
|
||||||
{
|
{
|
||||||
|
vkRelaxedRemapUniformMembers(loc, publicType, type, identifier);
|
||||||
|
|
||||||
if (parsingBuiltins || symbolTable.atBuiltInLevel() || !symbolTable.atGlobalLevel() ||
|
if (parsingBuiltins || symbolTable.atBuiltInLevel() || !symbolTable.atGlobalLevel() ||
|
||||||
type.getQualifier().storage != EvqUniform ||
|
type.getQualifier().storage != EvqUniform ||
|
||||||
!(type.containsNonOpaque()|| type.getBasicType() == EbtAtomicUint)) {
|
!(type.containsNonOpaque() || type.getBasicType() == EbtAtomicUint || (type.containsSampler() && type.isStruct()))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7436,6 +7446,251 @@ bool TParseContext::vkRelaxedRemapUniformVariable(const TSourceLoc& loc, TString
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Function>
|
||||||
|
static void ForEachOpaque(const TType& type, const TString& path, Function callback)
|
||||||
|
{
|
||||||
|
auto recursion = [&callback](const TType& type, const TString& path, bool skipArray, auto& recursion) -> void {
|
||||||
|
if (!skipArray && type.isArray())
|
||||||
|
{
|
||||||
|
std::vector<int> indices(type.getArraySizes()->getNumDims());
|
||||||
|
for (int flatIndex = 0;
|
||||||
|
flatIndex < type.getArraySizes()->getCumulativeSize();
|
||||||
|
++flatIndex)
|
||||||
|
{
|
||||||
|
TString subscriptPath = path;
|
||||||
|
for (int dimIndex = 0; dimIndex < indices.size(); ++dimIndex)
|
||||||
|
{
|
||||||
|
int index = indices[dimIndex];
|
||||||
|
subscriptPath.append("[");
|
||||||
|
subscriptPath.append(String(index));
|
||||||
|
subscriptPath.append("]");
|
||||||
|
}
|
||||||
|
|
||||||
|
recursion(type, subscriptPath, true, recursion);
|
||||||
|
|
||||||
|
for (int dimIndex = 0; dimIndex < indices.size(); ++dimIndex)
|
||||||
|
{
|
||||||
|
++indices[dimIndex];
|
||||||
|
if (indices[dimIndex] < type.getArraySizes()->getDimSize(dimIndex))
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
indices[dimIndex] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (type.isStruct() && type.containsOpaque())
|
||||||
|
{
|
||||||
|
const TTypeList& types = *type.getStruct();
|
||||||
|
for (const TTypeLoc& typeLoc : types)
|
||||||
|
{
|
||||||
|
TString nextPath = path;
|
||||||
|
nextPath.append(".");
|
||||||
|
nextPath.append(typeLoc.type->getFieldName());
|
||||||
|
|
||||||
|
recursion(*(typeLoc.type), nextPath, false, recursion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (type.isOpaque())
|
||||||
|
{
|
||||||
|
callback(type, path);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
recursion(type, path, false, recursion);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TParseContext::vkRelaxedRemapUniformMembers(const TSourceLoc& loc, const TPublicType& publicType, const TType& type,
|
||||||
|
const TString& identifier)
|
||||||
|
{
|
||||||
|
if (!type.isStruct() || !type.containsOpaque())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ForEachOpaque(type, identifier,
|
||||||
|
[&publicType, &loc, this](const TType& type, const TString& path) {
|
||||||
|
TArraySizes arraySizes = {};
|
||||||
|
if (type.getArraySizes()) arraySizes = *type.getArraySizes();
|
||||||
|
TTypeParameters typeParameters = {};
|
||||||
|
if (type.getTypeParameters()) typeParameters = *type.getTypeParameters();
|
||||||
|
|
||||||
|
TPublicType memberType{};
|
||||||
|
memberType.basicType = type.getBasicType();
|
||||||
|
memberType.sampler = type.getSampler();
|
||||||
|
memberType.qualifier = type.getQualifier();
|
||||||
|
memberType.vectorSize = type.getVectorSize();
|
||||||
|
memberType.matrixCols = type.getMatrixCols();
|
||||||
|
memberType.matrixRows = type.getMatrixRows();
|
||||||
|
memberType.coopmatNV = type.isCoopMatNV();
|
||||||
|
memberType.coopmatKHR = type.isCoopMatKHR();
|
||||||
|
memberType.arraySizes = nullptr;
|
||||||
|
memberType.userDef = nullptr;
|
||||||
|
memberType.loc = loc;
|
||||||
|
memberType.typeParameters = (type.getTypeParameters() ? &typeParameters : nullptr);
|
||||||
|
memberType.spirvType = nullptr;
|
||||||
|
|
||||||
|
memberType.qualifier.storage = publicType.qualifier.storage;
|
||||||
|
memberType.shaderQualifiers = publicType.shaderQualifiers;
|
||||||
|
|
||||||
|
TString& structMemberName = *NewPoolTString(path.c_str()); // A copy is required due to declareVariable() signature.
|
||||||
|
declareVariable(loc, structMemberName, memberType, nullptr, nullptr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void TParseContext::vkRelaxedRemapFunctionParameter(const TSourceLoc& loc, TFunction* function, TParameter& param, std::vector<int>* newParams)
|
||||||
|
{
|
||||||
|
function->addParameter(param);
|
||||||
|
|
||||||
|
if (!param.type->isStruct() || !param.type->containsOpaque())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ForEachOpaque(*param.type, (param.name ? *param.name : param.type->getFieldName()),
|
||||||
|
[function, param, newParams](const TType& type, const TString& path) {
|
||||||
|
TString* memberName = NewPoolTString(path.c_str());
|
||||||
|
|
||||||
|
TType* memberType = new TType();
|
||||||
|
memberType->shallowCopy(type);
|
||||||
|
memberType->getQualifier().storage = param.type->getQualifier().storage;
|
||||||
|
memberType->clearArraySizes();
|
||||||
|
|
||||||
|
TParameter memberParam = {};
|
||||||
|
memberParam.name = memberName;
|
||||||
|
memberParam.type = memberType;
|
||||||
|
memberParam.defaultValue = nullptr;
|
||||||
|
function->addParameter(memberParam);
|
||||||
|
if (newParams)
|
||||||
|
newParams->push_back(function->getParamCount()-1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Generates a valid GLSL dereferencing string for the input TIntermNode
|
||||||
|
//
|
||||||
|
struct AccessChainTraverser : public TIntermTraverser {
|
||||||
|
AccessChainTraverser() : TIntermTraverser(false, false, true)
|
||||||
|
{}
|
||||||
|
|
||||||
|
TString path = "";
|
||||||
|
|
||||||
|
bool visitBinary(TVisit, TIntermBinary* binary) override {
|
||||||
|
if (binary->getOp() == EOpIndexDirectStruct)
|
||||||
|
{
|
||||||
|
const TTypeList& members = *binary->getLeft()->getType().getStruct();
|
||||||
|
const TTypeLoc& member =
|
||||||
|
members[binary->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst()];
|
||||||
|
TString memberName = member.type->getFieldName();
|
||||||
|
|
||||||
|
if (path != "")
|
||||||
|
path.append(".");
|
||||||
|
|
||||||
|
path.append(memberName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (binary->getOp() == EOpIndexDirect)
|
||||||
|
{
|
||||||
|
const TConstUnionArray& indices = binary->getRight()->getAsConstantUnion()->getConstArray();
|
||||||
|
for (int index = 0; index < indices.size(); ++index)
|
||||||
|
{
|
||||||
|
path.append("[");
|
||||||
|
path.append(String(indices[index].getIConst()));
|
||||||
|
path.append("]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitSymbol(TIntermSymbol* symbol) override {
|
||||||
|
if (!IsAnonymous(symbol->getName()))
|
||||||
|
path.append(symbol->getName());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TIntermNode* TParseContext::vkRelaxedRemapFunctionArgument(const TSourceLoc& loc, TFunction* function, TIntermTyped* intermTyped)
|
||||||
|
{
|
||||||
|
AccessChainTraverser accessChainTraverser{};
|
||||||
|
intermTyped->traverse(&accessChainTraverser);
|
||||||
|
|
||||||
|
TParameter param = { NewPoolTString(accessChainTraverser.path.c_str()), new TType };
|
||||||
|
param.type->shallowCopy(intermTyped->getType());
|
||||||
|
|
||||||
|
std::vector<int> newParams = {};
|
||||||
|
vkRelaxedRemapFunctionParameter(loc, function, param, &newParams);
|
||||||
|
|
||||||
|
if (intermTyped->getType().isOpaque())
|
||||||
|
{
|
||||||
|
TIntermNode* remappedArgument = intermTyped;
|
||||||
|
{
|
||||||
|
TIntermSymbol* intermSymbol = nullptr;
|
||||||
|
TSymbol* symbol = symbolTable.find(*param.name);
|
||||||
|
if (symbol && symbol->getAsVariable())
|
||||||
|
intermSymbol = intermediate.addSymbol(*symbol->getAsVariable(), loc);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TVariable* variable = new TVariable(param.name, *param.type);
|
||||||
|
intermSymbol = intermediate.addSymbol(*variable, loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
remappedArgument = intermSymbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
return remappedArgument;
|
||||||
|
}
|
||||||
|
else if (!(intermTyped->isStruct() && intermTyped->getType().containsOpaque()))
|
||||||
|
return intermTyped;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TIntermNode* remappedArgument = intermTyped;
|
||||||
|
{
|
||||||
|
TSymbol* symbol = symbolTable.find(*param.name);
|
||||||
|
if (symbol && symbol->getAsVariable())
|
||||||
|
remappedArgument = intermediate.addSymbol(*symbol->getAsVariable(), loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newParams.empty())
|
||||||
|
remappedArgument = intermediate.makeAggregate(remappedArgument, loc);
|
||||||
|
|
||||||
|
for (int paramIndex : newParams)
|
||||||
|
{
|
||||||
|
TParameter& newParam = function->operator[](paramIndex);
|
||||||
|
TIntermSymbol* intermSymbol = nullptr;
|
||||||
|
TSymbol* symbol = symbolTable.find(*newParam.name);
|
||||||
|
if (symbol && symbol->getAsVariable())
|
||||||
|
intermSymbol = intermediate.addSymbol(*symbol->getAsVariable(), loc);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TVariable* variable = new TVariable(newParam.name, *newParam.type);
|
||||||
|
intermSymbol = intermediate.addSymbol(*variable, loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
remappedArgument = intermediate.growAggregate(remappedArgument, intermSymbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
return remappedArgument;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TIntermTyped* TParseContext::vkRelaxedRemapDotDereference(const TSourceLoc&, TIntermTyped& base, const TType& member,
|
||||||
|
const TString& identifier)
|
||||||
|
{
|
||||||
|
if (!member.isOpaque())
|
||||||
|
return &base;
|
||||||
|
|
||||||
|
AccessChainTraverser traverser{};
|
||||||
|
base.traverse(&traverser);
|
||||||
|
if (!traverser.path.empty())
|
||||||
|
traverser.path.append(".");
|
||||||
|
traverser.path.append(identifier);
|
||||||
|
|
||||||
|
const TSymbol* symbol = symbolTable.find(traverser.path);
|
||||||
|
if (!symbol)
|
||||||
|
return &base;
|
||||||
|
|
||||||
|
TIntermTyped* result = intermediate.addSymbol(*symbol->getAsVariable());
|
||||||
|
result->setType(symbol->getType());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Do everything necessary to handle a variable (non-block) declaration.
|
// Do everything necessary to handle a variable (non-block) declaration.
|
||||||
// Either redeclaring a variable, or making a new one, updating the symbol
|
// Either redeclaring a variable, or making a new one, updating the symbol
|
||||||
|
|
|
||||||
|
|
@ -180,6 +180,7 @@ public:
|
||||||
// Basic parsing state, easily accessible to the grammar
|
// Basic parsing state, easily accessible to the grammar
|
||||||
|
|
||||||
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
|
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
|
||||||
|
TVector<TString> relaxedSymbols;
|
||||||
int statementNestingLevel; // 0 if outside all flow control or compound statements
|
int statementNestingLevel; // 0 if outside all flow control or compound statements
|
||||||
int loopNestingLevel; // 0 if outside all loops
|
int loopNestingLevel; // 0 if outside all loops
|
||||||
int structNestingLevel; // 0 if outside structures
|
int structNestingLevel; // 0 if outside structures
|
||||||
|
|
@ -367,6 +368,10 @@ public:
|
||||||
TIntermTyped* vkRelaxedRemapFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
|
TIntermTyped* vkRelaxedRemapFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
|
||||||
// returns true if the variable was remapped to something else
|
// returns true if the variable was remapped to something else
|
||||||
bool vkRelaxedRemapUniformVariable(const TSourceLoc&, TString&, const TPublicType&, TArraySizes*, TIntermTyped*, TType&);
|
bool vkRelaxedRemapUniformVariable(const TSourceLoc&, TString&, const TPublicType&, TArraySizes*, TIntermTyped*, TType&);
|
||||||
|
void vkRelaxedRemapUniformMembers(const TSourceLoc&, const TPublicType&, const TType&, const TString&);
|
||||||
|
void vkRelaxedRemapFunctionParameter(const TSourceLoc&, TFunction*, TParameter&, std::vector<int>* newParams = nullptr);
|
||||||
|
TIntermNode* vkRelaxedRemapFunctionArgument(const TSourceLoc&, TFunction*, TIntermTyped*);
|
||||||
|
TIntermTyped* vkRelaxedRemapDotDereference(const TSourceLoc&, TIntermTyped&, const TType&, const TString&);
|
||||||
|
|
||||||
void assignError(const TSourceLoc&, const char* op, TString left, TString right);
|
void assignError(const TSourceLoc&, const char* op, TString left, TString right);
|
||||||
void unaryOpError(const TSourceLoc&, const char* op, TString operand);
|
void unaryOpError(const TSourceLoc&, const char* op, TString operand);
|
||||||
|
|
|
||||||
|
|
@ -492,19 +492,42 @@ function_call_header_no_parameters
|
||||||
|
|
||||||
function_call_header_with_parameters
|
function_call_header_with_parameters
|
||||||
: function_call_header assignment_expression {
|
: function_call_header assignment_expression {
|
||||||
|
if (parseContext.spvVersion.vulkan > 0
|
||||||
|
&& parseContext.spvVersion.vulkanRelaxed
|
||||||
|
&& $2->getType().containsOpaque())
|
||||||
|
{
|
||||||
|
$$.intermNode = parseContext.vkRelaxedRemapFunctionArgument($$.loc, $1.function, $2);
|
||||||
|
$$.function = $1.function;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
TParameter param = { 0, new TType };
|
TParameter param = { 0, new TType };
|
||||||
param.type->shallowCopy($2->getType());
|
param.type->shallowCopy($2->getType());
|
||||||
|
|
||||||
$1.function->addParameter(param);
|
$1.function->addParameter(param);
|
||||||
$$.function = $1.function;
|
$$.function = $1.function;
|
||||||
$$.intermNode = $2;
|
$$.intermNode = $2;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
| function_call_header_with_parameters COMMA assignment_expression {
|
| function_call_header_with_parameters COMMA assignment_expression {
|
||||||
|
if (parseContext.spvVersion.vulkan > 0
|
||||||
|
&& parseContext.spvVersion.vulkanRelaxed
|
||||||
|
&& $3->getType().containsOpaque())
|
||||||
|
{
|
||||||
|
TIntermNode* remappedNode = parseContext.vkRelaxedRemapFunctionArgument($2.loc, $1.function, $3);
|
||||||
|
$$.intermNode = parseContext.intermediate.mergeAggregate($1.intermNode, remappedNode, $2.loc);
|
||||||
|
$$.function = $1.function;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
TParameter param = { 0, new TType };
|
TParameter param = { 0, new TType };
|
||||||
param.type->shallowCopy($3->getType());
|
param.type->shallowCopy($3->getType());
|
||||||
|
|
||||||
$1.function->addParameter(param);
|
$1.function->addParameter(param);
|
||||||
$$.function = $1.function;
|
$$.function = $1.function;
|
||||||
$$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, $3, $2.loc);
|
$$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, $3, $2.loc);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
function_call_header
|
function_call_header
|
||||||
|
|
@ -980,7 +1003,12 @@ function_header_with_parameters
|
||||||
// Add the parameter
|
// Add the parameter
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
if ($2.param.type->getBasicType() != EbtVoid)
|
if ($2.param.type->getBasicType() != EbtVoid)
|
||||||
|
{
|
||||||
|
if (!(parseContext.spvVersion.vulkan > 0 && parseContext.spvVersion.vulkanRelaxed))
|
||||||
$1->addParameter($2.param);
|
$1->addParameter($2.param);
|
||||||
|
else
|
||||||
|
parseContext.vkRelaxedRemapFunctionParameter($2.loc, $1, $2.param);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
delete $2.param.type;
|
delete $2.param.type;
|
||||||
}
|
}
|
||||||
|
|
@ -998,7 +1026,10 @@ function_header_with_parameters
|
||||||
} else {
|
} else {
|
||||||
// Add the parameter
|
// Add the parameter
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
|
if (!(parseContext.spvVersion.vulkan > 0 && parseContext.spvVersion.vulkanRelaxed))
|
||||||
$1->addParameter($3.param);
|
$1->addParameter($3.param);
|
||||||
|
else
|
||||||
|
parseContext.vkRelaxedRemapFunctionParameter($3.loc, $1, $3.param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
@ -3549,11 +3580,17 @@ precision_qualifier
|
||||||
|
|
||||||
struct_specifier
|
struct_specifier
|
||||||
: STRUCT IDENTIFIER LEFT_BRACE { parseContext.nestedStructCheck($1.loc); } struct_declaration_list RIGHT_BRACE {
|
: STRUCT IDENTIFIER LEFT_BRACE { parseContext.nestedStructCheck($1.loc); } struct_declaration_list RIGHT_BRACE {
|
||||||
|
|
||||||
TType* structure = new TType($5, *$2.string);
|
TType* structure = new TType($5, *$2.string);
|
||||||
parseContext.structArrayCheck($2.loc, *structure);
|
parseContext.structArrayCheck($2.loc, *structure);
|
||||||
|
|
||||||
TVariable* userTypeDef = new TVariable($2.string, *structure, true);
|
TVariable* userTypeDef = new TVariable($2.string, *structure, true);
|
||||||
if (! parseContext.symbolTable.insert(*userTypeDef))
|
if (! parseContext.symbolTable.insert(*userTypeDef))
|
||||||
parseContext.error($2.loc, "redefinition", $2.string->c_str(), "struct");
|
parseContext.error($2.loc, "redefinition", $2.string->c_str(), "struct");
|
||||||
|
else if (parseContext.spvVersion.vulkanRelaxed
|
||||||
|
&& structure->containsOpaque())
|
||||||
|
parseContext.relaxedSymbols.push_back(structure->getTypeName());
|
||||||
|
|
||||||
$$.init($1.loc);
|
$$.init($1.loc);
|
||||||
$$.basicType = EbtStruct;
|
$$.basicType = EbtStruct;
|
||||||
$$.userDef = structure;
|
$$.userDef = structure;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -528,6 +528,8 @@ public:
|
||||||
TOperator mapTypeToConstructorOp(const TType&) const;
|
TOperator mapTypeToConstructorOp(const TType&) const;
|
||||||
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
|
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
|
||||||
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
|
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
|
||||||
|
TIntermAggregate* mergeAggregate(TIntermNode* left, TIntermNode* right);
|
||||||
|
TIntermAggregate* mergeAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
|
||||||
TIntermAggregate* makeAggregate(TIntermNode* node);
|
TIntermAggregate* makeAggregate(TIntermNode* node);
|
||||||
TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
|
TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
|
||||||
TIntermAggregate* makeAggregate(const TSourceLoc&);
|
TIntermAggregate* makeAggregate(const TSourceLoc&);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue