Updated glslang.

This commit is contained in:
Бранимир Караџић
2020-05-22 20:59:38 -07:00
parent 5a863ea47d
commit 2a43c86c24
13 changed files with 128 additions and 56 deletions

View File

@@ -1448,7 +1448,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
builder.addExecutionMode(shaderEntry, spv::ExecutionModeXfb);
}
if (sourceExtensions.find("GL_EXT_ray_flags_primitive_culling") != sourceExtensions.end()) {
if (glslangIntermediate->getLayoutPrimitiveCulling()) {
builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingProvisionalKHR);
}

View File

@@ -1235,6 +1235,7 @@ struct TShaderQualifiers {
bool layoutDerivativeGroupQuads; // true if layout derivative_group_quadsNV set
bool layoutDerivativeGroupLinear; // true if layout derivative_group_linearNV set
int primitives; // mesh shader "max_primitives"DerivativeGroupLinear; // true if layout derivative_group_linearNV set
bool layoutPrimitiveCulling; // true if layout primitive_culling set
TLayoutDepth getDepth() const { return layoutDepth; }
#else
TLayoutDepth getDepth() const { return EldNone; }
@@ -1268,6 +1269,7 @@ struct TShaderQualifiers {
layoutOverrideCoverage = false;
layoutDerivativeGroupQuads = false;
layoutDerivativeGroupLinear = false;
layoutPrimitiveCulling = false;
primitives = TQualifier::layoutNotSet;
interlockOrdering = EioNone;
#endif
@@ -1331,6 +1333,8 @@ struct TShaderQualifiers {
primitives = src.primitives;
if (src.interlockOrdering != EioNone)
interlockOrdering = src.interlockOrdering;
if (src.layoutPrimitiveCulling)
layoutPrimitiveCulling = src.layoutPrimitiveCulling;
#endif
}
};

View File

@@ -1,3 +1,3 @@
// This header is generated by the make-revision script.
#define GLSLANG_PATCH_LEVEL 3763
#define GLSLANG_PATCH_LEVEL 3766

View File

@@ -1733,12 +1733,14 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtUint64:
case EbtFloat:
case EbtDouble:
return true;
return version >= 400 || extensionRequested(E_GL_ARB_gpu_shader_fp64);
case EbtInt16:
case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
return (version >= 400 || extensionRequested(E_GL_ARB_gpu_shader_fp64)) &&
extensionRequested(E_GL_AMD_gpu_shader_int16);
case EbtFloat16:
return extensionRequested(E_GL_AMD_gpu_shader_half_float);
return (version >= 400 || extensionRequested(E_GL_ARB_gpu_shader_fp64)) &&
extensionRequested(E_GL_AMD_gpu_shader_half_float);
default:
return false;
}

View File

@@ -5173,6 +5173,12 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
}
}
}
if (id == "primitive_culling") {
requireExtensions(loc, 1, &E_GL_EXT_ray_flags_primitive_culling, "primitive culling");
publicType.shaderQualifiers.layoutPrimitiveCulling = true;
return;
}
#endif
error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), "");
@@ -6104,6 +6110,8 @@ void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQua
error(loc, message, "num_views", "");
if (shaderQualifiers.interlockOrdering != EioNone)
error(loc, message, TQualifier::getInterlockOrderingString(shaderQualifiers.interlockOrdering), "");
if (shaderQualifiers.layoutPrimitiveCulling)
error(loc, "can only be applied as standalone", "primitive_culling", "");
#endif
}
@@ -8368,6 +8376,16 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con
{
checkIoArraysConsistency(loc);
}
if (publicType.shaderQualifiers.layoutPrimitiveCulling) {
if (publicType.qualifier.storage != EvqTemporary)
error(loc, "layout qualifier can not have storage qualifiers", "primitive_culling","", "");
else {
intermediate.setLayoutPrimitiveCulling();
}
// Exit early as further checks are not valid
return;
}
#endif
const TQualifier& qualifier = publicType.qualifier;
@@ -8527,7 +8545,7 @@ const TTypeList* TParseContext::recordStructCopy(TStructRecord& record, const TT
size_t memberCount = tmpType->getStruct()->size();
size_t originHash = 0, tmpHash = 0;
std::hash<size_t> hasher;
for (uint32_t i = 0; i < memberCount; i++) {
for (size_t i = 0; i < memberCount; i++) {
size_t originMemberHash = hasher(originType->getStruct()->at(i).type->getQualifier().layoutPacking +
originType->getStruct()->at(i).type->getQualifier().layoutMatrix);
size_t tmpMemberHash = hasher(tmpType->getStruct()->at(i).type->getQualifier().layoutPacking +

View File

@@ -579,10 +579,7 @@ TDefaultGlslIoResolver::TDefaultGlslIoResolver(const TIntermediate& intermediate
int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) {
const TType& type = ent.symbol->getType();
const TString& name = IsAnonymous(ent.symbol->getName()) ?
ent.symbol->getType().getTypeName()
:
ent.symbol->getName();
const TString& name = getAccessName(ent.symbol);
if (currentStage != stage) {
preStage = currentStage;
currentStage = stage;
@@ -630,7 +627,7 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf
TVarSlotMap::iterator iter = storageSlotMap[resourceKey].find(name);
if (iter != storageSlotMap[resourceKey].end()) {
// If interface resource be found, set it has location and this symbol's new location
// equal the symbol's explicit location declarated in pre or next stage.
// equal the symbol's explicit location declaration in pre or next stage.
//
// vs: out vec4 a;
// fs: layout(..., location = 3,...) in vec4 a;
@@ -666,10 +663,7 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf
int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
const TType& type = ent.symbol->getType();
const TString& name = IsAnonymous(ent.symbol->getName()) ?
ent.symbol->getType().getTypeName()
:
ent.symbol->getName();
const TString& name = getAccessName(ent.symbol);
// kick out of not doing this
if (! doAutoLocationMapping()) {
return ent.newLocation = -1;
@@ -712,7 +706,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
TVarSlotMap::iterator iter = slotMap.find(name);
if (iter != slotMap.end()) {
// If uniform resource be found, set it has location and this symbol's new location
// equal the uniform's explicit location declarated in other stage.
// equal the uniform's explicit location declaration in other stage.
//
// vs: uniform vec4 a;
// fs: layout(..., location = 3,...) uniform vec4 a;
@@ -720,7 +714,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
location = iter->second;
}
if (! hasLocation) {
// No explicit location declaraten in other stage.
// No explicit location declaration in other stage.
// So we should find a new slot for this uniform.
//
// vs: uniform vec4 a;
@@ -729,7 +723,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
storageSlotMap[resourceKey][name] = location;
}
} else {
// the first uniform declarated in a program.
// the first uniform declaration in a program.
TVarSlotMap varSlotMap;
location = getFreeSlot(resourceKey, 0, size);
varSlotMap[name] = location;
@@ -740,11 +734,8 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) {
const TType& type = ent.symbol->getType();
const TString& name = IsAnonymous(ent.symbol->getName()) ?
ent.symbol->getType().getTypeName()
:
ent.symbol->getName();
// On OpenGL arrays of opaque types take a seperate binding for each element
const TString& name = getAccessName(ent.symbol);
// On OpenGL arrays of opaque types take a separate binding for each element
int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
TResourceType resource = getResourceType(type);
// don't need to handle uniform symbol, it will be handled in resolveUniformLocation
@@ -818,10 +809,7 @@ void TDefaultGlslIoResolver::endCollect(EShLanguage /*stage*/) {
void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
const TType& type = ent.symbol->getType();
const TString& name = IsAnonymous(ent.symbol->getName()) ?
ent.symbol->getType().getTypeName()
:
ent.symbol->getName();
const TString& name = getAccessName(ent.symbol);
TStorageQualifier storage = type.getQualifier().storage;
EShLanguage stage(EShLangCount);
switch (storage) {
@@ -881,10 +869,7 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink&
void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
const TType& type = ent.symbol->getType();
const TString& name = IsAnonymous(ent.symbol->getName()) ?
ent.symbol->getType().getTypeName()
:
ent.symbol->getName();
const TString& name = getAccessName(ent.symbol);
int resource = getResourceType(type);
if (type.getQualifier().hasBinding()) {
TVarSlotMap& varSlotMap = resourceSlotMap[resource];
@@ -907,6 +892,13 @@ void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink&
}
}
const TString& TDefaultGlslIoResolver::getAccessName(const TIntermSymbol* symbol)
{
return symbol->getBasicType() == EbtBlock ?
symbol->getType().getTypeName() :
symbol->getName();
}
//TDefaultGlslIoResolver end
/*

View File

@@ -203,6 +203,7 @@ public:
void endCollect(EShLanguage) override;
void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
const TString& getAccessName(const TIntermSymbol*);
// in/out symbol and uniform symbol are stored in the same resourceSlotMap, the storage key is used to identify each type of symbol.
// We use stage and storage qualifier to construct a storage key. it can help us identify the same storage resource used in different stage.
// if a resource is a program resource and we don't need know it usage stage, we can use same stage to build storage key.

View File

@@ -153,7 +153,7 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
if (vertices == TQualifier::layoutNotSet)
vertices = unit.vertices;
else if (vertices != unit.vertices) {
else if (unit.vertices != TQualifier::layoutNotSet && vertices != unit.vertices) {
if (language == EShLangGeometry || language == EShLangMeshNV)
error(infoSink, "Contradictory layout max_vertices values");
else if (language == EShLangTessControl)
@@ -172,12 +172,12 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
if (inputPrimitive == ElgNone)
inputPrimitive = unit.inputPrimitive;
else if (inputPrimitive != unit.inputPrimitive)
else if (unit.inputPrimitive != ElgNone && inputPrimitive != unit.inputPrimitive)
error(infoSink, "Contradictory input layout primitives");
if (outputPrimitive == ElgNone)
outputPrimitive = unit.outputPrimitive;
else if (outputPrimitive != unit.outputPrimitive)
else if (unit.outputPrimitive != ElgNone && outputPrimitive != unit.outputPrimitive)
error(infoSink, "Contradictory output layout primitives");
if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger)

View File

@@ -265,6 +265,7 @@ public:
computeDerivativeMode(LayoutDerivativeNone),
primitives(TQualifier::layoutNotSet),
numTaskNVBlocks(0),
layoutPrimitiveCulling(false),
autoMapBindings(false),
autoMapLocations(false),
flattenUniformArrays(false),
@@ -742,6 +743,8 @@ public:
void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; }
bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; }
ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; }
void setLayoutPrimitiveCulling() { layoutPrimitiveCulling = true; }
bool getLayoutPrimitiveCulling() const { return layoutPrimitiveCulling; }
bool setPrimitives(int m)
{
if (primitives != TQualifier::layoutNotSet)
@@ -974,6 +977,7 @@ protected:
ComputeDerivativeMode computeDerivativeMode;
int primitives;
int numTaskNVBlocks;
bool layoutPrimitiveCulling;
// Base shift values
std::array<unsigned int, EResCount> shiftBinding;

View File

@@ -92,8 +92,8 @@ public:
if (processedDerefs.find(&base) == processedDerefs.end()) {
processedDerefs.insert(&base);
uint32_t blockIndex = -1;
uint32_t offset = -1;
int blockIndex = -1;
int offset = -1;
TList<TIntermBinary*> derefs;
TString baseName = base.getName();

View File

@@ -68,7 +68,7 @@
// This should always increase, as some paths to do not consume
// a more major number.
// It should increment by one when new functionality is added.
#define GLSLANG_MINOR_VERSION 13
#define GLSLANG_MINOR_VERSION 14
//
// Call before doing any other compiler/linker operations.

View File

@@ -1169,7 +1169,7 @@ bool HlslParseContext::shouldFlatten(const TType& type, TStorageQualifier qualif
}
// Top level variable flattening: construct data
void HlslParseContext::flatten(const TVariable& variable, bool linkage)
void HlslParseContext::flatten(const TVariable& variable, bool linkage, bool arrayed)
{
const TType& type = variable.getType();
@@ -1181,8 +1181,15 @@ void HlslParseContext::flatten(const TVariable& variable, bool linkage)
TFlattenData(type.getQualifier().layoutBinding,
type.getQualifier().layoutLocation)));
// the item is a map pair, so first->second is the TFlattenData itself.
flatten(variable, type, entry.first->second, variable.getName(), linkage, type.getQualifier(), nullptr);
// if flattening arrayed io struct, array each member of dereferenced type
if (arrayed) {
const TType dereferencedType(type, 0);
flatten(variable, dereferencedType, entry.first->second, variable.getName(), linkage,
type.getQualifier(), type.getArraySizes());
} else {
flatten(variable, type, entry.first->second, variable.getName(), linkage,
type.getQualifier(), nullptr);
}
}
// Recursively flatten the given variable at the provided type, building the flattenData as we go.
@@ -1256,6 +1263,10 @@ int HlslParseContext::addFlattenedMember(const TVariable& variable, const TType&
}
}
// Only propagate arraysizes here for arrayed io
if (variable.getType().getQualifier().isArrayedIo(language) && builtInArraySizes != nullptr)
memberVariable->getWritableType().copyArraySizes(*builtInArraySizes);
flattenData.offsets.push_back(static_cast<int>(flattenData.members.size()));
flattenData.members.push_back(memberVariable);
@@ -2068,11 +2079,8 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
// Further this return/in/out transform by flattening, splitting, and assigning locations
const auto makeVariableInOut = [&](TVariable& variable) {
if (variable.getType().isStruct()) {
if (variable.getType().getQualifier().isArrayedIo(language)) {
if (variable.getType().containsBuiltIn())
split(variable);
} else if (shouldFlatten(variable.getType(), EvqVaryingIn /* not assigned yet, but close enough */, true))
flatten(variable, false /* don't track linkage here, it will be tracked in assignToInterface() */);
bool arrayed = variable.getType().getQualifier().isArrayedIo(language);
flatten(variable, false /* don't track linkage here, it will be tracked in assignToInterface() */, arrayed);
}
// TODO: flatten arrays too
// TODO: flatten everything in I/O
@@ -2733,17 +2741,33 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
wasSplit(binaryNode->getLeft());
};
// Return symbol if node is symbol or index ref
const auto getSymbol = [](const TIntermTyped* node) -> const TIntermSymbol* {
const TIntermSymbol* symbolNode = node->getAsSymbolNode();
if (symbolNode != nullptr)
return symbolNode;
const TIntermBinary* binaryNode = node->getAsBinaryNode();
if (binaryNode != nullptr && (binaryNode->getOp() == EOpIndexDirect || binaryNode->getOp() == EOpIndexIndirect))
return binaryNode->getLeft()->getAsSymbolNode();
return nullptr;
};
// Return true if this stage assigns clip position with potentially inverted Y
const auto assignsClipPos = [this](const TIntermTyped* node) -> bool {
return node->getType().getQualifier().builtIn == EbvPosition &&
(language == EShLangVertex || language == EShLangGeometry || language == EShLangTessEvaluation);
};
const TIntermSymbol* leftSymbol = getSymbol(left);
const TIntermSymbol* rightSymbol = getSymbol(right);
const bool isSplitLeft = wasSplit(left) || indexesSplit(left);
const bool isSplitRight = wasSplit(right) || indexesSplit(right);
const bool isFlattenLeft = wasFlattened(left);
const bool isFlattenRight = wasFlattened(right);
const bool isFlattenLeft = wasFlattened(leftSymbol);
const bool isFlattenRight = wasFlattened(rightSymbol);
// OK to do a single assign if neither side is split or flattened. Otherwise,
// fall through to a member-wise copy.
@@ -2791,10 +2815,10 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
memberCount = left->getType().getCumulativeArraySize();
if (isFlattenLeft)
leftVariables = &flattenMap.find(left->getAsSymbolNode()->getId())->second.members;
leftVariables = &flattenMap.find(leftSymbol->getId())->second.members;
if (isFlattenRight) {
rightVariables = &flattenMap.find(right->getAsSymbolNode()->getId())->second.members;
rightVariables = &flattenMap.find(rightSymbol->getId())->second.members;
} else {
// The RHS is not flattened. There are several cases:
// 1. 1 item to copy: Use the RHS directly.
@@ -2828,8 +2852,10 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
TStorageQualifier leftStorage = left->getType().getQualifier().storage;
TStorageQualifier rightStorage = right->getType().getQualifier().storage;
int leftOffset = findSubtreeOffset(*left);
int rightOffset = findSubtreeOffset(*right);
int leftOffsetStart = findSubtreeOffset(*left);
int rightOffsetStart = findSubtreeOffset(*right);
int leftOffset = leftOffsetStart;
int rightOffset = rightOffsetStart;
const auto getMember = [&](bool isLeft, const TType& type, int member, TIntermTyped* splitNode, int splitMember,
bool flattened)
@@ -2869,10 +2895,35 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
}
}
} else if (flattened && !shouldFlatten(derefType, isLeft ? leftStorage : rightStorage, false)) {
if (isLeft)
if (isLeft) {
// offset will cycle through variables for arrayed io
if (leftOffset >= static_cast<int>(leftVariables->size()))
leftOffset = leftOffsetStart;
subTree = intermediate.addSymbol(*(*leftVariables)[leftOffset++]);
else
} else {
// offset will cycle through variables for arrayed io
if (rightOffset >= static_cast<int>(rightVariables->size()))
rightOffset = rightOffsetStart;
subTree = intermediate.addSymbol(*(*rightVariables)[rightOffset++]);
}
// arrayed io
if (subTree->getType().isArray()) {
if (!arrayElement.empty()) {
const TType derefType(subTree->getType(), arrayElement.front());
subTree = intermediate.addIndex(EOpIndexDirect, subTree,
intermediate.addConstantUnion(arrayElement.front(), loc), loc);
subTree->setType(derefType);
} else {
// There's an index operation we should transfer to the output builtin.
assert(splitNode->getAsOperator() != nullptr &&
splitNode->getAsOperator()->getOp() == EOpIndexIndirect);
const TType splitDerefType(subTree->getType(), 0);
subTree = intermediate.addIndex(splitNode->getAsOperator()->getOp(), subTree,
splitNode->getAsBinaryNode()->getRight(), loc);
subTree->setType(splitDerefType);
}
}
} else {
// Index operator if it's an aggregate, else EOpNull
const TOperator accessOp = type.isArray() ? EOpIndexDirect
@@ -9911,8 +9962,8 @@ void HlslParseContext::addPatchConstantInvocation()
TVariable* pcfOutput = makeInternalVariable("@patchConstantOutput", outType);
pcfOutput->getWritableType().getQualifier().storage = EvqVaryingOut;
if (pcfOutput->getType().containsBuiltIn())
split(*pcfOutput);
if (pcfOutput->getType().isStruct())
flatten(*pcfOutput, false);
assignToInterface(*pcfOutput);

View File

@@ -276,7 +276,7 @@ protected:
void fixBuiltInIoType(TType&);
void flatten(const TVariable& variable, bool linkage);
void flatten(const TVariable& variable, bool linkage, bool arrayed = false);
int flatten(const TVariable& variable, const TType&, TFlattenData&, TString name, bool linkage,
const TQualifier& outerQualifier, const TArraySizes* builtInArraySizes);
int flattenStruct(const TVariable& variable, const TType&, TFlattenData&, TString name, bool linkage,