Handle resizing/error checks for mesh shader out arrays

This commit is contained in:
Sahil Parmar
2019-02-13 17:40:27 -08:00
parent 9466850f54
commit 6708b0ee82
2 changed files with 75 additions and 55 deletions

View File

@@ -586,68 +586,80 @@ void TParseContext::handleIoResizeArrayAccess(const TSourceLoc& /*loc*/, TInterm
// Types without an array size will be given one. // Types without an array size will be given one.
// Types already having a size that is wrong will get an error. // Types already having a size that is wrong will get an error.
// //
void TParseContext::checkIoArraysConsistency(const TSourceLoc &loc, const TQualifier &qualifier, bool tailOnly) void TParseContext::checkIoArraysConsistency(const TSourceLoc &loc, bool tailOnly)
{ {
int requiredSize = getIoArrayImplicitSize(qualifier); int requiredSize = 0;
if (requiredSize == 0) TString featureString;
return; size_t listSize = ioArraySymbolResizeList.size();
size_t i = 0;
const char* feature; // If tailOnly = true, only check the last array symbol in the list.
if (language == EShLangGeometry) if (tailOnly) {
feature = TQualifier::getGeometryString(intermediate.getInputPrimitive()); i = listSize - 1;
else if (language == EShLangTessControl }
for (bool firstIteration = true; i < listSize; ++i) {
TType &type = ioArraySymbolResizeList[i]->getWritableType();
// As I/O array sizes don't change, fetch requiredSize only once,
// except for mesh shaders which could have different I/O array sizes based on type qualifiers.
if (firstIteration
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
|| language == EShLangFragment || (language == EShLangMeshNV)
#endif #endif
) )
{
requiredSize = getIoArrayImplicitSize(type.getQualifier(), &featureString);
if (requiredSize == 0)
break;
firstIteration = false;
}
feature = "vertices"; checkIoArrayConsistency(loc, requiredSize, featureString.c_str(), type,
#ifdef NV_EXTENSIONS ioArraySymbolResizeList[i]->getName());
else if (language == EShLangMeshNV) {
if (qualifier.builtIn == EbvPrimitiveIndicesNV) {
TLayoutGeometry outPrimitive = intermediate.getOutputPrimitive();
TString featureString = "max_primitives*";
featureString += TQualifier::getGeometryString(outPrimitive);
feature = featureString.c_str();
} else
feature = qualifier.isPerPrimitive() ? "max_primitives" : "max_vertices";
} }
#endif
else
feature = "unknown";
if (tailOnly) {
checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList.back()->getWritableType(), ioArraySymbolResizeList.back()->getName());
return;
}
for (size_t i = 0; i < ioArraySymbolResizeList.size(); ++i)
checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList[i]->getWritableType(), ioArraySymbolResizeList[i]->getName());
} }
int TParseContext::getIoArrayImplicitSize(const TQualifier& qualifier) const int TParseContext::getIoArrayImplicitSize(const TQualifier &qualifier, TString *featureString) const
{ {
int expectedSize = 0;
TString str = "unknown";
unsigned int maxVertices = intermediate.getVertices() != TQualifier::layoutNotSet ? intermediate.getVertices() : 0; unsigned int maxVertices = intermediate.getVertices() != TQualifier::layoutNotSet ? intermediate.getVertices() : 0;
if (language == EShLangGeometry)
return TQualifier::mapGeometryToSize(intermediate.getInputPrimitive()); if (language == EShLangGeometry) {
else if (language == EShLangTessControl) expectedSize = TQualifier::mapGeometryToSize(intermediate.getInputPrimitive());
return maxVertices; str = TQualifier::getGeometryString(intermediate.getInputPrimitive());
}
else if (language == EShLangTessControl) {
expectedSize = maxVertices;
str = "vertices";
}
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
else if (language == EShLangFragment) else if (language == EShLangFragment) {
return 3; //Number of vertices for Fragment shader is always three. // Number of vertices for Fragment shader is always three.
expectedSize = 3;
str = "vertices";
}
else if (language == EShLangMeshNV) { else if (language == EShLangMeshNV) {
unsigned int maxPrimitives = intermediate.getPrimitives() != TQualifier::layoutNotSet ? intermediate.getPrimitives() : 0; unsigned int maxPrimitives =
if (qualifier.builtIn == EbvPrimitiveIndicesNV) intermediate.getPrimitives() != TQualifier::layoutNotSet ? intermediate.getPrimitives() : 0;
return maxPrimitives * TQualifier::mapGeometryToSize(intermediate.getOutputPrimitive()); if (qualifier.builtIn == EbvPrimitiveIndicesNV) {
else if (qualifier.isPerPrimitive()) expectedSize = maxPrimitives * TQualifier::mapGeometryToSize(intermediate.getOutputPrimitive());
return maxPrimitives; str = "max_primitives*";
else str += TQualifier::getGeometryString(intermediate.getOutputPrimitive());
return maxVertices; }
else if (qualifier.isPerPrimitive()) {
expectedSize = maxPrimitives;
str = "max_primitives";
}
else {
expectedSize = maxVertices;
str = "max_vertices";
}
} }
#endif #endif
if (featureString)
else *featureString = str;
return 0; return expectedSize;
} }
void TParseContext::checkIoArrayConsistency(const TSourceLoc& loc, int requiredSize, const char* feature, TType& type, const TString& name) void TParseContext::checkIoArrayConsistency(const TSourceLoc& loc, int requiredSize, const char* feature, TType& type, const TString& name)
@@ -3739,7 +3751,7 @@ void TParseContext::declareArray(const TSourceLoc& loc, const TString& identifie
if (! symbolTable.atBuiltInLevel()) { if (! symbolTable.atBuiltInLevel()) {
if (isIoResizeArray(type)) { if (isIoResizeArray(type)) {
ioArraySymbolResizeList.push_back(symbol); ioArraySymbolResizeList.push_back(symbol);
checkIoArraysConsistency(loc, symbol->getType().getQualifier(), true); checkIoArraysConsistency(loc, true);
} else } else
fixIoArraySize(loc, symbol->getWritableType()); fixIoArraySize(loc, symbol->getWritableType());
} }
@@ -3792,7 +3804,7 @@ void TParseContext::declareArray(const TSourceLoc& loc, const TString& identifie
existingType.updateArraySizes(type); existingType.updateArraySizes(type);
if (isIoResizeArray(type)) if (isIoResizeArray(type))
checkIoArraysConsistency(loc, symbol->getType().getQualifier(), true); checkIoArraysConsistency(loc);
} }
// Policy and error check for needing a runtime sized array. // Policy and error check for needing a runtime sized array.
@@ -4284,7 +4296,7 @@ void TParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& newT
// Tracking for implicit sizing of array // Tracking for implicit sizing of array
if (isIoResizeArray(block->getType())) { if (isIoResizeArray(block->getType())) {
ioArraySymbolResizeList.push_back(block); ioArraySymbolResizeList.push_back(block);
checkIoArraysConsistency(loc, block->getType().getQualifier(), true); checkIoArraysConsistency(loc, true);
} else if (block->getType().isArray()) } else if (block->getType().isArray())
fixIoArraySize(loc, block->getWritableType()); fixIoArraySize(loc, block->getWritableType());
@@ -7116,7 +7128,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
// fix up // fix up
if (isIoResizeArray(blockType)) { if (isIoResizeArray(blockType)) {
ioArraySymbolResizeList.push_back(&variable); ioArraySymbolResizeList.push_back(&variable);
checkIoArraysConsistency(loc, blockType.getQualifier(), true); checkIoArraysConsistency(loc, true);
} else } else
fixIoArraySize(loc, variable.getWritableType()); fixIoArraySize(loc, variable.getWritableType());
@@ -7503,7 +7515,7 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con
error(loc, "cannot change previously set layout value", id, ""); error(loc, "cannot change previously set layout value", id, "");
if (language == EShLangTessControl) if (language == EShLangTessControl)
checkIoArraysConsistency(loc, publicType.qualifier); checkIoArraysConsistency(loc);
} }
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
if (publicType.shaderQualifiers.primitives != TQualifier::layoutNotSet) { if (publicType.shaderQualifiers.primitives != TQualifier::layoutNotSet) {
@@ -7540,7 +7552,7 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con
#endif #endif
if (intermediate.setInputPrimitive(publicType.shaderQualifiers.geometry)) { if (intermediate.setInputPrimitive(publicType.shaderQualifiers.geometry)) {
if (language == EShLangGeometry) if (language == EShLangGeometry)
checkIoArraysConsistency(loc, publicType.qualifier); checkIoArraysConsistency(loc);
} else } else
error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
break; break;
@@ -7699,6 +7711,14 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con
else else
error(loc, "can only apply to 'in'", "derivative_group_linearNV", ""); error(loc, "can only apply to 'in'", "derivative_group_linearNV", "");
} }
// Check mesh out array sizes, once all the necessary out qualifiers are defined.
if ((language == EShLangMeshNV) &&
(intermediate.getVertices() != TQualifier::layoutNotSet) &&
(intermediate.getPrimitives() != TQualifier::layoutNotSet) &&
(intermediate.getOutputPrimitive() != ElgNone))
{
checkIoArraysConsistency(loc);
}
#endif #endif
const TQualifier& qualifier = publicType.qualifier; const TQualifier& qualifier = publicType.qualifier;

View File

@@ -299,8 +299,8 @@ public:
void fixIoArraySize(const TSourceLoc&, TType&); void fixIoArraySize(const TSourceLoc&, TType&);
void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier); void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier);
void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base); void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base);
void checkIoArraysConsistency(const TSourceLoc&, const TQualifier&, bool tailOnly = false); void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false);
int getIoArrayImplicitSize(const TQualifier&) const; int getIoArrayImplicitSize(const TQualifier&, TString* featureString = nullptr) const;
void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&); void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&);
TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right); TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);