Handle resizing/error checks for mesh shader out arrays
This commit is contained in:
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user