Implement GL_NV_cooperative_matrix
This commit is contained in:
parent
ec484527b6
commit
4605e2ed2b
37 changed files with 5630 additions and 4211 deletions
138
glslang/MachineIndependent/ParseHelper.cpp
Executable file → Normal file
138
glslang/MachineIndependent/ParseHelper.cpp
Executable file → Normal file
|
|
@ -275,6 +275,12 @@ void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>&
|
|||
if (tokens.size() != 1)
|
||||
error(loc, "extra tokens", "#pragma", "");
|
||||
intermediate.setUseVulkanMemoryModel();
|
||||
} else if (spvVersion.spv > 0 && tokens[0].compare("use_variable_pointers") == 0) {
|
||||
if (tokens.size() != 1)
|
||||
error(loc, "extra tokens", "#pragma", "");
|
||||
if (spvVersion.spv < glslang::EShTargetSpv_1_3)
|
||||
error(loc, "requires SPIR-V 1.3", "#pragma use_variable_pointers", "");
|
||||
intermediate.setUseVariablePointers();
|
||||
} else if (tokens[0].compare("once") == 0) {
|
||||
warn(loc, "not implemented", "#pragma once", "");
|
||||
} else if (tokens[0].compare("glslang_binary_double_output") == 0)
|
||||
|
|
@ -371,7 +377,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
|
|||
// basic type checks...
|
||||
variableCheck(base);
|
||||
|
||||
if (! base->isArray() && ! base->isMatrix() && ! base->isVector()) {
|
||||
if (! base->isArray() && ! base->isMatrix() && ! base->isVector() && ! base->getType().isCoopMat()) {
|
||||
if (base->getAsSymbolNode())
|
||||
error(loc, " left of '[' is not of type array, matrix, or vector ", base->getAsSymbolNode()->getName().c_str(), "");
|
||||
else
|
||||
|
|
@ -767,7 +773,7 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
|
|||
const char* feature = ".length() on vectors and matrices";
|
||||
requireProfile(loc, ~EEsProfile, feature);
|
||||
profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, feature);
|
||||
} else {
|
||||
} else if (!base->getType().isCoopMat()) {
|
||||
error(loc, "does not operate on this type:", field.c_str(), base->getType().getCompleteString().c_str());
|
||||
|
||||
return base;
|
||||
|
|
@ -784,6 +790,11 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
|
|||
return base;
|
||||
}
|
||||
|
||||
if (base->getType().isCoopMat()) {
|
||||
error(loc, "cannot apply to a cooperative matrix type:", ".", field.c_str());
|
||||
return base;
|
||||
}
|
||||
|
||||
// It's neither an array nor .length() if we get here,
|
||||
// leaving swizzles and struct/block dereferences.
|
||||
|
||||
|
|
@ -1204,6 +1215,13 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
|
|||
}
|
||||
result = addOutputArgumentConversions(*fnCandidate, *result->getAsAggregate());
|
||||
}
|
||||
|
||||
if (result->getAsTyped()->getType().isCoopMat() &&
|
||||
!result->getAsTyped()->getType().isParameterized()) {
|
||||
assert(fnCandidate->getBuiltInOp() == EOpCooperativeMatrixMulAdd);
|
||||
|
||||
result->setType(result->getAsAggregate()->getSequence()[2]->getAsTyped()->getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1430,6 +1448,8 @@ TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction
|
|||
length = type.getMatrixCols();
|
||||
else if (type.isVector())
|
||||
length = type.getVectorSize();
|
||||
else if (type.isCoopMat())
|
||||
return intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, intermNode, TType(EbtInt));
|
||||
else {
|
||||
// we should not get here, because earlier semantic checking should have prevented this path
|
||||
error(loc, ".length()", "unexpected use of .length()", "");
|
||||
|
|
@ -1456,7 +1476,8 @@ void TParseContext::addInputArgumentConversions(const TFunction& function, TInte
|
|||
// means take 'arguments' itself as the one argument.
|
||||
TIntermTyped* arg = function.getParamCount() == 1 ? arguments->getAsTyped() : (aggregate ? aggregate->getSequence()[i]->getAsTyped() : arguments->getAsTyped());
|
||||
if (*function[i].type != arg->getType()) {
|
||||
if (function[i].type->getQualifier().isParamInput()) {
|
||||
if (function[i].type->getQualifier().isParamInput() &&
|
||||
!function[i].type->isCoopMat()) {
|
||||
// In-qualified arguments just need an extra node added above the argument to
|
||||
// convert to the correct type.
|
||||
arg = intermediate.addConversion(EOpFunctionCall, *function[i].type, arg);
|
||||
|
|
@ -1524,7 +1545,14 @@ TIntermTyped* TParseContext::addOutputArgumentConversions(const TFunction& funct
|
|||
if (function[i].type->getQualifier().isParamOutput()) {
|
||||
// Out-qualified arguments need to use the topology set up above.
|
||||
// do the " ...(tempArg, ...), arg = tempArg" bit from above
|
||||
TVariable* tempArg = makeInternalVariable("tempArg", *function[i].type);
|
||||
TType paramType;
|
||||
paramType.shallowCopy(*function[i].type);
|
||||
if (arguments[i]->getAsTyped()->getType().isParameterized() &&
|
||||
!paramType.isParameterized()) {
|
||||
paramType.shallowCopy(arguments[i]->getAsTyped()->getType());
|
||||
paramType.copyTypeParameters(*arguments[i]->getAsTyped()->getType().getTypeParameters());
|
||||
}
|
||||
TVariable* tempArg = makeInternalVariable("tempArg", paramType);
|
||||
tempArg->getWritableType().getQualifier().makeTemporary();
|
||||
TIntermSymbol* tempArgNode = intermediate.addSymbol(*tempArg, intermNode.getLoc());
|
||||
TIntermTyped* tempAssign = intermediate.addAssign(EOpAssign, arguments[i]->getAsTyped(), tempArgNode, arguments[i]->getLoc());
|
||||
|
|
@ -2913,6 +2941,16 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
|
|||
return true;
|
||||
}
|
||||
|
||||
if (type.isCoopMat() && function.getParamCount() != 1) {
|
||||
error(loc, "wrong number of arguments", "constructor", "");
|
||||
return true;
|
||||
}
|
||||
if (type.isCoopMat() &&
|
||||
!(function[0].type->isScalar() || function[0].type->isCoopMat())) {
|
||||
error(loc, "Cooperative matrix constructor argument must be scalar or cooperative matrix", "constructor", "");
|
||||
return true;
|
||||
}
|
||||
|
||||
TIntermTyped* typed = node->getAsTyped();
|
||||
if (typed == nullptr) {
|
||||
error(loc, "constructor argument does not have a type", "constructor", "");
|
||||
|
|
@ -3534,7 +3572,7 @@ bool TParseContext::containsFieldWithBasicType(const TType& type, TBasicType bas
|
|||
//
|
||||
// Do size checking for an array type's size.
|
||||
//
|
||||
void TParseContext::arraySizeCheck(const TSourceLoc& loc, TIntermTyped* expr, TArraySize& sizePair)
|
||||
void TParseContext::arraySizeCheck(const TSourceLoc& loc, TIntermTyped* expr, TArraySize& sizePair, const char *sizeType)
|
||||
{
|
||||
bool isConst = false;
|
||||
sizePair.node = nullptr;
|
||||
|
|
@ -3554,18 +3592,24 @@ void TParseContext::arraySizeCheck(const TSourceLoc& loc, TIntermTyped* expr, TA
|
|||
TIntermSymbol* symbol = expr->getAsSymbolNode();
|
||||
if (symbol && symbol->getConstArray().size() > 0)
|
||||
size = symbol->getConstArray()[0].getIConst();
|
||||
} else if (expr->getAsUnaryNode() &&
|
||||
expr->getAsUnaryNode()->getOp() == glslang::EOpArrayLength &&
|
||||
expr->getAsUnaryNode()->getOperand()->getType().isCoopMat()) {
|
||||
isConst = true;
|
||||
size = 1;
|
||||
sizePair.node = expr->getAsUnaryNode();
|
||||
}
|
||||
}
|
||||
|
||||
sizePair.size = size;
|
||||
|
||||
if (! isConst || (expr->getBasicType() != EbtInt && expr->getBasicType() != EbtUint)) {
|
||||
error(loc, "array size must be a constant integer expression", "", "");
|
||||
error(loc, sizeType, "", "must be a constant integer expression");
|
||||
return;
|
||||
}
|
||||
|
||||
if (size <= 0) {
|
||||
error(loc, "array size must be a positive integer", "", "");
|
||||
error(loc, sizeType, "", "must be a positive integer");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -3623,7 +3667,7 @@ bool TParseContext::arrayError(const TSourceLoc& loc, const TType& type)
|
|||
//
|
||||
void TParseContext::arraySizeRequiredCheck(const TSourceLoc& loc, const TArraySizes& arraySizes)
|
||||
{
|
||||
if (arraySizes.hasUnsized())
|
||||
if (!parsingBuiltins && arraySizes.hasUnsized())
|
||||
error(loc, "array size required", "", "");
|
||||
}
|
||||
|
||||
|
|
@ -3660,7 +3704,8 @@ void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qua
|
|||
arraySizes->clearInnerUnsized();
|
||||
}
|
||||
|
||||
if (arraySizes->isInnerSpecialization())
|
||||
if (arraySizes->isInnerSpecialization() &&
|
||||
(qualifier.storage != EvqTemporary && qualifier.storage != EvqGlobal && qualifier.storage != EvqShared && qualifier.storage != EvqConst))
|
||||
error(loc, "only outermost dimension of an array of arrays can be a specialization constant", "[]", "");
|
||||
|
||||
// desktop always allows outer-dimension-unsized variable arrays,
|
||||
|
|
@ -6035,9 +6080,18 @@ const TFunction* TParseContext::findFunction400(const TSourceLoc& loc, const TFu
|
|||
symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn);
|
||||
|
||||
// can 'from' convert to 'to'?
|
||||
const auto convertible = [this](const TType& from, const TType& to, TOperator, int) -> bool {
|
||||
const auto convertible = [this,builtIn](const TType& from, const TType& to, TOperator, int) -> bool {
|
||||
if (from == to)
|
||||
return true;
|
||||
if (from.coopMatParameterOK(to))
|
||||
return true;
|
||||
// Allow a sized array to be passed through an unsized array parameter, for coopMatLoad/Store functions
|
||||
if (builtIn && from.isArray() && to.isUnsizedArray()) {
|
||||
TType fromElementType(from, 0);
|
||||
TType toElementType(to, 0);
|
||||
if (fromElementType == toElementType)
|
||||
return true;
|
||||
}
|
||||
if (from.isArray() || to.isArray() || ! from.sameElementShape(to))
|
||||
return false;
|
||||
return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType());
|
||||
|
|
@ -6100,9 +6154,18 @@ const TFunction* TParseContext::findFunctionExplicitTypes(const TSourceLoc& loc,
|
|||
symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn);
|
||||
|
||||
// can 'from' convert to 'to'?
|
||||
const auto convertible = [this](const TType& from, const TType& to, TOperator, int) -> bool {
|
||||
const auto convertible = [this,builtIn](const TType& from, const TType& to, TOperator, int) -> bool {
|
||||
if (from == to)
|
||||
return true;
|
||||
if (from.coopMatParameterOK(to))
|
||||
return true;
|
||||
// Allow a sized array to be passed through an unsized array parameter, for coopMatLoad/Store functions
|
||||
if (builtIn && from.isArray() && to.isUnsizedArray()) {
|
||||
TType fromElementType(from, 0);
|
||||
TType toElementType(to, 0);
|
||||
if (fromElementType == toElementType)
|
||||
return true;
|
||||
}
|
||||
if (from.isArray() || to.isArray() || ! from.sameElementShape(to))
|
||||
return false;
|
||||
return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType());
|
||||
|
|
@ -6194,6 +6257,25 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
|
|||
type.copyArrayInnerSizes(publicType.arraySizes);
|
||||
arrayOfArrayVersionCheck(loc, type.getArraySizes());
|
||||
|
||||
if (type.isCoopMat()) {
|
||||
intermediate.setUseVulkanMemoryModel();
|
||||
intermediate.setUseStorageBuffer();
|
||||
|
||||
if (!publicType.typeParameters || publicType.typeParameters->getNumDims() != 4) {
|
||||
error(loc, "expected four type parameters", identifier.c_str(), "");
|
||||
}
|
||||
if (publicType.typeParameters &&
|
||||
publicType.typeParameters->getDimSize(0) != 16 &&
|
||||
publicType.typeParameters->getDimSize(0) != 32 &&
|
||||
publicType.typeParameters->getDimSize(0) != 64) {
|
||||
error(loc, "expected 16, 32, or 64 bits for first type parameter", identifier.c_str(), "");
|
||||
}
|
||||
} else {
|
||||
if (publicType.typeParameters && publicType.typeParameters->getNumDims() != 0) {
|
||||
error(loc, "unexpected type parameters", identifier.c_str(), "");
|
||||
}
|
||||
}
|
||||
|
||||
if (voidErrorCheck(loc, identifier, type.getBasicType()))
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -6218,6 +6300,10 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
|
|||
requireInt8Arithmetic(loc, "qualifier", "(u)int8 types can only be in uniform block or buffer storage");
|
||||
}
|
||||
|
||||
if (type.getQualifier().storage == EvqShared &&
|
||||
type.containsCoopMat())
|
||||
error(loc, "qualifier", "Cooperative matrix types must not be used in shared memory", "");
|
||||
|
||||
if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger))
|
||||
error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", "");
|
||||
if (identifier != "gl_FragDepth" && publicType.shaderQualifiers.layoutDepth != EldNone)
|
||||
|
|
@ -6809,6 +6895,33 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
case EOpConstructCooperativeMatrix:
|
||||
if (!node->getType().isCoopMat()) {
|
||||
if (type.getBasicType() != node->getType().getBasicType()) {
|
||||
node = intermediate.addConversion(type.getBasicType(), node);
|
||||
}
|
||||
node = intermediate.setAggregateOperator(node, EOpConstructCooperativeMatrix, type, node->getLoc());
|
||||
} else {
|
||||
switch (type.getBasicType()) {
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
case EbtFloat:
|
||||
assert(node->getType().getBasicType() == EbtFloat16);
|
||||
node = intermediate.addUnaryNode(EOpConvFloat16ToFloat, node, node->getLoc(), type);
|
||||
break;
|
||||
case EbtFloat16:
|
||||
assert(node->getType().getBasicType() == EbtFloat);
|
||||
node = intermediate.addUnaryNode(EOpConvFloatToFloat16, node, node->getLoc(), type);
|
||||
break;
|
||||
}
|
||||
// If it's a (non-specialization) constant, it must be folded.
|
||||
if (node->getAsUnaryNode()->getOperand()->getAsConstantUnion())
|
||||
return node->getAsUnaryNode()->getOperand()->getAsConstantUnion()->fold(op, node->getType());
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
default:
|
||||
error(loc, "unsupported construction", "", "");
|
||||
|
||||
|
|
@ -6895,6 +7008,9 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
|
|||
|
||||
if (memberType.containsOpaque())
|
||||
error(memberLoc, "member of block cannot be or contain a sampler, image, or atomic_uint type", typeList[member].type->getFieldName().c_str(), "");
|
||||
|
||||
if (memberType.containsCoopMat())
|
||||
error(memberLoc, "member of block cannot be or contain a cooperative matrix type", typeList[member].type->getFieldName().c_str(), "");
|
||||
}
|
||||
|
||||
// This might be a redeclaration of a built-in block. If so, redeclareBuiltinBlock() will
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue