Update glslang

This commit is contained in:
Alex Szpakowski
2020-10-12 17:29:08 -03:00
parent dcf0968f05
commit d083c87d74
60 changed files with 8915 additions and 6065 deletions
@@ -35,5 +35,6 @@ static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shade
static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered";
static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density";
static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation";
static const char* const E_SPV_EXT_shader_atomic_float_add = "SPV_EXT_shader_atomic_float_add";
#endif // #ifndef GLSLextEXT_H
+5 -2
View File
@@ -1,5 +1,6 @@
/*
** Copyright (c) 2014-2016 The Khronos Group Inc.
** Copyright (c) 2014-2020 The Khronos Group Inc.
** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and/or associated documentation files (the "Materials"),
@@ -44,5 +45,7 @@ static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physi
static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer";
static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock";
static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock";
static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info";
static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing";
static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query";
#endif // #ifndef GLSLextKHR_H
+711 -274
View File
File diff suppressed because it is too large Load Diff
View File
+1 -1
View File
@@ -69,4 +69,4 @@ std::string SpvBuildLogger::getAllMessages() const {
} // end spv namespace
#endif
#endif
@@ -0,0 +1,50 @@
// Copyright (c) 2020 The Khronos Group Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and/or associated documentation files (the
// "Materials"), to deal in the Materials without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Materials, and to
// permit persons to whom the Materials are furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Materials.
//
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
// https://www.khronos.org/registry/
//
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
//
#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
#ifdef __cplusplus
extern "C" {
#endif
enum {
NonSemanticDebugPrintfRevision = 1,
NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff
};
enum NonSemanticDebugPrintfInstructions {
NonSemanticDebugPrintfDebugPrintf = 1,
NonSemanticDebugPrintfInstructionsMax = 0x7fffffff
};
#ifdef __cplusplus
}
#endif
#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
+12 -1
View File
@@ -625,6 +625,9 @@ namespace spv {
break;
}
case spv::OperandVariableLiteralStrings:
return nextInst;
// Execution mode might have extra literal operands. Skip them.
case spv::OperandExecutionMode:
return nextInst;
@@ -827,7 +830,15 @@ namespace spv {
[&](spv::Id& id) {
if (thisOpCode != spv::OpNop) {
++idCounter;
const std::uint32_t hashval = opCounter[thisOpCode] * thisOpCode * 50047 + idCounter + fnId * 117;
const std::uint32_t hashval =
// Explicitly cast operands to unsigned int to avoid integer
// promotion to signed int followed by integer overflow,
// which would result in undefined behavior.
static_cast<unsigned int>(opCounter[thisOpCode])
* thisOpCode
* 50047
+ idCounter
+ static_cast<unsigned int>(fnId) * 117;
if (isOldIdUnmapped(id))
localId(id, nextUnusedId(hashval % softTypeIdLimit + firstMappedID));
+164 -30
View File
@@ -1,6 +1,7 @@
//
// Copyright (C) 2014-2015 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@@ -496,7 +497,8 @@ Id Builder::makeFunctionType(Id returnType, const std::vector<Id>& paramTypes)
return type->getResultId();
}
Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format)
Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled,
ImageFormat format)
{
assert(sampled == 1 || sampled == 2);
@@ -601,16 +603,31 @@ Id Builder::makeSampledImageType(Id imageType)
}
#ifndef GLSLANG_WEB
Id Builder::makeAccelerationStructureNVType()
Id Builder::makeAccelerationStructureType()
{
Instruction *type;
if (groupedTypes[OpTypeAccelerationStructureNV].size() == 0) {
type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureNV);
groupedTypes[OpTypeAccelerationStructureNV].push_back(type);
if (groupedTypes[OpTypeAccelerationStructureKHR].size() == 0) {
type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureKHR);
groupedTypes[OpTypeAccelerationStructureKHR].push_back(type);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
} else {
type = groupedTypes[OpTypeAccelerationStructureNV].back();
type = groupedTypes[OpTypeAccelerationStructureKHR].back();
}
return type->getResultId();
}
Id Builder::makeRayQueryType()
{
Instruction *type;
if (groupedTypes[OpTypeRayQueryProvisionalKHR].size() == 0) {
type = new Instruction(getUniqueId(), NoType, OpTypeRayQueryProvisionalKHR);
groupedTypes[OpTypeRayQueryProvisionalKHR].push_back(type);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
} else {
type = groupedTypes[OpTypeRayQueryProvisionalKHR].back();
}
return type->getResultId();
@@ -1166,6 +1183,28 @@ void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int val
executionModes.push_back(std::unique_ptr<Instruction>(instr));
}
void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, const std::vector<unsigned>& literals)
{
Instruction* instr = new Instruction(OpExecutionMode);
instr->addIdOperand(entryPoint->getId());
instr->addImmediateOperand(mode);
for (auto literal : literals)
instr->addImmediateOperand(literal);
executionModes.push_back(std::unique_ptr<Instruction>(instr));
}
void Builder::addExecutionModeId(Function* entryPoint, ExecutionMode mode, const std::vector<Id>& operandIds)
{
Instruction* instr = new Instruction(OpExecutionModeId);
instr->addIdOperand(entryPoint->getId());
instr->addImmediateOperand(mode);
for (auto operandId : operandIds)
instr->addIdOperand(operandId);
executionModes.push_back(std::unique_ptr<Instruction>(instr));
}
void Builder::addName(Id id, const char* string)
{
Instruction* name = new Instruction(OpName);
@@ -1204,7 +1243,7 @@ void Builder::addDecoration(Id id, Decoration decoration, const char* s)
if (decoration == spv::DecorationMax)
return;
Instruction* dec = new Instruction(OpDecorateStringGOOGLE);
Instruction* dec = new Instruction(OpDecorateString);
dec->addIdOperand(id);
dec->addImmediateOperand(decoration);
dec->addStringOperand(s);
@@ -1212,6 +1251,34 @@ void Builder::addDecoration(Id id, Decoration decoration, const char* s)
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
void Builder::addDecoration(Id id, Decoration decoration, const std::vector<unsigned>& literals)
{
if (decoration == spv::DecorationMax)
return;
Instruction* dec = new Instruction(OpDecorate);
dec->addIdOperand(id);
dec->addImmediateOperand(decoration);
for (auto literal : literals)
dec->addImmediateOperand(literal);
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
void Builder::addDecoration(Id id, Decoration decoration, const std::vector<const char*>& strings)
{
if (decoration == spv::DecorationMax)
return;
Instruction* dec = new Instruction(OpDecorateString);
dec->addIdOperand(id);
dec->addImmediateOperand(decoration);
for (auto string : strings)
dec->addStringOperand(string);
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration)
{
if (decoration == spv::DecorationMax)
@@ -1225,6 +1292,21 @@ void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration)
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
void Builder::addDecorationId(Id id, Decoration decoration, const std::vector<Id>& operandIds)
{
if(decoration == spv::DecorationMax)
return;
Instruction* dec = new Instruction(OpDecorateId);
dec->addIdOperand(id);
dec->addImmediateOperand(decoration);
for (auto operandId : operandIds)
dec->addIdOperand(operandId);
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num)
{
if (decoration == spv::DecorationMax)
@@ -1254,6 +1336,36 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector<unsigned>& literals)
{
if (decoration == spv::DecorationMax)
return;
Instruction* dec = new Instruction(OpMemberDecorate);
dec->addIdOperand(id);
dec->addImmediateOperand(member);
dec->addImmediateOperand(decoration);
for (auto literal : literals)
dec->addImmediateOperand(literal);
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector<const char*>& strings)
{
if (decoration == spv::DecorationMax)
return;
Instruction* dec = new Instruction(OpMemberDecorateString);
dec->addIdOperand(id);
dec->addImmediateOperand(member);
dec->addImmediateOperand(decoration);
for (auto string : strings)
dec->addStringOperand(string);
decorations.push_back(std::unique_ptr<Instruction>(dec));
}
// Comments in header
Function* Builder::makeEntryPoint(const char* entryPoint)
{
@@ -1270,7 +1382,8 @@ Function* Builder::makeEntryPoint(const char* entryPoint)
// Comments in header
Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name,
const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& decorations, Block **entry)
const std::vector<Id>& paramTypes,
const std::vector<std::vector<Decoration>>& decorations, Block **entry)
{
// Make the function and initial instructions in it
Id typeId = makeFunctionType(returnType, paramTypes);
@@ -1279,9 +1392,12 @@ Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const
// Set up the precisions
setPrecision(function->getId(), precision);
function->setReturnPrecision(precision);
for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) {
for (int d = 0; d < (int)decorations[p].size(); ++d)
for (int d = 0; d < (int)decorations[p].size(); ++d) {
addDecoration(firstParamId + p, decorations[p][d]);
function->addParamPrecision(p, decorations[p][d]);
}
}
// CFG
@@ -1338,7 +1454,7 @@ void Builder::makeDiscard()
}
// Comments in header
Id Builder::createVariable(StorageClass storageClass, Id type, const char* name, Id initializer)
Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name, Id initializer)
{
Id pointerType = makePointer(storageClass, type);
Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable);
@@ -1360,6 +1476,7 @@ Id Builder::createVariable(StorageClass storageClass, Id type, const char* name,
if (name)
addName(inst->getResultId(), name);
setPrecision(inst->getResultId(), precision);
return inst->getResultId();
}
@@ -1373,7 +1490,8 @@ Id Builder::createUndefined(Id type)
}
// av/vis/nonprivate are unnecessary and illegal for some storage classes.
spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const
spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
const
{
switch (sc) {
case spv::StorageClassUniform:
@@ -1392,7 +1510,8 @@ spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAc
}
// Comments in header
void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope,
unsigned int alignment)
{
Instruction* store = new Instruction(OpStore);
store->addIdOperand(lValue);
@@ -1414,7 +1533,8 @@ void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAcce
}
// Comments in header
Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
Id Builder::createLoad(Id lValue, spv::Decoration precision, spv::MemoryAccessMask memoryAccess,
spv::Scope scope, unsigned int alignment)
{
Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad);
load->addIdOperand(lValue);
@@ -1432,6 +1552,7 @@ Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope
}
buildPoint->addInstruction(std::unique_ptr<Instruction>(load));
setPrecision(load->getResultId(), precision);
return load->getResultId();
}
@@ -1495,7 +1616,8 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
// Generate code for spec constants if in spec constant operation
// generation mode.
if (generatingOpCodeForSpecConst) {
return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite), std::vector<Id>(1, index));
return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite),
std::vector<Id>(1, index));
}
Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
extract->addIdOperand(composite);
@@ -1697,7 +1819,8 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector<IdImmediate>& opera
return op->getResultId();
}
Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands, const std::vector<unsigned>& literals)
Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands,
const std::vector<unsigned>& literals)
{
Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp);
op->addImmediateOperand((unsigned) opCode);
@@ -2144,7 +2267,7 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
Op op;
switch (getMostBasicTypeClass(valueType)) {
case OpTypeFloat:
op = equal ? OpFOrdEqual : OpFOrdNotEqual;
op = equal ? OpFOrdEqual : OpFUnordNotEqual;
break;
case OpTypeInt:
default:
@@ -2187,7 +2310,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
if (constituent == 0)
resultId = subResultId;
else
resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), precision);
resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId),
precision);
}
return resultId;
@@ -2196,7 +2320,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
// OpCompositeConstruct
Id Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constituents)
{
assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size()));
assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 &&
getNumTypeConstituents(typeId) == (int)constituents.size()));
if (generatingOpCodeForSpecConst) {
// Sometime, even in spec-constant-op mode, the constant composite to be
@@ -2609,7 +2734,8 @@ void Builder::clearAccessChain()
}
// Comments in header
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType,
AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
{
accessChain.coherentFlags |= coherentFlags;
accessChain.alignment |= alignment;
@@ -2649,7 +2775,7 @@ void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, sp
// If swizzle still exists, it is out-of-order or not full, we must load the target vector,
// extract and insert elements to perform writeMask and/or swizzle.
if (accessChain.swizzle.size() > 0) {
Id tempBaseId = createLoad(base);
Id tempBaseId = createLoad(base, spv::NoPrecision);
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
}
@@ -2663,7 +2789,8 @@ void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, sp
}
// Comments in header
Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType,
spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
{
Id id;
@@ -2687,17 +2814,19 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
if (constant) {
id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
setPrecision(id, precision);
} else {
Id lValue = NoResult;
if (spvVersion >= Spv_1_4) {
if (spvVersion >= Spv_1_4 && isValidInitializer(accessChain.base)) {
// make a new function variable for this r-value, using an initializer,
// and mark it as NonWritable so that downstream it can be detected as a lookup
// table
lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable",
accessChain.base);
lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base),
"indexable", accessChain.base);
addDecoration(lValue, DecorationNonWritable);
} else {
lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base),
"indexable");
// store into it
createStore(accessChain.base, lValue);
}
@@ -2706,9 +2835,8 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
accessChain.isRValue = false;
// load through the access chain
id = createLoad(collapseAccessChain());
id = createLoad(collapseAccessChain(), precision);
}
setPrecision(id, precision);
} else
id = accessChain.base; // no precision, it was set when this was defined
} else {
@@ -2721,8 +2849,13 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
}
// load through the access chain
id = createLoad(collapseAccessChain(), memoryAccess, scope, alignment);
setPrecision(id, precision);
id = collapseAccessChain();
// Apply nonuniform both to the access chain and the loaded value.
// Buffer accesses need the access chain decorated, and this is where
// loaded image types get decorated. TODO: This should maybe move to
// createImageTextureFunctionCall.
addDecoration(id, nonUniform);
id = createLoad(id, precision, memoryAccess, scope, alignment);
addDecoration(id, nonUniform);
}
@@ -3075,7 +3208,8 @@ void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
dumpSourceInstructions(iItr->first, *iItr->second, out);
}
void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<std::unique_ptr<Instruction> >& instructions) const
void Builder::dumpInstructions(std::vector<unsigned int>& out,
const std::vector<std::unique_ptr<Instruction> >& instructions) const
{
for (int i = 0; i < (int)instructions.size(); ++i) {
instructions[i]->dump(out);
+101 -37
View File
@@ -1,7 +1,8 @@
//
// Copyright (C) 2014-2015 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2015-2020 Google, Inc.
// Copyright (C) 2017 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@@ -94,6 +95,7 @@ public:
const char* file_c_str = str.c_str();
fileString->addStringOperand(file_c_str);
strings.push_back(std::unique_ptr<Instruction>(fileString));
module.mapInstruction(fileString);
stringIds[file_c_str] = strId;
return strId;
}
@@ -181,7 +183,9 @@ public:
Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols);
// accelerationStructureNV type
Id makeAccelerationStructureNVType();
Id makeAccelerationStructureType();
// rayQueryEXT type
Id makeRayQueryType();
// For querying about types.
Id getTypeId(Id resultId) const { return module.getTypeId(resultId); }
@@ -196,7 +200,8 @@ public:
Id getContainedTypeId(Id typeId) const;
Id getContainedTypeId(Id typeId, int) const;
StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); }
ImageFormat getImageTypeFormat(Id typeId) const { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
ImageFormat getImageTypeFormat(Id typeId) const
{ return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); }
bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); }
@@ -206,12 +211,17 @@ public:
bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); }
bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); }
bool isBoolType(Id typeId) { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
bool isIntType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
bool isUintType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
bool isBoolType(Id typeId)
{ return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
bool isIntType(Id typeId) const
{ return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
bool isUintType(Id typeId) const
{ return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; }
bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; }
bool isScalarType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; }
bool isScalarType(Id typeId) const
{ return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt ||
getTypeClass(typeId) == OpTypeBool; }
bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; }
bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; }
bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; }
@@ -221,7 +231,8 @@ public:
#else
bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; }
#endif
bool isAggregateType(Id typeId) const { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); }
bool isAggregateType(Id typeId) const
{ return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); }
bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; }
bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; }
bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
@@ -233,9 +244,17 @@ public:
bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); }
bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); }
unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); }
unsigned int getConstantScalar(Id resultId) const
{ return module.getInstruction(resultId)->getImmediateOperand(0); }
StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); }
bool isVariableOpCode(Op opcode) const { return opcode == OpVariable; }
bool isVariable(Id resultId) const { return isVariableOpCode(getOpCode(resultId)); }
bool isGlobalStorage(Id resultId) const { return getStorageClass(resultId) != StorageClassFunction; }
bool isGlobalVariable(Id resultId) const { return isVariable(resultId) && isGlobalStorage(resultId); }
// See if a resultId is valid for use as an initializer.
bool isValidInitializer(Id resultId) const { return isConstant(resultId) || isGlobalVariable(resultId); }
int getScalarTypeWidth(Id typeId) const
{
Id scalarTypeId = getScalarTypeId(typeId);
@@ -275,14 +294,22 @@ public:
// For making new constants (will return old constant if the requested one was already made).
Id makeBoolConstant(bool b, bool specConstant = false);
Id makeInt8Constant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); }
Id makeUint8Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(8), u, specConstant); }
Id makeInt16Constant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); }
Id makeUint16Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(16), u, specConstant); }
Id makeIntConstant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); }
Id makeUintConstant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(32), u, specConstant); }
Id makeInt64Constant(long long i, bool specConstant = false) { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); }
Id makeUint64Constant(unsigned long long u, bool specConstant = false) { return makeInt64Constant(makeUintType(64), u, specConstant); }
Id makeInt8Constant(int i, bool specConstant = false)
{ return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); }
Id makeUint8Constant(unsigned u, bool specConstant = false)
{ return makeIntConstant(makeUintType(8), u, specConstant); }
Id makeInt16Constant(int i, bool specConstant = false)
{ return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); }
Id makeUint16Constant(unsigned u, bool specConstant = false)
{ return makeIntConstant(makeUintType(16), u, specConstant); }
Id makeIntConstant(int i, bool specConstant = false)
{ return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); }
Id makeUintConstant(unsigned u, bool specConstant = false)
{ return makeIntConstant(makeUintType(32), u, specConstant); }
Id makeInt64Constant(long long i, bool specConstant = false)
{ return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); }
Id makeUint64Constant(unsigned long long u, bool specConstant = false)
{ return makeInt64Constant(makeUintType(64), u, specConstant); }
Id makeFloatConstant(float f, bool specConstant = false);
Id makeDoubleConstant(double d, bool specConstant = false);
Id makeFloat16Constant(float f16, bool specConstant = false);
@@ -294,13 +321,20 @@ public:
// Methods for adding information outside the CFG.
Instruction* addEntryPoint(ExecutionModel, Function*, const char* name);
void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1);
void addExecutionMode(Function*, ExecutionMode mode, const std::vector<unsigned>& literals);
void addExecutionModeId(Function*, ExecutionMode mode, const std::vector<Id>& operandIds);
void addName(Id, const char* name);
void addMemberName(Id, int member, const char* name);
void addDecoration(Id, Decoration, int num = -1);
void addDecoration(Id, Decoration, const char*);
void addDecoration(Id, Decoration, const std::vector<unsigned>& literals);
void addDecoration(Id, Decoration, const std::vector<const char*>& strings);
void addDecorationId(Id id, Decoration, Id idDecoration);
void addDecorationId(Id id, Decoration, const std::vector<Id>& operandIds);
void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1);
void addMemberDecoration(Id, unsigned int member, Decoration, const char*);
void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector<unsigned>& literals);
void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector<const char*>& strings);
// At the end of what block do the next create*() instructions go?
void setBuildPoint(Block* bp) { buildPoint = bp; }
@@ -313,8 +347,8 @@ public:
// Make a shader-style function, and create its entry block if entry is non-zero.
// Return the function, pass back the entry.
// The returned pointer is only valid for the lifetime of this builder.
Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, const std::vector<Id>& paramTypes,
const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name,
const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
// Create a return. An 'implicit' return is one not appearing in the source
// code. In the case of an implicit return, no post-return block is inserted.
@@ -327,16 +361,20 @@ public:
void makeDiscard();
// Create a global or function local or IO variable.
Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult);
Id createVariable(Decoration precision, StorageClass, Id type, const char* name = nullptr,
Id initializer = NoResult);
// Create an intermediate with an undefined value.
Id createUndefined(Id type);
// Store into an Id and return the l-value
void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
// Load from an Id and return it
Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
Id createLoad(Id lValue, spv::Decoration precision,
spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
// Create an OpAccessChain instruction
Id createAccessChain(StorageClass, Id base, const std::vector<Id>& offsets);
@@ -495,7 +533,7 @@ public:
// recursion stack can hold the memory for it.
//
void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector<int>& caseValues,
const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB); // return argument
const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB);
// Add a branch to the innermost switch's merge block.
void addSwitchBreak();
@@ -512,7 +550,7 @@ public:
Block &head, &body, &merge, &continue_target;
private:
LoopBlocks();
LoopBlocks& operator=(const LoopBlocks&);
LoopBlocks& operator=(const LoopBlocks&) = delete;
};
// Start a new loop and prepare the builder to generate code for it. Until
@@ -569,10 +607,13 @@ public:
std::vector<Id> indexChain;
Id instr; // cache the instruction that generates this access chain
std::vector<unsigned> swizzle; // each std::vector element selects the next GLSL component number
Id component; // a dynamic component index, can coexist with a swizzle, done after the swizzle, NoResult if not present
Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present
Id component; // a dynamic component index, can coexist with a swizzle,
// done after the swizzle, NoResult if not present
Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied;
// NoType unless a swizzle or component is present
bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value
unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. Only tracks base and (optional) component selection alignment.
unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment.
// Only tracks base and (optional) component selection alignment.
// Accumulate whether anything in the chain of structures has coherent decorations.
struct CoherentFlags {
@@ -583,12 +624,17 @@ public:
CoherentFlags operator |=(const CoherentFlags &other) { return *this; }
#else
bool isVolatile() const { return volatil; }
bool anyCoherent() const {
return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent ||
subgroupcoherent || shadercallcoherent;
}
unsigned coherent : 1;
unsigned devicecoherent : 1;
unsigned queuefamilycoherent : 1;
unsigned workgroupcoherent : 1;
unsigned subgroupcoherent : 1;
unsigned shadercallcoherent : 1;
unsigned nonprivate : 1;
unsigned volatil : 1;
unsigned isImage : 1;
@@ -599,6 +645,7 @@ public:
queuefamilycoherent = 0;
workgroupcoherent = 0;
subgroupcoherent = 0;
shadercallcoherent = 0;
nonprivate = 0;
volatil = 0;
isImage = 0;
@@ -610,6 +657,7 @@ public:
queuefamilycoherent |= other.queuefamilycoherent;
workgroupcoherent |= other.workgroupcoherent;
subgroupcoherent |= other.subgroupcoherent;
shadercallcoherent |= other.shadercallcoherent;
nonprivate |= other.nonprivate;
volatil |= other.volatil;
isImage |= other.isImage;
@@ -655,11 +703,13 @@ public:
}
// push new swizzle onto the end of any existing swizzle, merging into a single swizzle
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType,
AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
// push a dynamic component selection onto the access chain, only applicable with a
// non-trivial swizzle or no swizzle
void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags,
unsigned int alignment)
{
if (accessChain.swizzle.size() != 1) {
accessChain.component = component;
@@ -671,10 +721,18 @@ public:
}
// use accessChain and swizzle to store value
void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
// use accessChain and swizzle to load an r-value
Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType,
spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax,
unsigned int alignment = 0);
// Return whether or not the access chain can be represented in SPIR-V
// as an l-value.
// E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be.
bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; }
// get the direct pointer for an l-value
Id accessChainGetLValue();
@@ -703,7 +761,8 @@ public:
void createBranch(Block* block);
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, const std::vector<unsigned int>& operands);
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
const std::vector<unsigned int>& operands);
// Sets to generate opcode for specialization constants.
void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }
@@ -729,7 +788,8 @@ public:
void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector<unsigned int>&) const;
void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
void dumpModuleProcesses(std::vector<unsigned int>&) const;
spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const;
spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
const;
unsigned int spvVersion; // the version of SPIR-V to emit in the header
SourceLanguage source;
@@ -764,10 +824,14 @@ public:
std::vector<std::unique_ptr<Instruction> > externals;
std::vector<std::unique_ptr<Function> > functions;
// not output, internally used for quick & dirty canonical (unique) creation
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants; // map type opcodes to constant inst.
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants; // map struct-id to constant instructions
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes; // map type opcodes to type instructions
// not output, internally used for quick & dirty canonical (unique) creation
// map type opcodes to constant inst.
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants;
// map struct-id to constant instructions
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants;
// map type opcodes to type instructions
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes;
// stack of switches
std::stack<Block*> switchMerges;
+65 -38
View File
@@ -1,6 +1,6 @@
//
// Copyright (C) 2014-2016 LunarG, Inc.
// Copyright (C) 2018 Google, Inc.
// Copyright (C) 2018-2020 Google, Inc.
//
// All rights reserved.
//
@@ -67,6 +67,8 @@ spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLog
logger->missingFunctionality("Target version for SPIRV-Tools validator");
return spv_target_env::SPV_ENV_VULKAN_1_1;
}
case glslang::EShTargetVulkan_1_2:
return spv_target_env::SPV_ENV_VULKAN_1_2;
default:
break;
}
@@ -78,6 +80,39 @@ spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLog
return spv_target_env::SPV_ENV_UNIVERSAL_1_0;
}
// Callback passed to spvtools::Optimizer::SetMessageConsumer
void OptimizerMesssageConsumer(spv_message_level_t level, const char *source,
const spv_position_t &position, const char *message)
{
auto &out = std::cerr;
switch (level)
{
case SPV_MSG_FATAL:
case SPV_MSG_INTERNAL_ERROR:
case SPV_MSG_ERROR:
out << "error: ";
break;
case SPV_MSG_WARNING:
out << "warning: ";
break;
case SPV_MSG_INFO:
case SPV_MSG_DEBUG:
out << "info: ";
break;
default:
break;
}
if (source)
{
out << source << ":";
}
out << position.line << ":" << position.column << ":" << position.index << ":";
if (message)
{
out << " " << message;
}
out << std::endl;
}
// Use the SPIRV-Tools disassembler to print SPIR-V.
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv)
@@ -126,45 +161,14 @@ void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<
spvContextDestroy(context);
}
// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
// legalizing HLSL SPIR-V.
void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*, const SpvOptions* options)
// Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process.
void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger* logger, const SpvOptions* options)
{
spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
spv_target_env target_env = MapToSpirvToolsEnv(intermediate.getSpv(), logger);
spvtools::Optimizer optimizer(target_env);
optimizer.SetMessageConsumer(
[](spv_message_level_t level, const char *source, const spv_position_t &position, const char *message) {
auto &out = std::cerr;
switch (level)
{
case SPV_MSG_FATAL:
case SPV_MSG_INTERNAL_ERROR:
case SPV_MSG_ERROR:
out << "error: ";
break;
case SPV_MSG_WARNING:
out << "warning: ";
break;
case SPV_MSG_INFO:
case SPV_MSG_DEBUG:
out << "info: ";
break;
default:
break;
}
if (source)
{
out << source << ":";
}
out << position.line << ":" << position.column << ":" << position.index << ":";
if (message)
{
out << " " << message;
}
out << std::endl;
});
optimizer.SetMessageConsumer(OptimizerMesssageConsumer);
// If debug (specifically source line info) is being generated, propagate
// line information into all SPIR-V instructions. This avoids loss of
@@ -173,6 +177,9 @@ void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>
if (options->generateDebugInfo) {
optimizer.RegisterPass(spvtools::CreatePropagateLineInfoPass());
}
else if (options->stripDebugInfo) {
optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
}
optimizer.RegisterPass(spvtools::CreateWrapOpKillPass());
optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass());
optimizer.RegisterPass(spvtools::CreateMergeReturnPass());
@@ -205,7 +212,27 @@ void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>
}
spvtools::OptimizerOptions spvOptOptions;
spvOptOptions.set_run_validator(false); // The validator may run as a seperate step later on
optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on
optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
}
// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V. This is implicitly done by
// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if
// optimization is disabled.
void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate,
std::vector<unsigned int>& spirv, spv::SpvBuildLogger* logger)
{
spv_target_env target_env = MapToSpirvToolsEnv(intermediate.getSpv(), logger);
spvtools::Optimizer optimizer(target_env);
optimizer.SetMessageConsumer(OptimizerMesssageConsumer);
optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
spvtools::OptimizerOptions spvOptOptions;
optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on
optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
}
+11 -5
View File
@@ -52,9 +52,10 @@
namespace glslang {
struct SpvOptions {
SpvOptions() : generateDebugInfo(false), disableOptimizer(true),
SpvOptions() : generateDebugInfo(false), stripDebugInfo(false), disableOptimizer(true),
optimizeSize(false), disassemble(false), validate(false) { }
bool generateDebugInfo;
bool stripDebugInfo;
bool disableOptimizer;
bool optimizeSize;
bool disassemble;
@@ -70,10 +71,15 @@ void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& s
void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*, bool prelegalization);
// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
// legalizing HLSL SPIR-V.
void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*, const SpvOptions*);
// Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process.
void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*, const SpvOptions*);
// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V. This is implicitly done by
// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if
// optimization is disabled.
void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate,
std::vector<unsigned int>& spirv, spv::SpvBuildLogger*);
#endif
+12 -2
View File
@@ -46,7 +46,6 @@
#include "disassemble.h"
#include "doc.h"
#include "SpvTools.h"
namespace spv {
extern "C" {
@@ -75,6 +74,7 @@ enum ExtInstSet {
GLSLextAMDInst,
GLSLextNVInst,
OpenCLExtInst,
NonSemanticDebugPrintfExtInst,
};
// Container class for a single instance of a SPIR-V stream, with methods for disassembly.
@@ -480,8 +480,12 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
if (opCode == OpExtInst) {
ExtInstSet extInstSet = GLSL450Inst;
const char* name = idDescriptor[stream[word - 2]].c_str();
if (0 == memcmp("OpenCL", name, 6)) {
if (strcmp("OpenCL.std", name) == 0) {
extInstSet = OpenCLExtInst;
} else if (strcmp("OpenCL.DebugInfo.100", name) == 0) {
extInstSet = OpenCLExtInst;
} else if (strcmp("NonSemantic.DebugPrintf", name) == 0) {
extInstSet = NonSemanticDebugPrintfExtInst;
} else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 ||
strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 ||
strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 ||
@@ -505,6 +509,8 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
}
else if (extInstSet == GLSLextNVInst) {
out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")";
} else if (extInstSet == NonSemanticDebugPrintfExtInst) {
out << "(DebugPrintf)";
}
}
break;
@@ -512,6 +518,10 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
case OperandLiteralString:
numOperands -= disassembleString();
break;
case OperandVariableLiteralStrings:
while (numOperands > 0)
numOperands -= disassembleString();
return;
case OperandMemoryAccess:
outputMask(OperandMemoryAccess, stream[word++]);
--numOperands;
+224 -65
View File
@@ -1,5 +1,6 @@
//
// Copyright (C) 2014-2015 LunarG, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@@ -99,12 +100,12 @@ const char* ExecutionModelString(int model)
default: return "Bad";
case ExecutionModelRayGenerationNV: return "RayGenerationNV";
case ExecutionModelIntersectionNV: return "IntersectionNV";
case ExecutionModelAnyHitNV: return "AnyHitNV";
case ExecutionModelClosestHitNV: return "ClosestHitNV";
case ExecutionModelMissNV: return "MissNV";
case ExecutionModelCallableNV: return "CallableNV";
case ExecutionModelRayGenerationKHR: return "RayGenerationKHR";
case ExecutionModelIntersectionKHR: return "IntersectionKHR";
case ExecutionModelAnyHitKHR: return "AnyHitKHR";
case ExecutionModelClosestHitKHR: return "ClosestHitKHR";
case ExecutionModelMissKHR: return "MissKHR";
case ExecutionModelCallableKHR: return "CallableKHR";
}
}
@@ -133,7 +134,7 @@ const char* MemoryString(int mem)
}
}
const int ExecutionModeCeiling = 33;
const int ExecutionModeCeiling = 40;
const char* ExecutionModeString(int mode)
{
@@ -172,7 +173,21 @@ const char* ExecutionModeString(int mode)
case 31: return "ContractionOff";
case 32: return "Bad";
case 4446: return "PostDepthCoverage";
case ExecutionModeInitializer: return "Initializer";
case ExecutionModeFinalizer: return "Finalizer";
case ExecutionModeSubgroupSize: return "SubgroupSize";
case ExecutionModeSubgroupsPerWorkgroup: return "SubgroupsPerWorkgroup";
case ExecutionModeSubgroupsPerWorkgroupId: return "SubgroupsPerWorkgroupId";
case ExecutionModeLocalSizeId: return "LocalSizeId";
case ExecutionModeLocalSizeHintId: return "LocalSizeHintId";
case ExecutionModePostDepthCoverage: return "PostDepthCoverage";
case ExecutionModeDenormPreserve: return "DenormPreserve";
case ExecutionModeDenormFlushToZero: return "DenormFlushToZero";
case ExecutionModeSignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve";
case ExecutionModeRoundingModeRTE: return "RoundingModeRTE";
case ExecutionModeRoundingModeRTZ: return "RoundingModeRTZ";
case ExecutionModeStencilRefReplacingEXT: return "StencilRefReplacingEXT";
case ExecutionModeOutputLinesNV: return "OutputLinesNV";
case ExecutionModeOutputPrimitivesNV: return "OutputPrimitivesNV";
@@ -187,6 +202,11 @@ const char* ExecutionModeString(int mode)
case ExecutionModeShadingRateInterlockOrderedEXT: return "ShadingRateInterlockOrderedEXT";
case ExecutionModeShadingRateInterlockUnorderedEXT: return "ShadingRateInterlockUnorderedEXT";
case ExecutionModeMaxWorkgroupSizeINTEL: return "MaxWorkgroupSizeINTEL";
case ExecutionModeMaxWorkDimINTEL: return "MaxWorkDimINTEL";
case ExecutionModeNoGlobalOffsetINTEL: return "NoGlobalOffsetINTEL";
case ExecutionModeNumSIMDWorkitemsINTEL: return "NumSIMDWorkitemsINTEL";
case ExecutionModeCeiling:
default: return "Bad";
}
@@ -209,12 +229,12 @@ const char* StorageClassString(int StorageClass)
case 11: return "Image";
case 12: return "StorageBuffer";
case StorageClassRayPayloadNV: return "RayPayloadNV";
case StorageClassHitAttributeNV: return "HitAttributeNV";
case StorageClassIncomingRayPayloadNV: return "IncomingRayPayloadNV";
case StorageClassShaderRecordBufferNV: return "ShaderRecordBufferNV";
case StorageClassCallableDataNV: return "CallableDataNV";
case StorageClassIncomingCallableDataNV: return "IncomingCallableDataNV";
case StorageClassRayPayloadKHR: return "RayPayloadKHR";
case StorageClassHitAttributeKHR: return "HitAttributeKHR";
case StorageClassIncomingRayPayloadKHR: return "IncomingRayPayloadKHR";
case StorageClassShaderRecordBufferKHR: return "ShaderRecordBufferKHR";
case StorageClassCallableDataKHR: return "CallableDataKHR";
case StorageClassIncomingCallableDataKHR: return "IncomingCallableDataKHR";
case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT";
@@ -361,32 +381,33 @@ const char* BuiltInString(int builtIn)
case 4996: return "BaryCoordSmoothCentroidAMD";
case 4997: return "BaryCoordSmoothSampleAMD";
case 4998: return "BaryCoordPullModelAMD";
case BuiltInLaunchIdNV: return "LaunchIdNV";
case BuiltInLaunchSizeNV: return "LaunchSizeNV";
case BuiltInWorldRayOriginNV: return "WorldRayOriginNV";
case BuiltInWorldRayDirectionNV: return "WorldRayDirectionNV";
case BuiltInObjectRayOriginNV: return "ObjectRayOriginNV";
case BuiltInObjectRayDirectionNV: return "ObjectRayDirectionNV";
case BuiltInRayTminNV: return "RayTminNV";
case BuiltInRayTmaxNV: return "RayTmaxNV";
case BuiltInInstanceCustomIndexNV: return "InstanceCustomIndexNV";
case BuiltInObjectToWorldNV: return "ObjectToWorldNV";
case BuiltInWorldToObjectNV: return "WorldToObjectNV";
case BuiltInHitTNV: return "HitTNV";
case BuiltInHitKindNV: return "HitKindNV";
case BuiltInIncomingRayFlagsNV: return "IncomingRayFlagsNV";
case BuiltInViewportMaskNV: return "ViewportMaskNV";
case BuiltInSecondaryPositionNV: return "SecondaryPositionNV";
case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
case BuiltInPositionPerViewNV: return "PositionPerViewNV";
case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
case BuiltInLaunchIdKHR: return "LaunchIdKHR";
case BuiltInLaunchSizeKHR: return "LaunchSizeKHR";
case BuiltInWorldRayOriginKHR: return "WorldRayOriginKHR";
case BuiltInWorldRayDirectionKHR: return "WorldRayDirectionKHR";
case BuiltInObjectRayOriginKHR: return "ObjectRayOriginKHR";
case BuiltInObjectRayDirectionKHR: return "ObjectRayDirectionKHR";
case BuiltInRayTminKHR: return "RayTminKHR";
case BuiltInRayTmaxKHR: return "RayTmaxKHR";
case BuiltInInstanceCustomIndexKHR: return "InstanceCustomIndexKHR";
case BuiltInRayGeometryIndexKHR: return "RayGeometryIndexKHR";
case BuiltInObjectToWorldKHR: return "ObjectToWorldKHR";
case BuiltInWorldToObjectKHR: return "WorldToObjectKHR";
case BuiltInHitTKHR: return "HitTKHR";
case BuiltInHitKindKHR: return "HitKindKHR";
case BuiltInIncomingRayFlagsKHR: return "IncomingRayFlagsKHR";
case BuiltInViewportMaskNV: return "ViewportMaskNV";
case BuiltInSecondaryPositionNV: return "SecondaryPositionNV";
case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
case BuiltInPositionPerViewNV: return "PositionPerViewNV";
case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
// case BuiltInFragmentSizeNV: return "FragmentSizeNV"; // superseded by BuiltInFragSizeEXT
// case BuiltInInvocationsPerPixelNV: return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT
case BuiltInBaryCoordNV: return "BaryCoordNV";
case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
case BuiltInBaryCoordNV: return "BaryCoordNV";
case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
case BuiltInFragSizeEXT: return "FragSizeEXT";
case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT";
case BuiltInFragSizeEXT: return "FragSizeEXT";
case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT";
case 5264: return "FullyCoveredEXT";
@@ -890,6 +911,9 @@ const char* CapabilityString(int info)
case CapabilityPerViewAttributesNV: return "PerViewAttributesNV";
case CapabilityGroupNonUniformPartitionedNV: return "GroupNonUniformPartitionedNV";
case CapabilityRayTracingNV: return "RayTracingNV";
case CapabilityRayTracingProvisionalKHR: return "RayTracingProvisionalKHR";
case CapabilityRayQueryProvisionalKHR: return "RayQueryProvisionalKHR";
case CapabilityRayTraversalPrimitiveCullingProvisionalKHR: return "RayTraversalPrimitiveCullingProvisionalKHR";
case CapabilityComputeDerivativeGroupQuadsNV: return "ComputeDerivativeGroupQuadsNV";
case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV";
case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV";
@@ -933,6 +957,9 @@ const char* CapabilityString(int info)
case CapabilityIntegerFunctions2INTEL: return "CapabilityIntegerFunctions2INTEL";
case CapabilityAtomicFloat32AddEXT: return "AtomicFloat32AddEXT";
case CapabilityAtomicFloat64AddEXT: return "AtomicFloat64AddEXT";
default: return "Bad";
}
}
@@ -1264,6 +1291,7 @@ const char* OpcodeString(int op)
case 320: return "OpImageSparseRead";
case OpModuleProcessed: return "OpModuleProcessed";
case OpExecutionModeId: return "OpExecutionModeId";
case OpDecorateId: return "OpDecorateId";
case 333: return "OpGroupNonUniformElect";
@@ -1308,6 +1336,8 @@ const char* OpcodeString(int op)
case 4430: return "OpSubgroupAllEqualKHR";
case 4432: return "OpSubgroupReadInvocationKHR";
case OpAtomicFAddEXT: return "OpAtomicFAddEXT";
case 5000: return "OpGroupIAddNonUniformAMD";
case 5001: return "OpGroupFAddNonUniformAMD";
case 5002: return "OpGroupFMinNonUniformAMD";
@@ -1326,15 +1356,40 @@ const char* OpcodeString(int op)
case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE";
case OpGroupNonUniformPartitionNV: return "OpGroupNonUniformPartitionNV";
case OpReportIntersectionNV: return "OpReportIntersectionNV";
case OpIgnoreIntersectionNV: return "OpIgnoreIntersectionNV";
case OpTerminateRayNV: return "OpTerminateRayNV";
case OpTraceNV: return "OpTraceNV";
case OpTypeAccelerationStructureNV: return "OpTypeAccelerationStructureNV";
case OpExecuteCallableNV: return "OpExecuteCallableNV";
case OpReportIntersectionKHR: return "OpReportIntersectionKHR";
case OpIgnoreIntersectionKHR: return "OpIgnoreIntersectionKHR";
case OpTerminateRayKHR: return "OpTerminateRayKHR";
case OpTraceRayKHR: return "OpTraceRayKHR";
case OpTypeAccelerationStructureKHR: return "OpTypeAccelerationStructureKHR";
case OpExecuteCallableKHR: return "OpExecuteCallableKHR";
case OpImageSampleFootprintNV: return "OpImageSampleFootprintNV";
case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV";
case OpTypeRayQueryProvisionalKHR: return "OpTypeRayQueryProvisionalKHR";
case OpRayQueryInitializeKHR: return "OpRayQueryInitializeKHR";
case OpRayQueryTerminateKHR: return "OpRayQueryTerminateKHR";
case OpRayQueryGenerateIntersectionKHR: return "OpRayQueryGenerateIntersectionKHR";
case OpRayQueryConfirmIntersectionKHR: return "OpRayQueryConfirmIntersectionKHR";
case OpRayQueryProceedKHR: return "OpRayQueryProceedKHR";
case OpRayQueryGetIntersectionTypeKHR: return "OpRayQueryGetIntersectionTypeKHR";
case OpRayQueryGetRayTMinKHR: return "OpRayQueryGetRayTMinKHR";
case OpRayQueryGetRayFlagsKHR: return "OpRayQueryGetRayFlagsKHR";
case OpRayQueryGetIntersectionTKHR: return "OpRayQueryGetIntersectionTKHR";
case OpRayQueryGetIntersectionInstanceCustomIndexKHR: return "OpRayQueryGetIntersectionInstanceCustomIndexKHR";
case OpRayQueryGetIntersectionInstanceIdKHR: return "OpRayQueryGetIntersectionInstanceIdKHR";
case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: return "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR";
case OpRayQueryGetIntersectionGeometryIndexKHR: return "OpRayQueryGetIntersectionGeometryIndexKHR";
case OpRayQueryGetIntersectionPrimitiveIndexKHR: return "OpRayQueryGetIntersectionPrimitiveIndexKHR";
case OpRayQueryGetIntersectionBarycentricsKHR: return "OpRayQueryGetIntersectionBarycentricsKHR";
case OpRayQueryGetIntersectionFrontFaceKHR: return "OpRayQueryGetIntersectionFrontFaceKHR";
case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: return "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR";
case OpRayQueryGetIntersectionObjectRayDirectionKHR: return "OpRayQueryGetIntersectionObjectRayDirectionKHR";
case OpRayQueryGetIntersectionObjectRayOriginKHR: return "OpRayQueryGetIntersectionObjectRayOriginKHR";
case OpRayQueryGetWorldRayDirectionKHR: return "OpRayQueryGetWorldRayDirectionKHR";
case OpRayQueryGetWorldRayOriginKHR: return "OpRayQueryGetWorldRayOriginKHR";
case OpRayQueryGetIntersectionObjectToWorldKHR: return "OpRayQueryGetIntersectionObjectToWorldKHR";
case OpRayQueryGetIntersectionWorldToObjectKHR: return "OpRayQueryGetIntersectionWorldToObjectKHR";
case OpTypeCooperativeMatrixNV: return "OpTypeCooperativeMatrixNV";
case OpCooperativeMatrixLoadNV: return "OpCooperativeMatrixLoadNV";
case OpCooperativeMatrixStoreNV: return "OpCooperativeMatrixStoreNV";
@@ -1388,6 +1443,7 @@ void Parameterize()
InstructionDesc[OpMemoryModel].setResultAndType(false, false);
InstructionDesc[OpEntryPoint].setResultAndType(false, false);
InstructionDesc[OpExecutionMode].setResultAndType(false, false);
InstructionDesc[OpExecutionModeId].setResultAndType(false, false);
InstructionDesc[OpTypeVoid].setResultAndType(true, false);
InstructionDesc[OpTypeBool].setResultAndType(true, false);
InstructionDesc[OpTypeInt].setResultAndType(true, false);
@@ -1574,6 +1630,10 @@ void Parameterize()
InstructionDesc[OpExecutionMode].operands.push(OperandExecutionMode, "'Mode'");
InstructionDesc[OpExecutionMode].operands.push(OperandOptionalLiteral, "See <<Execution_Mode,Execution Mode>>");
InstructionDesc[OpExecutionModeId].operands.push(OperandId, "'Entry Point'");
InstructionDesc[OpExecutionModeId].operands.push(OperandExecutionMode, "'Mode'");
InstructionDesc[OpExecutionModeId].operands.push(OperandVariableIds, "See <<Execution_Mode,Execution Mode>>");
InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Width'");
InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Signedness'");
@@ -1667,7 +1727,7 @@ void Parameterize()
InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandId, "'Target'");
InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandDecoration, "");
InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandLiteralString, "'Literal String'");
InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandVariableLiteralStrings, "'Literal Strings'");
InstructionDesc[OpMemberDecorate].operands.push(OperandId, "'Structure Type'");
InstructionDesc[OpMemberDecorate].operands.push(OperandLiteralNumber, "'Member'");
@@ -1677,7 +1737,7 @@ void Parameterize()
InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandId, "'Structure Type'");
InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralNumber, "'Member'");
InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandDecoration, "");
InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralString, "'Literal String'");
InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandVariableLiteralStrings, "'Literal Strings'");
InstructionDesc[OpGroupDecorate].operands.push(OperandId, "'Decoration Group'");
InstructionDesc[OpGroupDecorate].operands.push(OperandVariableIds, "'Targets'");
@@ -2230,6 +2290,11 @@ void Parameterize()
InstructionDesc[OpAtomicIAdd].operands.push(OperandMemorySemantics, "'Semantics'");
InstructionDesc[OpAtomicIAdd].operands.push(OperandId, "'Value'");
InstructionDesc[OpAtomicFAddEXT].operands.push(OperandId, "'Pointer'");
InstructionDesc[OpAtomicFAddEXT].operands.push(OperandScope, "'Scope'");
InstructionDesc[OpAtomicFAddEXT].operands.push(OperandMemorySemantics, "'Semantics'");
InstructionDesc[OpAtomicFAddEXT].operands.push(OperandId, "'Value'");
InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Pointer'");
InstructionDesc[OpAtomicISub].operands.push(OperandScope, "'Scope'");
InstructionDesc[OpAtomicISub].operands.push(OperandMemorySemantics, "'Semantics'");
@@ -2694,31 +2759,125 @@ void Parameterize()
InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X");
InstructionDesc[OpTypeAccelerationStructureNV].setResultAndType(true, false);
InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
InstructionDesc[OpTraceNV].operands.push(OperandId, "'NV Acceleration Structure'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Flags'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Cull Mask'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Offset'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Stride'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Miss Index'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Origin'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMin'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Direction'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMax'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Payload'");
InstructionDesc[OpTraceNV].setResultAndType(false, false);
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'NV Acceleration Structure'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Flags'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Cull Mask'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Offset'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Stride'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Miss Index'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Origin'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMin'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Direction'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMax'");
InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Payload'");
InstructionDesc[OpTraceRayKHR].setResultAndType(false, false);
InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Parameter'");
InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Kind'");
InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Parameter'");
InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Kind'");
InstructionDesc[OpIgnoreIntersectionNV].setResultAndType(false, false);
InstructionDesc[OpIgnoreIntersectionKHR].setResultAndType(false, false);
InstructionDesc[OpTerminateRayNV].setResultAndType(false, false);
InstructionDesc[OpTerminateRayKHR].setResultAndType(false, false);
InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "SBT Record Index");
InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "CallableData ID");
InstructionDesc[OpExecuteCallableNV].setResultAndType(false, false);
InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "SBT Record Index");
InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "CallableData ID");
InstructionDesc[OpExecuteCallableKHR].setResultAndType(false, false);
// Ray Query
InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
InstructionDesc[OpTypeRayQueryProvisionalKHR].setResultAndType(true, false);
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'AccelerationS'");
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayFlags'");
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'CullMask'");
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Origin'");
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmin'");
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Direction'");
InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmax'");
InstructionDesc[OpRayQueryInitializeKHR].setResultAndType(false, false);
InstructionDesc[OpRayQueryTerminateKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryTerminateKHR].setResultAndType(false, false);
InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'THit'");
InstructionDesc[OpRayQueryGenerateIntersectionKHR].setResultAndType(false, false);
InstructionDesc[OpRayQueryConfirmIntersectionKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryConfirmIntersectionKHR].setResultAndType(false, false);
InstructionDesc[OpRayQueryProceedKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryProceedKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionTypeKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetRayTMinKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetRayTMinKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetRayFlagsKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetRayFlagsKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionTKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetWorldRayOriginKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetWorldRayOriginKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].setResultAndType(true, true);
InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'RayQuery'");
InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'Committed'");
InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].setResultAndType(true, true);
InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Sampled Image'");
InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coordinate'");
+1
View File
@@ -125,6 +125,7 @@ enum OperandClass {
OperandVariableLiteralId,
OperandLiteralNumber,
OperandLiteralString,
OperandVariableLiteralStrings,
OperandSource,
OperandExecutionModel,
OperandAddressing,
+2 -2
View File
@@ -784,8 +784,8 @@ inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value,
if (val.isInfinity()) {
// Fail the parse. Emulate standard behaviour by setting the value to
// the closest normal value, and set the fail bit on the stream.
value.set_value((value.isNegative() | negate_value) ? T::lowest()
: T::max());
value.set_value((value.isNegative() || negate_value) ? T::lowest()
: T::max());
is.setstate(std::ios_base::failbit);
}
return is;
+195 -5
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2014-2019 The Khronos Group Inc.
// Copyright (c) 2014-2020 The Khronos Group Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and/or associated documentation files (the "Materials"),
@@ -49,12 +49,12 @@ namespace spv {
typedef unsigned int Id;
#define SPV_VERSION 0x10400
#define SPV_REVISION 1
#define SPV_VERSION 0x10500
#define SPV_REVISION 3
static const unsigned int MagicNumber = 0x07230203;
static const unsigned int Version = 0x00010400;
static const unsigned int Revision = 1;
static const unsigned int Version = 0x00010500;
static const unsigned int Revision = 3;
static const unsigned int OpCodeMask = 0xffff;
static const unsigned int WordCountShift = 16;
@@ -78,11 +78,17 @@ enum ExecutionModel {
ExecutionModelKernel = 6,
ExecutionModelTaskNV = 5267,
ExecutionModelMeshNV = 5268,
ExecutionModelRayGenerationKHR = 5313,
ExecutionModelRayGenerationNV = 5313,
ExecutionModelIntersectionKHR = 5314,
ExecutionModelIntersectionNV = 5314,
ExecutionModelAnyHitKHR = 5315,
ExecutionModelAnyHitNV = 5315,
ExecutionModelClosestHitKHR = 5316,
ExecutionModelClosestHitNV = 5316,
ExecutionModelMissKHR = 5317,
ExecutionModelMissNV = 5317,
ExecutionModelCallableKHR = 5318,
ExecutionModelCallableNV = 5318,
ExecutionModelMax = 0x7fffffff,
};
@@ -162,6 +168,10 @@ enum ExecutionMode {
ExecutionModeSampleInterlockUnorderedEXT = 5369,
ExecutionModeShadingRateInterlockOrderedEXT = 5370,
ExecutionModeShadingRateInterlockUnorderedEXT = 5371,
ExecutionModeMaxWorkgroupSizeINTEL = 5893,
ExecutionModeMaxWorkDimINTEL = 5894,
ExecutionModeNoGlobalOffsetINTEL = 5895,
ExecutionModeNumSIMDWorkitemsINTEL = 5896,
ExecutionModeMax = 0x7fffffff,
};
@@ -179,14 +189,21 @@ enum StorageClass {
StorageClassAtomicCounter = 10,
StorageClassImage = 11,
StorageClassStorageBuffer = 12,
StorageClassCallableDataKHR = 5328,
StorageClassCallableDataNV = 5328,
StorageClassIncomingCallableDataKHR = 5329,
StorageClassIncomingCallableDataNV = 5329,
StorageClassRayPayloadKHR = 5338,
StorageClassRayPayloadNV = 5338,
StorageClassHitAttributeKHR = 5339,
StorageClassHitAttributeNV = 5339,
StorageClassIncomingRayPayloadKHR = 5342,
StorageClassIncomingRayPayloadNV = 5342,
StorageClassShaderRecordBufferKHR = 5343,
StorageClassShaderRecordBufferNV = 5343,
StorageClassPhysicalStorageBuffer = 5349,
StorageClassPhysicalStorageBufferEXT = 5349,
StorageClassCodeSectionINTEL = 5605,
StorageClassMax = 0x7fffffff,
};
@@ -465,11 +482,24 @@ enum Decoration {
DecorationRestrictPointerEXT = 5355,
DecorationAliasedPointer = 5356,
DecorationAliasedPointerEXT = 5356,
DecorationReferencedIndirectlyINTEL = 5602,
DecorationCounterBuffer = 5634,
DecorationHlslCounterBufferGOOGLE = 5634,
DecorationHlslSemanticGOOGLE = 5635,
DecorationUserSemantic = 5635,
DecorationUserTypeGOOGLE = 5636,
DecorationRegisterINTEL = 5825,
DecorationMemoryINTEL = 5826,
DecorationNumbanksINTEL = 5827,
DecorationBankwidthINTEL = 5828,
DecorationMaxPrivateCopiesINTEL = 5829,
DecorationSinglepumpINTEL = 5830,
DecorationDoublepumpINTEL = 5831,
DecorationMaxReplicatesINTEL = 5832,
DecorationSimpleDualPortINTEL = 5833,
DecorationMergeINTEL = 5834,
DecorationBankBitsINTEL = 5835,
DecorationForcePow2DepthINTEL = 5836,
DecorationMax = 0x7fffffff,
};
@@ -558,20 +588,35 @@ enum BuiltIn {
BuiltInFragmentSizeNV = 5292,
BuiltInFragInvocationCountEXT = 5293,
BuiltInInvocationsPerPixelNV = 5293,
BuiltInLaunchIdKHR = 5319,
BuiltInLaunchIdNV = 5319,
BuiltInLaunchSizeKHR = 5320,
BuiltInLaunchSizeNV = 5320,
BuiltInWorldRayOriginKHR = 5321,
BuiltInWorldRayOriginNV = 5321,
BuiltInWorldRayDirectionKHR = 5322,
BuiltInWorldRayDirectionNV = 5322,
BuiltInObjectRayOriginKHR = 5323,
BuiltInObjectRayOriginNV = 5323,
BuiltInObjectRayDirectionKHR = 5324,
BuiltInObjectRayDirectionNV = 5324,
BuiltInRayTminKHR = 5325,
BuiltInRayTminNV = 5325,
BuiltInRayTmaxKHR = 5326,
BuiltInRayTmaxNV = 5326,
BuiltInInstanceCustomIndexKHR = 5327,
BuiltInInstanceCustomIndexNV = 5327,
BuiltInObjectToWorldKHR = 5330,
BuiltInObjectToWorldNV = 5330,
BuiltInWorldToObjectKHR = 5331,
BuiltInWorldToObjectNV = 5331,
BuiltInHitTKHR = 5332,
BuiltInHitTNV = 5332,
BuiltInHitKindKHR = 5333,
BuiltInHitKindNV = 5333,
BuiltInIncomingRayFlagsKHR = 5351,
BuiltInIncomingRayFlagsNV = 5351,
BuiltInRayGeometryIndexKHR = 5352,
BuiltInWarpsPerSMNV = 5374,
BuiltInSMCountNV = 5375,
BuiltInWarpIDNV = 5376,
@@ -601,6 +646,13 @@ enum LoopControlShift {
LoopControlIterationMultipleShift = 6,
LoopControlPeelCountShift = 7,
LoopControlPartialCountShift = 8,
LoopControlInitiationIntervalINTELShift = 16,
LoopControlMaxConcurrencyINTELShift = 17,
LoopControlDependencyArrayINTELShift = 18,
LoopControlPipelineEnableINTELShift = 19,
LoopControlLoopCoalesceINTELShift = 20,
LoopControlMaxInterleavingINTELShift = 21,
LoopControlSpeculatedIterationsINTELShift = 22,
LoopControlMax = 0x7fffffff,
};
@@ -615,6 +667,13 @@ enum LoopControlMask {
LoopControlIterationMultipleMask = 0x00000040,
LoopControlPeelCountMask = 0x00000080,
LoopControlPartialCountMask = 0x00000100,
LoopControlInitiationIntervalINTELMask = 0x00010000,
LoopControlMaxConcurrencyINTELMask = 0x00020000,
LoopControlDependencyArrayINTELMask = 0x00040000,
LoopControlPipelineEnableINTELMask = 0x00080000,
LoopControlLoopCoalesceINTELMask = 0x00100000,
LoopControlMaxInterleavingINTELMask = 0x00200000,
LoopControlSpeculatedIterationsINTELMask = 0x00400000,
};
enum FunctionControlShift {
@@ -709,6 +768,7 @@ enum Scope {
ScopeInvocation = 4,
ScopeQueueFamily = 5,
ScopeQueueFamilyKHR = 5,
ScopeShaderCallKHR = 6,
ScopeMax = 0x7fffffff,
};
@@ -833,6 +893,8 @@ enum Capability {
CapabilitySignedZeroInfNanPreserve = 4466,
CapabilityRoundingModeRTE = 4467,
CapabilityRoundingModeRTZ = 4468,
CapabilityRayQueryProvisionalKHR = 4471,
CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478,
CapabilityFloat16ImageAMD = 5008,
CapabilityImageGatherBiasLodAMD = 5009,
CapabilityFragmentMaskAMD = 5010,
@@ -886,6 +948,7 @@ enum Capability {
CapabilityPhysicalStorageBufferAddresses = 5347,
CapabilityPhysicalStorageBufferAddressesEXT = 5347,
CapabilityComputeDerivativeGroupLinearNV = 5350,
CapabilityRayTracingProvisionalKHR = 5353,
CapabilityCooperativeMatrixNV = 5357,
CapabilityFragmentShaderSampleInterlockEXT = 5363,
CapabilityFragmentShaderShadingRateInterlockEXT = 5372,
@@ -897,12 +960,70 @@ enum Capability {
CapabilitySubgroupImageBlockIOINTEL = 5570,
CapabilitySubgroupImageMediaBlockIOINTEL = 5579,
CapabilityIntegerFunctions2INTEL = 5584,
CapabilityFunctionPointersINTEL = 5603,
CapabilityIndirectReferencesINTEL = 5604,
CapabilitySubgroupAvcMotionEstimationINTEL = 5696,
CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
CapabilityFPGAMemoryAttributesINTEL = 5824,
CapabilityUnstructuredLoopControlsINTEL = 5886,
CapabilityFPGALoopControlsINTEL = 5888,
CapabilityKernelAttributesINTEL = 5892,
CapabilityFPGAKernelAttributesINTEL = 5897,
CapabilityBlockingPipesINTEL = 5945,
CapabilityFPGARegINTEL = 5948,
CapabilityAtomicFloat32AddEXT = 6033,
CapabilityAtomicFloat64AddEXT = 6034,
CapabilityMax = 0x7fffffff,
};
enum RayFlagsShift {
RayFlagsOpaqueKHRShift = 0,
RayFlagsNoOpaqueKHRShift = 1,
RayFlagsTerminateOnFirstHitKHRShift = 2,
RayFlagsSkipClosestHitShaderKHRShift = 3,
RayFlagsCullBackFacingTrianglesKHRShift = 4,
RayFlagsCullFrontFacingTrianglesKHRShift = 5,
RayFlagsCullOpaqueKHRShift = 6,
RayFlagsCullNoOpaqueKHRShift = 7,
RayFlagsSkipTrianglesKHRShift = 8,
RayFlagsSkipAABBsKHRShift = 9,
RayFlagsMax = 0x7fffffff,
};
enum RayFlagsMask {
RayFlagsMaskNone = 0,
RayFlagsOpaqueKHRMask = 0x00000001,
RayFlagsNoOpaqueKHRMask = 0x00000002,
RayFlagsTerminateOnFirstHitKHRMask = 0x00000004,
RayFlagsSkipClosestHitShaderKHRMask = 0x00000008,
RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010,
RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020,
RayFlagsCullOpaqueKHRMask = 0x00000040,
RayFlagsCullNoOpaqueKHRMask = 0x00000080,
RayFlagsSkipTrianglesKHRMask = 0x00000100,
RayFlagsSkipAABBsKHRMask = 0x00000200,
};
enum RayQueryIntersection {
RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0,
RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1,
RayQueryIntersectionMax = 0x7fffffff,
};
enum RayQueryCommittedIntersectionType {
RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0,
RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1,
RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2,
RayQueryCommittedIntersectionTypeMax = 0x7fffffff,
};
enum RayQueryCandidateIntersectionType {
RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0,
RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1,
RayQueryCandidateIntersectionTypeMax = 0x7fffffff,
};
enum Op {
OpNop = 0,
OpUndef = 1,
@@ -1254,6 +1375,13 @@ enum Op {
OpSubgroupAnyKHR = 4429,
OpSubgroupAllEqualKHR = 4430,
OpSubgroupReadInvocationKHR = 4432,
OpTypeRayQueryProvisionalKHR = 4472,
OpRayQueryInitializeKHR = 4473,
OpRayQueryTerminateKHR = 4474,
OpRayQueryGenerateIntersectionKHR = 4475,
OpRayQueryConfirmIntersectionKHR = 4476,
OpRayQueryProceedKHR = 4477,
OpRayQueryGetIntersectionTypeKHR = 4479,
OpGroupIAddNonUniformAMD = 5000,
OpGroupFAddNonUniformAMD = 5001,
OpGroupFMinNonUniformAMD = 5002,
@@ -1268,11 +1396,17 @@ enum Op {
OpImageSampleFootprintNV = 5283,
OpGroupNonUniformPartitionNV = 5296,
OpWritePackedPrimitiveIndices4x8NV = 5299,
OpReportIntersectionKHR = 5334,
OpReportIntersectionNV = 5334,
OpIgnoreIntersectionKHR = 5335,
OpIgnoreIntersectionNV = 5335,
OpTerminateRayKHR = 5336,
OpTerminateRayNV = 5336,
OpTraceNV = 5337,
OpTraceRayKHR = 5337,
OpTypeAccelerationStructureKHR = 5341,
OpTypeAccelerationStructureNV = 5341,
OpExecuteCallableKHR = 5344,
OpExecuteCallableNV = 5344,
OpTypeCooperativeMatrixNV = 5358,
OpCooperativeMatrixLoadNV = 5359,
@@ -1307,6 +1441,8 @@ enum Op {
OpUSubSatINTEL = 5596,
OpIMul32x16INTEL = 5597,
OpUMul32x16INTEL = 5598,
OpFunctionPointerINTEL = 5600,
OpFunctionPointerCallINTEL = 5601,
OpDecorateString = 5632,
OpDecorateStringGOOGLE = 5632,
OpMemberDecorateString = 5633,
@@ -1429,6 +1565,28 @@ enum Op {
OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
OpLoopControlINTEL = 5887,
OpReadPipeBlockingINTEL = 5946,
OpWritePipeBlockingINTEL = 5947,
OpFPGARegINTEL = 5949,
OpRayQueryGetRayTMinKHR = 6016,
OpRayQueryGetRayFlagsKHR = 6017,
OpRayQueryGetIntersectionTKHR = 6018,
OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019,
OpRayQueryGetIntersectionInstanceIdKHR = 6020,
OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021,
OpRayQueryGetIntersectionGeometryIndexKHR = 6022,
OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023,
OpRayQueryGetIntersectionBarycentricsKHR = 6024,
OpRayQueryGetIntersectionFrontFaceKHR = 6025,
OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026,
OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027,
OpRayQueryGetIntersectionObjectRayOriginKHR = 6028,
OpRayQueryGetWorldRayDirectionKHR = 6029,
OpRayQueryGetWorldRayOriginKHR = 6030,
OpRayQueryGetIntersectionObjectToWorldKHR = 6031,
OpRayQueryGetIntersectionWorldToObjectKHR = 6032,
OpAtomicFAddEXT = 6035,
OpMax = 0x7fffffff,
};
@@ -1787,6 +1945,13 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break;
case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break;
case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break;
case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break;
case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break;
case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break;
case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break;
case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break;
case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break;
case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break;
case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break;
case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break;
@@ -1840,6 +2005,8 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;
case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
case OpFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;
case OpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break;
case OpDecorateString: *hasResult = false; *hasResultType = false; break;
case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break;
case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break;
@@ -1960,6 +2127,28 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break;
case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break;
case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break;
case OpLoopControlINTEL: *hasResult = false; *hasResultType = false; break;
case OpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
case OpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
case OpFPGARegINTEL: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break;
case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break;
case OpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break;
}
}
#endif /* SPV_ENABLE_UTILITY_CODE */
@@ -1974,6 +2163,7 @@ inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask
inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); }
inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); }
inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); }
inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); }
} // end namespace spv
+24 -3
View File
@@ -55,6 +55,7 @@
#include <iostream>
#include <memory>
#include <vector>
#include <set>
namespace spv {
@@ -235,8 +236,7 @@ public:
assert(instructions.size() > 0);
instructions.resize(1);
successors.clear();
Instruction* unreachable = new Instruction(OpUnreachable);
addInstruction(std::unique_ptr<Instruction>(unreachable));
addInstruction(std::unique_ptr<Instruction>(new Instruction(OpUnreachable)));
}
// Change this block into a canonical dead continue target branching to the
// given header ID. Delete instructions as necessary. A canonical dead continue
@@ -352,10 +352,28 @@ public:
const std::vector<Block*>& getBlocks() const { return blocks; }
void addLocalVariable(std::unique_ptr<Instruction> inst);
Id getReturnType() const { return functionInstruction.getTypeId(); }
void setReturnPrecision(Decoration precision)
{
if (precision == DecorationRelaxedPrecision)
reducedPrecisionReturn = true;
}
Decoration getReturnPrecision() const
{ return reducedPrecisionReturn ? DecorationRelaxedPrecision : NoPrecision; }
void setImplicitThis() { implicitThis = true; }
bool hasImplicitThis() const { return implicitThis; }
void addParamPrecision(unsigned param, Decoration precision)
{
if (precision == DecorationRelaxedPrecision)
reducedPrecisionParams.insert(param);
}
Decoration getParamPrecision(unsigned param) const
{
return reducedPrecisionParams.find(param) != reducedPrecisionParams.end() ?
DecorationRelaxedPrecision : NoPrecision;
}
void dump(std::vector<unsigned int>& out) const
{
// OpFunction
@@ -380,6 +398,8 @@ protected:
std::vector<Instruction*> parameterInstructions;
std::vector<Block*> blocks;
bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument
bool reducedPrecisionReturn;
std::set<int> reducedPrecisionParams; // list of parameter indexes that need a relaxed precision arg
};
//
@@ -440,7 +460,8 @@ protected:
// - the OpFunction instruction
// - all the OpFunctionParameter instructions
__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent)
: parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false)
: parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false),
reducedPrecisionReturn(false)
{
// OpFunction
functionInstruction.addImmediateOperand(FunctionControlMaskNone);
@@ -2,6 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@@ -61,8 +62,9 @@ enum TBasicType {
EbtSampler,
EbtStruct,
EbtBlock,
EbtAccStructNV,
EbtAccStruct,
EbtReference,
EbtRayQuery,
// HLSL types that live only temporarily.
EbtString,
@@ -90,11 +92,11 @@ enum TStorageQualifier {
EvqBuffer, // read/write, shared with app
EvqShared, // compute shader's read/write 'shared' qualifier
EvqPayloadNV,
EvqPayloadInNV,
EvqHitAttrNV,
EvqCallableDataNV,
EvqCallableDataInNV,
EvqPayload,
EvqPayloadIn,
EvqHitAttr,
EvqCallableData,
EvqCallableDataIn,
// parameters
EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter
@@ -229,6 +231,9 @@ enum TBuiltInVariable {
EbvFragSizeEXT,
EbvFragInvocationCountEXT,
EbvSecondaryFragDataEXT,
EbvSecondaryFragColorEXT,
EbvViewportMaskNV,
EbvSecondaryPositionNV,
EbvSecondaryViewportMaskNV,
@@ -238,20 +243,23 @@ enum TBuiltInVariable {
EbvFragmentSizeNV,
EbvInvocationsPerPixelNV,
// ray tracing
EbvLaunchIdNV,
EbvLaunchSizeNV,
EbvInstanceCustomIndexNV,
EbvWorldRayOriginNV,
EbvWorldRayDirectionNV,
EbvObjectRayOriginNV,
EbvObjectRayDirectionNV,
EbvRayTminNV,
EbvRayTmaxNV,
EbvHitTNV,
EbvHitKindNV,
EbvObjectToWorldNV,
EbvWorldToObjectNV,
EbvIncomingRayFlagsNV,
EbvLaunchId,
EbvLaunchSize,
EbvInstanceCustomIndex,
EbvGeometryIndex,
EbvWorldRayOrigin,
EbvWorldRayDirection,
EbvObjectRayOrigin,
EbvObjectRayDirection,
EbvRayTmin,
EbvRayTmax,
EbvHitT,
EbvHitKind,
EbvObjectToWorld,
EbvObjectToWorld3x4,
EbvWorldToObject,
EbvWorldToObject3x4,
EbvIncomingRayFlags,
// barycentrics
EbvBaryCoordNV,
EbvBaryCoordNoPerspNV,
@@ -328,11 +336,11 @@ __inline const char* GetStorageQualifierString(TStorageQualifier q)
case EvqPointCoord: return "gl_PointCoord"; break;
case EvqFragColor: return "fragColor"; break;
case EvqFragDepth: return "gl_FragDepth"; break;
case EvqPayloadNV: return "rayPayloadNV"; break;
case EvqPayloadInNV: return "rayPayloadInNV"; break;
case EvqHitAttrNV: return "hitAttributeNV"; break;
case EvqCallableDataNV: return "callableDataNV"; break;
case EvqCallableDataInNV: return "callableDataInNV"; break;
case EvqPayload: return "rayPayloadNV"; break;
case EvqPayloadIn: return "rayPayloadInNV"; break;
case EvqHitAttr: return "hitAttributeNV"; break;
case EvqCallableData: return "callableDataNV"; break;
case EvqCallableDataIn: return "callableDataInNV"; break;
default: return "unknown qualifier";
}
}
@@ -428,6 +436,9 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
case EbvFragSizeEXT: return "FragSizeEXT";
case EbvFragInvocationCountEXT: return "FragInvocationCountEXT";
case EbvSecondaryFragDataEXT: return "SecondaryFragDataEXT";
case EbvSecondaryFragColorEXT: return "SecondaryFragColorEXT";
case EbvViewportMaskNV: return "ViewportMaskNV";
case EbvSecondaryPositionNV: return "SecondaryPositionNV";
case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
@@ -436,20 +447,21 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
case EbvFragFullyCoveredNV: return "FragFullyCoveredNV";
case EbvFragmentSizeNV: return "FragmentSizeNV";
case EbvInvocationsPerPixelNV: return "InvocationsPerPixelNV";
case EbvLaunchIdNV: return "LaunchIdNV";
case EbvLaunchSizeNV: return "LaunchSizeNV";
case EbvInstanceCustomIndexNV: return "InstanceCustomIndexNV";
case EbvWorldRayOriginNV: return "WorldRayOriginNV";
case EbvWorldRayDirectionNV: return "WorldRayDirectionNV";
case EbvObjectRayOriginNV: return "ObjectRayOriginNV";
case EbvObjectRayDirectionNV: return "ObjectRayDirectionNV";
case EbvRayTminNV: return "ObjectRayTminNV";
case EbvRayTmaxNV: return "ObjectRayTmaxNV";
case EbvHitTNV: return "HitTNV";
case EbvHitKindNV: return "HitKindNV";
case EbvIncomingRayFlagsNV: return "IncomingRayFlagsNV";
case EbvObjectToWorldNV: return "ObjectToWorldNV";
case EbvWorldToObjectNV: return "WorldToObjectNV";
case EbvLaunchId: return "LaunchIdNV";
case EbvLaunchSize: return "LaunchSizeNV";
case EbvInstanceCustomIndex: return "InstanceCustomIndexNV";
case EbvGeometryIndex: return "GeometryIndexEXT";
case EbvWorldRayOrigin: return "WorldRayOriginNV";
case EbvWorldRayDirection: return "WorldRayDirectionNV";
case EbvObjectRayOrigin: return "ObjectRayOriginNV";
case EbvObjectRayDirection: return "ObjectRayDirectionNV";
case EbvRayTmin: return "ObjectRayTminNV";
case EbvRayTmax: return "ObjectRayTmaxNV";
case EbvHitT: return "HitTNV";
case EbvHitKind: return "HitKindNV";
case EbvIncomingRayFlags: return "IncomingRayFlagsNV";
case EbvObjectToWorld: return "ObjectToWorldNV";
case EbvWorldToObject: return "WorldToObjectNV";
case EbvBaryCoordNV: return "BaryCoordNV";
case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
+11 -12
View File
@@ -37,6 +37,17 @@
#ifndef _COMMON_INCLUDED_
#define _COMMON_INCLUDED_
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <list>
#include <map>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#if defined(__ANDROID__) || (defined(_MSC_VER) && _MSC_VER < 1700)
#include <sstream>
@@ -93,18 +104,6 @@ std::string to_string(const T& val) {
#pragma warning(disable : 4201) // nameless union
#endif
#include <set>
#include <unordered_set>
#include <vector>
#include <map>
#include <unordered_map>
#include <list>
#include <algorithm>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include "PoolAlloc.h"
//
@@ -921,7 +921,7 @@ public:
else
unionArray = new TConstUnionVector(size);
}
TConstUnionArray(const TConstUnionArray& a) : unionArray(a.unionArray) { }
TConstUnionArray(const TConstUnionArray& a) = default;
TConstUnionArray(const TConstUnionArray& a, int start, int size)
{
unionArray = new TConstUnionVector(size);
@@ -142,6 +142,7 @@ struct TBuiltInResource {
int maxTaskWorkGroupSizeY_NV;
int maxTaskWorkGroupSizeZ_NV;
int maxMeshViewCountNV;
int maxDualSourceDrawBuffersEXT;
TLimits limits;
};
+50 -10
View File
@@ -3,6 +3,7 @@
// Copyright (C) 2012-2016 LunarG, Inc.
// Copyright (C) 2015-2016 Google, Inc.
// Copyright (C) 2017 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@@ -472,6 +473,18 @@ enum TInterlockOrdering {
EioCount,
};
enum TShaderInterface
{
// Includes both uniform blocks and buffer blocks
EsiUniform = 0,
EsiInput,
EsiOutput,
EsiNone,
EsiCount
};
class TQualifier {
public:
static const int layoutNotSet = -1;
@@ -532,6 +545,7 @@ public:
queuefamilycoherent = false;
workgroupcoherent = false;
subgroupcoherent = false;
shadercallcoherent = false;
nonprivate = false;
volatil = false;
restrict = false;
@@ -553,6 +567,7 @@ public:
// having a constant_id is not sufficient: expressions have no id, but are still specConstant
bool specConstant : 1;
bool nonUniform : 1;
bool explicitOffset : 1;
#ifdef GLSLANG_WEB
bool isWriteOnly() const { return false; }
@@ -590,6 +605,7 @@ public:
bool queuefamilycoherent : 1;
bool workgroupcoherent : 1;
bool subgroupcoherent : 1;
bool shadercallcoherent : 1;
bool nonprivate : 1;
bool isWriteOnly() const { return writeonly; }
bool isReadOnly() const { return readonly; }
@@ -599,11 +615,11 @@ public:
bool isSample() const { return sample; }
bool isMemory() const
{
return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate;
return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate;
}
bool isMemoryQualifierImageAndSSBOOnly() const
{
return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly;
return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly;
}
bool bufferReferenceNeedsVulkanMemoryModel() const
{
@@ -773,7 +789,7 @@ public:
layoutViewportRelative = false;
// -2048 as the default value indicating layoutSecondaryViewportRelative is not set
layoutSecondaryViewportRelativeOffset = -2048;
layoutShaderRecordNV = false;
layoutShaderRecord = false;
layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd;
layoutFormat = ElfNone;
#endif
@@ -812,7 +828,7 @@ public:
hasAnyLocation() ||
hasStream() ||
hasFormat() ||
isShaderRecordNV() ||
isShaderRecord() ||
isPushConstant() ||
hasBufferReference();
}
@@ -871,7 +887,7 @@ public:
bool layoutPassthrough;
bool layoutViewportRelative;
int layoutSecondaryViewportRelativeOffset;
bool layoutShaderRecordNV;
bool layoutShaderRecord;
#endif
bool hasUniformLayout() const
@@ -942,7 +958,7 @@ public:
bool hasAttachment() const { return false; }
TLayoutFormat getFormat() const { return ElfNone; }
bool isPushConstant() const { return false; }
bool isShaderRecordNV() const { return false; }
bool isShaderRecord() const { return false; }
bool hasBufferReference() const { return false; }
bool hasBufferReferenceAlign() const { return false; }
bool isNonUniform() const { return false; }
@@ -993,7 +1009,7 @@ public:
}
TLayoutFormat getFormat() const { return layoutFormat; }
bool isPushConstant() const { return layoutPushConstant; }
bool isShaderRecordNV() const { return layoutShaderRecordNV; }
bool isShaderRecord() const { return layoutShaderRecord; }
bool hasBufferReference() const { return layoutBufferReference; }
bool hasBufferReferenceAlign() const
{
@@ -1219,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; }
@@ -1252,6 +1269,7 @@ struct TShaderQualifiers {
layoutOverrideCoverage = false;
layoutDerivativeGroupQuads = false;
layoutDerivativeGroupLinear = false;
layoutPrimitiveCulling = false;
primitives = TQualifier::layoutNotSet;
interlockOrdering = EioNone;
#endif
@@ -1315,6 +1333,8 @@ struct TShaderQualifiers {
primitives = src.primitives;
if (src.interlockOrdering != EioNone)
interlockOrdering = src.interlockOrdering;
if (src.layoutPrimitiveCulling)
layoutPrimitiveCulling = src.layoutPrimitiveCulling;
#endif
}
};
@@ -1612,6 +1632,23 @@ public:
assert(fieldName);
return *fieldName;
}
TShaderInterface getShaderInterface() const
{
if (basicType != EbtBlock)
return EsiNone;
switch (qualifier.storage) {
default:
return EsiNone;
case EvqVaryingIn:
return EsiInput;
case EvqVaryingOut:
return EsiOutput;
case EvqUniform:
case EvqBuffer:
return EsiUniform;
}
}
virtual TBasicType getBasicType() const { return basicType; }
virtual const TSampler& getSampler() const { return sampler; }
@@ -1670,7 +1707,7 @@ public:
}
virtual bool isOpaque() const { return basicType == EbtSampler
#ifndef GLSLANG_WEB
|| basicType == EbtAtomicUint || basicType == EbtAccStructNV
|| basicType == EbtAtomicUint || basicType == EbtAccStruct || basicType == EbtRayQuery
#endif
; }
virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
@@ -1946,7 +1983,8 @@ public:
case EbtAtomicUint: return "atomic_uint";
case EbtStruct: return "structure";
case EbtBlock: return "block";
case EbtAccStructNV: return "accelerationStructureNV";
case EbtAccStruct: return "accelerationStructureNV";
case EbtRayQuery: return "rayQueryEXT";
case EbtReference: return "reference";
#endif
default: return "unknown type";
@@ -2056,7 +2094,7 @@ public:
appendStr(" layoutSecondaryViewportRelativeOffset=");
appendInt(qualifier.layoutSecondaryViewportRelativeOffset);
}
if (qualifier.layoutShaderRecordNV)
if (qualifier.layoutShaderRecord)
appendStr(" shaderRecordNV");
appendStr(")");
@@ -2099,6 +2137,8 @@ public:
appendStr(" workgroupcoherent");
if (qualifier.subgroupcoherent)
appendStr(" subgroupcoherent");
if (qualifier.shadercallcoherent)
appendStr(" shadercallcoherent");
if (qualifier.nonprivate)
appendStr(" nonprivate");
if (qualifier.volatil)
@@ -2,6 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2016 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@@ -621,6 +622,8 @@ enum TOperator {
EOpIsHelperInvocation,
EOpDebugPrintf,
//
// Branch
//
@@ -908,12 +911,41 @@ enum TOperator {
EOpAverageRounded,
EOpMul32x16,
EOpTraceNV,
EOpReportIntersectionNV,
EOpIgnoreIntersectionNV,
EOpTerminateRayNV,
EOpExecuteCallableNV,
EOpTrace,
EOpReportIntersection,
EOpIgnoreIntersection,
EOpTerminateRay,
EOpExecuteCallable,
EOpWritePackedPrimitiveIndices4x8NV,
//
// GL_EXT_ray_query operations
//
EOpRayQueryInitialize,
EOpRayQueryTerminate,
EOpRayQueryGenerateIntersection,
EOpRayQueryConfirmIntersection,
EOpRayQueryProceed,
EOpRayQueryGetIntersectionType,
EOpRayQueryGetRayTMin,
EOpRayQueryGetRayFlags,
EOpRayQueryGetIntersectionT,
EOpRayQueryGetIntersectionInstanceCustomIndex,
EOpRayQueryGetIntersectionInstanceId,
EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset,
EOpRayQueryGetIntersectionGeometryIndex,
EOpRayQueryGetIntersectionPrimitiveIndex,
EOpRayQueryGetIntersectionBarycentrics,
EOpRayQueryGetIntersectionFrontFace,
EOpRayQueryGetIntersectionCandidateAABBOpaque,
EOpRayQueryGetIntersectionObjectRayDirection,
EOpRayQueryGetIntersectionObjectRayOrigin,
EOpRayQueryGetWorldRayDirection,
EOpRayQueryGetWorldRayOrigin,
EOpRayQueryGetIntersectionObjectToWorld,
EOpRayQueryGetIntersectionWorldToObject,
//
// HLSL operations
//
@@ -1199,6 +1231,7 @@ public:
TOperator getFlowOp() const { return flowOp; }
TIntermTyped* getExpression() const { return expression; }
void setExpression(TIntermTyped* pExpression) { expression = pExpression; }
void updatePrecision(TPrecisionQualifier parentPrecision);
protected:
TOperator flowOp;
TIntermTyped* expression;
@@ -2,7 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Copyright (C) 2018 Google, Inc.
// Copyright (C) 2018-2020 Google, Inc.
//
// All rights reserved.
//
@@ -1012,6 +1012,7 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
case EOpMin:
case EOpMax:
case EOpMix:
case EOpMod:
case EOpClamp:
case EOpLessThan:
case EOpGreaterThan:
@@ -1074,6 +1075,14 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
case EOpPow:
newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
break;
case EOpMod:
{
double arg0 = childConstUnions[0][arg0comp].getDConst();
double arg1 = childConstUnions[1][arg1comp].getDConst();
double result = arg0 - arg1 * floor(arg0 / arg1);
newConstArray[comp].setDConst(result);
break;
}
case EOpMin:
switch(children[0]->getAsTyped()->getBasicType()) {
case EbtFloat16:
File diff suppressed because it is too large Load Diff
+214 -185
View File
@@ -1,7 +1,7 @@
//
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2015 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2015-2020 Google, Inc.
// Copyright (C) 2017 ARM Limited.
//
// All rights reserved.
@@ -113,14 +113,14 @@ TIntermSymbol* TIntermediate::addSymbol(const TType& type, const TSourceLoc& loc
//
// Returns nullptr if the working conversions and promotions could not be found.
//
TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc)
TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& loc)
{
// No operations work on blocks
if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
return nullptr;
// Convert "reference +/- int" and "reference - reference" to integer math
if ((op == EOpAdd || op == EOpSub) && extensionRequested(E_GL_EXT_buffer_reference2)) {
if (op == EOpAdd || op == EOpSub) {
// No addressing math on struct with unsized array.
if ((left->isReference() && left->getType().getReferentType()->containsUnsizedArray()) ||
@@ -140,43 +140,44 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
return node;
}
if (op == EOpAdd && right->isReference() && isTypeInt(left->getBasicType())) {
const TType& referenceType = right->getType();
TIntermConstantUnion* size = addConstantUnion((unsigned long long)computeBufferReferenceTypeSize(right->getType()), loc, true);
right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
left = createConversion(EbtInt64, left);
left = addBinaryMath(EOpMul, left, size, loc);
TIntermTyped *node = addBinaryMath(op, left, right, loc);
node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
return node;
}
if (op == EOpSub && left->isReference() && right->isReference()) {
TIntermConstantUnion* size = addConstantUnion((long long)computeBufferReferenceTypeSize(left->getType()), loc, true);
left = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, left, TType(EbtUint64));
right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
left = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, left, TType(EbtInt64));
right = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, right, TType(EbtInt64));
left = addBinaryMath(EOpSub, left, right, loc);
TIntermTyped *node = addBinaryMath(EOpDiv, left, size, loc);
return node;
}
// No other math operators supported on references
if (left->isReference() || right->isReference()) {
return nullptr;
}
}
if (op == EOpAdd && right->isReference() && isTypeInt(left->getBasicType())) {
const TType& referenceType = right->getType();
TIntermConstantUnion* size =
addConstantUnion((unsigned long long)computeBufferReferenceTypeSize(right->getType()), loc, true);
right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
left = createConversion(EbtInt64, left);
left = addBinaryMath(EOpMul, left, size, loc);
TIntermTyped *node = addBinaryMath(op, left, right, loc);
node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
return node;
}
if (op == EOpSub && left->isReference() && right->isReference()) {
TIntermConstantUnion* size =
addConstantUnion((long long)computeBufferReferenceTypeSize(left->getType()), loc, true);
left = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, left, TType(EbtUint64));
right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
left = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, left, TType(EbtInt64));
right = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, right, TType(EbtInt64));
left = addBinaryMath(EOpSub, left, right, loc);
TIntermTyped *node = addBinaryMath(EOpDiv, left, size, loc);
return node;
}
// No other math operators supported on references
if (left->isReference() || right->isReference())
return nullptr;
// Try converting the children's base types to compatible types.
auto children = addConversion(op, left, right);
auto children = addPairConversion(op, left, right);
left = std::get<0>(children);
right = std::get<1>(children);
@@ -226,13 +227,12 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
//
// Low level: add binary node (no promotions or other argument modifications)
//
TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) const
TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right,
const TSourceLoc& loc) const
{
// build the node
TIntermBinary* node = new TIntermBinary(op);
if (loc.line == 0)
loc = left->getLoc();
node->setLoc(loc);
node->setLoc(loc.line != 0 ? loc : left->getLoc());
node->setLeft(left);
node->setRight(right);
@@ -242,7 +242,8 @@ TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TI
//
// like non-type form, but sets node's type.
//
TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc, const TType& type) const
TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right,
const TSourceLoc& loc, const TType& type) const
{
TIntermBinary* node = addBinaryNode(op, left, right, loc);
node->setType(type);
@@ -252,12 +253,10 @@ TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TI
//
// Low level: add unary node (no promotions or other argument modifications)
//
TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc) const
TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc& loc) const
{
TIntermUnary* node = new TIntermUnary(op);
if (loc.line == 0)
loc = child->getLoc();
node->setLoc(loc);
node->setLoc(loc.line != 0 ? loc : child->getLoc());
node->setOperand(child);
return node;
@@ -266,7 +265,8 @@ TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSo
//
// like non-type form, but sets node's type.
//
TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc, const TType& type) const
TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc& loc, const TType& type)
const
{
TIntermUnary* node = addUnaryNode(op, child, loc);
node->setType(type);
@@ -281,7 +281,8 @@ TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSo
// Returns nullptr if the 'right' type could not be converted to match the 'left' type,
// or the resulting operation cannot be properly promoted.
//
TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc)
TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right,
const TSourceLoc& loc)
{
// No block assignment
if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
@@ -290,9 +291,7 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
// Convert "reference += int" to "reference = reference + int". We need this because the
// "reference + int" calculation involves a cast back to the original type, which makes it
// not an lvalue.
if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference() &&
extensionRequested(E_GL_EXT_buffer_reference2)) {
if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference()) {
if (!(right->getType().isScalar() && right->getType().isIntegerDomain()))
return nullptr;
@@ -338,7 +337,8 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
// Returns the added node.
// The caller should set the type of the returned node.
//
TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc loc)
TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index,
const TSourceLoc& loc)
{
// caller should set the type
return addBinaryNode(op, base, index, loc);
@@ -349,7 +349,8 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT
//
// Returns the added node.
//
TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSourceLoc loc)
TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child,
const TSourceLoc& loc)
{
if (child == 0)
return nullptr;
@@ -495,7 +496,8 @@ TIntermTyped* TIntermediate::addBuiltInFunctionCall(const TSourceLoc& loc, TOper
// Returns an aggregate node, which could be the one passed in if
// it was already an aggregate.
//
TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TType& type, TSourceLoc loc)
TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TType& type,
const TSourceLoc& loc)
{
TIntermAggregate* aggNode;
@@ -510,8 +512,6 @@ TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator o
//
aggNode = new TIntermAggregate();
aggNode->getSequence().push_back(node);
if (loc.line == 0)
loc = node->getLoc();
}
} else
aggNode = new TIntermAggregate();
@@ -520,8 +520,8 @@ TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator o
// Set the operator.
//
aggNode->setOperator(op);
if (loc.line != 0)
aggNode->setLoc(loc);
if (loc.line != 0 || node != nullptr)
aggNode->setLoc(loc.line != 0 ? loc : node->getLoc());
aggNode->setType(type);
@@ -538,7 +538,7 @@ bool TIntermediate::isConversionAllowed(TOperator op, TIntermTyped* node) const
return false;
case EbtAtomicUint:
case EbtSampler:
case EbtAccStructNV:
case EbtAccStruct:
// opaque types can be passed to functions
if (op == EOpFunction)
break;
@@ -819,22 +819,25 @@ TIntermTyped* TIntermediate::createConversion(TBasicType convertTo, TIntermTyped
node->getBasicType() == EbtFloat ||
node->getBasicType() == EbtDouble);
if (! getArithemeticInt8Enabled()) {
if (((convertTo == EbtInt8 || convertTo == EbtUint8) && ! convertFromIntTypes) ||
((node->getBasicType() == EbtInt8 || node->getBasicType() == EbtUint8) && ! convertToIntTypes))
if (((convertTo == EbtInt8 || convertTo == EbtUint8) && ! convertFromIntTypes) ||
((node->getBasicType() == EbtInt8 || node->getBasicType() == EbtUint8) && ! convertToIntTypes)) {
if (! getArithemeticInt8Enabled()) {
return nullptr;
}
}
if (! getArithemeticInt16Enabled()) {
if (((convertTo == EbtInt16 || convertTo == EbtUint16) && ! convertFromIntTypes) ||
((node->getBasicType() == EbtInt16 || node->getBasicType() == EbtUint16) && ! convertToIntTypes))
if (((convertTo == EbtInt16 || convertTo == EbtUint16) && ! convertFromIntTypes) ||
((node->getBasicType() == EbtInt16 || node->getBasicType() == EbtUint16) && ! convertToIntTypes)) {
if (! getArithemeticInt16Enabled()) {
return nullptr;
}
}
if (! getArithemeticFloat16Enabled()) {
if ((convertTo == EbtFloat16 && ! convertFromFloatTypes) ||
(node->getBasicType() == EbtFloat16 && ! convertToFloatTypes))
if ((convertTo == EbtFloat16 && ! convertFromFloatTypes) ||
(node->getBasicType() == EbtFloat16 && ! convertToFloatTypes)) {
if (! getArithemeticFloat16Enabled()) {
return nullptr;
}
}
#endif
@@ -887,7 +890,7 @@ TIntermTyped* TIntermediate::addConversion(TBasicType convertTo, TIntermTyped* n
// Returns the converted pair of nodes.
// Returns <nullptr, nullptr> when there is no conversion.
std::tuple<TIntermTyped*, TIntermTyped*>
TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1)
TIntermediate::addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1)
{
if (!isConversionAllowed(op, node0) || !isConversionAllowed(op, node1))
return std::make_tuple(nullptr, nullptr);
@@ -940,7 +943,7 @@ TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* no
if (node0->getBasicType() == node1->getBasicType())
return std::make_tuple(node0, node1);
promoteTo = getConversionDestinatonType(node0->getBasicType(), node1->getBasicType(), op);
promoteTo = getConversionDestinationType(node0->getBasicType(), node1->getBasicType(), op);
if (std::get<0>(promoteTo) == EbtNumTypes || std::get<1>(promoteTo) == EbtNumTypes)
return std::make_tuple(nullptr, nullptr);
@@ -1040,64 +1043,30 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
// Note: callers are responsible for other aspects of shape,
// like vector and matrix sizes.
TBasicType promoteTo;
// GL_EXT_shader_16bit_storage can't do OpConstantComposite with
// 16-bit types, so disable promotion for those types.
bool canPromoteConstant = true;
switch (op) {
//
// Explicit conversions (unary operations)
//
case EOpConstructBool:
promoteTo = EbtBool;
break;
case EOpConstructFloat:
promoteTo = EbtFloat;
break;
case EOpConstructInt:
promoteTo = EbtInt;
break;
case EOpConstructUint:
promoteTo = EbtUint;
break;
#ifndef GLSLANG_WEB
case EOpConstructDouble:
promoteTo = EbtDouble;
break;
case EOpConstructFloat16:
promoteTo = EbtFloat16;
canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16);
break;
case EOpConstructInt8:
promoteTo = EbtInt8;
canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
break;
case EOpConstructUint8:
promoteTo = EbtUint8;
canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
break;
case EOpConstructInt16:
promoteTo = EbtInt16;
canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
break;
case EOpConstructUint16:
promoteTo = EbtUint16;
canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
break;
case EOpConstructInt64:
promoteTo = EbtInt64;
break;
case EOpConstructUint64:
promoteTo = EbtUint64;
break;
#endif
//
// Implicit conversions
//
case EOpLogicalNot:
case EOpFunctionCall:
@@ -1152,9 +1121,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
if (type.getBasicType() == node->getType().getBasicType())
return node;
if (canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op))
promoteTo = type.getBasicType();
else
if (! canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op))
return nullptr;
break;
@@ -1164,9 +1131,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
case EOpLeftShiftAssign:
case EOpRightShiftAssign:
{
if (getSource() == EShSourceHlsl && node->getType().getBasicType() == EbtBool)
promoteTo = type.getBasicType();
else {
if (!(getSource() == EShSourceHlsl && node->getType().getBasicType() == EbtBool)) {
if (isTypeInt(type.getBasicType()) && isTypeInt(node->getBasicType()))
return node;
else
@@ -1184,13 +1149,44 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
return nullptr;
}
bool canPromoteConstant = true;
#ifndef GLSLANG_WEB
// GL_EXT_shader_16bit_storage can't do OpConstantComposite with
// 16-bit types, so disable promotion for those types.
// Many issues with this, from JohnK:
// - this isn't really right to discuss SPIR-V here
// - this could easily be entirely about scalars, so is overstepping
// - we should be looking at what the shader asked for, and saying whether or
// not it can be done, in the parser, by calling requireExtensions(), not
// changing language sementics on the fly by asking what extensions are in use
// - at the time of this writing (14-Aug-2020), no test results are changed by this.
switch (op) {
case EOpConstructFloat16:
canPromoteConstant = numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16);
break;
case EOpConstructInt8:
case EOpConstructUint8:
canPromoteConstant = numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8);
break;
case EOpConstructInt16:
case EOpConstructUint16:
canPromoteConstant = numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16);
break;
default:
break;
}
#endif
if (canPromoteConstant && node->getAsConstantUnion())
return promoteConstantUnion(promoteTo, node->getAsConstantUnion());
return promoteConstantUnion(type.getBasicType(), node->getAsConstantUnion());
//
// Add a new newNode for the conversion.
//
TIntermTyped* newNode = createConversion(promoteTo, node);
TIntermTyped* newNode = createConversion(type.getBasicType(), node);
return newNode;
}
@@ -1620,7 +1616,7 @@ bool TIntermediate::isFPIntegralConversion(TBasicType from, TBasicType to) const
//
bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op) const
{
if (isEsProfile() || version == 110)
if ((isEsProfile() && version < 310 ) || version == 110)
return false;
if (from == to)
@@ -1659,46 +1655,51 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
}
}
bool explicitTypesEnabled = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int32) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int64) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float32) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float64);
if (explicitTypesEnabled) {
// integral promotions
if (isIntegralPromotion(from, to)) {
if (getSource() == EShSourceHlsl) {
// HLSL
if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat))
return true;
}
} else {
// GLSL
if (isIntegralPromotion(from, to) ||
isFPPromotion(from, to) ||
isIntegralConversion(from, to) ||
isFPConversion(from, to) ||
isFPIntegralConversion(from, to)) {
// floating-point promotions
if (isFPPromotion(from, to)) {
return true;
}
// integral conversions
if (isIntegralConversion(from, to)) {
return true;
}
// floating-point conversions
if (isFPConversion(from, to)) {
return true;
}
// floating-integral conversions
if (isFPIntegralConversion(from, to)) {
return true;
}
// hlsl supported conversions
if (getSource() == EShSourceHlsl) {
if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat))
if (numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int32) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int64) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float32) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float64)) {
return true;
}
}
}
if (isEsProfile()) {
switch (to) {
case EbtFloat:
switch (from) {
case EbtInt:
case EbtUint:
return numericFeatures.contains(TNumericFeatures::shader_implicit_conversions);
default:
return false;
}
case EbtUint:
switch (from) {
case EbtInt:
return numericFeatures.contains(TNumericFeatures::shader_implicit_conversions);
default:
return false;
}
default:
return false;
}
} else {
switch (to) {
case EbtDouble:
@@ -1708,13 +1709,14 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtInt64:
case EbtUint64:
case EbtFloat:
case EbtDouble:
return true;
return version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64);
case EbtInt16:
case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
return (version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64)) &&
numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
case EbtFloat16:
return extensionRequested(E_GL_AMD_gpu_shader_half_float);
return (version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64)) &&
numericFeatures.contains(TNumericFeatures::gpu_shader_half_float);
default:
return false;
}
@@ -1722,16 +1724,14 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
switch (from) {
case EbtInt:
case EbtUint:
case EbtFloat:
return true;
case EbtBool:
return getSource() == EShSourceHlsl;
case EbtInt16:
case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
case EbtFloat16:
return
extensionRequested(E_GL_AMD_gpu_shader_half_float) ||
return numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) ||
getSource() == EShSourceHlsl;
default:
return false;
@@ -1739,25 +1739,21 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtUint:
switch (from) {
case EbtInt:
return version >= 400 || getSource() == EShSourceHlsl;
case EbtUint:
return true;
return version >= 400 || getSource() == EShSourceHlsl;
case EbtBool:
return getSource() == EShSourceHlsl;
case EbtInt16:
case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
default:
return false;
}
case EbtInt:
switch (from) {
case EbtInt:
return true;
case EbtBool:
return getSource() == EShSourceHlsl;
case EbtInt16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
default:
return false;
}
@@ -1766,21 +1762,19 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtInt:
case EbtUint:
case EbtInt64:
case EbtUint64:
return true;
case EbtInt16:
case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
default:
return false;
}
case EbtInt64:
switch (from) {
case EbtInt:
case EbtInt64:
return true;
case EbtInt16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
default:
return false;
}
@@ -1788,9 +1782,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
switch (from) {
case EbtInt16:
case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
case EbtFloat16:
return extensionRequested(E_GL_AMD_gpu_shader_half_float);
return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
default:
break;
}
@@ -1798,8 +1790,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtUint16:
switch (from) {
case EbtInt16:
case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16);
return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
default:
break;
}
@@ -1926,12 +1917,14 @@ static TBasicType getCorrespondingUnsignedType(TBasicType type)
// integer type corresponding to the type of the operand with signed
// integer type.
std::tuple<TBasicType, TBasicType> TIntermediate::getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const
std::tuple<TBasicType, TBasicType> TIntermediate::getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const
{
TBasicType res0 = EbtNumTypes;
TBasicType res1 = EbtNumTypes;
if (isEsProfile() || version == 110)
if ((isEsProfile() &&
(version < 310 || !numericFeatures.contains(TNumericFeatures::shader_implicit_conversions))) ||
version == 110)
return std::make_tuple(res0, res1);
if (getSource() == EShSourceHlsl) {
@@ -2463,7 +2456,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true
//
// Get compatible types.
//
auto children = addConversion(EOpSequence, trueBlock, falseBlock);
auto children = addPairConversion(EOpSequence, trueBlock, falseBlock);
trueBlock = std::get<0>(children);
falseBlock = std::get<1>(children);
@@ -2750,6 +2743,22 @@ TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expres
return node;
}
// Propagate precision from formal function return type to actual return type,
// and on to its subtree.
void TIntermBranch::updatePrecision(TPrecisionQualifier parentPrecision)
{
TIntermTyped* exp = getExpression();
if (exp == nullptr)
return;
if (exp->getBasicType() == EbtInt || exp->getBasicType() == EbtUint ||
exp->getBasicType() == EbtFloat || exp->getBasicType() == EbtFloat16) {
if (parentPrecision != EpqNone && exp->getQualifier().precision == EpqNone) {
exp->propagatePrecision(parentPrecision);
}
}
}
//
// This is to be executed after the final root is put on top by the parsing
// process.
@@ -2774,6 +2783,9 @@ bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/)
case EShTexSampTransUpgradeTextureRemoveSampler:
performTextureUpgradeAndSamplerRemovalTransformation(root);
break;
case EShTexSampTransCount:
assert(0);
break;
}
#endif
@@ -3234,10 +3246,17 @@ bool TIntermediate::promoteUnary(TIntermUnary& node)
return false;
break;
default:
if (operand->getBasicType() != EbtFloat)
// HLSL uses this path for initial function signature finding for built-ins
// taking a single argument, which generally don't participate in
// operator-based type promotion (type conversion will occur later).
// For now, scalar argument cases are relying on the setType() call below.
if (getSource() == EShSourceHlsl)
break;
// GLSL only allows integer arguments for the cases identified above in the
// case statements.
if (operand->getBasicType() != EbtFloat)
return false;
}
@@ -3247,9 +3266,11 @@ bool TIntermediate::promoteUnary(TIntermUnary& node)
return true;
}
// Propagate precision qualifiers *up* from children to parent.
void TIntermUnary::updatePrecision()
{
if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
if (getBasicType() == EbtInt || getBasicType() == EbtUint ||
getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
if (operand->getQualifier().precision > getQualifier().precision)
getQualifier().precision = operand->getQualifier().precision;
}
@@ -3745,9 +3766,12 @@ bool TIntermediate::promoteAggregate(TIntermAggregate& node)
return false;
}
// Propagate precision qualifiers *up* from children to parent, and then
// back *down* again to the children's subtrees.
void TIntermBinary::updatePrecision()
{
if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
if (getBasicType() == EbtInt || getBasicType() == EbtUint ||
getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision);
if (getQualifier().precision != EpqNone) {
left->propagatePrecision(getQualifier().precision);
@@ -3756,9 +3780,14 @@ void TIntermBinary::updatePrecision()
}
}
// Recursively propagate precision qualifiers *down* the subtree of the current node,
// until reaching a node that already has a precision qualifier or otherwise does
// not participate in precision propagation.
void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision)
{
if (getQualifier().precision != EpqNone || (getBasicType() != EbtInt && getBasicType() != EbtUint && getBasicType() != EbtFloat && getBasicType() != EbtFloat16))
if (getQualifier().precision != EpqNone ||
(getBasicType() != EbtInt && getBasicType() != EbtUint &&
getBasicType() != EbtFloat && getBasicType() != EbtFloat16))
return;
getQualifier().precision = newPrecision;
@@ -74,14 +74,33 @@ public:
for (unsigned int f = 0; f < globals.size(); ++f) {
TIntermAggregate* candidate = globals[f]->getAsAggregate();
if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) {
functions.push_back(candidate);
destinations.push_back(candidate);
break;
}
}
}
typedef std::list<TIntermAggregate*> TFunctionStack;
TFunctionStack functions;
void pushGlobalReference(const TString& name)
{
TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence();
for (unsigned int f = 0; f < globals.size(); ++f) {
TIntermAggregate* candidate = globals[f]->getAsAggregate();
if (candidate && candidate->getOp() == EOpSequence &&
candidate->getSequence().size() == 1 &&
candidate->getSequence()[0]->getAsBinaryNode()) {
TIntermBinary* binary = candidate->getSequence()[0]->getAsBinaryNode();
TIntermSymbol* symbol = binary->getLeft()->getAsSymbolNode();
if (symbol && symbol->getQualifier().storage == EvqGlobal &&
symbol->getName() == name) {
destinations.push_back(candidate);
break;
}
}
}
}
typedef std::list<TIntermAggregate*> TDestinationStack;
TDestinationStack destinations;
protected:
// To catch which function calls are not dead, and hence which functions must be visited.
@@ -117,16 +136,27 @@ protected:
// and only visit each function once.
void addFunctionCall(TIntermAggregate* call)
{
// // just use the map to ensure we process each function at most once
// just use the map to ensure we process each function at most once
if (liveFunctions.find(call->getName()) == liveFunctions.end()) {
liveFunctions.insert(call->getName());
pushFunction(call->getName());
}
}
void addGlobalReference(const TString& name)
{
// just use the map to ensure we process each global at most once
if (liveGlobals.find(name) == liveGlobals.end()) {
liveGlobals.insert(name);
pushGlobalReference(name);
}
}
const TIntermediate& intermediate;
typedef std::unordered_set<TString> TLiveFunctions;
TLiveFunctions liveFunctions;
typedef std::unordered_set<TString> TLiveGlobals;
TLiveGlobals liveGlobals;
bool traverseAll;
private:
@@ -157,11 +157,11 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
case EvqBuffer:
if (node->getQualifier().isReadOnly())
message = "can't modify a readonly buffer";
if (node->getQualifier().isShaderRecordNV())
if (node->getQualifier().isShaderRecord())
message = "can't modify a shaderrecordnv qualified buffer";
break;
case EvqHitAttrNV:
if (language != EShLangIntersectNV)
case EvqHitAttr:
if (language != EShLangIntersect)
message = "cannot modify hitAttributeNV in this stage";
break;
#endif
@@ -181,9 +181,12 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
case EbtAtomicUint:
message = "can't modify an atomic_uint";
break;
case EbtAccStructNV:
case EbtAccStruct:
message = "can't modify accelerationStructureNV";
break;
case EbtRayQuery:
message = "can't modify rayQueryEXT";
break;
#endif
default:
break;
@@ -3,6 +3,7 @@
// Copyright (C) 2012-2015 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2017, 2019 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@@ -245,7 +246,9 @@ void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>&
else if (tokens[2].compare("off") == 0)
contextPragma.optimize = false;
else {
error(loc, "\"on\" or \"off\" expected after '(' for 'optimize' pragma", "#pragma", "");
if(relaxedErrors())
// If an implementation does not recognize the tokens following #pragma, then it will ignore that pragma.
warn(loc, "\"on\" or \"off\" expected after '(' for 'optimize' pragma", "#pragma", "");
return;
}
@@ -269,7 +272,9 @@ void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>&
else if (tokens[2].compare("off") == 0)
contextPragma.debug = false;
else {
error(loc, "\"on\" or \"off\" expected after '(' for 'debug' pragma", "#pragma", "");
if(relaxedErrors())
// If an implementation does not recognize the tokens following #pragma, then it will ignore that pragma.
warn(loc, "\"on\" or \"off\" expected after '(' for 'debug' pragma", "#pragma", "");
return;
}
@@ -427,8 +432,18 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
#ifndef GLSLANG_WEB
if (base->isReference() && ! base->isArray()) {
requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "buffer reference indexing");
result = intermediate.addBinaryMath(EOpAdd, base, index, loc);
result->setType(base->getType());
if (base->getType().getReferentType()->containsUnsizedArray()) {
error(loc, "cannot index reference to buffer containing an unsized array", "", "");
result = nullptr;
} else {
result = intermediate.addBinaryMath(EOpAdd, base, index, loc);
if (result != nullptr)
result->setType(base->getType());
}
if (result == nullptr) {
error(loc, "cannot index buffer reference", "", "");
result = intermediate.addConstantUnion(0.0, EbtFloat, loc);
}
return result;
}
if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
@@ -740,8 +755,11 @@ TIntermTyped* TParseContext::handleBinaryMath(const TSourceLoc& loc, const char*
}
TIntermTyped* result = nullptr;
if (allowed)
if (allowed) {
if ((left->isReference() || right->isReference()))
requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "buffer reference math");
result = intermediate.addBinaryMath(op, left, right, loc);
}
if (result == nullptr)
binaryOpError(loc, str, left->getCompleteString(), right->getCompleteString());
@@ -821,50 +839,7 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
TIntermTyped* result = base;
if ((base->isVector() || base->isScalar()) &&
(base->isFloatingDomain() || base->isIntegerDomain() || base->getBasicType() == EbtBool)) {
if (base->isScalar()) {
const char* dotFeature = "scalar swizzle";
requireProfile(loc, ~EEsProfile, dotFeature);
profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature);
}
TSwizzleSelectors<TVectorSelector> selectors;
parseSwizzleSelector(loc, field, base->getVectorSize(), selectors);
if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitFloat())
requireFloat16Arithmetic(loc, ".", "can't swizzle types containing float16");
if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitInt())
requireInt16Arithmetic(loc, ".", "can't swizzle types containing (u)int16");
if (base->isVector() && selectors.size() != 1 && base->getType().contains8BitInt())
requireInt8Arithmetic(loc, ".", "can't swizzle types containing (u)int8");
if (base->isScalar()) {
if (selectors.size() == 1)
return result;
else {
TType type(base->getBasicType(), EvqTemporary, selectors.size());
// Swizzle operations propagate specialization-constantness
if (base->getQualifier().isSpecConstant())
type.getQualifier().makeSpecConstant();
return addConstructor(loc, base, type);
}
}
if (base->getType().getQualifier().isFrontEndConstant())
result = intermediate.foldSwizzle(base, selectors, loc);
else {
if (selectors.size() == 1) {
TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc);
result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision));
} else {
TIntermTyped* index = intermediate.addSwizzle(selectors, loc);
result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc);
result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size()));
}
// Swizzle operations propagate specialization-constantness
if (base->getType().getQualifier().isSpecConstant())
result->getWritableType().getQualifier().makeSpecConstant();
}
result = handleDotSwizzle(loc, base, field);
} else if (base->isStruct() || base->isReference()) {
const TTypeList* fields = base->isReference() ?
base->getType().getReferentType()->getStruct() :
@@ -905,6 +880,60 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
return result;
}
//
// Handle seeing a base.swizzle, a subset of base.identifier in the grammar.
//
TIntermTyped* TParseContext::handleDotSwizzle(const TSourceLoc& loc, TIntermTyped* base, const TString& field)
{
TIntermTyped* result = base;
if (base->isScalar()) {
const char* dotFeature = "scalar swizzle";
requireProfile(loc, ~EEsProfile, dotFeature);
profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature);
}
TSwizzleSelectors<TVectorSelector> selectors;
parseSwizzleSelector(loc, field, base->getVectorSize(), selectors);
if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitFloat())
requireFloat16Arithmetic(loc, ".", "can't swizzle types containing float16");
if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitInt())
requireInt16Arithmetic(loc, ".", "can't swizzle types containing (u)int16");
if (base->isVector() && selectors.size() != 1 && base->getType().contains8BitInt())
requireInt8Arithmetic(loc, ".", "can't swizzle types containing (u)int8");
if (base->isScalar()) {
if (selectors.size() == 1)
return result;
else {
TType type(base->getBasicType(), EvqTemporary, selectors.size());
// Swizzle operations propagate specialization-constantness
if (base->getQualifier().isSpecConstant())
type.getQualifier().makeSpecConstant();
return addConstructor(loc, base, type);
}
}
if (base->getType().getQualifier().isFrontEndConstant())
result = intermediate.foldSwizzle(base, selectors, loc);
else {
if (selectors.size() == 1) {
TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc);
result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision));
} else {
TIntermTyped* index = intermediate.addSwizzle(selectors, loc);
result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc);
result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size()));
}
// Swizzle operations propagate specialization-constantness
if (base->getType().getQualifier().isSpecConstant())
result->getWritableType().getQualifier().makeSpecConstant();
}
return result;
}
void TParseContext::blockMemberExtensionCheck(const TSourceLoc& loc, const TIntermTyped* base, int member, const TString& memberName)
{
// a block that needs extension checking is either 'base', or if arrayed,
@@ -1273,7 +1302,7 @@ TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNo
TIntermTyped *result = intermediate.addBuiltInFunctionCall(loc, function.getBuiltInOp(),
function.getParamCount() == 1,
arguments, function.getType());
if (obeyPrecisionQualifiers())
if (result != nullptr && obeyPrecisionQualifiers())
computeBuiltinPrecisions(*result, function);
if (result == nullptr) {
@@ -1353,6 +1382,9 @@ void TParseContext::computeBuiltinPrecisions(TIntermTyped& node, const TFunction
case EOpInterpolateAtSample:
numArgs = 1;
break;
case EOpDebugPrintf:
numArgs = 0;
break;
default:
break;
}
@@ -1390,23 +1422,28 @@ TIntermNode* TParseContext::handleReturnValue(const TSourceLoc& loc, TIntermType
#endif
functionReturnsValue = true;
TIntermBranch* branch = nullptr;
if (currentFunctionType->getBasicType() == EbtVoid) {
error(loc, "void function cannot return a value", "return", "");
return intermediate.addBranch(EOpReturn, loc);
branch = intermediate.addBranch(EOpReturn, loc);
} else if (*currentFunctionType != value->getType()) {
TIntermTyped* converted = intermediate.addConversion(EOpReturn, *currentFunctionType, value);
if (converted) {
if (*currentFunctionType != converted->getType())
error(loc, "cannot convert return value to function return type", "return", "");
if (version < 420)
warn(loc, "type conversion on return values was not explicitly allowed until version 420", "return", "");
return intermediate.addBranch(EOpReturn, converted, loc);
warn(loc, "type conversion on return values was not explicitly allowed until version 420",
"return", "");
branch = intermediate.addBranch(EOpReturn, converted, loc);
} else {
error(loc, "type does not match, or is not convertible to, the function's return type", "return", "");
return intermediate.addBranch(EOpReturn, value, loc);
branch = intermediate.addBranch(EOpReturn, value, loc);
}
} else
return intermediate.addBranch(EOpReturn, value, loc);
branch = intermediate.addBranch(EOpReturn, value, loc);
branch->updatePrecision(currentFunctionType->getQualifier().precision);
return branch;
}
// See if the operation is being done in an illegal location.
@@ -1650,6 +1687,14 @@ TIntermTyped* TParseContext::addOutputArgumentConversions(const TFunction& funct
#endif
}
TIntermTyped* TParseContext::addAssign(const TSourceLoc& loc, TOperator op, TIntermTyped* left, TIntermTyped* right)
{
if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference())
requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "+= and -= on a buffer reference");
return intermediate.addAssign(op, left, right, loc);
}
void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction& fnCandidate, const TIntermOperator& callNode)
{
const TIntermSequence* argp = &callNode.getAsAggregate()->getSequence();
@@ -1672,6 +1717,9 @@ void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction&
unsigned int semantics = 0, storageClassSemantics = 0;
unsigned int semantics2 = 0, storageClassSemantics2 = 0;
const TIntermTyped* arg0 = (*argp)[0]->getAsTyped();
const bool isMS = arg0->getBasicType() == EbtSampler && arg0->getType().getSampler().isMultiSample();
// Grab the semantics and storage class semantics from the operands, based on opcode
switch (callNode.getOp()) {
case EOpAtomicAdd:
@@ -1704,18 +1752,18 @@ void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction&
case EOpImageAtomicXor:
case EOpImageAtomicExchange:
case EOpImageAtomicStore:
storageClassSemantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst();
semantics = (*argp)[5]->getAsConstantUnion()->getConstArray()[0].getIConst();
storageClassSemantics = (*argp)[isMS ? 5 : 4]->getAsConstantUnion()->getConstArray()[0].getIConst();
semantics = (*argp)[isMS ? 6 : 5]->getAsConstantUnion()->getConstArray()[0].getIConst();
break;
case EOpImageAtomicLoad:
storageClassSemantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst();
semantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst();
storageClassSemantics = (*argp)[isMS ? 4 : 3]->getAsConstantUnion()->getConstArray()[0].getIConst();
semantics = (*argp)[isMS ? 5 : 4]->getAsConstantUnion()->getConstArray()[0].getIConst();
break;
case EOpImageAtomicCompSwap:
storageClassSemantics = (*argp)[5]->getAsConstantUnion()->getConstArray()[0].getIConst();
semantics = (*argp)[6]->getAsConstantUnion()->getConstArray()[0].getIConst();
storageClassSemantics2 = (*argp)[7]->getAsConstantUnion()->getConstArray()[0].getIConst();
semantics2 = (*argp)[8]->getAsConstantUnion()->getConstArray()[0].getIConst();
storageClassSemantics = (*argp)[isMS ? 6 : 5]->getAsConstantUnion()->getConstArray()[0].getIConst();
semantics = (*argp)[isMS ? 7 : 6]->getAsConstantUnion()->getConstArray()[0].getIConst();
storageClassSemantics2 = (*argp)[isMS ? 8 : 7]->getAsConstantUnion()->getConstArray()[0].getIConst();
semantics2 = (*argp)[isMS ? 9 : 8]->getAsConstantUnion()->getConstArray()[0].getIConst();
break;
case EOpBarrier:
@@ -2006,18 +2054,20 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
if (arg > 0) {
#ifndef GLSLANG_WEB
bool f16ShadowCompare = (*argp)[1]->getAsTyped()->getBasicType() == EbtFloat16 && arg0->getType().getSampler().shadow;
bool f16ShadowCompare = (*argp)[1]->getAsTyped()->getBasicType() == EbtFloat16 &&
arg0->getType().getSampler().shadow;
if (f16ShadowCompare)
++arg;
#endif
if (! (*argp)[arg]->getAsConstantUnion())
if (! (*argp)[arg]->getAsTyped()->getQualifier().isConstant())
error(loc, "argument must be compile-time constant", "texel offset", "");
else {
else if ((*argp)[arg]->getAsConstantUnion()) {
const TType& type = (*argp)[arg]->getAsTyped()->getType();
for (int c = 0; c < type.getVectorSize(); ++c) {
int offset = (*argp)[arg]->getAsConstantUnion()->getConstArray()[c].getIConst();
if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset)
error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]");
error(loc, "value is out of range:", "texel offset",
"[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]");
}
}
}
@@ -2026,15 +2076,32 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
}
#ifndef GLSLANG_WEB
case EOpTraceNV:
case EOpTrace:
if (!(*argp)[10]->getAsConstantUnion())
error(loc, "argument must be compile-time constant", "payload number", "");
break;
case EOpExecuteCallableNV:
case EOpExecuteCallable:
if (!(*argp)[1]->getAsConstantUnion())
error(loc, "argument must be compile-time constant", "callable data number", "");
break;
case EOpRayQueryGetIntersectionType:
case EOpRayQueryGetIntersectionT:
case EOpRayQueryGetIntersectionInstanceCustomIndex:
case EOpRayQueryGetIntersectionInstanceId:
case EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset:
case EOpRayQueryGetIntersectionGeometryIndex:
case EOpRayQueryGetIntersectionPrimitiveIndex:
case EOpRayQueryGetIntersectionBarycentrics:
case EOpRayQueryGetIntersectionFrontFace:
case EOpRayQueryGetIntersectionObjectRayDirection:
case EOpRayQueryGetIntersectionObjectRayOrigin:
case EOpRayQueryGetIntersectionObjectToWorld:
case EOpRayQueryGetIntersectionWorldToObject:
if (!(*argp)[1]->getAsConstantUnion())
error(loc, "argument must be compile-time constant", "committed", "");
break;
case EOpTextureQuerySamples:
case EOpImageQuerySamples:
// GL_ARB_shader_texture_image_samples
@@ -2058,7 +2125,14 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
if (imageType.getQualifier().getFormat() != ElfR32i && imageType.getQualifier().getFormat() != ElfR32ui)
error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), "");
} else {
if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0)
bool isImageAtomicOnFloatAllowed = ((fnCandidate.getName().compare(0, 14, "imageAtomicAdd") == 0) ||
(fnCandidate.getName().compare(0, 15, "imageAtomicLoad") == 0) ||
(fnCandidate.getName().compare(0, 16, "imageAtomicStore") == 0) ||
(fnCandidate.getName().compare(0, 19, "imageAtomicExchange") == 0));
if (imageType.getSampler().type == EbtFloat && isImageAtomicOnFloatAllowed &&
(fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0)) // imageAtomicExchange doesn't require GL_EXT_shader_atomic_float
requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str());
if (!isImageAtomicOnFloatAllowed)
error(loc, "only supported on integer images", fnCandidate.getName().c_str(), "");
else if (imageType.getQualifier().getFormat() != ElfR32f && isEsProfile())
error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), "");
@@ -2087,10 +2161,18 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
if (argp->size() > 3) {
requireExtensions(loc, 1, &E_GL_KHR_memory_scope_semantics, fnCandidate.getName().c_str());
memorySemanticsCheck(loc, fnCandidate, callNode);
if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange ||
callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpAtomicStore) &&
(arg0->getType().isFloatingDomain())) {
requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str());
}
} else if (arg0->getType().getBasicType() == EbtInt64 || arg0->getType().getBasicType() == EbtUint64) {
const char* const extensions[2] = { E_GL_NV_shader_atomic_int64,
E_GL_EXT_shader_atomic_int64 };
requireExtensions(loc, 2, extensions, fnCandidate.getName().c_str());
} else if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange) &&
(arg0->getType().isFloatingDomain())) {
requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str());
}
break;
}
@@ -2172,6 +2254,28 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
memorySemanticsCheck(loc, fnCandidate, callNode);
}
break;
case EOpMix:
if (profile == EEsProfile && version < 310) {
// Look for specific signatures
if ((*argp)[0]->getAsTyped()->getBasicType() != EbtFloat &&
(*argp)[1]->getAsTyped()->getBasicType() != EbtFloat &&
(*argp)[2]->getAsTyped()->getBasicType() == EbtBool) {
requireExtensions(loc, 1, &E_GL_EXT_shader_integer_mix, "specific signature of builtin mix");
}
}
if (profile != EEsProfile && version < 450) {
if ((*argp)[0]->getAsTyped()->getBasicType() != EbtFloat &&
(*argp)[0]->getAsTyped()->getBasicType() != EbtDouble &&
(*argp)[1]->getAsTyped()->getBasicType() != EbtFloat &&
(*argp)[1]->getAsTyped()->getBasicType() != EbtDouble &&
(*argp)[2]->getAsTyped()->getBasicType() == EbtBool) {
requireExtensions(loc, 1, &E_GL_EXT_shader_integer_mix, fnCandidate.getName().c_str());
}
}
break;
#endif
default:
@@ -2698,7 +2802,10 @@ void TParseContext::reservedPpErrorCheck(const TSourceLoc& loc, const char* iden
if (strncmp(identifier, "GL_", 3) == 0)
ppError(loc, "names beginning with \"GL_\" can't be (un)defined:", op, identifier);
else if (strncmp(identifier, "defined", 8) == 0)
ppError(loc, "\"defined\" can't be (un)defined:", op, identifier);
if (relaxedErrors())
ppWarn(loc, "\"defined\" is (un)defined:", op, identifier);
else
ppError(loc, "\"defined\" can't be (un)defined:", op, identifier);
else if (strstr(identifier, "__") != 0) {
if (isEsProfile() && version >= 300 &&
(strcmp(identifier, "__LINE__") == 0 ||
@@ -2706,7 +2813,7 @@ void TParseContext::reservedPpErrorCheck(const TSourceLoc& loc, const char* iden
strcmp(identifier, "__VERSION__") == 0))
ppError(loc, "predefined names can't be (un)defined:", op, identifier);
else {
if (isEsProfile() && version < 300)
if (isEsProfile() && version < 300 && !relaxedErrors())
ppError(loc, "names containing consecutive underscores are reserved, and an error if version < 300:", op, identifier);
else
ppWarn(loc, "names containing consecutive underscores are reserved:", op, identifier);
@@ -3083,7 +3190,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
error(loc, "constructor argument does not have a type", "constructor", "");
return true;
}
if (op != EOpConstructStruct && typed->getBasicType() == EbtSampler) {
if (op != EOpConstructStruct && op != EOpConstructNonuniform && typed->getBasicType() == EbtSampler) {
error(loc, "cannot convert a sampler", "constructor", "");
return true;
}
@@ -3128,7 +3235,7 @@ bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const
if (function[0].type->getBasicType() != EbtSampler ||
! function[0].type->getSampler().isTexture() ||
function[0].type->isArray()) {
error(loc, "sampler-constructor first argument must be a scalar textureXXX type", token, "");
error(loc, "sampler-constructor first argument must be a scalar *texture* type", token, "");
return true;
}
// simulate the first argument's impact on the result type, so it can be compared with the encapsulated operator!=()
@@ -3136,7 +3243,8 @@ bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const
texture.setCombined(false);
texture.shadow = false;
if (texture != function[0].type->getSampler()) {
error(loc, "sampler-constructor first argument must match type and dimensionality of constructor type", token, "");
error(loc, "sampler-constructor first argument must be a *texture* type"
" matching the dimensionality and sampled type of the constructor", token, "");
return true;
}
@@ -3146,7 +3254,7 @@ bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const
if ( function[1].type->getBasicType() != EbtSampler ||
! function[1].type->getSampler().isPureSampler() ||
function[1].type->isArray()) {
error(loc, "sampler-constructor second argument must be a scalar type 'sampler'", token, "");
error(loc, "sampler-constructor second argument must be a scalar sampler or samplerShadow", token, "");
return true;
}
@@ -3222,14 +3330,14 @@ void TParseContext::atomicUintCheck(const TSourceLoc& loc, const TType& type, co
error(loc, "atomic_uints can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
}
void TParseContext::accStructNVCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
void TParseContext::accStructCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
{
if (type.getQualifier().storage == EvqUniform)
return;
if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAccStructNV))
if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAccStruct))
error(loc, "non-uniform struct contains an accelerationStructureNV:", type.getBasicTypeString().c_str(), identifier.c_str());
else if (type.getBasicType() == EbtAccStructNV && type.getQualifier().storage != EvqUniform)
else if (type.getBasicType() == EbtAccStruct && type.getQualifier().storage != EvqUniform)
error(loc, "accelerationStructureNV can only be used in uniform variables or function parameters:",
type.getBasicTypeString().c_str(), identifier.c_str());
@@ -3327,6 +3435,11 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
!qualifier.hasBufferReference())
error(loc, "buffers can be declared only as blocks", "buffer", "");
if (qualifier.storage != EvqVaryingIn && publicType.basicType == EbtDouble &&
extensionTurnedOn(E_GL_ARB_vertex_attrib_64bit) && language == EShLangVertex &&
version < 400) {
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 410, E_GL_ARB_gpu_shader_fp64, "vertex-shader `double` type");
}
if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut)
return;
@@ -3377,7 +3490,7 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays");
}
if (publicType.basicType == EbtDouble)
profileRequires(loc, ~EEsProfile, 410, nullptr, "vertex-shader `double` type input");
profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_vertex_attrib_64bit, "vertex-shader `double` type input");
if (qualifier.isAuxiliary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.invariant)
error(loc, "vertex input cannot be further qualified", "", "");
break;
@@ -3513,12 +3626,14 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons
dst.precision = src.precision;
#ifndef GLSLANG_WEB
if (!force && ((src.coherent && (dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)) ||
(src.devicecoherent && (dst.coherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)) ||
(src.queuefamilycoherent && (dst.coherent || dst.devicecoherent || dst.workgroupcoherent || dst.subgroupcoherent)) ||
(src.workgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.subgroupcoherent)) ||
(src.subgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent)))) {
error(loc, "only one coherent/devicecoherent/queuefamilycoherent/workgroupcoherent/subgroupcoherent qualifier allowed", GetPrecisionQualifierString(src.precision), "");
if (!force && ((src.coherent && (dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) ||
(src.devicecoherent && (dst.coherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) ||
(src.queuefamilycoherent && (dst.coherent || dst.devicecoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) ||
(src.workgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.subgroupcoherent || dst.shadercallcoherent)) ||
(src.subgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.shadercallcoherent)) ||
(src.shadercallcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)))) {
error(loc, "only one coherent/devicecoherent/queuefamilycoherent/workgroupcoherent/subgroupcoherent/shadercallcoherent qualifier allowed",
GetPrecisionQualifierString(src.precision), "");
}
#endif
// Layout qualifiers
@@ -3546,6 +3661,7 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons
MERGE_SINGLETON(queuefamilycoherent);
MERGE_SINGLETON(workgroupcoherent);
MERGE_SINGLETON(subgroupcoherent);
MERGE_SINGLETON(shadercallcoherent);
MERGE_SINGLETON(nonprivate);
MERGE_SINGLETON(volatil);
MERGE_SINGLETON(restrict);
@@ -3983,7 +4099,7 @@ void TParseContext::checkRuntimeSizable(const TSourceLoc& loc, const TIntermType
}
// check for additional things allowed by GL_EXT_nonuniform_qualifier
if (base.getBasicType() == EbtSampler || base.getBasicType() == EbtAccStructNV ||
if (base.getBasicType() == EbtSampler || base.getBasicType() == EbtAccStruct || base.getBasicType() == EbtRayQuery ||
(base.getBasicType() == EbtBlock && base.getType().getQualifier().isUniformOrBuffer()))
requireExtensions(loc, 1, &E_GL_EXT_nonuniform_qualifier, "variable index");
else
@@ -4487,6 +4603,7 @@ void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& quali
type.getQualifier().queuefamilycoherent = qualifier.queuefamilycoherent;
type.getQualifier().workgroupcoherent = qualifier.workgroupcoherent;
type.getQualifier().subgroupcoherent = qualifier.subgroupcoherent;
type.getQualifier().shadercallcoherent = qualifier.shadercallcoherent;
type.getQualifier().nonprivate = qualifier.nonprivate;
type.getQualifier().readonly = qualifier.readonly;
type.getQualifier().writeonly = qualifier.writeonly;
@@ -4868,7 +4985,7 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
#ifndef GLSLANG_WEB
if (id == TQualifier::getLayoutPackingString(ElpStd430)) {
requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "std430");
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "std430");
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_shader_storage_buffer_object, "std430");
profileRequires(loc, EEsProfile, 310, nullptr, "std430");
publicType.qualifier.layoutPacking = ElpStd430;
return;
@@ -5067,13 +5184,19 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
return;
}
} else {
if (language == EShLangRayGenNV || language == EShLangIntersectNV ||
language == EShLangAnyHitNV || language == EShLangClosestHitNV ||
language == EShLangMissNV || language == EShLangCallableNV) {
if (id == "shaderrecordnv") {
publicType.qualifier.layoutShaderRecordNV = true;
if (language == EShLangRayGen || language == EShLangIntersect ||
language == EShLangAnyHit || language == EShLangClosestHit ||
language == EShLangMiss || language == EShLangCallable) {
if (id == "shaderrecordnv" || id == "shaderrecordext") {
if (id == "shaderrecordnv") {
requireExtensions(loc, 1, &E_GL_NV_ray_tracing, "shader record NV");
} else {
requireExtensions(loc, 1, &E_GL_EXT_ray_tracing, "shader record EXT");
}
publicType.qualifier.layoutShaderRecord = true;
return;
}
}
}
if (language == EShLangCompute) {
@@ -5088,6 +5211,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(), "");
@@ -5135,6 +5264,7 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
profileRequires(loc, EEsProfile, 310, nullptr, feature);
}
publicType.qualifier.layoutOffset = value;
publicType.qualifier.explicitOffset = true;
if (nonLiteral)
error(loc, "needs a literal integer", "offset", "");
return;
@@ -5347,10 +5477,10 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
case EShLangFragment:
if (id == "index") {
requireProfile(loc, ECompatibilityProfile | ECoreProfile, "index layout qualifier on fragment output");
requireProfile(loc, ECompatibilityProfile | ECoreProfile | EEsProfile, "index layout qualifier on fragment output");
const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location };
profileRequires(loc, ECompatibilityProfile | ECoreProfile, 330, 2, exts, "index layout qualifier on fragment output");
profileRequires(loc, EEsProfile ,310, E_GL_EXT_blend_func_extended, "index layout qualifier on fragment output");
// "It is also a compile-time error if a fragment shader sets a layout index to less than 0 or greater than 1."
if (value < 0 || value > 1) {
value = 0;
@@ -5514,8 +5644,8 @@ void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifie
dst.layoutViewportRelative = true;
if (src.layoutSecondaryViewportRelativeOffset != -2048)
dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset;
if (src.layoutShaderRecordNV)
dst.layoutShaderRecordNV = true;
if (src.layoutShaderRecord)
dst.layoutShaderRecord = true;
if (src.pervertexNV)
dst.pervertexNV = true;
#endif
@@ -5583,7 +5713,7 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb
error(loc, "cannot specify on a variable declaration", "align", "");
if (qualifier.isPushConstant())
error(loc, "can only specify on a uniform block", "push_constant", "");
if (qualifier.isShaderRecordNV())
if (qualifier.isShaderRecord())
error(loc, "can only specify on a buffer block", "shaderRecordNV", "");
}
break;
@@ -5657,11 +5787,11 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
error(loc, "cannot apply to uniform or buffer block", "location", "");
break;
#ifndef GLSLANG_WEB
case EvqPayloadNV:
case EvqPayloadInNV:
case EvqHitAttrNV:
case EvqCallableDataNV:
case EvqCallableDataInNV:
case EvqPayload:
case EvqPayloadIn:
case EvqHitAttr:
case EvqCallableData:
case EvqCallableDataIn:
break;
#endif
default:
@@ -5684,6 +5814,8 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
int repeated = intermediate.addXfbBufferOffset(type);
if (repeated >= 0)
error(loc, "overlapping offsets at", "xfb_offset", "offset %d in buffer %d", repeated, qualifier.layoutXfbBuffer);
if (type.isUnsizedArray())
error(loc, "unsized array", "xfb_offset", "in buffer %d", qualifier.layoutXfbBuffer);
// "The offset must be a multiple of the size of the first component of the first
// qualified variable or block member, or a compile-time error results. Further, if applied to an aggregate
@@ -5756,7 +5888,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
if (spvVersion.spv > 0) {
if (qualifier.isUniformOrBuffer()) {
if (type.getBasicType() == EbtBlock && !qualifier.isPushConstant() &&
!qualifier.isShaderRecordNV() &&
!qualifier.isShaderRecord() &&
!qualifier.hasAttachment() &&
!qualifier.hasBufferReference())
error(loc, "uniform/buffer blocks require layout(binding=X)", "binding", "");
@@ -5813,7 +5945,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
if (qualifier.hasBufferReference() && type.getBasicType() != EbtBlock)
error(loc, "can only be used with a block", "buffer_reference", "");
if (qualifier.isShaderRecordNV() && type.getBasicType() != EbtBlock)
if (qualifier.isShaderRecord() && type.getBasicType() != EbtBlock)
error(loc, "can only be used with a block", "shaderRecordNV", "");
// input attachment
@@ -5958,7 +6090,7 @@ void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier
if (qualifier.storage != EvqBuffer)
error(loc, "can only be used with buffer", "buffer_reference", "");
}
if (qualifier.isShaderRecordNV()) {
if (qualifier.isShaderRecord()) {
if (qualifier.storage != EvqBuffer)
error(loc, "can only be used with a buffer", "shaderRecordNV", "");
if (qualifier.hasBinding())
@@ -5967,7 +6099,7 @@ void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier
error(loc, "cannot be used with shaderRecordNV", "set", "");
}
if (qualifier.storage == EvqHitAttrNV && qualifier.hasLayout()) {
if (qualifier.storage == EvqHitAttr && qualifier.hasLayout()) {
error(loc, "cannot apply layout qualifiers to hitAttributeNV variable", "hitAttributeNV", "");
}
}
@@ -6018,6 +6150,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
}
@@ -6079,6 +6213,15 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunct
#endif
const TFunction* function = nullptr;
// debugPrintfEXT has var args and is in the symbol table as "debugPrintfEXT()",
// mangled to "debugPrintfEXT("
if (call.getName() == "debugPrintfEXT") {
TSymbol* symbol = symbolTable.find("debugPrintfEXT(", &builtIn);
if (symbol)
return symbol->getAsFunction();
}
bool explicitTypesEnabled = extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8) ||
extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16) ||
@@ -6088,7 +6231,10 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunct
extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32) ||
extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64);
if (isEsProfile() || version < 120)
if (isEsProfile())
function = (extensionTurnedOn(E_GL_EXT_shader_implicit_conversions) && version >= 310) ?
findFunction120(loc, call, builtIn) : findFunctionExact(loc, call, builtIn);
else if (version < 120)
function = findFunctionExact(loc, call, builtIn);
else if (version < 400)
function = extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) ? findFunction400(loc, call, builtIn) : findFunction120(loc, call, builtIn);
@@ -6422,6 +6568,12 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
type.copyArrayInnerSizes(publicType.arraySizes);
arrayOfArrayVersionCheck(loc, type.getArraySizes());
if (initializer) {
if (type.getBasicType() == EbtRayQuery) {
error(loc, "ray queries can only be initialized by using the rayQueryInitializeEXT intrinsic:", "=", identifier.c_str());
}
}
if (type.isCoopMat()) {
intermediate.setUseVulkanMemoryModel();
intermediate.setUseStorageBuffer();
@@ -6461,7 +6613,7 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
transparentOpaqueCheck(loc, type, identifier);
#ifndef GLSLANG_WEB
atomicUintCheck(loc, type, identifier);
accStructNVCheck(loc, type, identifier);
accStructCheck(loc, type, identifier);
checkAndResizeMeshViewDim(loc, type, /*isBlockMember*/ false);
#endif
if (type.getQualifier().storage == EvqConst && type.containsReference()) {
@@ -7177,6 +7329,8 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
if (!node->getType().isCoopMat()) {
if (type.getBasicType() != node->getType().getBasicType()) {
node = intermediate.addConversion(type.getBasicType(), node);
if (node == nullptr)
return nullptr;
}
node = intermediate.setAggregateOperator(node, EOpConstructCooperativeMatrix, type, node->getLoc());
} else {
@@ -7355,8 +7509,8 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
arraySizesCheck(memberLoc, currentBlockQualifier, memberType.getArraySizes(), nullptr, member == typeList.size() - 1);
if (memberQualifier.hasOffset()) {
if (spvVersion.spv == 0) {
requireProfile(memberLoc, ~EEsProfile, "offset on block member");
profileRequires(memberLoc, ~EEsProfile, 440, E_GL_ARB_enhanced_layouts, "offset on block member");
profileRequires(memberLoc, ~EEsProfile, 440, E_GL_ARB_enhanced_layouts, "\"offset\" on block member");
profileRequires(memberLoc, EEsProfile, 300, E_GL_ARB_enhanced_layouts, "\"offset\" on block member");
}
}
@@ -7395,7 +7549,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
// Special case for "push_constant uniform", which has a default of std430,
// contrary to normal uniform defaults, and can't have a default tracked for it.
if ((currentBlockQualifier.isPushConstant() && !currentBlockQualifier.hasPacking()) ||
(currentBlockQualifier.isShaderRecordNV() && !currentBlockQualifier.hasPacking()))
(currentBlockQualifier.isShaderRecord() && !currentBlockQualifier.hasPacking()))
currentBlockQualifier.layoutPacking = ElpStd430;
// Special case for "taskNV in/out", which has a default of std430,
@@ -7495,6 +7649,8 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation);
fixXfbOffsets(currentBlockQualifier, typeList);
fixBlockUniformOffsets(currentBlockQualifier, typeList);
fixBlockUniformLayoutMatrix(currentBlockQualifier, &typeList, nullptr);
fixBlockUniformLayoutPacking(currentBlockQualifier, &typeList, nullptr);
for (unsigned int member = 0; member < typeList.size(); ++member)
layoutTypeCheck(typeList[member].loc, *typeList[member].type);
@@ -7612,6 +7768,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
// with a particular stage.
void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier)
{
const char *extsrt[2] = { E_GL_NV_ray_tracing, E_GL_EXT_ray_tracing };
switch (qualifier.storage) {
case EvqUniform:
profileRequires(loc, EEsProfile, 300, nullptr, "uniform block");
@@ -7621,7 +7778,7 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q
break;
case EvqBuffer:
requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "buffer block");
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "buffer block");
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_shader_storage_buffer_object, "buffer block");
profileRequires(loc, EEsProfile, 310, nullptr, "buffer block");
break;
case EvqVaryingIn:
@@ -7650,28 +7807,28 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q
}
break;
#ifndef GLSLANG_WEB
case EvqPayloadNV:
profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV block");
requireStage(loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangAnyHitNVMask | EShLangClosestHitNVMask | EShLangMissNVMask),
case EvqPayload:
profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadNV block");
requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangAnyHitMask | EShLangClosestHitMask | EShLangMissMask),
"rayPayloadNV block");
break;
case EvqPayloadInNV:
profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV block");
requireStage(loc, (EShLanguageMask)(EShLangAnyHitNVMask | EShLangClosestHitNVMask | EShLangMissNVMask),
case EvqPayloadIn:
profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadInNV block");
requireStage(loc, (EShLanguageMask)(EShLangAnyHitMask | EShLangClosestHitMask | EShLangMissMask),
"rayPayloadInNV block");
break;
case EvqHitAttrNV:
profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV block");
requireStage(loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangAnyHitNVMask | EShLangClosestHitNVMask), "hitAttributeNV block");
case EvqHitAttr:
profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "hitAttributeNV block");
requireStage(loc, (EShLanguageMask)(EShLangIntersectMask | EShLangAnyHitMask | EShLangClosestHitMask), "hitAttributeNV block");
break;
case EvqCallableDataNV:
profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "callableDataNV block");
requireStage(loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask),
case EvqCallableData:
profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "callableDataNV block");
requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask),
"callableDataNV block");
break;
case EvqCallableDataInNV:
profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV block");
requireStage(loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV block");
case EvqCallableDataIn:
profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "callableDataInNV block");
requireStage(loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV block");
break;
#endif
default:
@@ -7710,8 +7867,8 @@ void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier&
error(loc, "cannot use invariant qualifier on an interface block", "invariant", "");
if (qualifier.isPushConstant())
intermediate.addPushConstantCount();
if (qualifier.isShaderRecordNV())
intermediate.addShaderRecordNVCount();
if (qualifier.isShaderRecord())
intermediate.addShaderRecordCount();
if (qualifier.isTaskMemory())
intermediate.addTaskNVCount();
}
@@ -7864,6 +8021,101 @@ void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typ
}
}
//
// Spread LayoutMatrix to uniform block member, if a uniform block member is a struct,
// we need spread LayoutMatrix to this struct member too. and keep this rule for recursive.
//
void TParseContext::fixBlockUniformLayoutMatrix(TQualifier& qualifier, TTypeList* originTypeList,
TTypeList* tmpTypeList)
{
assert(tmpTypeList == nullptr || originTypeList->size() == tmpTypeList->size());
for (unsigned int member = 0; member < originTypeList->size(); ++member) {
if (qualifier.layoutPacking != ElpNone) {
if (tmpTypeList == nullptr) {
if (((*originTypeList)[member].type->isMatrix() ||
(*originTypeList)[member].type->getBasicType() == EbtStruct) &&
(*originTypeList)[member].type->getQualifier().layoutMatrix == ElmNone) {
(*originTypeList)[member].type->getQualifier().layoutMatrix = qualifier.layoutMatrix;
}
} else {
if (((*tmpTypeList)[member].type->isMatrix() ||
(*tmpTypeList)[member].type->getBasicType() == EbtStruct) &&
(*tmpTypeList)[member].type->getQualifier().layoutMatrix == ElmNone) {
(*tmpTypeList)[member].type->getQualifier().layoutMatrix = qualifier.layoutMatrix;
}
}
}
if ((*originTypeList)[member].type->getBasicType() == EbtStruct) {
TQualifier* memberQualifier = nullptr;
// block member can be declare a matrix style, so it should be update to the member's style
if ((*originTypeList)[member].type->getQualifier().layoutMatrix == ElmNone) {
memberQualifier = &qualifier;
} else {
memberQualifier = &((*originTypeList)[member].type->getQualifier());
}
const TType* tmpType = tmpTypeList == nullptr ?
(*originTypeList)[member].type->clone() : (*tmpTypeList)[member].type;
fixBlockUniformLayoutMatrix(*memberQualifier, (*originTypeList)[member].type->getWritableStruct(),
tmpType->getWritableStruct());
const TTypeList* structure = recordStructCopy(matrixFixRecord, (*originTypeList)[member].type, tmpType);
if (tmpTypeList == nullptr) {
(*originTypeList)[member].type->setStruct(const_cast<TTypeList*>(structure));
}
if (tmpTypeList != nullptr) {
(*tmpTypeList)[member].type->setStruct(const_cast<TTypeList*>(structure));
}
}
}
}
//
// Spread LayoutPacking to block member, if a block member is a struct, we need spread LayoutPacking to
// this struct member too. and keep this rule for recursive.
//
void TParseContext::fixBlockUniformLayoutPacking(TQualifier& qualifier, TTypeList* originTypeList,
TTypeList* tmpTypeList)
{
assert(tmpTypeList == nullptr || originTypeList->size() == tmpTypeList->size());
for (unsigned int member = 0; member < originTypeList->size(); ++member) {
if (qualifier.layoutPacking != ElpNone) {
if (tmpTypeList == nullptr) {
if ((*originTypeList)[member].type->getQualifier().layoutPacking == ElpNone) {
(*originTypeList)[member].type->getQualifier().layoutPacking = qualifier.layoutPacking;
}
} else {
if ((*tmpTypeList)[member].type->getQualifier().layoutPacking == ElpNone) {
(*tmpTypeList)[member].type->getQualifier().layoutPacking = qualifier.layoutPacking;
}
}
}
if ((*originTypeList)[member].type->getBasicType() == EbtStruct) {
// Deep copy the type in pool.
// Because, struct use in different block may have different layout qualifier.
// We have to new a object to distinguish between them.
const TType* tmpType = tmpTypeList == nullptr ?
(*originTypeList)[member].type->clone() : (*tmpTypeList)[member].type;
fixBlockUniformLayoutPacking(qualifier, (*originTypeList)[member].type->getWritableStruct(),
tmpType->getWritableStruct());
const TTypeList* structure = recordStructCopy(packingFixRecord, (*originTypeList)[member].type, tmpType);
if (tmpTypeList == nullptr) {
(*originTypeList)[member].type->setStruct(const_cast<TTypeList*>(structure));
}
if (tmpTypeList != nullptr) {
(*tmpTypeList)[member].type->setStruct(const_cast<TTypeList*>(structure));
}
}
}
}
// For an identifier that is already declared, add more qualification to it.
void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, const TString& identifier)
{
@@ -8172,6 +8424,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;
@@ -8233,7 +8495,7 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con
error(loc, "cannot declare a default, can only be used on a block", "buffer_reference", "");
if (qualifier.hasSpecConstantId())
error(loc, "cannot declare a default, can only be used on a scalar", "constant_id", "");
if (qualifier.isShaderRecordNV())
if (qualifier.isShaderRecord())
error(loc, "cannot declare a default, can only be used on a block", "shaderRecordNV", "");
}
@@ -8322,5 +8584,43 @@ TIntermNode* TParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expre
return switchNode;
}
//
// When a struct used in block, and has it's own layout packing, layout matrix,
// record the origin structure of a struct to map, and Record the structure copy to the copy table,
//
const TTypeList* TParseContext::recordStructCopy(TStructRecord& record, const TType* originType, const TType* tmpType)
{
size_t memberCount = tmpType->getStruct()->size();
size_t originHash = 0, tmpHash = 0;
std::hash<size_t> hasher;
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 +
tmpType->getStruct()->at(i).type->getQualifier().layoutMatrix);
originHash = hasher((originHash ^ originMemberHash) << 1);
tmpHash = hasher((tmpHash ^ tmpMemberHash) << 1);
}
const TTypeList* originStruct = originType->getStruct();
const TTypeList* tmpStruct = tmpType->getStruct();
if (originHash != tmpHash) {
auto fixRecords = record.find(originStruct);
if (fixRecords != record.end()) {
auto fixRecord = fixRecords->second.find(tmpHash);
if (fixRecord != fixRecords->second.end()) {
return fixRecord->second;
} else {
record[originStruct][tmpHash] = tmpStruct;
return tmpStruct;
}
} else {
record[originStruct] = std::map<size_t, const TTypeList*>();
record[originStruct][tmpHash] = tmpStruct;
return tmpStruct;
}
}
return originStruct;
}
} // end namespace glslang
@@ -68,6 +68,7 @@ class TScanContext;
class TPpContext;
typedef std::set<int> TIdSetType;
typedef std::map<const TTypeList*, std::map<size_t, const TTypeList*>> TStructRecord;
//
// Sharable code (as well as what's in TParseVersions) across
@@ -83,6 +84,7 @@ public:
scopeMangler("::"),
symbolTable(symbolTable),
statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
currentFunctionType(nullptr),
postEntryPointReturn(false),
contextPragma(true, false),
beginInvocationInterlockCount(0), endInvocationInterlockCount(0),
@@ -315,6 +317,7 @@ public:
TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
TIntermTyped* handleDotSwizzle(const TSourceLoc&, TIntermTyped* base, const TString& field);
void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName);
TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
@@ -326,6 +329,7 @@ public:
TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
TIntermTyped* addAssign(const TSourceLoc&, TOperator op, TIntermTyped* left, TIntermTyped* right);
void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&);
void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&);
@@ -358,7 +362,7 @@ public:
void boolCheck(const TSourceLoc&, const TPublicType&);
void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
void accStructNVCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
void memberQualifierCheck(glslang::TPublicType&);
void globalQualifierFixCheck(const TSourceLoc&, TQualifier&);
@@ -417,12 +421,15 @@ public:
void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
void fixXfbOffsets(TQualifier&, TTypeList&);
void fixBlockUniformOffsets(TQualifier&, TTypeList&);
void fixBlockUniformLayoutMatrix(TQualifier&, TTypeList*, TTypeList*);
void fixBlockUniformLayoutPacking(TQualifier&, TTypeList*, TTypeList*);
void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier);
void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
void invariantCheck(const TSourceLoc&, const TQualifier&);
void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
const TTypeList* recordStructCopy(TStructRecord&, const TType*, const TType*);
#ifndef GLSLANG_WEB
TAttributeType attributeFromName(const TString& name) const;
@@ -483,6 +490,8 @@ protected:
bool anyIndexLimits;
TIdSetType inductiveLoopIds;
TVector<TIntermTyped*> needsIndexLimitationChecking;
TStructRecord matrixFixRecord;
TStructRecord packingFixRecord;
//
// Geometry shader input arrays:
@@ -2,6 +2,8 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Copyright (C) 2020 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@@ -187,17 +189,15 @@ bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstT
if (lookingInMiddle) {
notFirstToken = true;
// make forward progress by finishing off the current line plus extra new lines
if (peek() == '\n' || peek() == '\r') {
while (peek() == '\n' || peek() == '\r')
get();
} else
if (peek() != '\n' && peek() != '\r') {
do {
c = get();
} while (c != EndOfInput && c != '\n' && c != '\r');
while (peek() == '\n' || peek() == '\r')
get();
if (peek() == EndOfInput)
return true;
}
while (peek() == '\n' || peek() == '\r')
get();
if (peek() == EndOfInput)
return true;
}
lookingInMiddle = true;
@@ -416,6 +416,7 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["queuefamilycoherent"] = QUEUEFAMILYCOHERENT;
(*KeywordMap)["workgroupcoherent"] = WORKGROUPCOHERENT;
(*KeywordMap)["subgroupcoherent"] = SUBGROUPCOHERENT;
(*KeywordMap)["shadercallcoherent"] = SHADERCALLCOHERENT;
(*KeywordMap)["nonprivate"] = NONPRIVATE;
(*KeywordMap)["restrict"] = RESTRICT;
(*KeywordMap)["readonly"] = READONLY;
@@ -704,11 +705,18 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["precise"] = PRECISE;
(*KeywordMap)["rayPayloadNV"] = PAYLOADNV;
(*KeywordMap)["rayPayloadEXT"] = PAYLOADEXT;
(*KeywordMap)["rayPayloadInNV"] = PAYLOADINNV;
(*KeywordMap)["rayPayloadInEXT"] = PAYLOADINEXT;
(*KeywordMap)["hitAttributeNV"] = HITATTRNV;
(*KeywordMap)["hitAttributeEXT"] = HITATTREXT;
(*KeywordMap)["callableDataNV"] = CALLDATANV;
(*KeywordMap)["callableDataEXT"] = CALLDATAEXT;
(*KeywordMap)["callableDataInNV"] = CALLDATAINNV;
(*KeywordMap)["callableDataInEXT"] = CALLDATAINEXT;
(*KeywordMap)["accelerationStructureNV"] = ACCSTRUCTNV;
(*KeywordMap)["accelerationStructureEXT"] = ACCSTRUCTEXT;
(*KeywordMap)["rayQueryEXT"] = RAYQUERYEXT;
(*KeywordMap)["perprimitiveNV"] = PERPRIMITIVENV;
(*KeywordMap)["perviewNV"] = PERVIEWNV;
(*KeywordMap)["taskNV"] = PERTASKNV;
@@ -843,6 +851,7 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
parseContext.error(loc, "not supported", "::", "");
break;
case PpAtomConstString: parserToken->sType.lex.string = NewPoolTString(tokenText); return STRING_LITERAL;
case PpAtomConstInt: parserToken->sType.lex.i = ppToken.ival; return INTCONSTANT;
case PpAtomConstUint: parserToken->sType.lex.i = ppToken.ival; return UINTCONSTANT;
case PpAtomConstFloat: parserToken->sType.lex.d = ppToken.dval; return FLOATCONSTANT;
@@ -908,7 +917,8 @@ int TScanContext::tokenizeIdentifier()
case BUFFER:
afterBuffer = true;
if ((parseContext.isEsProfile() && parseContext.version < 310) ||
(!parseContext.isEsProfile() && parseContext.version < 430))
(!parseContext.isEsProfile() && (parseContext.version < 430 &&
!parseContext.extensionTurnedOn(E_GL_ARB_shader_storage_buffer_object))))
return identifierOrType();
return keyword;
@@ -1014,6 +1024,23 @@ int TScanContext::tokenizeIdentifier()
parseContext.extensionTurnedOn(E_GL_NV_ray_tracing))
return keyword;
return identifierOrType();
case PAYLOADEXT:
case PAYLOADINEXT:
case HITATTREXT:
case CALLDATAEXT:
case CALLDATAINEXT:
case ACCSTRUCTEXT:
if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_ray_tracing) ||
parseContext.extensionTurnedOn(E_GL_EXT_ray_query))
return keyword;
return identifierOrType();
case RAYQUERYEXT:
if (parseContext.symbolTable.atBuiltInLevel() ||
(!parseContext.isEsProfile() && parseContext.version >= 460
&& parseContext.extensionTurnedOn(E_GL_EXT_ray_query)))
return keyword;
return identifierOrType();
case ATOMIC_UINT:
if ((parseContext.isEsProfile() && parseContext.version >= 310) ||
parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters))
@@ -1025,6 +1052,7 @@ int TScanContext::tokenizeIdentifier()
case QUEUEFAMILYCOHERENT:
case WORKGROUPCOHERENT:
case SUBGROUPCOHERENT:
case SHADERCALLCOHERENT:
case NONPRIVATE:
case RESTRICT:
case READONLY:
@@ -1168,8 +1196,8 @@ int TScanContext::tokenizeIdentifier()
afterType = true;
if (parseContext.isEsProfile() || parseContext.version < 150 ||
(!parseContext.symbolTable.atBuiltInLevel() &&
parseContext.version < 400 &&
!parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64)))
(parseContext.version < 400 && !parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) &&
(parseContext.version < 410 && !parseContext.extensionTurnedOn(E_GL_ARB_vertex_attrib_64bit)))))
reservedWord();
return keyword;
@@ -1764,7 +1792,9 @@ int TScanContext::dMat()
if (!parseContext.isEsProfile() && (parseContext.version >= 400 ||
parseContext.symbolTable.atBuiltInLevel() ||
(parseContext.version >= 150 && parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64))))
(parseContext.version >= 150 && parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64)) ||
(parseContext.version >= 150 && parseContext.extensionTurnedOn(E_GL_ARB_vertex_attrib_64bit)
&& parseContext.language == EShLangVertex)))
return keyword;
if (parseContext.isForwardCompatible())
@@ -1,7 +1,7 @@
//
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013-2016 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2015-2020 Google, Inc.
//
// All rights reserved.
//
@@ -51,9 +51,9 @@
#include "ScanContext.h"
#ifdef ENABLE_HLSL
#include "../../hlsl/hlslParseHelper.h"
#include "../../hlsl/hlslParseables.h"
#include "../../hlsl/hlslScanContext.h"
#include "../HLSL/hlslParseHelper.h"
#include "../HLSL/hlslParseables.h"
#include "../HLSL/hlslScanContext.h"
#endif
#include "../Include/ShHandle.h"
@@ -72,6 +72,9 @@
// token to print ", but none of that seems appropriate for this file.
#include "preprocessor/PpTokens.h"
// Build-time generated includes
#include "../../glslang/build_info.h"
namespace { // anonymous namespace for file-local functions and symbols
// Total number of successful initializers of glslang: a refcount
@@ -291,6 +294,9 @@ void InitializeStageSymbolTable(TBuiltInParseables& builtInParseables, int versi
#ifdef GLSLANG_WEB
profile = EEsProfile;
version = 310;
#elif defined(GLSLANG_ANGLE)
profile = ECoreProfile;
version = 450;
#endif
(*symbolTables[language]).adoptLevels(*commonTable[CommonIndex(profile, language)]);
@@ -312,6 +318,9 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS
#ifdef GLSLANG_WEB
profile = EEsProfile;
version = 310;
#elif defined(GLSLANG_ANGLE)
profile = ECoreProfile;
version = 450;
#endif
std::unique_ptr<TBuiltInParseables> builtInParseables(CreateBuiltInParseables(infoSink, source));
@@ -351,7 +360,6 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS
(profile == EEsProfile && version >= 310))
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangGeometry, source,
infoSink, commonTable, symbolTables);
#endif
// check for compute
if ((profile != EEsProfile && version >= 420) ||
@@ -359,19 +367,20 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source,
infoSink, commonTable, symbolTables);
#ifndef GLSLANG_ANGLE
// check for ray tracing stages
if (profile != EEsProfile && version >= 450) {
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGenNV, source,
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGen, source,
infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersectNV, source,
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersect, source,
infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHitNV, source,
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHit, source,
infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHitNV, source,
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHit, source,
infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMissNV, source,
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMiss, source,
infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallableNV, source,
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallable, source,
infoSink, commonTable, symbolTables);
}
@@ -386,6 +395,8 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS
(profile == EEsProfile && version >= 320))
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTaskNV, source,
infoSink, commonTable, symbolTables);
#endif // !GLSLANG_ANGLE
#endif // !GLSLANG_WEB
return true;
}
@@ -487,7 +498,7 @@ void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& sp
// Function to Print all builtins
void DumpBuiltinSymbolTable(TInfoSink& infoSink, const TSymbolTable& symbolTable)
{
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
infoSink.debug << "BuiltinSymbolTable {\n";
symbolTable.dump(infoSink, true);
@@ -591,7 +602,7 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
break;
}
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
// Correct for stage type...
switch (stage) {
case EShLangGeometry:
@@ -623,12 +634,12 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
version = profile == EEsProfile ? 310 : 420;
}
break;
case EShLangRayGenNV:
case EShLangIntersectNV:
case EShLangAnyHitNV:
case EShLangClosestHitNV:
case EShLangMissNV:
case EShLangCallableNV:
case EShLangRayGen:
case EShLangIntersect:
case EShLangAnyHit:
case EShLangClosestHit:
case EShLangMiss:
case EShLangCallable:
if (profile == EEsProfile || version < 460) {
correct = false;
infoSink.info.message(EPrefixError, "#version: ray tracing shaders require non-es profile with version 460 or above");
@@ -716,6 +727,9 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages
case EShClientOpenGL:
spvVersion.openGl = environment->input.dialectVersion;
break;
case EShClientCount:
assert(0);
break;
}
switch (environment->input.languageFamily) {
case EShSourceNone:
@@ -728,6 +742,9 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages
source = EShSourceHlsl;
messages = static_cast<EShMessages>(messages | EShMsgReadHlsl);
break;
case EShSourceCount:
assert(0);
break;
}
}
@@ -861,7 +878,7 @@ bool ProcessDeferred(
: userInput.scanVersion(version, profile, versionNotFirstToken);
bool versionNotFound = version == 0;
if (forceDefaultVersionAndProfile && source == EShSourceGlsl) {
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound &&
(version != defaultVersion || profile != defaultProfile)) {
compiler->infoSink.info << "Warning, (version, profile) forced to be ("
@@ -884,10 +901,13 @@ bool ProcessDeferred(
#ifdef GLSLANG_WEB
profile = EEsProfile;
version = 310;
#elif defined(GLSLANG_ANGLE)
profile = ECoreProfile;
version = 450;
#endif
bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst));
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
bool warnVersionNotFirst = false;
if (! versionWillBeError && versionNotFirstToken) {
if (messages & EShMsgRelaxedErrors)
@@ -957,7 +977,7 @@ bool ProcessDeferred(
parseContext->setLimits(*resources);
if (! goodVersion)
parseContext->addError();
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
if (warnVersionNotFirst) {
TSourceLoc loc;
loc.init();
@@ -994,7 +1014,7 @@ bool ProcessDeferred(
return success;
}
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
// Responsible for keeping track of the most recent source string and line in
// the preprocessor and outputting newlines appropriately if the source string
@@ -1217,14 +1237,16 @@ struct DoFullParse{
parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n";
}
#ifndef GLSLANG_ANGLE
if (messages & EShMsgAST)
intermediate.output(parseContext.infoSink, true);
#endif
return success;
}
};
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
// Take a single compilation unit, and run the preprocessor on it.
// Return: True if there were no issues found in preprocessing,
// False if during preprocessing any unknown version, pragmas or
@@ -1678,19 +1700,29 @@ int ShGetUniformLocation(const ShHandle handle, const char* name)
namespace glslang {
#include "../Include/revision.h"
Version GetVersion()
{
Version version;
version.major = GLSLANG_VERSION_MAJOR;
version.minor = GLSLANG_VERSION_MINOR;
version.patch = GLSLANG_VERSION_PATCH;
version.flavor = GLSLANG_VERSION_FLAVOR;
return version;
}
#define QUOTE(s) #s
#define STR(n) QUOTE(n)
const char* GetEsslVersionString()
{
return "OpenGL ES GLSL 3.20 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL);
return "OpenGL ES GLSL 3.20 glslang Khronos. " STR(GLSLANG_VERSION_MAJOR) "." STR(GLSLANG_VERSION_MINOR) "." STR(
GLSLANG_VERSION_PATCH) GLSLANG_VERSION_FLAVOR;
}
const char* GetGlslVersionString()
{
return "4.60 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL);
return "4.60 glslang Khronos. " STR(GLSLANG_VERSION_MAJOR) "." STR(GLSLANG_VERSION_MINOR) "." STR(
GLSLANG_VERSION_PATCH) GLSLANG_VERSION_FLAVOR;
}
int GetKhronosToolId()
@@ -1771,6 +1803,8 @@ void TShader::setSourceEntryPoint(const char* name)
sourceEntryPointName = name;
}
// Log initial settings and transforms.
// See comment for class TProcesses.
void TShader::addProcesses(const std::vector<std::string>& p)
{
intermediate->addProcesses(p);
@@ -1852,7 +1886,7 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion
&environment);
}
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
// Fill in a string with the result of preprocessing ShaderStrings
// Returns true if all extensions, pragmas and version strings were valid.
//
@@ -1890,7 +1924,7 @@ const char* TShader::getInfoDebugLog()
}
TProgram::TProgram() :
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
reflection(0),
#endif
linked(false)
@@ -1906,7 +1940,7 @@ TProgram::TProgram() :
TProgram::~TProgram()
{
delete infoSink;
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
delete reflection;
#endif
@@ -1953,7 +1987,7 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
if (stages[stage].size() == 0)
return true;
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
int numEsShaders = 0, numNonEsShaders = 0;
for (auto it = stages[stage].begin(); it != stages[stage].end(); ++it) {
if ((*it)->intermediate->getProfile() == EEsProfile) {
@@ -2007,8 +2041,10 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
#endif
intermediate[stage]->finalCheck(*infoSink, (messages & EShMsgKeepUncalled) != 0);
#ifndef GLSLANG_ANGLE
if (messages & EShMsgAST)
intermediate[stage]->output(*infoSink, true);
#endif
return intermediate[stage]->getNumErrors() == 0;
}
@@ -2023,7 +2059,7 @@ const char* TProgram::getInfoDebugLog()
return infoSink->debug.c_str();
}
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
//
// Reflection implementation.
@@ -2105,6 +2141,6 @@ bool TProgram::mapIO(TIoMapResolver* pResolver, TIoMapper* pIoMapper)
return ioMapper->doMap(pResolver, *infoSink);
}
#endif // GLSLANG_WEB
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
} // end namespace glslang
@@ -3,6 +3,7 @@
// Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@@ -74,7 +75,8 @@ void TType::buildMangledName(TString& mangledName) const
case EbtInt64: mangledName += "i64"; break;
case EbtUint64: mangledName += "u64"; break;
case EbtAtomicUint: mangledName += "au"; break;
case EbtAccStructNV: mangledName += "asnv"; break;
case EbtAccStruct: mangledName += "as"; break;
case EbtRayQuery: mangledName += "rq"; break;
#endif
case EbtSampler:
switch (sampler.type) {
@@ -120,7 +122,7 @@ void TType::buildMangledName(TString& mangledName) const
mangledName += "-tx-struct";
char text[16]; // plenty enough space for the small integers.
snprintf(text, sizeof(text), "%d-", sampler.getStructReturnIndex());
snprintf(text, sizeof(text), "%u-", sampler.getStructReturnIndex());
mangledName += text;
} else {
switch (sampler.getVectorSize()) {
@@ -176,7 +178,7 @@ void TType::buildMangledName(TString& mangledName) const
}
}
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
//
// Dump functions.
@@ -117,7 +117,7 @@ public:
virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); }
virtual const char** getExtensions() const { return extensions->data(); }
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0;
void dumpExtensions(TInfoSink& infoSink) const;
#endif
@@ -196,7 +196,7 @@ public:
}
virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); }
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
virtual void dump(TInfoSink& infoSink, bool complete = false) const;
#endif
@@ -319,7 +319,7 @@ public:
virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
virtual const TParameter& operator[](int i) const { return parameters[i]; }
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
#endif
@@ -381,7 +381,7 @@ public:
virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); }
virtual int getAnonId() const { return anonId; }
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
#endif
@@ -551,7 +551,7 @@ public:
void relateToOperator(const char* name, TOperator op);
void setFunctionExtensions(const char* name, int num, const char* const extensions[]);
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
void dump(TInfoSink& infoSink, bool complete = false) const;
#endif
TSymbolTableLevel* clone() const;
@@ -854,7 +854,7 @@ public:
}
int getMaxSymbolId() { return uniqueId; }
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
void dump(TInfoSink& infoSink, bool complete = false) const;
#endif
void copyTable(const TSymbolTable& copyOf);
@@ -2,7 +2,8 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2015-2020 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@@ -63,6 +64,7 @@
// checkDeprecated()
// requireNotRemoved()
// requireExtensions()
// extensionRequires()
//
// Typically, only the first two calls are needed. They go into a code path that
// implements Feature F, and will log the proper error/warning messages. Parsing
@@ -77,9 +79,11 @@
// const char* const XXX_extension_X = "XXX_extension_X";
//
// 2) Add extension initialization to TParseVersions::initializeExtensionBehavior(),
// the first function below:
// the first function below and optionally a entry to extensionData for additional
// error checks:
//
// extensionBehavior[XXX_extension_X] = EBhDisable;
// (Optional) exts[] = {XXX_extension_X, EShTargetSpv_1_4}
//
// 3) Add any preprocessor directives etc. in the next function, TParseVersions::getPreamble():
//
@@ -139,6 +143,8 @@
// set of extensions that both enable them and are necessary, given the version of the symbol
// table. (There is a different symbol table for each version.)
//
// 7) If the extension has additional requirements like minimum SPIR-V version required, add them
// to extensionRequires()
#include "parseVersions.h"
#include "localintermediate.h"
@@ -154,6 +160,20 @@ namespace glslang {
//
void TParseVersions::initializeExtensionBehavior()
{
typedef struct {
const char *const extensionName;
EShTargetLanguageVersion minSpvVersion;
} extensionData;
const extensionData exts[] = { {E_GL_EXT_ray_tracing, EShTargetSpv_1_4} };
for (size_t ii = 0; ii < sizeof(exts) / sizeof(exts[0]); ii++) {
// Add only extensions which require > spv1.0 to save space in map
if (exts[ii].minSpvVersion > EShTargetSpv_1_0) {
extensionMinSpv[E_GL_EXT_ray_tracing] = exts[ii].minSpvVersion;
}
}
extensionBehavior[E_GL_OES_texture_3D] = EBhDisable;
extensionBehavior[E_GL_OES_standard_derivatives] = EBhDisable;
extensionBehavior[E_GL_EXT_frag_depth] = EBhDisable;
@@ -197,6 +217,12 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_ARB_shader_clock] = EBhDisable;
extensionBehavior[E_GL_ARB_uniform_buffer_object] = EBhDisable;
extensionBehavior[E_GL_ARB_sample_shading] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_bit_encoding] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_image_size] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_storage_buffer_object] = EBhDisable;
extensionBehavior[E_GL_ARB_shading_language_packing] = EBhDisable;
extensionBehavior[E_GL_ARB_texture_query_lod] = EBhDisable;
extensionBehavior[E_GL_ARB_vertex_attrib_64bit] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_basic] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_vote] = EBhDisable;
@@ -222,6 +248,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_buffer_reference2] = EBhDisable;
extensionBehavior[E_GL_EXT_buffer_reference_uvec2] = EBhDisable;
extensionBehavior[E_GL_EXT_demote_to_helper_invocation] = EBhDisable;
extensionBehavior[E_GL_EXT_debug_printf] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_16bit_storage] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable;
@@ -290,11 +317,17 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_OES_tessellation_point_size] = EBhDisable;
extensionBehavior[E_GL_OES_texture_buffer] = EBhDisable;
extensionBehavior[E_GL_OES_texture_cube_map_array] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_integer_mix] = EBhDisable;
// EXT extensions
extensionBehavior[E_GL_EXT_device_group] = EBhDisable;
extensionBehavior[E_GL_EXT_multiview] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_realtime_clock] = EBhDisable;
extensionBehavior[E_GL_EXT_device_group] = EBhDisable;
extensionBehavior[E_GL_EXT_multiview] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_realtime_clock] = EBhDisable;
extensionBehavior[E_GL_EXT_ray_tracing] = EBhDisable;
extensionBehavior[E_GL_EXT_ray_query] = EBhDisable;
extensionBehavior[E_GL_EXT_ray_flags_primitive_culling] = EBhDisable;
extensionBehavior[E_GL_EXT_blend_func_extended] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_implicit_conversions] = EBhDisable;
// OVR extensions
extensionBehavior[E_GL_OVR_multiview] = EBhDisable;
@@ -315,7 +348,9 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int16] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int64] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_float16] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_atomic_float] = EBhDisable;
}
#endif // GLSLANG_WEB
// Get code that is not part of a shared symbol table, is specific to this shader,
@@ -354,6 +389,9 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_tessellation_point_size 1\n"
"#define GL_EXT_texture_buffer 1\n"
"#define GL_EXT_texture_cube_map_array 1\n"
"#define GL_EXT_shader_implicit_conversions 1\n"
"#define GL_EXT_shader_integer_mix 1\n"
"#define GL_EXT_blend_func_extended 1\n"
// OES matching AEP
"#define GL_OES_geometry_shader 1\n"
@@ -403,10 +441,16 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_ARB_sparse_texture_clamp 1\n"
"#define GL_ARB_shader_stencil_export 1\n"
"#define GL_ARB_sample_shading 1\n"
"#define GL_ARB_shader_image_size 1\n"
"#define GL_ARB_shading_language_packing 1\n"
// "#define GL_ARB_cull_distance 1\n" // present for 4.5, but need extension control over block members
"#define GL_ARB_post_depth_coverage 1\n"
"#define GL_ARB_fragment_shader_interlock 1\n"
"#define GL_ARB_uniform_buffer_object 1\n"
"#define GL_ARB_shader_bit_encoding 1\n"
"#define GL_ARB_shader_storage_buffer_object 1\n"
"#define GL_ARB_texture_query_lod 1\n"
"#define GL_ARB_vertex_attrib_64bit 1\n"
"#define GL_EXT_shader_non_constant_global_initializers 1\n"
"#define GL_EXT_shader_image_load_formatted 1\n"
"#define GL_EXT_post_depth_coverage 1\n"
@@ -421,6 +465,7 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_buffer_reference2 1\n"
"#define GL_EXT_buffer_reference_uvec2 1\n"
"#define GL_EXT_demote_to_helper_invocation 1\n"
"#define GL_EXT_debug_printf 1\n"
// GL_KHR_shader_subgroup
"#define GL_KHR_shader_subgroup_basic 1\n"
@@ -432,8 +477,11 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_KHR_shader_subgroup_clustered 1\n"
"#define GL_KHR_shader_subgroup_quad 1\n"
"#define E_GL_EXT_shader_atomic_int64 1\n"
"#define E_GL_EXT_shader_realtime_clock 1\n"
"#define GL_EXT_shader_atomic_int64 1\n"
"#define GL_EXT_shader_realtime_clock 1\n"
"#define GL_EXT_ray_tracing 1\n"
"#define GL_EXT_ray_query 1\n"
"#define GL_EXT_ray_flags_primitive_culling 1\n"
"#define GL_AMD_shader_ballot 1\n"
"#define GL_AMD_shader_trinary_minmax 1\n"
@@ -476,6 +524,8 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_shader_subgroup_extended_types_int16 1\n"
"#define GL_EXT_shader_subgroup_extended_types_int64 1\n"
"#define GL_EXT_shader_subgroup_extended_types_float16 1\n"
"#define GL_EXT_shader_atomic_float 1\n"
;
if (version >= 150) {
@@ -547,12 +597,12 @@ const char* StageName(EShLanguage stage)
case EShLangTessControl: return "tessellation control";
case EShLangTessEvaluation: return "tessellation evaluation";
case EShLangGeometry: return "geometry";
case EShLangRayGenNV: return "ray-generation";
case EShLangIntersectNV: return "intersection";
case EShLangAnyHitNV: return "any-hit";
case EShLangClosestHitNV: return "closest-hit";
case EShLangMissNV: return "miss";
case EShLangCallableNV: return "callable";
case EShLangRayGen: return "ray-generation";
case EShLangIntersect: return "intersection";
case EShLangAnyHit: return "any-hit";
case EShLangClosestHit: return "closest-hit";
case EShLangMiss: return "miss";
case EShLangCallable: return "callable";
case EShLangMeshNV: return "mesh";
case EShLangTaskNV: return "task";
#endif
@@ -715,7 +765,8 @@ bool TParseVersions::checkExtensionsRequested(const TSourceLoc& loc, int numExte
// Use when there are no profile/version to check, it's just an error if one of the
// extensions is not present.
//
void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[],
const char* featureDesc)
{
if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc))
return;
@@ -734,7 +785,8 @@ void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions,
// Use by preprocessor when there are no profile/version to check, it's just an error if one of the
// extensions is not present.
//
void TParseVersions::ppRequireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
void TParseVersions::ppRequireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[],
const char* featureDesc)
{
if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc))
return;
@@ -800,10 +852,14 @@ void TParseVersions::updateExtensionBehavior(int line, const char* extension, co
error(getCurrentLoc(), "behavior not supported:", "#extension", behaviorString);
return;
}
bool on = behavior != EBhDisable;
// check if extension is used with correct shader stage
checkExtensionStage(getCurrentLoc(), extension);
// check if extension has additional requirements
extensionRequires(getCurrentLoc(), extension ,behaviorString);
// update the requested extension
updateExtensionBehavior(extension, behavior);
@@ -866,6 +922,32 @@ void TParseVersions::updateExtensionBehavior(int line, const char* extension, co
updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_int64", behaviorString);
else if (strcmp(extension, "GL_EXT_shader_subgroup_extended_types_float16") == 0)
updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_float16", behaviorString);
// see if we need to update the numeric features
else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types, on);
else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int8") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int8, on);
else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int16") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int16, on);
else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int32") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int32, on);
else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int64") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int64, on);
else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_float16") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_float16, on);
else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_float32") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_float32, on);
else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_float64") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_float64, on);
else if (strcmp(extension, "GL_EXT_shader_implicit_conversions") == 0)
intermediate.updateNumericFeature(TNumericFeatures::shader_implicit_conversions, on);
else if (strcmp(extension, "GL_ARB_gpu_shader_fp64") == 0)
intermediate.updateNumericFeature(TNumericFeatures::gpu_shader_fp64, on);
else if (strcmp(extension, "GL_AMD_gpu_shader_int16") == 0)
intermediate.updateNumericFeature(TNumericFeatures::gpu_shader_int16, on);
else if (strcmp(extension, "GL_AMD_gpu_shader_half_float") == 0)
intermediate.updateNumericFeature(TNumericFeatures::gpu_shader_half_float, on);
}
void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBehavior behavior)
@@ -901,7 +983,7 @@ void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBe
} else {
if (iter->second == EBhDisablePartial)
warn(getCurrentLoc(), "extension is only partially supported:", "#extension", extension);
if (behavior == EBhEnable || behavior == EBhRequire)
if (behavior != EBhDisable)
intermediate.addRequestedExtension(extension);
iter->second = behavior;
}
@@ -920,6 +1002,24 @@ void TParseVersions::checkExtensionStage(const TSourceLoc& loc, const char * con
}
}
// Check if extension has additional requirements
void TParseVersions::extensionRequires(const TSourceLoc &loc, const char * const extension, const char *behaviorString)
{
bool isEnabled = false;
if (!strcmp("require", behaviorString))
isEnabled = true;
else if (!strcmp("enable", behaviorString))
isEnabled = true;
if (isEnabled) {
unsigned int minSpvVersion = 0;
auto iter = extensionMinSpv.find(TString(extension));
if (iter != extensionMinSpv.end())
minSpvVersion = iter->second;
requireSpv(loc, extension, minSpvVersion);
}
}
// Call for any operation needing full GLSL integer data-type support.
void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
{
@@ -930,8 +1030,13 @@ void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
// Call for any operation needing GLSL double data-type support.
void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op)
{
//requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader_fp64, op);
if (language == EShLangVertex) {
const char* const f64_Extensions[] = {E_GL_ARB_gpu_shader_fp64, E_GL_ARB_vertex_attrib_64bit};
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, 2, f64_Extensions, op);
} else
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader_fp64, op);
}
// Call for any operation needing GLSL float16 data-type support.
@@ -1172,5 +1277,12 @@ void TParseVersions::requireSpv(const TSourceLoc& loc, const char* op)
error(loc, "only allowed when generating SPIR-V", op, "");
#endif
}
void TParseVersions::requireSpv(const TSourceLoc& loc, const char *op, unsigned int version)
{
#ifndef GLSLANG_WEB
if (spvVersion.spv < version)
error(loc, "not supported for current targeted SPIR-V version", op, "");
#endif
}
} // end namespace glslang
@@ -3,6 +3,7 @@
// Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@@ -35,9 +36,12 @@
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#ifndef _VERSIONS_INCLUDED_
#define _VERSIONS_INCLUDED_
#define LAST_ELEMENT_MARKER(x) x
//
// Help manage multiple profiles, versions, extensions etc.
//
@@ -49,12 +53,13 @@
// Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible
// defects from mixing the two different forms.
//
typedef enum {
typedef enum : unsigned {
EBadProfile = 0,
ENoProfile = (1 << 0), // only for desktop, before profiles showed up
ECoreProfile = (1 << 1),
ECompatibilityProfile = (1 << 2),
EEsProfile = (1 << 3)
EEsProfile = (1 << 3),
LAST_ELEMENT_MARKER(EProfileCount),
} EProfile;
namespace glslang {
@@ -149,6 +154,12 @@ const char* const E_GL_ARB_fragment_shader_interlock = "GL_ARB_fragment_shade
const char* const E_GL_ARB_shader_clock = "GL_ARB_shader_clock";
const char* const E_GL_ARB_uniform_buffer_object = "GL_ARB_uniform_buffer_object";
const char* const E_GL_ARB_sample_shading = "GL_ARB_sample_shading";
const char* const E_GL_ARB_shader_bit_encoding = "GL_ARB_shader_bit_encoding";
const char* const E_GL_ARB_shader_image_size = "GL_ARB_shader_image_size";
const char* const E_GL_ARB_shader_storage_buffer_object = "GL_ARB_shader_storage_buffer_object";
const char* const E_GL_ARB_shading_language_packing = "GL_ARB_shading_language_packing";
const char* const E_GL_ARB_texture_query_lod = "GL_ARB_texture_query_lod";
const char* const E_GL_ARB_vertex_attrib_64bit = "GL_ARB_vertex_attrib_64bit";
const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic";
const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote";
@@ -183,6 +194,12 @@ const char* const E_GL_EXT_buffer_reference2 = "GL_EXT_buffer_ref
const char* const E_GL_EXT_buffer_reference_uvec2 = "GL_EXT_buffer_reference_uvec2";
const char* const E_GL_EXT_demote_to_helper_invocation = "GL_EXT_demote_to_helper_invocation";
const char* const E_GL_EXT_shader_realtime_clock = "GL_EXT_shader_realtime_clock";
const char* const E_GL_EXT_debug_printf = "GL_EXT_debug_printf";
const char* const E_GL_EXT_ray_tracing = "GL_EXT_ray_tracing";
const char* const E_GL_EXT_ray_query = "GL_EXT_ray_query";
const char* const E_GL_EXT_ray_flags_primitive_culling = "GL_EXT_ray_flags_primitive_culling";
const char* const E_GL_EXT_blend_func_extended = "GL_EXT_blend_func_extended";
const char* const E_GL_EXT_shader_implicit_conversions = "GL_EXT_shader_implicit_conversions";
// Arrays of extensions for the above viewportEXTs duplications
@@ -254,6 +271,7 @@ const char* const E_GL_EXT_tessellation_shader = "GL_EXT_tessel
const char* const E_GL_EXT_tessellation_point_size = "GL_EXT_tessellation_point_size";
const char* const E_GL_EXT_texture_buffer = "GL_EXT_texture_buffer";
const char* const E_GL_EXT_texture_cube_map_array = "GL_EXT_texture_cube_map_array";
const char* const E_GL_EXT_shader_integer_mix = "GL_EXT_shader_integer_mix";
// OES matching AEP
const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader";
@@ -281,6 +299,8 @@ const char* const E_GL_EXT_shader_subgroup_extended_types_int16 = "GL_EXT_shad
const char* const E_GL_EXT_shader_subgroup_extended_types_int64 = "GL_EXT_shader_subgroup_extended_types_int64";
const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16";
const char* const E_GL_EXT_shader_atomic_float = "GL_EXT_shader_atomic_float";
// Arrays of extensions for the above AEP duplications
const char* const AEP_geometry_shader[] = { E_GL_EXT_geometry_shader, E_GL_OES_geometry_shader };
@@ -52,6 +52,14 @@
#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FE5
#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FE6
#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FE7
#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1
#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2
#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3
#define GL_INT16_NV 0x8FE4
#define GL_INT16_VEC2_NV 0x8FE5
#define GL_INT16_VEC3_NV 0x8FE6
#define GL_INT16_VEC4_NV 0x8FE7
#define GL_BOOL 0x8B56
#define GL_BOOL_VEC2 0x8B57
File diff suppressed because it is too large Load Diff
@@ -203,256 +203,265 @@ extern int yydebug;
F64MAT4X4 = 413,
ATOMIC_UINT = 414,
ACCSTRUCTNV = 415,
FCOOPMATNV = 416,
ICOOPMATNV = 417,
UCOOPMATNV = 418,
SAMPLERCUBEARRAY = 419,
SAMPLERCUBEARRAYSHADOW = 420,
ISAMPLERCUBEARRAY = 421,
USAMPLERCUBEARRAY = 422,
SAMPLER1D = 423,
SAMPLER1DARRAY = 424,
SAMPLER1DARRAYSHADOW = 425,
ISAMPLER1D = 426,
SAMPLER1DSHADOW = 427,
SAMPLER2DRECT = 428,
SAMPLER2DRECTSHADOW = 429,
ISAMPLER2DRECT = 430,
USAMPLER2DRECT = 431,
SAMPLERBUFFER = 432,
ISAMPLERBUFFER = 433,
USAMPLERBUFFER = 434,
SAMPLER2DMS = 435,
ISAMPLER2DMS = 436,
USAMPLER2DMS = 437,
SAMPLER2DMSARRAY = 438,
ISAMPLER2DMSARRAY = 439,
USAMPLER2DMSARRAY = 440,
SAMPLEREXTERNALOES = 441,
SAMPLEREXTERNAL2DY2YEXT = 442,
ISAMPLER1DARRAY = 443,
USAMPLER1D = 444,
USAMPLER1DARRAY = 445,
F16SAMPLER1D = 446,
F16SAMPLER2D = 447,
F16SAMPLER3D = 448,
F16SAMPLER2DRECT = 449,
F16SAMPLERCUBE = 450,
F16SAMPLER1DARRAY = 451,
F16SAMPLER2DARRAY = 452,
F16SAMPLERCUBEARRAY = 453,
F16SAMPLERBUFFER = 454,
F16SAMPLER2DMS = 455,
F16SAMPLER2DMSARRAY = 456,
F16SAMPLER1DSHADOW = 457,
F16SAMPLER2DSHADOW = 458,
F16SAMPLER1DARRAYSHADOW = 459,
F16SAMPLER2DARRAYSHADOW = 460,
F16SAMPLER2DRECTSHADOW = 461,
F16SAMPLERCUBESHADOW = 462,
F16SAMPLERCUBEARRAYSHADOW = 463,
IMAGE1D = 464,
IIMAGE1D = 465,
UIMAGE1D = 466,
IMAGE2D = 467,
IIMAGE2D = 468,
UIMAGE2D = 469,
IMAGE3D = 470,
IIMAGE3D = 471,
UIMAGE3D = 472,
IMAGE2DRECT = 473,
IIMAGE2DRECT = 474,
UIMAGE2DRECT = 475,
IMAGECUBE = 476,
IIMAGECUBE = 477,
UIMAGECUBE = 478,
IMAGEBUFFER = 479,
IIMAGEBUFFER = 480,
UIMAGEBUFFER = 481,
IMAGE1DARRAY = 482,
IIMAGE1DARRAY = 483,
UIMAGE1DARRAY = 484,
IMAGE2DARRAY = 485,
IIMAGE2DARRAY = 486,
UIMAGE2DARRAY = 487,
IMAGECUBEARRAY = 488,
IIMAGECUBEARRAY = 489,
UIMAGECUBEARRAY = 490,
IMAGE2DMS = 491,
IIMAGE2DMS = 492,
UIMAGE2DMS = 493,
IMAGE2DMSARRAY = 494,
IIMAGE2DMSARRAY = 495,
UIMAGE2DMSARRAY = 496,
F16IMAGE1D = 497,
F16IMAGE2D = 498,
F16IMAGE3D = 499,
F16IMAGE2DRECT = 500,
F16IMAGECUBE = 501,
F16IMAGE1DARRAY = 502,
F16IMAGE2DARRAY = 503,
F16IMAGECUBEARRAY = 504,
F16IMAGEBUFFER = 505,
F16IMAGE2DMS = 506,
F16IMAGE2DMSARRAY = 507,
TEXTURECUBEARRAY = 508,
ITEXTURECUBEARRAY = 509,
UTEXTURECUBEARRAY = 510,
TEXTURE1D = 511,
ITEXTURE1D = 512,
UTEXTURE1D = 513,
TEXTURE1DARRAY = 514,
ITEXTURE1DARRAY = 515,
UTEXTURE1DARRAY = 516,
TEXTURE2DRECT = 517,
ITEXTURE2DRECT = 518,
UTEXTURE2DRECT = 519,
TEXTUREBUFFER = 520,
ITEXTUREBUFFER = 521,
UTEXTUREBUFFER = 522,
TEXTURE2DMS = 523,
ITEXTURE2DMS = 524,
UTEXTURE2DMS = 525,
TEXTURE2DMSARRAY = 526,
ITEXTURE2DMSARRAY = 527,
UTEXTURE2DMSARRAY = 528,
F16TEXTURE1D = 529,
F16TEXTURE2D = 530,
F16TEXTURE3D = 531,
F16TEXTURE2DRECT = 532,
F16TEXTURECUBE = 533,
F16TEXTURE1DARRAY = 534,
F16TEXTURE2DARRAY = 535,
F16TEXTURECUBEARRAY = 536,
F16TEXTUREBUFFER = 537,
F16TEXTURE2DMS = 538,
F16TEXTURE2DMSARRAY = 539,
SUBPASSINPUT = 540,
SUBPASSINPUTMS = 541,
ISUBPASSINPUT = 542,
ISUBPASSINPUTMS = 543,
USUBPASSINPUT = 544,
USUBPASSINPUTMS = 545,
F16SUBPASSINPUT = 546,
F16SUBPASSINPUTMS = 547,
LEFT_OP = 548,
RIGHT_OP = 549,
INC_OP = 550,
DEC_OP = 551,
LE_OP = 552,
GE_OP = 553,
EQ_OP = 554,
NE_OP = 555,
AND_OP = 556,
OR_OP = 557,
XOR_OP = 558,
MUL_ASSIGN = 559,
DIV_ASSIGN = 560,
ADD_ASSIGN = 561,
MOD_ASSIGN = 562,
LEFT_ASSIGN = 563,
RIGHT_ASSIGN = 564,
AND_ASSIGN = 565,
XOR_ASSIGN = 566,
OR_ASSIGN = 567,
SUB_ASSIGN = 568,
LEFT_PAREN = 569,
RIGHT_PAREN = 570,
LEFT_BRACKET = 571,
RIGHT_BRACKET = 572,
LEFT_BRACE = 573,
RIGHT_BRACE = 574,
DOT = 575,
COMMA = 576,
COLON = 577,
EQUAL = 578,
SEMICOLON = 579,
BANG = 580,
DASH = 581,
TILDE = 582,
PLUS = 583,
STAR = 584,
SLASH = 585,
PERCENT = 586,
LEFT_ANGLE = 587,
RIGHT_ANGLE = 588,
VERTICAL_BAR = 589,
CARET = 590,
AMPERSAND = 591,
QUESTION = 592,
INVARIANT = 593,
HIGH_PRECISION = 594,
MEDIUM_PRECISION = 595,
LOW_PRECISION = 596,
PRECISION = 597,
PACKED = 598,
RESOURCE = 599,
SUPERP = 600,
FLOATCONSTANT = 601,
INTCONSTANT = 602,
UINTCONSTANT = 603,
BOOLCONSTANT = 604,
IDENTIFIER = 605,
TYPE_NAME = 606,
CENTROID = 607,
IN = 608,
OUT = 609,
INOUT = 610,
STRUCT = 611,
VOID = 612,
WHILE = 613,
BREAK = 614,
CONTINUE = 615,
DO = 616,
ELSE = 617,
FOR = 618,
IF = 619,
DISCARD = 620,
RETURN = 621,
SWITCH = 622,
CASE = 623,
DEFAULT = 624,
UNIFORM = 625,
SHARED = 626,
BUFFER = 627,
FLAT = 628,
SMOOTH = 629,
LAYOUT = 630,
DOUBLECONSTANT = 631,
INT16CONSTANT = 632,
UINT16CONSTANT = 633,
FLOAT16CONSTANT = 634,
INT32CONSTANT = 635,
UINT32CONSTANT = 636,
INT64CONSTANT = 637,
UINT64CONSTANT = 638,
SUBROUTINE = 639,
DEMOTE = 640,
PAYLOADNV = 641,
PAYLOADINNV = 642,
HITATTRNV = 643,
CALLDATANV = 644,
CALLDATAINNV = 645,
PATCH = 646,
SAMPLE = 647,
NONUNIFORM = 648,
COHERENT = 649,
VOLATILE = 650,
RESTRICT = 651,
READONLY = 652,
WRITEONLY = 653,
DEVICECOHERENT = 654,
QUEUEFAMILYCOHERENT = 655,
WORKGROUPCOHERENT = 656,
SUBGROUPCOHERENT = 657,
NONPRIVATE = 658,
NOPERSPECTIVE = 659,
EXPLICITINTERPAMD = 660,
PERVERTEXNV = 661,
PERPRIMITIVENV = 662,
PERVIEWNV = 663,
PERTASKNV = 664,
PRECISE = 665
ACCSTRUCTEXT = 416,
RAYQUERYEXT = 417,
FCOOPMATNV = 418,
ICOOPMATNV = 419,
UCOOPMATNV = 420,
SAMPLERCUBEARRAY = 421,
SAMPLERCUBEARRAYSHADOW = 422,
ISAMPLERCUBEARRAY = 423,
USAMPLERCUBEARRAY = 424,
SAMPLER1D = 425,
SAMPLER1DARRAY = 426,
SAMPLER1DARRAYSHADOW = 427,
ISAMPLER1D = 428,
SAMPLER1DSHADOW = 429,
SAMPLER2DRECT = 430,
SAMPLER2DRECTSHADOW = 431,
ISAMPLER2DRECT = 432,
USAMPLER2DRECT = 433,
SAMPLERBUFFER = 434,
ISAMPLERBUFFER = 435,
USAMPLERBUFFER = 436,
SAMPLER2DMS = 437,
ISAMPLER2DMS = 438,
USAMPLER2DMS = 439,
SAMPLER2DMSARRAY = 440,
ISAMPLER2DMSARRAY = 441,
USAMPLER2DMSARRAY = 442,
SAMPLEREXTERNALOES = 443,
SAMPLEREXTERNAL2DY2YEXT = 444,
ISAMPLER1DARRAY = 445,
USAMPLER1D = 446,
USAMPLER1DARRAY = 447,
F16SAMPLER1D = 448,
F16SAMPLER2D = 449,
F16SAMPLER3D = 450,
F16SAMPLER2DRECT = 451,
F16SAMPLERCUBE = 452,
F16SAMPLER1DARRAY = 453,
F16SAMPLER2DARRAY = 454,
F16SAMPLERCUBEARRAY = 455,
F16SAMPLERBUFFER = 456,
F16SAMPLER2DMS = 457,
F16SAMPLER2DMSARRAY = 458,
F16SAMPLER1DSHADOW = 459,
F16SAMPLER2DSHADOW = 460,
F16SAMPLER1DARRAYSHADOW = 461,
F16SAMPLER2DARRAYSHADOW = 462,
F16SAMPLER2DRECTSHADOW = 463,
F16SAMPLERCUBESHADOW = 464,
F16SAMPLERCUBEARRAYSHADOW = 465,
IMAGE1D = 466,
IIMAGE1D = 467,
UIMAGE1D = 468,
IMAGE2D = 469,
IIMAGE2D = 470,
UIMAGE2D = 471,
IMAGE3D = 472,
IIMAGE3D = 473,
UIMAGE3D = 474,
IMAGE2DRECT = 475,
IIMAGE2DRECT = 476,
UIMAGE2DRECT = 477,
IMAGECUBE = 478,
IIMAGECUBE = 479,
UIMAGECUBE = 480,
IMAGEBUFFER = 481,
IIMAGEBUFFER = 482,
UIMAGEBUFFER = 483,
IMAGE1DARRAY = 484,
IIMAGE1DARRAY = 485,
UIMAGE1DARRAY = 486,
IMAGE2DARRAY = 487,
IIMAGE2DARRAY = 488,
UIMAGE2DARRAY = 489,
IMAGECUBEARRAY = 490,
IIMAGECUBEARRAY = 491,
UIMAGECUBEARRAY = 492,
IMAGE2DMS = 493,
IIMAGE2DMS = 494,
UIMAGE2DMS = 495,
IMAGE2DMSARRAY = 496,
IIMAGE2DMSARRAY = 497,
UIMAGE2DMSARRAY = 498,
F16IMAGE1D = 499,
F16IMAGE2D = 500,
F16IMAGE3D = 501,
F16IMAGE2DRECT = 502,
F16IMAGECUBE = 503,
F16IMAGE1DARRAY = 504,
F16IMAGE2DARRAY = 505,
F16IMAGECUBEARRAY = 506,
F16IMAGEBUFFER = 507,
F16IMAGE2DMS = 508,
F16IMAGE2DMSARRAY = 509,
TEXTURECUBEARRAY = 510,
ITEXTURECUBEARRAY = 511,
UTEXTURECUBEARRAY = 512,
TEXTURE1D = 513,
ITEXTURE1D = 514,
UTEXTURE1D = 515,
TEXTURE1DARRAY = 516,
ITEXTURE1DARRAY = 517,
UTEXTURE1DARRAY = 518,
TEXTURE2DRECT = 519,
ITEXTURE2DRECT = 520,
UTEXTURE2DRECT = 521,
TEXTUREBUFFER = 522,
ITEXTUREBUFFER = 523,
UTEXTUREBUFFER = 524,
TEXTURE2DMS = 525,
ITEXTURE2DMS = 526,
UTEXTURE2DMS = 527,
TEXTURE2DMSARRAY = 528,
ITEXTURE2DMSARRAY = 529,
UTEXTURE2DMSARRAY = 530,
F16TEXTURE1D = 531,
F16TEXTURE2D = 532,
F16TEXTURE3D = 533,
F16TEXTURE2DRECT = 534,
F16TEXTURECUBE = 535,
F16TEXTURE1DARRAY = 536,
F16TEXTURE2DARRAY = 537,
F16TEXTURECUBEARRAY = 538,
F16TEXTUREBUFFER = 539,
F16TEXTURE2DMS = 540,
F16TEXTURE2DMSARRAY = 541,
SUBPASSINPUT = 542,
SUBPASSINPUTMS = 543,
ISUBPASSINPUT = 544,
ISUBPASSINPUTMS = 545,
USUBPASSINPUT = 546,
USUBPASSINPUTMS = 547,
F16SUBPASSINPUT = 548,
F16SUBPASSINPUTMS = 549,
LEFT_OP = 550,
RIGHT_OP = 551,
INC_OP = 552,
DEC_OP = 553,
LE_OP = 554,
GE_OP = 555,
EQ_OP = 556,
NE_OP = 557,
AND_OP = 558,
OR_OP = 559,
XOR_OP = 560,
MUL_ASSIGN = 561,
DIV_ASSIGN = 562,
ADD_ASSIGN = 563,
MOD_ASSIGN = 564,
LEFT_ASSIGN = 565,
RIGHT_ASSIGN = 566,
AND_ASSIGN = 567,
XOR_ASSIGN = 568,
OR_ASSIGN = 569,
SUB_ASSIGN = 570,
STRING_LITERAL = 571,
LEFT_PAREN = 572,
RIGHT_PAREN = 573,
LEFT_BRACKET = 574,
RIGHT_BRACKET = 575,
LEFT_BRACE = 576,
RIGHT_BRACE = 577,
DOT = 578,
COMMA = 579,
COLON = 580,
EQUAL = 581,
SEMICOLON = 582,
BANG = 583,
DASH = 584,
TILDE = 585,
PLUS = 586,
STAR = 587,
SLASH = 588,
PERCENT = 589,
LEFT_ANGLE = 590,
RIGHT_ANGLE = 591,
VERTICAL_BAR = 592,
CARET = 593,
AMPERSAND = 594,
QUESTION = 595,
INVARIANT = 596,
HIGH_PRECISION = 597,
MEDIUM_PRECISION = 598,
LOW_PRECISION = 599,
PRECISION = 600,
PACKED = 601,
RESOURCE = 602,
SUPERP = 603,
FLOATCONSTANT = 604,
INTCONSTANT = 605,
UINTCONSTANT = 606,
BOOLCONSTANT = 607,
IDENTIFIER = 608,
TYPE_NAME = 609,
CENTROID = 610,
IN = 611,
OUT = 612,
INOUT = 613,
STRUCT = 614,
VOID = 615,
WHILE = 616,
BREAK = 617,
CONTINUE = 618,
DO = 619,
ELSE = 620,
FOR = 621,
IF = 622,
DISCARD = 623,
RETURN = 624,
SWITCH = 625,
CASE = 626,
DEFAULT = 627,
UNIFORM = 628,
SHARED = 629,
BUFFER = 630,
FLAT = 631,
SMOOTH = 632,
LAYOUT = 633,
DOUBLECONSTANT = 634,
INT16CONSTANT = 635,
UINT16CONSTANT = 636,
FLOAT16CONSTANT = 637,
INT32CONSTANT = 638,
UINT32CONSTANT = 639,
INT64CONSTANT = 640,
UINT64CONSTANT = 641,
SUBROUTINE = 642,
DEMOTE = 643,
PAYLOADNV = 644,
PAYLOADINNV = 645,
HITATTRNV = 646,
CALLDATANV = 647,
CALLDATAINNV = 648,
PAYLOADEXT = 649,
PAYLOADINEXT = 650,
HITATTREXT = 651,
CALLDATAEXT = 652,
CALLDATAINEXT = 653,
PATCH = 654,
SAMPLE = 655,
NONUNIFORM = 656,
COHERENT = 657,
VOLATILE = 658,
RESTRICT = 659,
READONLY = 660,
WRITEONLY = 661,
DEVICECOHERENT = 662,
QUEUEFAMILYCOHERENT = 663,
WORKGROUPCOHERENT = 664,
SUBGROUPCOHERENT = 665,
NONPRIVATE = 666,
SHADERCALLCOHERENT = 667,
NOPERSPECTIVE = 668,
EXPLICITINTERPAMD = 669,
PERVERTEXNV = 670,
PERPRIMITIVENV = 671,
PERVIEWNV = 672,
PERTASKNV = 673,
PRECISE = 674
};
#endif
@@ -461,7 +470,7 @@ extern int yydebug;
union YYSTYPE
{
#line 96 "MachineIndependent/glslang.y" /* yacc.c:1909 */
#line 97 "MachineIndependent/glslang.y" /* yacc.c:1909 */
struct {
glslang::TSourceLoc loc;
@@ -497,7 +506,7 @@ union YYSTYPE
glslang::TArraySizes* typeParameters;
} interm;
#line 501 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */
#line 510 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */
};
typedef union YYSTYPE YYSTYPE;
@@ -2,6 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2016 LunarG, Inc.
// Copyright (C) 2017 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
//
// All rights reserved.
//
@@ -35,7 +36,7 @@
// POSSIBILITY OF SUCH DAMAGE.
//
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
#include "localintermediate.h"
#include "../Include/InfoSink.h"
@@ -1078,18 +1079,43 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpSubpassLoad: out.debug << "subpassLoad"; break;
case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
case EOpTraceNV: out.debug << "traceNV"; break;
case EOpReportIntersectionNV: out.debug << "reportIntersectionNV"; break;
case EOpIgnoreIntersectionNV: out.debug << "ignoreIntersectionNV"; break;
case EOpTerminateRayNV: out.debug << "terminateRayNV"; break;
case EOpExecuteCallableNV: out.debug << "executeCallableNV"; break;
case EOpTrace: out.debug << "traceNV"; break;
case EOpReportIntersection: out.debug << "reportIntersectionNV"; break;
case EOpIgnoreIntersection: out.debug << "ignoreIntersectionNV"; break;
case EOpTerminateRay: out.debug << "terminateRayNV"; break;
case EOpExecuteCallable: out.debug << "executeCallableNV"; break;
case EOpWritePackedPrimitiveIndices4x8NV: out.debug << "writePackedPrimitiveIndices4x8NV"; break;
case EOpRayQueryInitialize: out.debug << "rayQueryInitializeEXT"; break;
case EOpRayQueryTerminate: out.debug << "rayQueryTerminateEXT"; break;
case EOpRayQueryGenerateIntersection: out.debug << "rayQueryGenerateIntersectionEXT"; break;
case EOpRayQueryConfirmIntersection: out.debug << "rayQueryConfirmIntersectionEXT"; break;
case EOpRayQueryProceed: out.debug << "rayQueryProceedEXT"; break;
case EOpRayQueryGetIntersectionType: out.debug << "rayQueryGetIntersectionTypeEXT"; break;
case EOpRayQueryGetRayTMin: out.debug << "rayQueryGetRayTMinEXT"; break;
case EOpRayQueryGetRayFlags: out.debug << "rayQueryGetRayFlagsEXT"; break;
case EOpRayQueryGetIntersectionT: out.debug << "rayQueryGetIntersectionTEXT"; break;
case EOpRayQueryGetIntersectionInstanceCustomIndex: out.debug << "rayQueryGetIntersectionInstanceCustomIndexEXT"; break;
case EOpRayQueryGetIntersectionInstanceId: out.debug << "rayQueryGetIntersectionInstanceIdEXT"; break;
case EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: out.debug << "rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT"; break;
case EOpRayQueryGetIntersectionGeometryIndex: out.debug << "rayQueryGetIntersectionGeometryIndexEXT"; break;
case EOpRayQueryGetIntersectionPrimitiveIndex: out.debug << "rayQueryGetIntersectionPrimitiveIndexEXT"; break;
case EOpRayQueryGetIntersectionBarycentrics: out.debug << "rayQueryGetIntersectionBarycentricsEXT"; break;
case EOpRayQueryGetIntersectionFrontFace: out.debug << "rayQueryGetIntersectionFrontFaceEXT"; break;
case EOpRayQueryGetIntersectionCandidateAABBOpaque: out.debug << "rayQueryGetIntersectionCandidateAABBOpaqueEXT"; break;
case EOpRayQueryGetIntersectionObjectRayDirection: out.debug << "rayQueryGetIntersectionObjectRayDirectionEXT"; break;
case EOpRayQueryGetIntersectionObjectRayOrigin: out.debug << "rayQueryGetIntersectionObjectRayOriginEXT"; break;
case EOpRayQueryGetWorldRayDirection: out.debug << "rayQueryGetWorldRayDirectionEXT"; break;
case EOpRayQueryGetWorldRayOrigin: out.debug << "rayQueryGetWorldRayOriginEXT"; break;
case EOpRayQueryGetIntersectionObjectToWorld: out.debug << "rayQueryGetIntersectionObjectToWorldEXT"; break;
case EOpRayQueryGetIntersectionWorldToObject: out.debug << "rayQueryGetIntersectionWorldToObjectEXT"; break;
case EOpCooperativeMatrixLoad: out.debug << "Load cooperative matrix"; break;
case EOpCooperativeMatrixStore: out.debug << "Store cooperative matrix"; break;
case EOpCooperativeMatrixMulAdd: out.debug << "MulAdd cooperative matrices"; break;
case EOpIsHelperInvocation: out.debug << "IsHelperInvocation"; break;
case EOpDebugPrintf: out.debug << "Debug printf"; break;
default: out.debug.message(EPrefixError, "Bad aggregation op");
}
@@ -1536,4 +1562,4 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
} // end namespace glslang
#endif // not GLSLANG_WEB
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
@@ -33,7 +33,7 @@
// POSSIBILITY OF SUCH DAMAGE.
//
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
#include "../Include/Common.h"
#include "../Include/InfoSink.h"
@@ -79,6 +79,11 @@ public:
target = &outputList;
else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().isPushConstant())
target = &uniformList;
// If a global is being visited, then we should also traverse it incase it's evaluation
// ends up visiting inputs we want to tag as live
else if (base->getQualifier().storage == EvqGlobal)
addGlobalReference(base->getName());
if (target) {
TVarEntryInfo ent = {base->getId(), base, ! traverseAll};
ent.stage = intermediate.getStage();
@@ -161,7 +166,7 @@ struct TNotifyUniformAdaptor
}
private:
TNotifyUniformAdaptor& operator=(TNotifyUniformAdaptor&);
TNotifyUniformAdaptor& operator=(TNotifyUniformAdaptor&) = delete;
};
struct TNotifyInOutAdaptor
@@ -180,7 +185,7 @@ struct TNotifyInOutAdaptor
}
private:
TNotifyInOutAdaptor& operator=(TNotifyInOutAdaptor&);
TNotifyInOutAdaptor& operator=(TNotifyInOutAdaptor&) = delete;
};
struct TResolverUniformAdaptor {
@@ -236,7 +241,7 @@ struct TResolverUniformAdaptor {
bool& error;
private:
TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&);
TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&) = delete;
};
struct TResolverInOutAdaptor {
@@ -283,7 +288,7 @@ struct TResolverInOutAdaptor {
bool& error;
private:
TResolverInOutAdaptor& operator=(TResolverInOutAdaptor&);
TResolverInOutAdaptor& operator=(TResolverInOutAdaptor&) = delete;
};
// The class is used for reserving explicit uniform locations and ubo/ssbo/opaque bindings
@@ -309,26 +314,43 @@ struct TSymbolValidater
TIntermSymbol* base = ent1.symbol;
const TType& type = ent1.symbol->getType();
const TString& name = entKey.first;
TString mangleName1, mangleName2;
type.appendMangledName(mangleName1);
EShLanguage stage = ent1.stage;
TString mangleName1, mangleName2;
if (currentStage != stage) {
preStage = currentStage;
currentStage = stage;
nextStage = EShLangCount;
for (int i = currentStage + 1; i < EShLangCount; i++) {
if (inVarMaps[i] != nullptr)
if (inVarMaps[i] != nullptr) {
nextStage = static_cast<EShLanguage>(i);
break;
}
}
}
if (type.getQualifier().isArrayedIo(stage)) {
TType subType(type, 0);
subType.appendMangledName(mangleName1);
} else {
type.appendMangledName(mangleName1);
}
if (base->getQualifier().storage == EvqVaryingIn) {
// validate stage in;
if (preStage == EShLangCount)
return;
if (name == "gl_PerVertex")
return;
if (outVarMaps[preStage] != nullptr) {
auto ent2 = outVarMaps[preStage]->find(name);
if (ent2 != outVarMaps[preStage]->end()) {
ent2->second.symbol->getType().appendMangledName(mangleName2);
if (ent2->second.symbol->getType().getQualifier().isArrayedIo(preStage)) {
TType subType(ent2->second.symbol->getType(), 0);
subType.appendMangledName(mangleName2);
}
else {
ent2->second.symbol->getType().appendMangledName(mangleName2);
}
if (mangleName1 == mangleName2)
return;
else {
@@ -343,10 +365,18 @@ struct TSymbolValidater
// validate stage out;
if (nextStage == EShLangCount)
return;
if (name == "gl_PerVertex")
return;
if (outVarMaps[nextStage] != nullptr) {
auto ent2 = inVarMaps[nextStage]->find(name);
if (ent2 != inVarMaps[nextStage]->end()) {
ent2->second.symbol->getType().appendMangledName(mangleName2);
if (ent2->second.symbol->getType().getQualifier().isArrayedIo(nextStage)) {
TType subType(ent2->second.symbol->getType(), 0);
subType.appendMangledName(mangleName2);
}
else {
ent2->second.symbol->getType().appendMangledName(mangleName2);
}
if (mangleName1 == mangleName2)
return;
else {
@@ -384,7 +414,7 @@ struct TSymbolValidater
bool& hadError;
private:
TSymbolValidater& operator=(TSymbolValidater&);
TSymbolValidater& operator=(TSymbolValidater&) = delete;
};
struct TSlotCollector {
@@ -398,7 +428,7 @@ struct TSlotCollector {
TInfoSink& infoSink;
private:
TSlotCollector& operator=(TSlotCollector&);
TSlotCollector& operator=(TSlotCollector&) = delete;
};
TDefaultIoResolverBase::TDefaultIoResolverBase(const TIntermediate& intermediate)
@@ -579,7 +609,7 @@ TDefaultGlslIoResolver::TDefaultGlslIoResolver(const TIntermediate& intermediate
int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) {
const TType& type = ent.symbol->getType();
const TString& name = ent.symbol->getName();
const TString& name = getAccessName(ent.symbol);
if (currentStage != stage) {
preStage = currentStage;
currentStage = stage;
@@ -627,7 +657,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;
@@ -663,7 +693,7 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf
int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
const TType& type = ent.symbol->getType();
const TString& name = ent.symbol->getName();
const TString& name = getAccessName(ent.symbol);
// kick out of not doing this
if (! doAutoLocationMapping()) {
return ent.newLocation = -1;
@@ -706,7 +736,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;
@@ -714,7 +744,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;
@@ -723,7 +753,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;
@@ -734,8 +764,8 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) {
const TType& type = ent.symbol->getType();
const TString& name = 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
@@ -809,7 +839,7 @@ void TDefaultGlslIoResolver::endCollect(EShLanguage /*stage*/) {
void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
const TType& type = ent.symbol->getType();
const TString& name = ent.symbol->getName();
const TString& name = getAccessName(ent.symbol);
TStorageQualifier storage = type.getQualifier().storage;
EShLanguage stage(EShLangCount);
switch (storage) {
@@ -831,6 +861,7 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink&
if (iter->second != location) {
TString errorMsg = "Invalid location: " + name;
infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
hasError = true;
}
}
}
@@ -856,6 +887,7 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink&
if (iter->second != location) {
TString errorMsg = "Invalid location: " + name;
infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
hasError = true;
}
}
}
@@ -867,7 +899,7 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink&
void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
const TType& type = ent.symbol->getType();
const TString& name = ent.symbol->getName();
const TString& name = getAccessName(ent.symbol);
int resource = getResourceType(type);
if (type.getQualifier().hasBinding()) {
TVarSlotMap& varSlotMap = resourceSlotMap[resource];
@@ -884,11 +916,19 @@ void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink&
if (iter->second != binding) {
TString errorMsg = "Invalid binding: " + name;
infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
hasError = true;
}
}
}
}
const TString& TDefaultGlslIoResolver::getAccessName(const TIntermSymbol* symbol)
{
return symbol->getBasicType() == EbtBlock ?
symbol->getType().getTypeName() :
symbol->getName();
}
//TDefaultGlslIoResolver end
/*
@@ -1070,11 +1110,12 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSi
TVarGatherTraverser iter_binding_live(intermediate, false, inVarMap, outVarMap, uniformVarMap);
root->traverse(&iter_binding_all);
iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str());
while (! iter_binding_live.functions.empty()) {
TIntermNode* function = iter_binding_live.functions.back();
iter_binding_live.functions.pop_back();
function->traverse(&iter_binding_live);
while (! iter_binding_live.destinations.empty()) {
TIntermNode* destination = iter_binding_live.destinations.back();
iter_binding_live.destinations.pop_back();
destination->traverse(&iter_binding_live);
}
// sort entries by priority. see TVarEntryInfo::TOrderByPriority for info.
std::for_each(inVarMap.begin(), inVarMap.end(),
[&inVector](TVarLivePair p) { inVector.push_back(p); });
@@ -1158,18 +1199,19 @@ bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TIn
resolver = &defaultResolver;
}
resolver->addStage(stage);
inVarMaps[stage] = new TVarLiveMap, outVarMaps[stage] = new TVarLiveMap(), uniformVarMap[stage] = new TVarLiveMap();
inVarMaps[stage] = new TVarLiveMap(); outVarMaps[stage] = new TVarLiveMap(); uniformVarMap[stage] = new TVarLiveMap();
TVarGatherTraverser iter_binding_all(intermediate, true, *inVarMaps[stage], *outVarMaps[stage],
*uniformVarMap[stage]);
TVarGatherTraverser iter_binding_live(intermediate, false, *inVarMaps[stage], *outVarMaps[stage],
*uniformVarMap[stage]);
root->traverse(&iter_binding_all);
iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str());
while (! iter_binding_live.functions.empty()) {
TIntermNode* function = iter_binding_live.functions.back();
iter_binding_live.functions.pop_back();
function->traverse(&iter_binding_live);
while (! iter_binding_live.destinations.empty()) {
TIntermNode* destination = iter_binding_live.destinations.back();
iter_binding_live.destinations.pop_back();
destination->traverse(&iter_binding_live);
}
TNotifyInOutAdaptor inOutNotify(stage, *resolver);
TNotifyUniformAdaptor uniformNotify(stage, *resolver);
// Resolve current stage input symbol location with previous stage output here,
@@ -1246,4 +1288,4 @@ bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) {
} // end namespace glslang
#endif // GLSLANG_WEB
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
@@ -33,7 +33,7 @@
// POSSIBILITY OF SUCH DAMAGE.
//
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
#ifndef _IOMAPPER_INCLUDED
#define _IOMAPPER_INCLUDED
@@ -129,6 +129,7 @@ public:
uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage);
TSlotSetMap slots;
bool hasError = false;
protected:
TDefaultIoResolverBase(TDefaultIoResolverBase&);
@@ -185,7 +186,7 @@ protected:
}
};
// Defaulf I/O resolver for OpenGL
// Default I/O resolver for OpenGL
struct TDefaultGlslIoResolver : public TDefaultIoResolverBase {
public:
typedef std::map<TString, int> TVarSlotMap; // <resourceName, location/binding>
@@ -202,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.
@@ -237,12 +239,13 @@ typedef std::map<TString, TVarEntryInfo> TVarLiveMap;
// In the future, if the vc++ compiler can handle such a situation,
// this part of the code will be removed.
struct TVarLivePair : std::pair<const TString, TVarEntryInfo> {
TVarLivePair(std::pair<const TString, TVarEntryInfo>& _Right) : pair(_Right.first, _Right.second) {}
TVarLivePair(const std::pair<const TString, TVarEntryInfo>& _Right) : pair(_Right.first, _Right.second) {}
TVarLivePair& operator=(const TVarLivePair& _Right) {
const_cast<TString&>(first) = _Right.first;
second = _Right.second;
return (*this);
}
TVarLivePair(const TVarLivePair& src) : pair(src) { }
};
typedef std::vector<TVarLivePair> TVarLiveVector;
@@ -260,10 +263,10 @@ public:
class TGlslIoMapper : public TIoMapper {
public:
TGlslIoMapper() {
memset(inVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
memset(outVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
memset(intermediates, 0, sizeof(TIntermediate*) * (EShLangCount + 1));
memset(inVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount);
memset(outVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount);
memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * EShLangCount);
memset(intermediates, 0, sizeof(TIntermediate*) * EShLangCount);
}
virtual ~TGlslIoMapper() {
for (size_t stage = 0; stage < EShLangCount; stage++) {
@@ -296,4 +299,4 @@ public:
#endif // _IOMAPPER_INCLUDED
#endif // GLSLANG_WEB
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
@@ -82,7 +82,7 @@ void TIntermediate::warn(TInfoSink& infoSink, const char* message)
//
void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
{
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
mergeCallGraphs(infoSink, unit);
mergeModes(infoSink, unit);
mergeTrees(infoSink, unit);
@@ -104,7 +104,7 @@ void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit)
callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end());
}
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
#define MERGE_MAX(member) member = std::max(member, unit.member)
#define MERGE_TRUE(member) if (unit.member) member = unit.member;
@@ -138,7 +138,11 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
MERGE_MAX(spvVersion.openGl);
numErrors += unit.getNumErrors();
numPushConstants += unit.numPushConstants;
// Only one push_constant is allowed, mergeLinkerObjects() will ensure the push_constant
// is the same for all units.
if (numPushConstants > 1 || unit.numPushConstants > 1)
error(infoSink, "Only one push_constant block is allowed per stage");
numPushConstants = std::min(numPushConstants + unit.numPushConstants, 1);
if (unit.invocations != TQualifier::layoutNotSet) {
if (invocations == TQualifier::layoutNotSet)
@@ -149,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)
@@ -168,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)
@@ -286,7 +290,7 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
}
// Getting this far means we have two existing trees to merge...
numShaderRecordNVBlocks += unit.numShaderRecordNVBlocks;
numShaderRecordBlocks += unit.numShaderRecordBlocks;
numTaskNVBlocks += unit.numTaskNVBlocks;
// Get the top-level globals of each unit
@@ -299,10 +303,10 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
// Map by global name to unique ID to rationalize the same object having
// differing IDs in different trees.
TMap<TString, int> idMap;
TIdMaps idMaps;
int maxId;
seedIdMap(idMap, maxId);
remapIds(idMap, maxId + 1, unit);
seedIdMap(idMaps, maxId);
remapIds(idMaps, maxId + 1, unit);
mergeBodies(infoSink, globals, unitGlobals);
mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects);
@@ -311,27 +315,40 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
#endif
static const TString& getNameForIdMap(TIntermSymbol* symbol)
{
TShaderInterface si = symbol->getType().getShaderInterface();
if (si == EsiNone)
return symbol->getName();
else
return symbol->getType().getTypeName();
}
// Traverser that seeds an ID map with all built-ins, and tracks the
// maximum ID used.
// (It would be nice to put this in a function, but that causes warnings
// on having no bodies for the copy-constructor/operator=.)
class TBuiltInIdTraverser : public TIntermTraverser {
public:
TBuiltInIdTraverser(TMap<TString, int>& idMap) : idMap(idMap), maxId(0) { }
TBuiltInIdTraverser(TIdMaps& idMaps) : idMaps(idMaps), maxId(0) { }
// If it's a built in, add it to the map.
// Track the max ID.
virtual void visitSymbol(TIntermSymbol* symbol)
{
const TQualifier& qualifier = symbol->getType().getQualifier();
if (qualifier.builtIn != EbvNone)
idMap[symbol->getName()] = symbol->getId();
if (qualifier.builtIn != EbvNone) {
TShaderInterface si = symbol->getType().getShaderInterface();
idMaps[si][getNameForIdMap(symbol)] = symbol->getId();
}
maxId = std::max(maxId, symbol->getId());
}
int getMaxId() const { return maxId; }
protected:
TBuiltInIdTraverser(TBuiltInIdTraverser&);
TBuiltInIdTraverser& operator=(TBuiltInIdTraverser&);
TMap<TString, int>& idMap;
TIdMaps& idMaps;
int maxId;
};
@@ -340,31 +357,33 @@ protected:
// on having no bodies for the copy-constructor/operator=.)
class TUserIdTraverser : public TIntermTraverser {
public:
TUserIdTraverser(TMap<TString, int>& idMap) : idMap(idMap) { }
TUserIdTraverser(TIdMaps& idMaps) : idMaps(idMaps) { }
// If its a non-built-in global, add it to the map.
virtual void visitSymbol(TIntermSymbol* symbol)
{
const TQualifier& qualifier = symbol->getType().getQualifier();
if (qualifier.builtIn == EbvNone)
idMap[symbol->getName()] = symbol->getId();
if (qualifier.builtIn == EbvNone) {
TShaderInterface si = symbol->getType().getShaderInterface();
idMaps[si][getNameForIdMap(symbol)] = symbol->getId();
}
}
protected:
TUserIdTraverser(TUserIdTraverser&);
TUserIdTraverser& operator=(TUserIdTraverser&);
TMap<TString, int>& idMap; // over biggest id
TIdMaps& idMaps; // over biggest id
};
// Initialize the the ID map with what we know of 'this' AST.
void TIntermediate::seedIdMap(TMap<TString, int>& idMap, int& maxId)
void TIntermediate::seedIdMap(TIdMaps& idMaps, int& maxId)
{
// all built-ins everywhere need to align on IDs and contribute to the max ID
TBuiltInIdTraverser builtInIdTraverser(idMap);
TBuiltInIdTraverser builtInIdTraverser(idMaps);
treeRoot->traverse(&builtInIdTraverser);
maxId = builtInIdTraverser.getMaxId();
// user variables in the linker object list need to align on ids
TUserIdTraverser userIdTraverser(idMap);
TUserIdTraverser userIdTraverser(idMaps);
findLinkerObjects()->traverse(&userIdTraverser);
}
@@ -373,7 +392,7 @@ void TIntermediate::seedIdMap(TMap<TString, int>& idMap, int& maxId)
// on having no bodies for the copy-constructor/operator=.)
class TRemapIdTraverser : public TIntermTraverser {
public:
TRemapIdTraverser(const TMap<TString, int>& idMap, int idShift) : idMap(idMap), idShift(idShift) { }
TRemapIdTraverser(const TIdMaps& idMaps, int idShift) : idMaps(idMaps), idShift(idShift) { }
// Do the mapping:
// - if the same symbol, adopt the 'this' ID
// - otherwise, ensure a unique ID by shifting to a new space
@@ -382,8 +401,9 @@ public:
const TQualifier& qualifier = symbol->getType().getQualifier();
bool remapped = false;
if (qualifier.isLinkable() || qualifier.builtIn != EbvNone) {
auto it = idMap.find(symbol->getName());
if (it != idMap.end()) {
TShaderInterface si = symbol->getType().getShaderInterface();
auto it = idMaps[si].find(getNameForIdMap(symbol));
if (it != idMaps[si].end()) {
symbol->changeId(it->second);
remapped = true;
}
@@ -394,14 +414,14 @@ public:
protected:
TRemapIdTraverser(TRemapIdTraverser&);
TRemapIdTraverser& operator=(TRemapIdTraverser&);
const TMap<TString, int>& idMap;
const TIdMaps& idMaps;
int idShift;
};
void TIntermediate::remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate& unit)
void TIntermediate::remapIds(const TIdMaps& idMaps, int idShift, TIntermediate& unit)
{
// Remap all IDs to either share or be unique, as dictated by the idMap and idShift.
TRemapIdTraverser idTraverser(idMap, idShift);
TRemapIdTraverser idTraverser(idMaps, idShift);
unit.getTreeRoot()->traverse(&idTraverser);
}
@@ -443,7 +463,19 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode();
TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode();
assert(symbol && unitSymbol);
if (symbol->getName() == unitSymbol->getName()) {
bool isSameSymbol = false;
// If they are both blocks in the same shader interface,
// match by the block-name, not the identifier name.
if (symbol->getType().getBasicType() == EbtBlock && unitSymbol->getType().getBasicType() == EbtBlock) {
if (symbol->getType().getShaderInterface() == unitSymbol->getType().getShaderInterface()) {
isSameSymbol = symbol->getType().getTypeName() == unitSymbol->getType().getTypeName();
}
}
else if (symbol->getName() == unitSymbol->getName())
isSameSymbol = true;
if (isSameSymbol) {
// filter out copy
merge = false;
@@ -462,6 +494,9 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
// Check for consistent types/qualification/initializers etc.
mergeErrorCheck(infoSink, *symbol, *unitSymbol, false);
}
// If different symbols, verify they arn't push_constant since there can only be one per stage
else if (symbol->getQualifier().isPushConstant() && unitSymbol->getQualifier().isPushConstant())
error(infoSink, "Only one push_constant block is allowed per stage");
}
if (merge)
linkerObjects.push_back(unitLinkerObjects[unitLinkObj]);
@@ -498,7 +533,7 @@ void TIntermediate::mergeImplicitArraySizes(TType& type, const TType& unitType)
//
void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, bool crossStage)
{
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
bool writeTypeComparison = false;
// Types have to match
@@ -520,6 +555,22 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
writeTypeComparison = true;
}
// Uniform and buffer blocks must either both have an instance name, or
// must both be anonymous. The names don't need to match though.
if (symbol.getQualifier().isUniformOrBuffer() &&
(IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()))) {
error(infoSink, "Matched Uniform or Storage blocks must all be anonymous,"
" or all be named:");
writeTypeComparison = true;
}
if (symbol.getQualifier().storage == unitSymbol.getQualifier().storage &&
(IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()) ||
(!IsAnonymous(symbol.getName()) && symbol.getName() != unitSymbol.getName()))) {
warn(infoSink, "Matched shader interfaces are using different instance names.");
writeTypeComparison = true;
}
// Precision...
if (symbol.getQualifier().precision != unitSymbol.getQualifier().precision) {
error(infoSink, "Precision qualifiers must match:");
@@ -555,6 +606,7 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
symbol.getQualifier().queuefamilycoherent != unitSymbol.getQualifier().queuefamilycoherent ||
symbol.getQualifier().workgroupcoherent != unitSymbol.getQualifier().workgroupcoherent ||
symbol.getQualifier().subgroupcoherent != unitSymbol.getQualifier().subgroupcoherent ||
symbol.getQualifier().shadercallcoherent!= unitSymbol.getQualifier().shadercallcoherent ||
symbol.getQualifier().nonprivate != unitSymbol.getQualifier().nonprivate ||
symbol.getQualifier().volatil != unitSymbol.getQualifier().volatil ||
symbol.getQualifier().restrict != unitSymbol.getQualifier().restrict ||
@@ -589,9 +641,13 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
}
}
if (writeTypeComparison)
infoSink.info << " " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus \"" <<
unitSymbol.getType().getCompleteString() << "\"\n";
if (writeTypeComparison) {
infoSink.info << " " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus ";
if (symbol.getName() != unitSymbol.getName())
infoSink.info << unitSymbol.getName() << ": ";
infoSink.info << "\"" << unitSymbol.getType().getCompleteString() << "\"\n";
}
#endif
}
@@ -721,13 +777,13 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
break;
case EShLangCompute:
break;
case EShLangRayGenNV:
case EShLangIntersectNV:
case EShLangAnyHitNV:
case EShLangClosestHitNV:
case EShLangMissNV:
case EShLangCallableNV:
if (numShaderRecordNVBlocks > 1)
case EShLangRayGen:
case EShLangIntersect:
case EShLangAnyHit:
case EShLangClosestHit:
case EShLangMiss:
case EShLangCallable:
if (numShaderRecordBlocks > 1)
error(infoSink, "Only one shaderRecordNV buffer block is allowed per stage");
break;
case EShLangMeshNV:
@@ -1306,9 +1362,9 @@ unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains
// that component's size. Aggregate types are flattened down to the component
// level to get this sequence of components."
if (type.isArray()) {
if (type.isSizedArray()) {
// TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
assert(type.isSizedArray());
// Unsized array use to xfb should be a compile error.
TType elementType(type, 0);
return type.getOuterArraySize() * computeTypeXfbSize(elementType, contains64BitType, contains16BitType, contains16BitType);
}
@@ -1494,7 +1550,9 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, T
RoundToPow2(size, alignment);
stride = size; // uses full matrix size for stride of an array of matrices (not quite what rule 6/8, but what's expected)
// uses the assumption for rule 10 in the comment above
size = stride * type.getOuterArraySize();
// use one element to represent the last member of SSBO which is unsized array
int arraySize = (type.isUnsizedArray() && (type.getOuterArraySize() == 0)) ? 1 : type.getOuterArraySize();
size = stride * arraySize;
return alignment;
}
@@ -162,7 +162,10 @@ struct TXfbBuffer {
#endif
// Track a set of strings describing how the module was processed.
// Using the form:
// This includes command line options, transforms, etc., ideally inclusive enough
// to reproduce the steps used to transform the input source to the output.
// E.g., see SPIR-V OpModuleProcessed.
// Each "process" or "transform" uses is expressed in the form:
// process arg0 arg1 arg2 ...
// process arg0 arg1 arg2 ...
// where everything is textual, and there can be zero or more arguments
@@ -222,6 +225,40 @@ enum ComputeDerivativeMode {
LayoutDerivativeGroupLinear, // derivative_group_linearNV
};
class TIdMaps {
public:
TMap<TString, int>& operator[](int i) { return maps[i]; }
const TMap<TString, int>& operator[](int i) const { return maps[i]; }
private:
TMap<TString, int> maps[EsiCount];
};
class TNumericFeatures {
public:
TNumericFeatures() : features(0) { }
TNumericFeatures(const TNumericFeatures&) = delete;
TNumericFeatures& operator=(const TNumericFeatures&) = delete;
typedef enum : unsigned int {
shader_explicit_arithmetic_types = 1 << 0,
shader_explicit_arithmetic_types_int8 = 1 << 1,
shader_explicit_arithmetic_types_int16 = 1 << 2,
shader_explicit_arithmetic_types_int32 = 1 << 3,
shader_explicit_arithmetic_types_int64 = 1 << 4,
shader_explicit_arithmetic_types_float16 = 1 << 5,
shader_explicit_arithmetic_types_float32 = 1 << 6,
shader_explicit_arithmetic_types_float64 = 1 << 7,
shader_implicit_conversions = 1 << 8,
gpu_shader_fp64 = 1 << 9,
gpu_shader_int16 = 1 << 10,
gpu_shader_half_float = 1 << 11,
} feature;
void insert(feature f) { features |= f; }
void erase(feature f) { features &= ~f; }
bool contains(feature f) const { return (features & f) != 0; }
private:
unsigned int features;
};
//
// Set of helper functions to help parse and build the tree.
//
@@ -229,7 +266,10 @@ class TIntermediate {
public:
explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) :
language(l),
profile(p), version(v), treeRoot(0),
#ifndef GLSLANG_ANGLE
profile(p), version(v),
#endif
treeRoot(0),
numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
invertY(false),
useStorageBuffer(false),
@@ -244,15 +284,16 @@ public:
inputPrimitive(ElgNone), outputPrimitive(ElgNone),
pixelCenterInteger(false), originUpperLeft(false),
vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false),
postDepthCoverage(false), depthLayout(EldNone),
postDepthCoverage(false), depthLayout(EldNone),
hlslFunctionality1(false),
blendEquations(0), xfbMode(false), multiStream(false),
layoutOverrideCoverage(false),
geoPassthroughEXT(false),
numShaderRecordNVBlocks(0),
numShaderRecordBlocks(0),
computeDerivativeMode(LayoutDerivativeNone),
primitives(TQualifier::layoutNotSet),
numTaskNVBlocks(0),
layoutPrimitiveCulling(false),
autoMapBindings(false),
autoMapLocations(false),
flattenUniformArrays(false),
@@ -282,9 +323,20 @@ public:
#endif
}
void setVersion(int v) { version = v; }
void setVersion(int v)
{
#ifndef GLSLANG_ANGLE
version = v;
#endif
}
void setProfile(EProfile p)
{
#ifndef GLSLANG_ANGLE
profile = p;
#endif
}
int getVersion() const { return version; }
void setProfile(EProfile p) { profile = p; }
EProfile getProfile() const { return profile; }
void setSpv(const SpvVersion& s)
{
@@ -332,6 +384,9 @@ public:
case EShTargetVulkan_1_1:
processes.addProcess("target-env vulkan1.1");
break;
case EShTargetVulkan_1_2:
processes.addProcess("target-env vulkan1.2");
break;
default:
processes.addProcess("target-env vulkanUnknown");
break;
@@ -377,7 +432,7 @@ public:
void setSource(EShSource s) { source = s; }
EShSource getSource() const { return source; }
#else
void setSource(EShSource s) { assert(s == EShSourceGlsl); }
void setSource(EShSource s) { assert(s == EShSourceGlsl); (void)s; }
EShSource getSource() const { return EShSourceGlsl; }
#endif
@@ -388,15 +443,15 @@ public:
TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
TIntermSymbol* addSymbol(const TIntermSymbol&);
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
std::tuple<TIntermTyped*, TIntermTyped*> addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1);
std::tuple<TIntermTyped*, TIntermTyped*> addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1);
TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*);
TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const;
void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode);
TIntermTyped* addShapeConversion(const TType&, TIntermTyped*);
TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc);
TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&);
TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, const TSourceLoc&);
TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType);
bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const;
bool isIntegralPromotion(TBasicType from, TBasicType to) const;
@@ -410,7 +465,7 @@ public:
TIntermAggregate* makeAggregate(TIntermNode* node);
TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
TIntermAggregate* makeAggregate(const TSourceLoc&);
TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc);
TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, const TSourceLoc&);
bool areAllChildConst(TIntermAggregate* aggrNode);
TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
@@ -439,10 +494,11 @@ public:
// Low level functions to add nodes (no conversions or other higher level transformations)
// If a type is provided, the node's type will be set to it.
TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc) const;
TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, const TType&) const;
TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc) const;
TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc, const TType&) const;
TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&) const;
TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&,
const TType&) const;
TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&) const;
TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&, const TType&) const;
// Constant folding (in Constant.cpp)
TIntermTyped* fold(TIntermAggregate* aggrNode);
@@ -457,11 +513,7 @@ public:
void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
void setUseStorageBuffer()
{
useStorageBuffer = true;
processes.addProcess("use-storage-buffer");
}
void setUseStorageBuffer() { useStorageBuffer = true; }
bool usingStorageBuffer() const { return useStorageBuffer; }
void setDepthReplacing() { depthReplacing = true; }
bool isDepthReplacing() const { return depthReplacing; }
@@ -500,7 +552,7 @@ public:
bool getAutoMapBindings() const { return false; }
bool getAutoMapLocations() const { return false; }
int getNumPushConstants() const { return 0; }
void addShaderRecordNVCount() { }
void addShaderRecordCount() { }
void addTaskNVCount() { }
void setUseVulkanMemoryModel() { }
bool usingVulkanMemoryModel() const { return false; }
@@ -580,7 +632,7 @@ public:
processes.addProcess("flatten-uniform-arrays");
}
bool getFlattenUniformArrays() const { return flattenUniformArrays; }
#endif
#endif
void setNoStorageFormat(bool b)
{
useUnknownFormat = b;
@@ -617,7 +669,7 @@ public:
void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
int getNumPushConstants() const { return numPushConstants; }
void addShaderRecordNVCount() { ++numShaderRecordNVBlocks; }
void addShaderRecordCount() { ++numShaderRecordBlocks; }
void addTaskNVCount() { ++numTaskNVBlocks; }
bool setInvocations(int i)
@@ -720,6 +772,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)
@@ -831,22 +885,25 @@ public:
bool getArithemeticInt8Enabled() const { return false; }
bool getArithemeticInt16Enabled() const { return false; }
bool getArithemeticFloat16Enabled() const { return false; }
void updateNumericFeature(TNumericFeatures::feature f, bool on) { }
#else
bool getArithemeticInt8Enabled() const {
return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8);
}
bool getArithemeticInt16Enabled() const {
return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_AMD_gpu_shader_int16) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
numericFeatures.contains(TNumericFeatures::gpu_shader_int16) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16);
}
bool getArithemeticFloat16Enabled() const {
return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_AMD_gpu_shader_half_float) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16);
return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16);
}
void updateNumericFeature(TNumericFeatures::feature f, bool on)
{ on ? numericFeatures.insert(f) : numericFeatures.erase(f); }
#endif
protected:
@@ -856,8 +913,8 @@ protected:
void mergeCallGraphs(TInfoSink&, TIntermediate&);
void mergeModes(TInfoSink&, TIntermediate&);
void mergeTrees(TInfoSink&, TIntermediate&);
void seedIdMap(TMap<TString, int>& idMap, int& maxId);
void remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate&);
void seedIdMap(TIdMaps& idMaps, int& maxId);
void remapIds(const TIdMaps& idMaps, int idShift, TIntermediate&);
void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
void mergeImplicitArraySizes(TType&, const TType&);
@@ -878,17 +935,7 @@ protected:
bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root);
bool isConversionAllowed(TOperator op, TIntermTyped* node) const;
std::tuple<TBasicType, TBasicType> getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const;
// JohnK: I think this function should go away.
// This data structure is just a log to pass on to back ends.
// Versioning and extensions are handled in Version.cpp, with a rich
// set of functions for querying stages, versions, extension enable/disabled, etc.
#ifdef GLSLANG_WEB
bool extensionRequested(const char *extension) const { return false; }
#else
bool extensionRequested(const char *extension) const {return requestedExtensions.find(extension) != requestedExtensions.end();}
#endif
std::tuple<TBasicType, TBasicType> getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const;
static const char* getResourceName(TResourceType);
@@ -898,8 +945,13 @@ protected:
typedef std::list<TCall> TGraph;
TGraph callGraph;
#ifdef GLSLANG_ANGLE
const EProfile profile = ECoreProfile;
const int version = 450;
#else
EProfile profile; // source profile
int version; // source version
#endif
SpvVersion spvVersion;
TIntermNode* treeRoot;
std::set<std::string> requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
@@ -942,10 +994,11 @@ protected:
bool multiStream;
bool layoutOverrideCoverage;
bool geoPassthroughEXT;
int numShaderRecordNVBlocks;
int numShaderRecordBlocks;
ComputeDerivativeMode computeDerivativeMode;
int primitives;
int numTaskNVBlocks;
bool layoutPrimitiveCulling;
// Base shift values
std::array<unsigned int, EResCount> shiftBinding;
@@ -972,6 +1025,7 @@ protected:
std::unordered_map<std::string, int> uniformLocationOverrides;
int uniformLocationBase;
TNumericFeatures numericFeatures;
#endif
std::unordered_set<int> usedConstantId; // specialization constant ids used
@@ -165,17 +165,27 @@ void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
}
}
} else {
// matrix from vector
// matrix from vector or scalar
int count = 0;
const int startIndex = index;
int nodeComps = node->getType().computeNumComponents();
for (int i = startIndex; i < endIndex; i++) {
if (i >= instanceSize)
return;
if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 )
if (nodeComps == 1) {
// If there is a single scalar parameter to a matrix
// constructor, it is used to initialize all the
// components on the matrix's diagonal, with the
// remaining components initialized to 0.0.
if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 )
leftUnionArray[i] = rightUnionArray[count];
else
leftUnionArray[i].setDConst(0.0);
} else {
// construct the matrix in column-major order, from
// the components provided, in order
leftUnionArray[i] = rightUnionArray[count];
else
leftUnionArray[i].setDConst(0.0);
}
index++;
@@ -58,7 +58,7 @@ public:
const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink,
bool forwardCompatible, EShMessages messages)
:
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
forwardCompatible(forwardCompatible),
profile(profile),
#endif
@@ -101,6 +101,7 @@ public:
void updateExtensionBehavior(int line, const char* const extension, const char* behavior) { }
void updateExtensionBehavior(const char* const extension, TExtensionBehavior) { }
void checkExtensionStage(const TSourceLoc&, const char* const extension) { }
void extensionRequires(const TSourceLoc&, const char* const extension, const char* behavior) { }
void fullIntegerCheck(const TSourceLoc&, const char* op) { }
void doubleCheck(const TSourceLoc&, const char* op) { }
bool float16Arithmetic() { return false; }
@@ -115,9 +116,14 @@ public:
bool relaxedErrors() const { return false; }
bool suppressWarnings() const { return true; }
bool isForwardCompatible() const { return false; }
#else
#ifdef GLSLANG_ANGLE
const bool forwardCompatible = true;
const EProfile profile = ECoreProfile;
#else
bool forwardCompatible; // true if errors are to be given for use of deprecated features
EProfile profile; // the declared profile in the shader (core by default)
#endif
bool isEsProfile() const { return profile == EEsProfile; }
void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc);
void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions,
@@ -139,6 +145,7 @@ public:
virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[],
const char* featureDesc);
virtual void checkExtensionStage(const TSourceLoc&, const char* const extension);
virtual void extensionRequires(const TSourceLoc&, const char* const extension, const char* behavior);
virtual void fullIntegerCheck(const TSourceLoc&, const char* op);
virtual void unimplemented(const TSourceLoc&, const char* featureDesc);
@@ -170,6 +177,7 @@ public:
virtual void vulkanRemoved(const TSourceLoc&, const char* op);
virtual void requireVulkan(const TSourceLoc&, const char* op);
virtual void requireSpv(const TSourceLoc&, const char* op);
virtual void requireSpv(const TSourceLoc&, const char *op, unsigned int version);
#if defined(GLSLANG_WEB) && !defined(GLSLANG_WEB_DEVEL)
@@ -221,7 +229,8 @@ public:
TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree
protected:
TMap<TString, TExtensionBehavior> extensionBehavior; // for each extension string, what its current behavior is set to
TMap<TString, TExtensionBehavior> extensionBehavior; // for each extension string, what its current behavior is
TMap<TString, unsigned int> extensionMinSpv; // for each extension string, store minimum spirv required
EShMessages messages; // errors/warnings/rule-sets
int numErrors; // number of compile-time errors encountered
TInputScanner* currentScanner;
@@ -422,10 +422,10 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
if (! parseContext.isReadingHLSL() && isMacroInput()) {
if (parseContext.relaxedErrors())
parseContext.ppWarn(ppToken->loc, "nonportable when expanded from macros for preprocessor expression",
"defined", "");
"defined", "");
else
parseContext.ppError(ppToken->loc, "cannot use in preprocessor expression when expanded from macros",
"defined", "");
"defined", "");
}
bool needclose = 0;
token = scanToken(ppToken);
@@ -621,14 +621,25 @@ int TPpContext::CPPinclude(TPpToken* ppToken)
{
const TSourceLoc directiveLoc = ppToken->loc;
bool startWithLocalSearch = true; // to additionally include the extra "" paths
int token = scanToken(ppToken);
int token;
// handle <header-name>-style #include
if (token == '<') {
// Find the first non-whitespace char after #include
int ch = getChar();
while (ch == ' ' || ch == '\t') {
ch = getChar();
}
if (ch == '<') {
// <header-name> style
startWithLocalSearch = false;
token = scanHeaderName(ppToken, '>');
} else if (ch == '"') {
// "header-name" style
token = scanHeaderName(ppToken, '"');
} else {
// unexpected, get the full token to generate the error
ungetChar();
token = scanToken(ppToken);
}
// otherwise ppToken already has the header name and it was "header-name" style
if (token != PpAtomConstString) {
parseContext.ppError(directiveLoc, "must be followed by a header name", "#include", "");
@@ -711,7 +722,9 @@ int TPpContext::CPPline(TPpToken* ppToken)
const char* sourceName = nullptr; // Optional source file name.
bool lineErr = false;
bool fileErr = false;
disableEscapeSequences = true;
token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken);
disableEscapeSequences = false;
if (! lineErr) {
lineToken = lineRes;
if (token == '\n')
@@ -754,7 +767,9 @@ int TPpContext::CPPline(TPpToken* ppToken)
// Handle #error
int TPpContext::CPPerror(TPpToken* ppToken)
{
disableEscapeSequences = true;
int token = scanToken(ppToken);
disableEscapeSequences = false;
std::string message;
TSourceLoc loc = ppToken->loc;
@@ -1169,7 +1184,9 @@ MacroExpandResult TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, b
int macroAtom = atomStrings.getAtom(ppToken->name);
switch (macroAtom) {
case PpAtomLineMacro:
ppToken->ival = parseContext.getCurrentLoc().line;
// Arguments which are macro have been replaced in the first stage.
if (ppToken->ival == 0)
ppToken->ival = parseContext.getCurrentLoc().line;
snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival);
UngetToken(PpAtomConstInt, ppToken);
return MacroExpandStarted;
@@ -1270,6 +1287,11 @@ MacroExpandResult TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, b
nestStack.push_back('}');
else if (nestStack.size() > 0 && token == nestStack.back())
nestStack.pop_back();
//Macro replacement list is expanded in the last stage.
if (atomStrings.getAtom(ppToken->name) == PpAtomLineMacro)
ppToken->ival = parseContext.getCurrentLoc().line;
in->args[arg]->putToken(token, ppToken);
tokenRecorded = true;
}
@@ -87,7 +87,8 @@ namespace glslang {
TPpContext::TPpContext(TParseContextBase& pc, const std::string& rootFileName, TShader::Includer& inclr) :
preamble(0), strings(0), previous_token('\n'), parseContext(pc), includer(inclr), inComment(false),
rootFileName(rootFileName),
currentSourceFile(rootFileName)
currentSourceFile(rootFileName),
disableEscapeSequences(false)
{
ifdepth = 0;
for (elsetracker = 0; elsetracker < maxIfNesting; elsetracker++)
@@ -105,13 +105,13 @@ public:
}
// Used for comparing macro definitions, so checks what is relevant for that.
bool operator==(const TPpToken& right)
bool operator==(const TPpToken& right) const
{
return space == right.space &&
ival == right.ival && dval == right.dval && i64val == right.i64val &&
strncmp(name, right.name, MaxTokenLength) == 0;
}
bool operator!=(const TPpToken& right) { return ! operator==(right); }
bool operator!=(const TPpToken& right) const { return ! operator==(right); }
TSourceLoc loc;
// True if a space (for white space or a removed comment) should also be
@@ -695,6 +695,7 @@ protected:
std::string currentSourceFile;
std::istringstream strtodStream;
bool disableEscapeSequences;
};
} // end namespace glslang
@@ -1026,12 +1026,80 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
case '\'':
return pp->characterLiteral(ppToken);
case '"':
// TODO: If this gets enhanced to handle escape sequences, or
// anything that is different than what #include needs, then
// #include needs to use scanHeaderName() for this.
// #include uses scanHeaderName() to ignore these escape sequences.
ch = getch();
while (ch != '"' && ch != '\n' && ch != EndOfInput) {
if (len < MaxTokenLength) {
if (ch == '\\' && !pp->disableEscapeSequences) {
int nextCh = getch();
switch (nextCh) {
case '\'': ch = 0x27; break;
case '"': ch = 0x22; break;
case '?': ch = 0x3f; break;
case '\\': ch = 0x5c; break;
case 'a': ch = 0x07; break;
case 'b': ch = 0x08; break;
case 'f': ch = 0x0c; break;
case 'n': ch = 0x0a; break;
case 'r': ch = 0x0d; break;
case 't': ch = 0x09; break;
case 'v': ch = 0x0b; break;
case 'x':
// Hex value, arbitrary number of characters. Terminated by the first
// non-hex digit
{
int numDigits = 0;
ch = 0;
while (true) {
nextCh = getch();
if (nextCh >= '0' && nextCh <= '9')
nextCh -= '0';
else if (nextCh >= 'A' && nextCh <= 'F')
nextCh -= 'A' - 10;
else if (nextCh >= 'a' && nextCh <= 'f')
nextCh -= 'a' - 10;
else {
ungetch();
break;
}
numDigits++;
ch = ch * 0x10 + nextCh;
}
if (numDigits == 0) {
pp->parseContext.ppError(ppToken->loc, "Expected hex value in escape sequence", "string", "");
}
break;
}
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
// Octal value, up to three octal digits
{
int numDigits = 1;
ch = nextCh - '0';
while (numDigits < 3) {
nextCh = getch();
if (nextCh >= '0' && nextCh <= '7')
nextCh -= '0';
else {
ungetch();
break;
}
numDigits++;
ch = ch * 8 + nextCh;
}
break;
}
default:
pp->parseContext.ppError(ppToken->loc, "Invalid escape sequence", "string", "");
break;
}
}
ppToken->name[len] = (char)ch;
len++;
ch = getch();
@@ -1120,10 +1188,12 @@ int TPpContext::tokenize(TPpToken& ppToken)
continue;
break;
case PpAtomConstString:
// HLSL allows string literals.
// GLSL allows string literals with GL_EXT_debug_printf.
if (ifdepth == 0 && parseContext.intermediate.getSource() != EShSourceHlsl) {
// HLSL allows string literals.
parseContext.ppError(ppToken.loc, "string literals not supported", "\"\"", "");
continue;
parseContext.requireExtensions(ppToken.loc, 1, &E_GL_EXT_debug_printf, "string literal");
if (!parseContext.extensionTurnedOn(E_GL_EXT_debug_printf))
continue;
}
break;
case '\'':
@@ -867,4 +867,4 @@ void PropagateNoContraction(const glslang::TIntermediate& intermediate)
}
};
#endif // GLSLANG_WEB
#endif // GLSLANG_WEB
@@ -33,7 +33,7 @@
// POSSIBILITY OF SUCH DAMAGE.
//
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
#include "../Include/Common.h"
#include "reflection.h"
@@ -77,10 +77,10 @@ namespace glslang {
// This is in the glslang namespace directly so it can be a friend of TReflection.
//
class TReflectionTraverser : public TLiveTraverser {
class TReflectionTraverser : public TIntermTraverser {
public:
TReflectionTraverser(const TIntermediate& i, TReflection& r) :
TLiveTraverser(i), reflection(r) { }
TIntermTraverser(), intermediate(i), reflection(r), updateStageMasks(true) { }
virtual bool visitBinary(TVisit, TIntermBinary* node);
virtual void visitSymbol(TIntermSymbol* base);
@@ -92,11 +92,28 @@ public:
if (processedDerefs.find(&base) == processedDerefs.end()) {
processedDerefs.insert(&base);
int blockIndex = -1;
int offset = -1;
TList<TIntermBinary*> derefs;
TString baseName = base.getName();
if (base.getType().getBasicType() == EbtBlock) {
offset = 0;
bool anonymous = IsAnonymous(baseName);
const TString& blockName = base.getType().getTypeName();
if (!anonymous)
baseName = blockName;
else
baseName = "";
blockIndex = addBlockName(blockName, base.getType(), intermediate.getBlockSize(base.getType()));
}
// Use a degenerate (empty) set of dereferences to immediately put as at the end of
// the dereference change expected by blowUpActiveAggregate.
TList<TIntermBinary*> derefs;
blowUpActiveAggregate(base.getType(), base.getName(), derefs, derefs.end(), -1, -1, 0, 0,
base.getQualifier().storage, true);
blowUpActiveAggregate(base.getType(), baseName, derefs, derefs.end(), offset, blockIndex, 0, -1, 0,
base.getQualifier().storage, updateStageMasks);
}
}
@@ -155,9 +172,9 @@ public:
void getOffsets(const TType& type, TVector<int>& offsets)
{
const TTypeList& memberList = *type.getStruct();
int memberSize = 0;
int offset = 0;
for (size_t m = 0; m < offsets.size(); ++m) {
// if the user supplied an offset, snap to it now
if (memberList[m].type->getQualifier().hasOffset())
@@ -233,7 +250,7 @@ public:
// A value of 0 for arraySize will mean to use the full array's size.
void blowUpActiveAggregate(const TType& baseType, const TString& baseName, const TList<TIntermBinary*>& derefs,
TList<TIntermBinary*>::const_iterator deref, int offset, int blockIndex, int arraySize,
int topLevelArrayStride, TStorageQualifier baseStorage, bool active)
int topLevelArraySize, int topLevelArrayStride, TStorageQualifier baseStorage, bool active)
{
// when strictArraySuffix is enabled, we closely follow the rules from ARB_program_interface_query.
// Broadly:
@@ -262,14 +279,15 @@ public:
// Visit all the indices of this array, and for each one add on the remaining dereferencing
for (int i = 0; i < std::max(visitNode->getLeft()->getType().getOuterArraySize(), 1); ++i) {
TString newBaseName = name;
if (strictArraySuffix && blockParent)
if (terminalType->getBasicType() == EbtBlock) {}
else if (strictArraySuffix && blockParent)
newBaseName.append(TString("[0]"));
else if (strictArraySuffix || baseType.getBasicType() != EbtBlock)
newBaseName.append(TString("[") + String(i) + "]");
TList<TIntermBinary*>::const_iterator nextDeref = deref;
++nextDeref;
blowUpActiveAggregate(*terminalType, newBaseName, derefs, nextDeref, offset, blockIndex, arraySize,
topLevelArrayStride, baseStorage, active);
topLevelArraySize, topLevelArrayStride, baseStorage, active);
if (offset >= 0)
offset += stride;
@@ -282,9 +300,10 @@ public:
int stride = getArrayStride(baseType, visitNode->getLeft()->getType());
index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
if (strictArraySuffix && blockParent) {
if (terminalType->getBasicType() == EbtBlock) {}
else if (strictArraySuffix && blockParent)
name.append(TString("[0]"));
} else if (strictArraySuffix || baseType.getBasicType() != EbtBlock) {
else if (strictArraySuffix || baseType.getBasicType() != EbtBlock) {
name.append(TString("[") + String(index) + "]");
if (offset >= 0)
@@ -294,7 +313,10 @@ public:
if (topLevelArrayStride == 0)
topLevelArrayStride = stride;
blockParent = false;
// expand top-level arrays in blocks with [0] suffix
if (topLevelArrayStride != 0 && visitNode->getLeft()->getType().isArray()) {
blockParent = false;
}
break;
}
case EOpIndexDirectStruct:
@@ -304,6 +326,12 @@ public:
if (name.size() > 0)
name.append(".");
name.append((*visitNode->getLeft()->getType().getStruct())[index].type->getFieldName());
// expand non top-level arrays with [x] suffix
if (visitNode->getLeft()->getType().getBasicType() != EbtBlock && terminalType->isArray())
{
blockParent = false;
}
break;
default:
break;
@@ -323,24 +351,27 @@ public:
if (offset >= 0)
stride = getArrayStride(baseType, *terminalType);
if (topLevelArrayStride == 0)
topLevelArrayStride = stride;
int arrayIterateSize = std::max(terminalType->getOuterArraySize(), 1);
// for top-level arrays in blocks, only expand [0] to avoid explosion of items
if (strictArraySuffix && blockParent)
if ((strictArraySuffix && blockParent) ||
((topLevelArraySize == arrayIterateSize) && (topLevelArrayStride == 0))) {
arrayIterateSize = 1;
}
if (topLevelArrayStride == 0)
topLevelArrayStride = stride;
for (int i = 0; i < arrayIterateSize; ++i) {
TString newBaseName = name;
newBaseName.append(TString("[") + String(i) + "]");
if (terminalType->getBasicType() != EbtBlock)
newBaseName.append(TString("[") + String(i) + "]");
TType derefType(*terminalType, 0);
if (offset >= 0)
offset = baseOffset + stride * i;
blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
topLevelArrayStride, baseStorage, active);
topLevelArraySize, topLevelArrayStride, baseStorage, active);
}
} else {
// Visit all members of this aggregate, and for each one,
@@ -369,8 +400,31 @@ public:
arrayStride = getArrayStride(baseType, derefType);
}
blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
arrayStride, baseStorage, active);
if (topLevelArraySize == -1 && arrayStride == 0 && blockParent)
topLevelArraySize = 1;
if (strictArraySuffix && blockParent) {
// if this member is an array, store the top-level array stride but start the explosion from
// the inner struct type.
if (derefType.isArray() && derefType.isStruct()) {
newBaseName.append("[0]");
auto dimSize = derefType.isUnsizedArray() ? 0 : derefType.getArraySizes()->getDimSize(0);
blowUpActiveAggregate(TType(derefType, 0), newBaseName, derefs, derefs.end(), memberOffsets[i],
blockIndex, 0, dimSize, arrayStride, terminalType->getQualifier().storage, false);
}
else if (derefType.isArray()) {
auto dimSize = derefType.isUnsizedArray() ? 0 : derefType.getArraySizes()->getDimSize(0);
blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), memberOffsets[i], blockIndex,
0, dimSize, 0, terminalType->getQualifier().storage, false);
}
else {
blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), memberOffsets[i], blockIndex,
0, 1, 0, terminalType->getQualifier().storage, false);
}
} else {
blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
topLevelArraySize, arrayStride, baseStorage, active);
}
}
}
@@ -406,6 +460,7 @@ public:
if ((reflection.options & EShReflectionSeparateBuffers) && terminalType->isAtomic())
reflection.atomicCounterUniformIndices.push_back(uniformIndex);
variables.back().topLevelArraySize = topLevelArraySize;
variables.back().topLevelArrayStride = topLevelArrayStride;
if ((reflection.options & EShReflectionAllBlockVariables) && active) {
@@ -537,65 +592,17 @@ public:
if (! anonymous)
baseName = blockName;
if (base->getType().isArray()) {
TType derefType(base->getType(), 0);
assert(! anonymous);
for (int e = 0; e < base->getType().getCumulativeArraySize(); ++e)
blockIndex = addBlockName(blockName + "[" + String(e) + "]", derefType,
intermediate.getBlockSize(base->getType()));
baseName.append(TString("[0]"));
} else
blockIndex = addBlockName(blockName, base->getType(), intermediate.getBlockSize(base->getType()));
blockIndex = addBlockName(blockName, base->getType(), intermediate.getBlockSize(base->getType()));
if (reflection.options & EShReflectionAllBlockVariables) {
// Use a degenerate (empty) set of dereferences to immediately put as at the end of
// the dereference change expected by blowUpActiveAggregate.
TList<TIntermBinary*> derefs;
// because we don't have any derefs, the first thing blowUpActiveAggregate will do is iterate over each
// member in the struct definition. This will lose any information about whether the parent was a buffer
// block. So if we're using strict array rules which don't expand the first child of a buffer block we
// instead iterate over the children here.
const bool strictArraySuffix = (reflection.options & EShReflectionStrictArraySuffix);
bool blockParent = (base->getType().getBasicType() == EbtBlock && base->getQualifier().storage == EvqBuffer);
if (strictArraySuffix && blockParent) {
TType structDerefType(base->getType(), 0);
const TType &structType = base->getType().isArray() ? structDerefType : base->getType();
const TTypeList& typeList = *structType.getStruct();
TVector<int> memberOffsets;
memberOffsets.resize(typeList.size());
getOffsets(structType, memberOffsets);
for (int i = 0; i < (int)typeList.size(); ++i) {
TType derefType(structType, i);
TString name = baseName;
if (name.size() > 0)
name.append(".");
name.append(typeList[i].type->getFieldName());
// if this member is an array, store the top-level array stride but start the explosion from
// the inner struct type.
if (derefType.isArray() && derefType.isStruct()) {
name.append("[0]");
blowUpActiveAggregate(TType(derefType, 0), name, derefs, derefs.end(), memberOffsets[i],
blockIndex, 0, getArrayStride(structType, derefType),
base->getQualifier().storage, false);
} else {
blowUpActiveAggregate(derefType, name, derefs, derefs.end(), memberOffsets[i], blockIndex,
0, 0, base->getQualifier().storage, false);
}
}
} else {
// otherwise - if we're not using strict array suffix rules, or this isn't a block so we are
// expanding root arrays anyway, just start the iteration from the base block type.
blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.end(), 0, blockIndex, 0, 0,
// otherwise - if we're not using strict array suffix rules, or this isn't a block so we are
// expanding root arrays anyway, just start the iteration from the base block type.
blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.end(), 0, blockIndex, 0, -1, 0,
base->getQualifier().storage, false);
}
}
}
@@ -626,30 +633,40 @@ public:
else
baseName = base->getName();
}
blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.begin(), offset, blockIndex, arraySize, 0,
blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.begin(), offset, blockIndex, arraySize, -1, 0,
base->getQualifier().storage, true);
}
int addBlockName(const TString& name, const TType& type, int size)
{
TReflection::TMapIndexToReflection& blocks = reflection.GetBlockMapForStorage(type.getQualifier().storage);
int blockIndex;
TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
if (reflection.nameToIndex.find(name.c_str()) == reflection.nameToIndex.end()) {
blockIndex = (int)blocks.size();
reflection.nameToIndex[name.c_str()] = blockIndex;
blocks.push_back(TObjectReflection(name.c_str(), type, -1, -1, size, -1));
blocks.back().numMembers = countAggregateMembers(type);
EShLanguageMask& stages = blocks.back().stages;
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
int blockIndex = 0;
if (type.isArray()) {
TType derefType(type, 0);
for (int e = 0; e < type.getOuterArraySize(); ++e) {
int memberBlockIndex = addBlockName(name + "[" + String(e) + "]", derefType, size);
if (e == 0)
blockIndex = memberBlockIndex;
}
} else {
blockIndex = it->second;
TReflection::TMapIndexToReflection& blocks = reflection.GetBlockMapForStorage(type.getQualifier().storage);
EShLanguageMask& stages = blocks[blockIndex].stages;
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
if (reflection.nameToIndex.find(name.c_str()) == reflection.nameToIndex.end()) {
blockIndex = (int)blocks.size();
reflection.nameToIndex[name.c_str()] = blockIndex;
blocks.push_back(TObjectReflection(name.c_str(), type, -1, -1, size, blockIndex));
blocks.back().numMembers = countAggregateMembers(type);
EShLanguageMask& stages = blocks.back().stages;
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
}
else {
blockIndex = it->second;
EShLanguageMask& stages = blocks[blockIndex].stages;
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
}
}
return blockIndex;
@@ -995,8 +1012,10 @@ public:
return type.isArray() ? type.getOuterArraySize() : 1;
}
const TIntermediate& intermediate;
TReflection& reflection;
std::set<const TIntermNode*> processedDerefs;
bool updateStageMasks;
protected:
TReflectionTraverser(TReflectionTraverser&);
@@ -1029,7 +1048,21 @@ bool TReflectionTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
// To reflect non-dereferenced objects.
void TReflectionTraverser::visitSymbol(TIntermSymbol* base)
{
if (base->getQualifier().storage == EvqUniform)
if (base->getQualifier().storage == EvqUniform) {
if (base->getBasicType() == EbtBlock) {
if (reflection.options & EShReflectionSharedStd140UBO) {
addUniform(*base);
}
} else {
addUniform(*base);
}
}
// #TODO add std140/layout active rules for ssbo, same with ubo.
// Storage buffer blocks will be collected and expanding in this part.
if((reflection.options & EShReflectionSharedStd140SSBO) &&
(base->getQualifier().storage == EvqBuffer && base->getBasicType() == EbtBlock &&
(base->getQualifier().layoutPacking == ElpStd140 || base->getQualifier().layoutPacking == ElpShared)))
addUniform(*base);
if ((intermediate.getStage() == reflection.firstStage && base->getQualifier().isPipeInput()) ||
@@ -1135,15 +1168,47 @@ bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate)
TReflectionTraverser it(intermediate, *this);
// put the entry point on the list of functions to process
it.pushFunction(intermediate.getEntryPointMangledName().c_str());
// process all the functions
while (! it.functions.empty()) {
TIntermNode* function = it.functions.back();
it.functions.pop_back();
function->traverse(&it);
for (auto& sequnence : intermediate.getTreeRoot()->getAsAggregate()->getSequence()) {
if (sequnence->getAsAggregate() != nullptr) {
if (sequnence->getAsAggregate()->getOp() == glslang::EOpLinkerObjects) {
it.updateStageMasks = false;
TIntermAggregate* linkerObjects = sequnence->getAsAggregate();
for (auto& sequnence : linkerObjects->getSequence()) {
auto pNode = sequnence->getAsSymbolNode();
if (pNode != nullptr) {
if ((pNode->getQualifier().storage == EvqUniform &&
(options & EShReflectionSharedStd140UBO)) ||
(pNode->getQualifier().storage == EvqBuffer &&
(options & EShReflectionSharedStd140SSBO))) {
// collect std140 and shared uniform block form AST
if ((pNode->getBasicType() == EbtBlock) &&
((pNode->getQualifier().layoutPacking == ElpStd140) ||
(pNode->getQualifier().layoutPacking == ElpShared))) {
pNode->traverse(&it);
}
}
else if ((options & EShReflectionAllIOVariables) &&
(pNode->getQualifier().isPipeInput() || pNode->getQualifier().isPipeOutput()))
{
pNode->traverse(&it);
}
}
}
} else {
// This traverser will travers all function in AST.
// If we want reflect uncalled function, we need set linke message EShMsgKeepUncalled.
// When EShMsgKeepUncalled been set to true, all function will be keep in AST, even it is a uncalled function.
// This will keep some uniform variables in reflection, if those uniform variables is used in these uncalled function.
//
// If we just want reflect only live node, we can use a default link message or set EShMsgKeepUncalled false.
// When linke message not been set EShMsgKeepUncalled, linker won't keep uncalled function in AST.
// So, travers all function node can equivalent to travers live function.
it.updateStageMasks = true;
sequnence->getAsAggregate()->traverse(&it);
}
}
}
it.updateStageMasks = true;
buildCounterIndices(intermediate);
buildUniformStageMask(intermediate);
@@ -1188,7 +1253,7 @@ void TReflection::dump()
for (int dim=0; dim<3; ++dim)
if (getLocalSize(dim) > 1)
printf("Local size %s: %d\n", axis[dim], getLocalSize(dim));
printf("Local size %s: %u\n", axis[dim], getLocalSize(dim));
printf("\n");
}
@@ -1201,4 +1266,4 @@ void TReflection::dump()
} // end namespace glslang
#endif // GLSLANG_WEB
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
@@ -33,7 +33,7 @@
// POSSIBILITY OF SUCH DAMAGE.
//
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
#ifndef _REFLECTION_INCLUDED
#define _REFLECTION_INCLUDED
@@ -220,4 +220,4 @@ protected:
#endif // _REFLECTION_INCLUDED
#endif // GLSLANG_WEB
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
@@ -141,6 +141,7 @@ const TBuiltInResource DefaultTBuiltInResource = {
/* .maxTaskWorkGroupSizeY_NV = */ 1,
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
/* .maxMeshViewCountNV = */ 4,
/* .maxDualSourceDrawBuffersEXT = */ 1,
/* .limits = */ {
/* .nonInductiveForLoops = */ 1,
@@ -176,7 +177,12 @@ extern "C" {
* If null, the compilation failed.
*/
EMSCRIPTEN_KEEPALIVE
void* convert_glsl_to_spirv(const char* glsl, int stage_int, bool gen_debug, uint32_t** spirv, size_t* spirv_len)
void* convert_glsl_to_spirv(const char* glsl,
int stage_int,
bool gen_debug,
glslang::EShTargetLanguageVersion spirv_version,
uint32_t** spirv,
size_t* spirv_len)
{
if (glsl == nullptr) {
fprintf(stderr, "Input pointer null\n");
@@ -194,6 +200,18 @@ void* convert_glsl_to_spirv(const char* glsl, int stage_int, bool gen_debug, uin
return nullptr;
}
EShLanguage stage = static_cast<EShLanguage>(stage_int);
switch (spirv_version) {
case glslang::EShTargetSpv_1_0:
case glslang::EShTargetSpv_1_1:
case glslang::EShTargetSpv_1_2:
case glslang::EShTargetSpv_1_3:
case glslang::EShTargetSpv_1_4:
case glslang::EShTargetSpv_1_5:
break;
default:
fprintf(stderr, "Invalid SPIR-V version number\n");
return nullptr;
}
if (!initialized) {
glslang::InitializeProcess();
@@ -203,8 +221,8 @@ void* convert_glsl_to_spirv(const char* glsl, int stage_int, bool gen_debug, uin
glslang::TShader shader(stage);
shader.setStrings(&glsl, 1);
shader.setEnvInput(glslang::EShSourceGlsl, stage, glslang::EShClientVulkan, 100);
shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1);
shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3);
shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0);
shader.setEnvTarget(glslang::EShTargetSpv, spirv_version);
if (!shader.parse(&DefaultTBuiltInResource, 100, true, EShMsgDefault)) {
fprintf(stderr, "Parse failed\n");
fprintf(stderr, "%s\n", shader.getInfoLog());
@@ -260,7 +278,7 @@ void main() { })";
uint32_t* output;
size_t output_len;
void* id = convert_glsl_to_spirv(input, 4, false, &output, &output_len);
void* id = convert_glsl_to_spirv(input, 4, false, glslang::EShTargetSpv_1_0, &output, &output_len);
assert(output != nullptr);
assert(output_len != 0);
destroy_output_buffer(id);
@@ -1,23 +1,34 @@
Module['compileGLSLZeroCopy'] = function(glsl, shader_stage, gen_debug) {
Module['compileGLSLZeroCopy'] = function(glsl, shader_stage, gen_debug, spirv_version) {
gen_debug = !!gen_debug;
var shader_stage_int;
if (shader_stage === 'vertex') {
shader_stage_int = 0;
} else if (shader_stage === 'fragment') {
shader_stage_int = 4;
} else if (shader_stage === 'compute') {
shader_stage_int = 5;
} else {
throw new Error("shader_stage must be 'vertex', 'fragment', or 'compute'");
var shader_stage_int; // EShLanguage
switch (shader_stage) {
case 'vertex': shader_stage_int = 0; break;
case 'fragment': shader_stage_int = 4; break;
case 'compute': shader_stage_int = 5; break;
default:
throw new Error("shader_stage must be 'vertex', 'fragment', or 'compute'.");
}
spirv_version = spirv_version || '1.0';
var spirv_version_int; // EShTargetLanguageVersion
switch (spirv_version) {
case '1.0': spirv_version_int = (1 << 16) | (0 << 8); break;
case '1.1': spirv_version_int = (1 << 16) | (1 << 8); break;
case '1.2': spirv_version_int = (1 << 16) | (2 << 8); break;
case '1.3': spirv_version_int = (1 << 16) | (3 << 8); break;
case '1.4': spirv_version_int = (1 << 16) | (4 << 8); break;
case '1.5': spirv_version_int = (1 << 16) | (5 << 8); break;
default:
throw new Error("spirv_version must be '1.0' ~ '1.5'.");
}
var p_output = Module['_malloc'](4);
var p_output_len = Module['_malloc'](4);
var id = ccall('convert_glsl_to_spirv',
'number',
['string', 'number', 'boolean', 'number', 'number'],
[glsl, shader_stage_int, gen_debug, p_output, p_output_len]);
['string', 'number', 'boolean', 'number', 'number', 'number'],
[glsl, shader_stage_int, gen_debug, spirv_version_int, p_output, p_output_len]);
var output = getValue(p_output, 'i32');
var output_len = getValue(p_output_len, 'i32');
Module['_free'](p_output);
@@ -37,8 +48,8 @@ Module['compileGLSLZeroCopy'] = function(glsl, shader_stage, gen_debug) {
return ret;
};
Module['compileGLSL'] = function(glsl, shader_stage, gen_debug) {
var compiled = Module['compileGLSLZeroCopy'](glsl, shader_stage, gen_debug);
Module['compileGLSL'] = function(glsl, shader_stage, gen_debug, spirv_version) {
var compiled = Module['compileGLSLZeroCopy'](glsl, shader_stage, gen_debug, spirv_version);
var ret = compiled['data'].slice()
compiled['free']();
return ret;
+178 -132
View File
@@ -44,16 +44,25 @@
#include <vector>
#ifdef _WIN32
#define C_DECL __cdecl
//#ifdef SH_EXPORTING
// #define SH_IMPORT_EXPORT __declspec(dllexport)
//#else
// #define SH_IMPORT_EXPORT __declspec(dllimport)
//#endif
#define SH_IMPORT_EXPORT
#define C_DECL __cdecl
#else
#define SH_IMPORT_EXPORT
#define C_DECL
#define C_DECL
#endif
#ifdef GLSLANG_IS_SHARED_LIBRARY
#ifdef _WIN32
#ifdef GLSLANG_EXPORTING
#define GLSLANG_EXPORT __declspec(dllexport)
#else
#define GLSLANG_EXPORT __declspec(dllimport)
#endif
#elif __GNUC__ >= 4
#define GLSLANG_EXPORT __attribute__((visibility("default")))
#endif
#endif // GLSLANG_IS_SHARED_LIBRARY
#ifndef GLSLANG_EXPORT
#define GLSLANG_EXPORT
#endif
//
@@ -65,22 +74,17 @@
extern "C" {
#endif
// 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
//
// Call before doing any other compiler/linker operations.
//
// (Call once per process, not once per thread.)
//
SH_IMPORT_EXPORT int ShInitialize();
GLSLANG_EXPORT int ShInitialize();
//
// Call this at process shutdown to clean up memory.
//
SH_IMPORT_EXPORT int ShFinalize();
GLSLANG_EXPORT int ShFinalize();
//
// Types of languages the compiler can consume.
@@ -92,32 +96,45 @@ typedef enum {
EShLangGeometry,
EShLangFragment,
EShLangCompute,
EShLangRayGenNV,
EShLangIntersectNV,
EShLangAnyHitNV,
EShLangClosestHitNV,
EShLangMissNV,
EShLangCallableNV,
EShLangRayGen,
EShLangRayGenNV = EShLangRayGen,
EShLangIntersect,
EShLangIntersectNV = EShLangIntersect,
EShLangAnyHit,
EShLangAnyHitNV = EShLangAnyHit,
EShLangClosestHit,
EShLangClosestHitNV = EShLangClosestHit,
EShLangMiss,
EShLangMissNV = EShLangMiss,
EShLangCallable,
EShLangCallableNV = EShLangCallable,
EShLangTaskNV,
EShLangMeshNV,
EShLangCount,
LAST_ELEMENT_MARKER(EShLangCount),
} EShLanguage; // would be better as stage, but this is ancient now
typedef enum {
typedef enum : unsigned {
EShLangVertexMask = (1 << EShLangVertex),
EShLangTessControlMask = (1 << EShLangTessControl),
EShLangTessEvaluationMask = (1 << EShLangTessEvaluation),
EShLangGeometryMask = (1 << EShLangGeometry),
EShLangFragmentMask = (1 << EShLangFragment),
EShLangComputeMask = (1 << EShLangCompute),
EShLangRayGenNVMask = (1 << EShLangRayGenNV),
EShLangIntersectNVMask = (1 << EShLangIntersectNV),
EShLangAnyHitNVMask = (1 << EShLangAnyHitNV),
EShLangClosestHitNVMask = (1 << EShLangClosestHitNV),
EShLangMissNVMask = (1 << EShLangMissNV),
EShLangCallableNVMask = (1 << EShLangCallableNV),
EShLangRayGenMask = (1 << EShLangRayGen),
EShLangRayGenNVMask = EShLangRayGenMask,
EShLangIntersectMask = (1 << EShLangIntersect),
EShLangIntersectNVMask = EShLangIntersectMask,
EShLangAnyHitMask = (1 << EShLangAnyHit),
EShLangAnyHitNVMask = EShLangAnyHitMask,
EShLangClosestHitMask = (1 << EShLangClosestHit),
EShLangClosestHitNVMask = EShLangClosestHitMask,
EShLangMissMask = (1 << EShLangMiss),
EShLangMissNVMask = EShLangMissMask,
EShLangCallableMask = (1 << EShLangCallable),
EShLangCallableNVMask = EShLangCallableMask,
EShLangTaskNVMask = (1 << EShLangTaskNV),
EShLangMeshNVMask = (1 << EShLangMeshNV),
LAST_ELEMENT_MARKER(EShLanguageMaskCount),
} EShLanguageMask;
namespace glslang {
@@ -128,24 +145,29 @@ typedef enum {
EShSourceNone,
EShSourceGlsl, // GLSL, includes ESSL (OpenGL ES GLSL)
EShSourceHlsl, // HLSL
LAST_ELEMENT_MARKER(EShSourceCount),
} EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead
typedef enum {
EShClientNone, // use when there is no client, e.g. for validation
EShClientVulkan,
EShClientOpenGL,
LAST_ELEMENT_MARKER(EShClientCount),
} EShClient;
typedef enum {
EShTargetNone,
EShTargetSpv, // SPIR-V (preferred spelling)
EshTargetSpv = EShTargetSpv, // legacy spelling
LAST_ELEMENT_MARKER(EShTargetCount),
} EShTargetLanguage;
typedef enum {
EShTargetVulkan_1_0 = (1 << 22), // Vulkan 1.0
EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), // Vulkan 1.1
EShTargetVulkan_1_2 = (1 << 22) | (2 << 12), // Vulkan 1.2
EShTargetOpenGL_450 = 450, // OpenGL
LAST_ELEMENT_MARKER(EShTargetClientVersionCount),
} EShTargetClientVersion;
typedef EShTargetClientVersion EshTargetClientVersion;
@@ -157,6 +179,7 @@ typedef enum {
EShTargetSpv_1_3 = (1 << 16) | (3 << 8), // SPIR-V 1.3
EShTargetSpv_1_4 = (1 << 16) | (4 << 8), // SPIR-V 1.4
EShTargetSpv_1_5 = (1 << 16) | (5 << 8), // SPIR-V 1.5
LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount),
} EShTargetLanguageVersion;
struct TInputLanguage {
@@ -186,7 +209,7 @@ struct TEnvironment {
TTarget target; // what to generate
};
const char* StageName(EShLanguage);
GLSLANG_EXPORT const char* StageName(EShLanguage);
} // end namespace glslang
@@ -206,6 +229,7 @@ typedef enum {
EShOptNone,
EShOptSimple, // Optimizations that can be done quickly
EShOptFull, // Optimizations that will take more time
LAST_ELEMENT_MARKER(EshOptLevelCount),
} EShOptimizationLevel;
//
@@ -214,12 +238,13 @@ typedef enum {
typedef enum {
EShTexSampTransKeep, // keep textures and samplers as is (default)
EShTexSampTransUpgradeTextureRemoveSampler, // change texture w/o embeded sampler into sampled texture and throw away all samplers
LAST_ELEMENT_MARKER(EShTexSampTransCount),
} EShTextureSamplerTransformMode;
//
// Message choices for what errors and warnings are given.
//
enum EShMessages {
enum EShMessages : unsigned {
EShMsgDefault = 0, // default is to give all required errors and extra warnings
EShMsgRelaxedErrors = (1 << 0), // be liberal in accepting input
EShMsgSuppressWarnings = (1 << 1), // suppress all warnings, except those required by the specification
@@ -234,21 +259,26 @@ enum EShMessages {
EShMsgDebugInfo = (1 << 10), // save debug information
EShMsgHlslEnable16BitTypes = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL
EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages
EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (right now only for samplers)
EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (for samplers and semantics)
EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table
LAST_ELEMENT_MARKER(EShMsgCount),
};
//
// Options for building reflection
//
typedef enum {
EShReflectionDefault = 0, // default is original behaviour before options were added
EShReflectionStrictArraySuffix = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes
EShReflectionBasicArraySuffix = (1 << 1), // arrays of basic types will be appended with [0] as in GL reflection
EShReflectionIntermediateIO = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader
EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately
EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive
EShReflectionUnwrapIOBlocks = (1 << 5), // unwrap input/output blocks the same as with uniform blocks
EShReflectionDefault = 0, // default is original behaviour before options were added
EShReflectionStrictArraySuffix = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes
EShReflectionBasicArraySuffix = (1 << 1), // arrays of basic types will be appended with [0] as in GL reflection
EShReflectionIntermediateIO = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader
EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately
EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive
EShReflectionUnwrapIOBlocks = (1 << 5), // unwrap input/output blocks the same as with uniform blocks
EShReflectionAllIOVariables = (1 << 6), // reflect all input/output variables, even if they are inactive
EShReflectionSharedStd140SSBO = (1 << 7), // Apply std140/shared rules for ubo to ssbo
EShReflectionSharedStd140UBO = (1 << 8), // Apply std140/shared rules for ubo to ssbo
LAST_ELEMENT_MARKER(EShReflectionCount),
} EShReflectionOptions;
//
@@ -280,10 +310,10 @@ typedef void* ShHandle;
// Driver calls these to create and destroy compiler/linker
// objects.
//
SH_IMPORT_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); // one per shader
SH_IMPORT_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); // one per shader pair
SH_IMPORT_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object)
SH_IMPORT_EXPORT void ShDestruct(ShHandle);
GLSLANG_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); // one per shader
GLSLANG_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); // one per shader pair
GLSLANG_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object)
GLSLANG_EXPORT void ShDestruct(ShHandle);
//
// The return value of ShCompile is boolean, non-zero indicating
@@ -292,7 +322,7 @@ SH_IMPORT_EXPORT void ShDestruct(ShHandle);
// The info-log should be written by ShCompile into
// ShHandle, so it can answer future queries.
//
SH_IMPORT_EXPORT int ShCompile(
GLSLANG_EXPORT int ShCompile(
const ShHandle,
const char* const shaderStrings[],
const int numStrings,
@@ -305,7 +335,7 @@ SH_IMPORT_EXPORT int ShCompile(
EShMessages messages = EShMsgDefault // warnings and errors
);
SH_IMPORT_EXPORT int ShLinkExt(
GLSLANG_EXPORT int ShLinkExt(
const ShHandle, // linker object
const ShHandle h[], // compiler objects to link together
const int numHandles);
@@ -314,26 +344,26 @@ SH_IMPORT_EXPORT int ShLinkExt(
// ShSetEncrpytionMethod is a place-holder for specifying
// how source code is encrypted.
//
SH_IMPORT_EXPORT void ShSetEncryptionMethod(ShHandle);
GLSLANG_EXPORT void ShSetEncryptionMethod(ShHandle);
//
// All the following return 0 if the information is not
// available in the object passed down, or the object is bad.
//
SH_IMPORT_EXPORT const char* ShGetInfoLog(const ShHandle);
SH_IMPORT_EXPORT const void* ShGetExecutable(const ShHandle);
SH_IMPORT_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing
SH_IMPORT_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings
GLSLANG_EXPORT const char* ShGetInfoLog(const ShHandle);
GLSLANG_EXPORT const void* ShGetExecutable(const ShHandle);
GLSLANG_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing
GLSLANG_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings
//
// Tell the linker to never assign a vertex attribute to this list of physical attributes
//
SH_IMPORT_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count);
GLSLANG_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count);
//
// Returns the location ID of the named uniform.
// Returns -1 if error.
//
SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name);
GLSLANG_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name);
#ifdef __cplusplus
} // end extern "C"
@@ -364,19 +394,27 @@ class TInfoSink;
namespace glslang {
const char* GetEsslVersionString();
const char* GetGlslVersionString();
int GetKhronosToolId();
struct Version {
int major;
int minor;
int patch;
const char* flavor;
};
GLSLANG_EXPORT Version GetVersion();
GLSLANG_EXPORT const char* GetEsslVersionString();
GLSLANG_EXPORT const char* GetGlslVersionString();
GLSLANG_EXPORT int GetKhronosToolId();
class TIntermediate;
class TProgram;
class TPoolAllocator;
// Call this exactly once per process before using anything else
bool InitializeProcess();
GLSLANG_EXPORT bool InitializeProcess();
// Call once per process to tear down everything
void FinalizeProcess();
GLSLANG_EXPORT void FinalizeProcess();
// Resource type for IO resolver
enum TResourceType {
@@ -389,11 +427,14 @@ enum TResourceType {
EResCount
};
// Make one TShader per shader that you will link into a program. Then
// - provide the shader through setStrings() or setStringsWithLengths()
// - optionally call setEnv*(), see below for more detail
// - optionally use setPreamble() to set a special shader string that will be
// processed before all others but won't affect the validity of #version
// - optionally call addProcesses() for each setting/transform,
// see comment for class TProcesses
// - call parse(): source language and target environment must be selected
// either by correct setting of EShMessages sent to parse(), or by
// explicitly calling setEnv*()
@@ -406,40 +447,41 @@ enum TResourceType {
//
class TShader {
public:
explicit TShader(EShLanguage);
virtual ~TShader();
void setStrings(const char* const* s, int n);
void setStringsWithLengths(const char* const* s, const int* l, int n);
void setStringsWithLengthsAndNames(
GLSLANG_EXPORT explicit TShader(EShLanguage);
GLSLANG_EXPORT virtual ~TShader();
GLSLANG_EXPORT void setStrings(const char* const* s, int n);
GLSLANG_EXPORT void setStringsWithLengths(
const char* const* s, const int* l, int n);
GLSLANG_EXPORT void setStringsWithLengthsAndNames(
const char* const* s, const int* l, const char* const* names, int n);
void setPreamble(const char* s) { preamble = s; }
void setEntryPoint(const char* entryPoint);
void setSourceEntryPoint(const char* sourceEntryPointName);
void addProcesses(const std::vector<std::string>&);
GLSLANG_EXPORT void setEntryPoint(const char* entryPoint);
GLSLANG_EXPORT void setSourceEntryPoint(const char* sourceEntryPointName);
GLSLANG_EXPORT void addProcesses(const std::vector<std::string>&);
// IO resolver binding data: see comments in ShaderLang.cpp
void setShiftBinding(TResourceType res, unsigned int base);
void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding
void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set);
void setResourceSetBinding(const std::vector<std::string>& base);
void setAutoMapBindings(bool map);
void setAutoMapLocations(bool map);
void addUniformLocationOverride(const char* name, int loc);
void setUniformLocationBase(int base);
void setInvertY(bool invert);
GLSLANG_EXPORT void setShiftBinding(TResourceType res, unsigned int base);
GLSLANG_EXPORT void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding
GLSLANG_EXPORT void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding
GLSLANG_EXPORT void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set);
GLSLANG_EXPORT void setResourceSetBinding(const std::vector<std::string>& base);
GLSLANG_EXPORT void setAutoMapBindings(bool map);
GLSLANG_EXPORT void setAutoMapLocations(bool map);
GLSLANG_EXPORT void addUniformLocationOverride(const char* name, int loc);
GLSLANG_EXPORT void setUniformLocationBase(int base);
GLSLANG_EXPORT void setInvertY(bool invert);
#ifdef ENABLE_HLSL
void setHlslIoMapping(bool hlslIoMap);
void setFlattenUniformArrays(bool flatten);
GLSLANG_EXPORT void setHlslIoMapping(bool hlslIoMap);
GLSLANG_EXPORT void setFlattenUniformArrays(bool flatten);
#endif
void setNoStorageFormat(bool useUnknownFormat);
void setNanMinMaxClamp(bool nanMinMaxClamp);
void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
GLSLANG_EXPORT void setNoStorageFormat(bool useUnknownFormat);
GLSLANG_EXPORT void setNanMinMaxClamp(bool nanMinMaxClamp);
GLSLANG_EXPORT void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
// For setting up the environment (cleared to nothingness in the constructor).
// These must be called so that parsing is done for the right source language and
@@ -579,8 +621,10 @@ public:
virtual void releaseInclude(IncludeResult*) override { }
};
bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
bool forwardCompatible, EShMessages, Includer&);
GLSLANG_EXPORT bool parse(
const TBuiltInResource*, int defaultVersion, EProfile defaultProfile,
bool forceDefaultVersionAndProfile, bool forwardCompatible,
EShMessages, Includer&);
bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
bool forwardCompatible, EShMessages messages)
@@ -603,13 +647,14 @@ public:
// NOTE: Doing just preprocessing to obtain a correct preprocessed shader string
// is not an officially supported or fully working path.
bool preprocess(const TBuiltInResource* builtInResources,
int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
bool forwardCompatible, EShMessages message, std::string* outputString,
Includer& includer);
GLSLANG_EXPORT bool preprocess(
const TBuiltInResource* builtInResources, int defaultVersion,
EProfile defaultProfile, bool forceDefaultVersionAndProfile,
bool forwardCompatible, EShMessages message, std::string* outputString,
Includer& includer);
const char* getInfoLog();
const char* getInfoDebugLog();
GLSLANG_EXPORT const char* getInfoLog();
GLSLANG_EXPORT const char* getInfoDebugLog();
EShLanguage getStage() const { return stage; }
TIntermediate* getIntermediate() const { return intermediate; }
@@ -628,11 +673,11 @@ protected:
// stringNames is the optional names for all the strings. If stringNames
// is null, then none of the strings has name. If a certain element in
// stringNames is null, then the corresponding string does not have name.
const char* const* strings;
const char* const* strings; // explicit code to compile, see previous comment
const int* lengths;
const char* const* stringNames;
const char* preamble;
int numStrings;
int numStrings; // size of the above arrays
const char* preamble; // string of implicit code to compile before the explicitly provided code
// a function in the source string can be renamed FROM this TO the name given in setEntryPoint.
std::string sourceEntryPointName;
@@ -645,7 +690,7 @@ private:
TShader& operator=(TShader&);
};
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
//
// A reflection database and its interface, consistent with the OpenGL API reflection queries.
@@ -654,11 +699,11 @@ private:
// Data needed for just a single object at the granularity exchanged by the reflection API
class TObjectReflection {
public:
TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex);
GLSLANG_EXPORT TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex);
const TType* getType() const { return type; }
int getBinding() const;
void dump() const;
GLSLANG_EXPORT const TType* getType() const { return type; }
GLSLANG_EXPORT int getBinding() const;
GLSLANG_EXPORT void dump() const;
static TObjectReflection badReflection() { return TObjectReflection(); }
std::string name;
@@ -669,6 +714,7 @@ public:
int counterIndex;
int numMembers;
int arrayStride; // stride of an array variable
int topLevelArraySize; // size of the top-level variable in a storage buffer member
int topLevelArrayStride; // stride of the top-level variable in a storage buffer member
EShLanguageMask stages;
@@ -762,7 +808,7 @@ public:
virtual void addStage(EShLanguage stage) = 0;
};
#endif // GLSLANG_WEB
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
// Make one TProgram per set of shaders that will get linked together. Add all
// the shaders that are to be linked together. After calling shader.parse()
@@ -772,40 +818,40 @@ public:
//
class TProgram {
public:
TProgram();
virtual ~TProgram();
GLSLANG_EXPORT TProgram();
GLSLANG_EXPORT virtual ~TProgram();
void addShader(TShader* shader) { stages[shader->stage].push_back(shader); }
std::list<TShader*>& getShaders(EShLanguage stage) { return stages[stage]; }
// Link Validation interface
bool link(EShMessages);
const char* getInfoLog();
const char* getInfoDebugLog();
GLSLANG_EXPORT bool link(EShMessages);
GLSLANG_EXPORT const char* getInfoLog();
GLSLANG_EXPORT const char* getInfoDebugLog();
TIntermediate* getIntermediate(EShLanguage stage) const { return intermediate[stage]; }
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
// Reflection Interface
// call first, to do liveness analysis, index mapping, etc.; returns false on failure
bool buildReflection(int opts = EShReflectionDefault);
unsigned getLocalSize(int dim) const; // return dim'th local size
int getReflectionIndex(const char *name) const;
int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const;
int getNumUniformVariables() const;
const TObjectReflection& getUniform(int index) const;
int getNumUniformBlocks() const;
const TObjectReflection& getUniformBlock(int index) const;
int getNumPipeInputs() const;
const TObjectReflection& getPipeInput(int index) const;
int getNumPipeOutputs() const;
const TObjectReflection& getPipeOutput(int index) const;
int getNumBufferVariables() const;
const TObjectReflection& getBufferVariable(int index) const;
int getNumBufferBlocks() const;
const TObjectReflection& getBufferBlock(int index) const;
int getNumAtomicCounters() const;
const TObjectReflection& getAtomicCounter(int index) const;
GLSLANG_EXPORT bool buildReflection(int opts = EShReflectionDefault);
GLSLANG_EXPORT unsigned getLocalSize(int dim) const; // return dim'th local size
GLSLANG_EXPORT int getReflectionIndex(const char *name) const;
GLSLANG_EXPORT int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const;
GLSLANG_EXPORT int getNumUniformVariables() const;
GLSLANG_EXPORT const TObjectReflection& getUniform(int index) const;
GLSLANG_EXPORT int getNumUniformBlocks() const;
GLSLANG_EXPORT const TObjectReflection& getUniformBlock(int index) const;
GLSLANG_EXPORT int getNumPipeInputs() const;
GLSLANG_EXPORT const TObjectReflection& getPipeInput(int index) const;
GLSLANG_EXPORT int getNumPipeOutputs() const;
GLSLANG_EXPORT const TObjectReflection& getPipeOutput(int index) const;
GLSLANG_EXPORT int getNumBufferVariables() const;
GLSLANG_EXPORT const TObjectReflection& getBufferVariable(int index) const;
GLSLANG_EXPORT int getNumBufferBlocks() const;
GLSLANG_EXPORT const TObjectReflection& getBufferBlock(int index) const;
GLSLANG_EXPORT int getNumAtomicCounters() const;
GLSLANG_EXPORT const TObjectReflection& getAtomicCounter(int index) const;
// Legacy Reflection Interface - expressed in terms of above interface
@@ -872,22 +918,22 @@ public:
// returns a TType*
const TType *getAttributeTType(int index) const { return getPipeInput(index).getType(); }
void dumpReflection();
GLSLANG_EXPORT void dumpReflection();
// I/O mapping: apply base offsets and map live unbound variables
// If resolver is not provided it uses the previous approach
// and respects auto assignment and offsets.
bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr);
#endif
GLSLANG_EXPORT bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr);
#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
protected:
bool linkStage(EShLanguage, EShMessages);
GLSLANG_EXPORT bool linkStage(EShLanguage, EShMessages);
TPoolAllocator* pool;
std::list<TShader*> stages[EShLangCount];
TIntermediate* intermediate[EShLangCount];
bool newedIntermediate[EShLangCount]; // track which intermediate were "new" versus reusing a singleton unit in a stage
TInfoSink* infoSink;
#ifndef GLSLANG_WEB
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
TReflection* reflection;
#endif
bool linked;
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Khronos Group Inc.
//
// Copyright (C) 2018 The Khronos Group Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -14,7 +14,7 @@
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// Neither the name of The Khronos Group Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
@@ -30,6 +30,33 @@
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#include "pch.h"
#ifndef GLSLANG_BUILD_INFO
#define GLSLANG_BUILD_INFO
#define GLSLANG_VERSION_MAJOR 11
#define GLSLANG_VERSION_MINOR 0
#define GLSLANG_VERSION_PATCH 0
#define GLSLANG_VERSION_FLAVOR ""
#define GLSLANG_VERSION_GREATER_THAN(major, minor, patch) \
(((major) > GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \
(((minor) > GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \
((patch) > GLSLANG_VERSION_PATCH)))))
#define GLSLANG_VERSION_GREATER_OR_EQUAL_TO(major, minor, patch) \
(((major) > GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \
(((minor) > GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \
((patch) >= GLSLANG_VERSION_PATCH)))))
#define GLSLANG_VERSION_LESS_THAN(major, minor, patch) \
(((major) < GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \
(((minor) < GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \
((patch) < GLSLANG_VERSION_PATCH)))))
#define GLSLANG_VERSION_LESS_OR_EQUAL_TO(major, minor, patch) \
(((major) < GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \
(((minor) < GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \
((patch) <= GLSLANG_VERSION_PATCH)))))
#endif // GLSLANG_BUILD_INFO
+1
View File
@@ -118,6 +118,7 @@ static const TBuiltInResource defaultTBuiltInResource = {
/* .maxTaskWorkGroupSizeY_NV = */ 1,
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
/* .maxMeshViewCountNV = */ 4,
/* .maxDualSourceDrawBuffersEXT = */ 1,
/* .limits = */ {
/* .nonInductiveForLoops = */ 1,
/* .whileLoops = */ 1,