Non-functional. Rationalizations enabling future generalizations:
- Use much simpler method to update implicit array sizes. The previous overly complicated method was error prone. - Rationalize all use of unsized arrays. - Combine decorations when generating SPIR-V, to simplify adding extensions.
This commit is contained in:
@@ -2569,8 +2569,8 @@ bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
|
||||
TArraySizes* arraySizes = nullptr;
|
||||
acceptArraySpecifier(arraySizes);
|
||||
if (arraySizes) {
|
||||
if (arraySizes->isImplicit()) {
|
||||
parseContext.error(token.loc, "function parameter array cannot be implicitly sized", "", "");
|
||||
if (arraySizes->hasUnsized()) {
|
||||
parseContext.error(token.loc, "function parameter requires array size", "[]", "");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -829,6 +829,9 @@ TIntermTyped* HlslParseContext::handleBracketDereference(const TSourceLoc& loc,
|
||||
} else {
|
||||
// at least one of base and index is variable...
|
||||
|
||||
if (index->getQualifier().isFrontEndConstant())
|
||||
checkIndex(loc, base->getType(), indexValue);
|
||||
|
||||
if (base->getType().isScalarOrVec1())
|
||||
result = base;
|
||||
else if (base->getAsSymbolNode() && wasFlattened(base)) {
|
||||
@@ -839,14 +842,11 @@ TIntermTyped* HlslParseContext::handleBracketDereference(const TSourceLoc& loc,
|
||||
flattened = (result != base);
|
||||
} else {
|
||||
if (index->getQualifier().isFrontEndConstant()) {
|
||||
if (base->getType().isImplicitlySizedArray())
|
||||
updateImplicitArraySize(loc, base, indexValue);
|
||||
else
|
||||
checkIndex(loc, base->getType(), indexValue);
|
||||
if (base->getType().isUnsizedArray())
|
||||
base->getWritableType().updateImplicitArraySize(indexValue + 1);
|
||||
result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
|
||||
} else {
|
||||
} else
|
||||
result = intermediate.addIndex(EOpIndexIndirect, base, index, loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1318,7 +1318,7 @@ int HlslParseContext::flattenArray(const TVariable& variable, const TType& type,
|
||||
TFlattenData& flattenData, TString name, bool linkage,
|
||||
const TQualifier& outerQualifier)
|
||||
{
|
||||
assert(type.isArray() && !type.isImplicitlySizedArray());
|
||||
assert(type.isSizedArray());
|
||||
|
||||
const int size = type.getOuterArraySize();
|
||||
const TType dereferencedType(type, 0);
|
||||
@@ -3442,16 +3442,16 @@ void HlslParseContext::decomposeStructBufferMethods(const TSourceLoc& loc, TInte
|
||||
TIntermAggregate* body = nullptr;
|
||||
|
||||
// Length output:
|
||||
if (argArray->getType().isRuntimeSizedArray()) {
|
||||
TIntermTyped* lengthCall = intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, argArray,
|
||||
argNumItems->getType());
|
||||
TIntermTyped* assign = intermediate.addAssign(EOpAssign, argNumItems, lengthCall, loc);
|
||||
body = intermediate.growAggregate(body, assign, loc);
|
||||
} else {
|
||||
if (argArray->getType().isSizedArray()) {
|
||||
const int length = argArray->getType().getOuterArraySize();
|
||||
TIntermTyped* assign = intermediate.addAssign(EOpAssign, argNumItems,
|
||||
intermediate.addConstantUnion(length, loc, true), loc);
|
||||
body = intermediate.growAggregate(body, assign, loc);
|
||||
} else {
|
||||
TIntermTyped* lengthCall = intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, argArray,
|
||||
argNumItems->getType());
|
||||
TIntermTyped* assign = intermediate.addAssign(EOpAssign, argNumItems, lengthCall, loc);
|
||||
body = intermediate.growAggregate(body, assign, loc);
|
||||
}
|
||||
|
||||
// Stride output:
|
||||
@@ -6295,7 +6295,7 @@ bool HlslParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node
|
||||
bool arrayArg = false;
|
||||
for (int arg = 0; arg < function.getParamCount(); ++arg) {
|
||||
if (function[arg].type->isArray()) {
|
||||
if (! function[arg].type->isExplicitlySizedArray()) {
|
||||
if (function[arg].type->isUnsizedArray()) {
|
||||
// Can't construct from an unsized array.
|
||||
error(loc, "array argument must be sized", "constructor", "");
|
||||
return true;
|
||||
@@ -6330,11 +6330,10 @@ bool HlslParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type.isImplicitlySizedArray()) {
|
||||
if (type.isUnsizedArray()) {
|
||||
// auto adapt the constructor type to the number of arguments
|
||||
type.changeOuterArraySize(function.getParamCount());
|
||||
} else if (type.getOuterArraySize() != function.getParamCount() &&
|
||||
type.computeNumComponents() > size) {
|
||||
} else if (type.getOuterArraySize() != function.getParamCount() && type.computeNumComponents() > size) {
|
||||
error(loc, "array constructor needs one argument per array element", "constructor", "");
|
||||
return true;
|
||||
}
|
||||
@@ -6352,7 +6351,7 @@ bool HlslParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node
|
||||
return true;
|
||||
}
|
||||
|
||||
if (arraySizes.isInnerImplicit()) {
|
||||
if (arraySizes.isInnerUnsized()) {
|
||||
// "Arrays of arrays ..., and the size for any dimension is optional"
|
||||
// That means we need to adopt (from the first argument) the other array sizes into the type.
|
||||
for (int d = 1; d < arraySizes.getNumDims(); ++d) {
|
||||
@@ -6607,7 +6606,7 @@ void HlslParseContext::arraySizeCheck(const TSourceLoc& loc, TIntermTyped* expr,
|
||||
//
|
||||
void HlslParseContext::arraySizeRequiredCheck(const TSourceLoc& loc, const TArraySizes& arraySizes)
|
||||
{
|
||||
if (arraySizes.isImplicit())
|
||||
if (arraySizes.hasUnsized())
|
||||
error(loc, "array size required", "", "");
|
||||
}
|
||||
|
||||
@@ -6667,7 +6666,7 @@ void HlslParseContext::declareArray(const TSourceLoc& loc, const TString& identi
|
||||
// redeclareBuiltinVariable() should have already done the copyUp()
|
||||
TType& existingType = symbol->getWritableType();
|
||||
|
||||
if (existingType.isExplicitlySizedArray()) {
|
||||
if (existingType.isSizedArray()) {
|
||||
// be more lenient for input arrays to geometry shaders and tessellation control outputs,
|
||||
// where the redeclaration is the same size
|
||||
return;
|
||||
@@ -6676,52 +6675,6 @@ void HlslParseContext::declareArray(const TSourceLoc& loc, const TString& identi
|
||||
existingType.updateArraySizes(type);
|
||||
}
|
||||
|
||||
void HlslParseContext::updateImplicitArraySize(const TSourceLoc& loc, TIntermNode *node, int index)
|
||||
{
|
||||
// maybe there is nothing to do...
|
||||
TIntermTyped* typedNode = node->getAsTyped();
|
||||
if (typedNode->getType().getImplicitArraySize() > index)
|
||||
return;
|
||||
|
||||
// something to do...
|
||||
|
||||
// Figure out what symbol to lookup, as we will use its type to edit for the size change,
|
||||
// as that type will be shared through shallow copies for future references.
|
||||
TSymbol* symbol = nullptr;
|
||||
int blockIndex = -1;
|
||||
const TString* lookupName = nullptr;
|
||||
if (node->getAsSymbolNode())
|
||||
lookupName = &node->getAsSymbolNode()->getName();
|
||||
else if (node->getAsBinaryNode()) {
|
||||
const TIntermBinary* deref = node->getAsBinaryNode();
|
||||
// This has to be the result of a block dereference, unless it's bad shader code
|
||||
// If it's a uniform block, then an error will be issued elsewhere, but
|
||||
// return early now to avoid crashing later in this function.
|
||||
if (! deref->getLeft()->getAsSymbolNode() || deref->getLeft()->getBasicType() != EbtBlock ||
|
||||
deref->getLeft()->getType().getQualifier().storage == EvqUniform ||
|
||||
deref->getRight()->getAsConstantUnion() == nullptr)
|
||||
return;
|
||||
|
||||
blockIndex = deref->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
|
||||
|
||||
lookupName = &deref->getLeft()->getAsSymbolNode()->getName();
|
||||
if (IsAnonymous(*lookupName))
|
||||
lookupName = &(*deref->getLeft()->getType().getStruct())[blockIndex].type->getFieldName();
|
||||
}
|
||||
|
||||
// Lookup the symbol, should only fail if shader code is incorrect
|
||||
symbol = symbolTable.find(*lookupName);
|
||||
if (symbol == nullptr)
|
||||
return;
|
||||
|
||||
if (symbol->getAsFunction()) {
|
||||
error(loc, "array variable name expected", symbol->getName().c_str(), "");
|
||||
return;
|
||||
}
|
||||
|
||||
symbol->getWritableType().setImplicitArraySize(index + 1);
|
||||
}
|
||||
|
||||
//
|
||||
// Enforce non-initializer type/qualifier rules.
|
||||
//
|
||||
@@ -6785,7 +6738,7 @@ TIntermTyped* HlslParseContext::indexStructBufferContent(const TSourceLoc& loc,
|
||||
//
|
||||
TType* HlslParseContext::getStructBufferContentType(const TType& type) const
|
||||
{
|
||||
if (type.getBasicType() != EbtBlock)
|
||||
if (type.getBasicType() != EbtBlock || type.getQualifier().storage != EvqBuffer)
|
||||
return nullptr;
|
||||
|
||||
const int memberCount = (int)type.getStruct()->size();
|
||||
@@ -6793,7 +6746,7 @@ TType* HlslParseContext::getStructBufferContentType(const TType& type) const
|
||||
|
||||
TType* contentType = (*type.getStruct())[memberCount-1].type;
|
||||
|
||||
return contentType->isRuntimeSizedArray() ? contentType : nullptr;
|
||||
return contentType->isUnsizedArray() ? contentType : nullptr;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -7922,8 +7875,7 @@ TIntermNode* HlslParseContext::executeInitializer(const TSourceLoc& loc, TInterm
|
||||
}
|
||||
|
||||
// Fix outer arrayness if variable is unsized, getting size from the initializer
|
||||
if (initializer->getType().isExplicitlySizedArray() &&
|
||||
variable->getType().isImplicitlySizedArray())
|
||||
if (initializer->getType().isSizedArray() && variable->getType().isUnsizedArray())
|
||||
variable->getWritableType().changeOuterArraySize(initializer->getType().getOuterArraySize());
|
||||
|
||||
// Inner arrayness can also get set by an initializer
|
||||
@@ -8025,7 +7977,7 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
|
||||
arrayType.copyArraySizes(*type.getArraySizes()); // but get a fresh copy of the array information, to edit below
|
||||
|
||||
// edit array sizes to fill in unsized dimensions
|
||||
if (type.isImplicitlySizedArray())
|
||||
if (type.isUnsizedArray())
|
||||
arrayType.changeOuterArraySize((int)initList->getSequence().size());
|
||||
|
||||
// set unsized array dimensions that can be derived from the initializer's first element
|
||||
@@ -9621,7 +9573,7 @@ void HlslParseContext::addPatchConstantInvocation()
|
||||
const TType& type = *patchConstantFunction[param].type;
|
||||
const TBuiltInVariable biType = patchConstantFunction[param].getDeclaredBuiltIn();
|
||||
|
||||
return type.isArray() && !type.isRuntimeSizedArray() && biType == EbvOutputPatch;
|
||||
return type.isSizedArray() && biType == EbvOutputPatch;
|
||||
};
|
||||
|
||||
// We will perform these steps. Each is in a scoped block for separation: they could
|
||||
|
||||
@@ -164,8 +164,6 @@ public:
|
||||
void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
|
||||
TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body, const TAttributes&);
|
||||
|
||||
void updateImplicitArraySize(const TSourceLoc&, TIntermNode*, int index);
|
||||
|
||||
void nestLooping() { ++loopNestingLevel; }
|
||||
void unnestLooping() { --loopNestingLevel; }
|
||||
void nestAnnotations() { ++annotationNestingLevel; }
|
||||
|
||||
Reference in New Issue
Block a user