mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
Update glslang
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Executable → Regular
+711
-274
File diff suppressed because it is too large
Load Diff
Executable → Regular
@@ -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_
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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'");
|
||||
|
||||
@@ -125,6 +125,7 @@ enum OperandClass {
|
||||
OperandVariableLiteralId,
|
||||
OperandLiteralNumber,
|
||||
OperandLiteralString,
|
||||
OperandVariableLiteralStrings,
|
||||
OperandSource,
|
||||
OperandExecutionModel,
|
||||
OperandAddressing,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Executable → Regular
+24
-3
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
Executable → Regular
+214
-185
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
+31
-4
@@ -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
|
||||
@@ -118,6 +118,7 @@ static const TBuiltInResource defaultTBuiltInResource = {
|
||||
/* .maxTaskWorkGroupSizeY_NV = */ 1,
|
||||
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
|
||||
/* .maxMeshViewCountNV = */ 4,
|
||||
/* .maxDualSourceDrawBuffersEXT = */ 1,
|
||||
/* .limits = */ {
|
||||
/* .nonInductiveForLoops = */ 1,
|
||||
/* .whileLoops = */ 1,
|
||||
|
||||
Reference in New Issue
Block a user