TOOLS: updated glslang

master
Martin Gerhardy 2022-01-05 12:29:03 +01:00
parent 21e8219853
commit e351951b16
35 changed files with 538 additions and 213 deletions

View File

@ -169,6 +169,7 @@ update-glslang:
cp $(UPDATEDIR)/glslang.sync/gen_extension_headers.py tools/glslang/
cp $(UPDATEDIR)/glslang.sync/*.cmake tools/glslang/
cp $(UPDATEDIR)/glslang.sync/README* tools/glslang/
dos2unix tools/glslang/SPIRV/spirv.hpp
update-simplecpp:
$(call UPDATE_GIT,simplecpp,https://github.com/danmar/simplecpp.git)

View File

@ -19,8 +19,8 @@ See issue #1964.
If people are only using this location to get spirv.hpp, I recommend they get that from [SPIRV-Headers](https://github.com/KhronosGroup/SPIRV-Headers) instead.
[![Build Status](https://travis-ci.org/KhronosGroup/glslang.svg?branch=master)](https://travis-ci.org/KhronosGroup/glslang)
[![Build status](https://ci.appveyor.com/api/projects/status/q6fi9cb0qnhkla68/branch/master?svg=true)](https://ci.appveyor.com/project/Khronoswebmaster/glslang/branch/master)
[![appveyor status](https://ci.appveyor.com/api/projects/status/q6fi9cb0qnhkla68/branch/master?svg=true)](https://ci.appveyor.com/project/Khronoswebmaster/glslang/branch/master)
![Continuous Deployment](https://github.com/KhronosGroup/glslang/actions/workflows/continuous_deployment.yml/badge.svg)
# Glslang Components and Status

View File

@ -1256,8 +1256,10 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T
if (type.getBasicType() == glslang::EbtRayQuery)
return spv::StorageClassPrivate;
#ifndef GLSLANG_WEB
if (type.getQualifier().isSpirvByReference())
return spv::StorageClassFunction;
if (type.getQualifier().isSpirvByReference()) {
if (type.getQualifier().isParamInput() || type.getQualifier().isParamOutput())
return spv::StorageClassFunction;
}
#endif
if (type.getQualifier().isPipeInput())
return spv::StorageClassInput;
@ -1662,9 +1664,22 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
case EShLangCompute:
builder.addCapability(spv::CapabilityShader);
builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0),
glslangIntermediate->getLocalSize(1),
glslangIntermediate->getLocalSize(2));
if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) {
std::vector<spv::Id> dimConstId;
for (int dim = 0; dim < 3; ++dim) {
bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet);
dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst));
if (specConst) {
builder.addDecoration(dimConstId.back(), spv::DecorationSpecId,
glslangIntermediate->getLocalSizeSpecId(dim));
}
}
builder.addExecutionModeId(shaderEntry, spv::ExecutionModeLocalSizeId, dimConstId);
} else {
builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0),
glslangIntermediate->getLocalSize(1),
glslangIntermediate->getLocalSize(2));
}
if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupQuads) {
builder.addCapability(spv::CapabilityComputeDerivativeGroupQuadsNV);
builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupQuadsNV);
@ -1768,9 +1783,22 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
case EShLangMeshNV:
builder.addCapability(spv::CapabilityMeshShadingNV);
builder.addExtension(spv::E_SPV_NV_mesh_shader);
builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0),
glslangIntermediate->getLocalSize(1),
glslangIntermediate->getLocalSize(2));
if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) {
std::vector<spv::Id> dimConstId;
for (int dim = 0; dim < 3; ++dim) {
bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet);
dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst));
if (specConst) {
builder.addDecoration(dimConstId.back(), spv::DecorationSpecId,
glslangIntermediate->getLocalSizeSpecId(dim));
}
}
builder.addExecutionModeId(shaderEntry, spv::ExecutionModeLocalSizeId, dimConstId);
} else {
builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0),
glslangIntermediate->getLocalSize(1),
glslangIntermediate->getLocalSize(2));
}
if (glslangIntermediate->getStage() == EShLangMeshNV) {
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices,
glslangIntermediate->getVertices());
@ -3777,7 +3805,16 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
switch (node->getFlowOp()) {
case glslang::EOpKill:
builder.makeStatementTerminator(spv::OpKill, "post-discard");
if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) {
if (glslangIntermediate->getSource() == glslang::EShSourceHlsl) {
builder.addCapability(spv::CapabilityDemoteToHelperInvocation);
builder.createNoResultOp(spv::OpDemoteToHelperInvocationEXT);
} else {
builder.makeStatementTerminator(spv::OpTerminateInvocation, "post-terminate-invocation");
}
} else {
builder.makeStatementTerminator(spv::OpKill, "post-discard");
}
break;
case glslang::EOpTerminateInvocation:
builder.addExtension(spv::E_SPV_KHR_terminate_invocation);
@ -4148,23 +4185,23 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
const auto& spirvType = type.getSpirvType();
const auto& spirvInst = spirvType.spirvInst;
std::vector<spv::Id> operands;
std::vector<spv::IdImmediate> operands;
for (const auto& typeParam : spirvType.typeParams) {
// Constant expression
if (typeParam.constant->isLiteral()) {
if (typeParam.constant->getBasicType() == glslang::EbtFloat) {
float floatValue = static_cast<float>(typeParam.constant->getConstArray()[0].getDConst());
unsigned literal = *reinterpret_cast<unsigned*>(&floatValue);
operands.push_back(literal);
operands.push_back({false, literal});
} else if (typeParam.constant->getBasicType() == glslang::EbtInt) {
unsigned literal = typeParam.constant->getConstArray()[0].getIConst();
operands.push_back(literal);
operands.push_back({false, literal});
} else if (typeParam.constant->getBasicType() == glslang::EbtUint) {
unsigned literal = typeParam.constant->getConstArray()[0].getUConst();
operands.push_back(literal);
operands.push_back({false, literal});
} else if (typeParam.constant->getBasicType() == glslang::EbtBool) {
unsigned literal = typeParam.constant->getConstArray()[0].getBConst();
operands.push_back(literal);
operands.push_back({false, literal});
} else if (typeParam.constant->getBasicType() == glslang::EbtString) {
auto str = typeParam.constant->getConstArray()[0].getSConst()->c_str();
unsigned literal = 0;
@ -4176,7 +4213,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
*(literalPtr++) = ch;
++charCount;
if (charCount == 4) {
operands.push_back(literal);
operands.push_back({false, literal});
literalPtr = reinterpret_cast<char*>(&literal);
charCount = 0;
}
@ -4186,20 +4223,17 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
if (charCount > 0) {
for (; charCount < 4; ++charCount)
*(literalPtr++) = 0;
operands.push_back(literal);
operands.push_back({false, literal});
}
} else
assert(0); // Unexpected type
} else
operands.push_back(createSpvConstant(*typeParam.constant));
operands.push_back({true, createSpvConstant(*typeParam.constant)});
}
if (spirvInst.set == "")
spvType = builder.createOp(static_cast<spv::Op>(spirvInst.id), spv::NoType, operands);
else {
spvType = builder.createBuiltinCall(
spv::NoType, getExtBuiltins(spirvInst.set.c_str()), spirvInst.id, operands);
}
assert(spirvInst.set == ""); // Currently, couldn't be extended instructions.
spvType = builder.makeGenericType(static_cast<spv::Op>(spirvInst.id), operands);
break;
}
#endif
@ -8717,8 +8751,18 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutOffset);
}
if (symbol->getQualifier().hasLocation())
builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation);
if (symbol->getQualifier().hasLocation()) {
if (!(glslangIntermediate->isRayTracingStage() && glslangIntermediate->IsRequestedExtension(glslang::E_GL_EXT_ray_tracing)
&& (builder.getStorageClass(id) == spv::StorageClassRayPayloadKHR ||
builder.getStorageClass(id) == spv::StorageClassIncomingRayPayloadKHR ||
builder.getStorageClass(id) == spv::StorageClassCallableDataKHR ||
builder.getStorageClass(id) == spv::StorageClassIncomingCallableDataKHR))) {
// Location values are used to link TraceRayKHR and ExecuteCallableKHR to corresponding variables
// but are not valid in SPIRV since they are supported only for Input/Output Storage classes.
builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation);
}
}
builder.addDecoration(id, TranslateInvariantDecoration(symbol->getType().getQualifier()));
if (symbol->getQualifier().hasStream() && glslangIntermediate->isMultiStream()) {
builder.addCapability(spv::CapabilityGeometryStreams);
@ -8752,7 +8796,16 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
// add built-in variable decoration
if (builtIn != spv::BuiltInMax) {
builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn);
// WorkgroupSize deprecated in spirv1.6
if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_6 ||
builtIn != spv::BuiltInWorkgroupSize)
builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn);
}
// Add volatile decoration to HelperInvocation for spirv1.6 and beyond
if (builtIn == spv::BuiltInHelperInvocation &&
glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) {
builder.addDecoration(id, spv::DecorationVolatile);
}
#ifndef GLSLANG_WEB

View File

@ -297,15 +297,21 @@ namespace spv {
std::string spirvbin_t::literalString(unsigned word) const
{
std::string literal;
const spirword_t * pos = spv.data() + word;
literal.reserve(16);
const char* bytes = reinterpret_cast<const char*>(spv.data() + word);
while (bytes && *bytes)
literal += *bytes++;
return literal;
do {
spirword_t word = *pos;
for (int i = 0; i < 4; i++) {
char c = word & 0xff;
if (c == '\0')
return literal;
literal += c;
word >>= 8;
}
pos++;
} while (true);
}
void spirvbin_t::applyMap()

View File

@ -427,6 +427,37 @@ Id Builder::makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols)
return type->getResultId();
}
Id Builder::makeGenericType(spv::Op opcode, std::vector<spv::IdImmediate>& operands)
{
// try to find it
Instruction* type;
for (int t = 0; t < (int)groupedTypes[opcode].size(); ++t) {
type = groupedTypes[opcode][t];
if (type->getNumOperands() != operands.size())
continue; // Number mismatch, find next
bool match = true;
for (int op = 0; match && op < operands.size(); ++op) {
match = (operands[op].isId ? type->getIdOperand(op) : type->getImmediateOperand(op)) == operands[op].word;
}
if (match)
return type->getResultId();
}
// not found, make it
type = new Instruction(getUniqueId(), NoType, opcode);
for (int op = 0; op < operands.size(); ++op) {
if (operands[op].isId)
type->addIdOperand(operands[op].word);
else
type->addImmediateOperand(operands[op].word);
}
groupedTypes[opcode].push_back(type);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
return type->getResultId();
}
// TODO: performance: track arrays per stride
// If a stride is supplied (non-zero) make an array.

View File

@ -181,6 +181,7 @@ public:
Id makeSamplerType();
Id makeSampledImageType(Id imageType);
Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols);
Id makeGenericType(spv::Op opcode, std::vector<spv::IdImmediate>& operands);
// accelerationStructureNV type
Id makeAccelerationStructureType();

View File

@ -68,6 +68,26 @@ spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLog
}
case glslang::EShTargetVulkan_1_2:
return spv_target_env::SPV_ENV_VULKAN_1_2;
case glslang::EShTargetUniversal:
switch (spvVersion.spv) {
case EShTargetSpv_1_0:
return spv_target_env::SPV_ENV_UNIVERSAL_1_0;
case EShTargetSpv_1_1:
return spv_target_env::SPV_ENV_UNIVERSAL_1_1;
case EShTargetSpv_1_2:
return spv_target_env::SPV_ENV_UNIVERSAL_1_2;
case EShTargetSpv_1_3:
return spv_target_env::SPV_ENV_UNIVERSAL_1_3;
case EShTargetSpv_1_4:
return spv_target_env::SPV_ENV_UNIVERSAL_1_4;
case EShTargetSpv_1_5:
return spv_target_env::SPV_ENV_UNIVERSAL_1_5;
case EShTargetSpv_1_6:
return spv_target_env::SPV_ENV_UNIVERSAL_1_6;
default:
logger->missingFunctionality("Target version for SPIRV-Tools validator");
return spv_target_env::SPV_ENV_UNIVERSAL_1_6;
}
default:
break;
}

View File

@ -43,6 +43,7 @@
#include <stack>
#include <sstream>
#include <cstring>
#include <utility>
#include "disassemble.h"
#include "doc.h"
@ -100,6 +101,7 @@ protected:
void outputMask(OperandClass operandClass, unsigned mask);
void disassembleImmediates(int numOperands);
void disassembleIds(int numOperands);
std::pair<int, std::string> decodeString();
int disassembleString();
void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands);
@ -290,31 +292,44 @@ void SpirvStream::disassembleIds(int numOperands)
}
}
// return the number of operands consumed by the string
int SpirvStream::disassembleString()
// decode string from words at current position (non-consuming)
std::pair<int, std::string> SpirvStream::decodeString()
{
int startWord = word;
out << " \"";
const char* wordString;
std::string res;
int wordPos = word;
char c;
bool done = false;
do {
unsigned int content = stream[word];
wordString = (const char*)&content;
unsigned int content = stream[wordPos];
for (int charCount = 0; charCount < 4; ++charCount) {
if (*wordString == 0) {
c = content & 0xff;
content >>= 8;
if (c == '\0') {
done = true;
break;
}
out << *(wordString++);
res += c;
}
++word;
} while (! done);
++wordPos;
} while(! done);
return std::make_pair(wordPos - word, res);
}
// return the number of operands consumed by the string
int SpirvStream::disassembleString()
{
out << " \"";
std::pair<int, std::string> decoderes = decodeString();
out << decoderes.second;
out << "\"";
return word - startWord;
word += decoderes.first;
return decoderes.first;
}
void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands)
@ -331,7 +346,7 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
nextNestedControl = 0;
}
} else if (opCode == OpExtInstImport) {
idDescriptor[resultId] = (const char*)(&stream[word]);
idDescriptor[resultId] = decodeString().second;
}
else {
if (resultId != 0 && idDescriptor[resultId].size() == 0) {
@ -428,7 +443,7 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
--numOperands;
// Get names for printing "(XXX)" for readability, *after* this id
if (opCode == OpName)
idDescriptor[stream[word - 1]] = (const char*)(&stream[word]);
idDescriptor[stream[word - 1]] = decodeString().second;
break;
case OperandVariableIds:
disassembleIds(numOperands);

View File

@ -900,6 +900,12 @@ const char* CapabilityString(int info)
case CapabilityDeviceGroup: return "DeviceGroup";
case CapabilityMultiView: return "MultiView";
case CapabilityDenormPreserve: return "DenormPreserve";
case CapabilityDenormFlushToZero: return "DenormFlushToZero";
case CapabilitySignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve";
case CapabilityRoundingModeRTE: return "RoundingModeRTE";
case CapabilityRoundingModeRTZ: return "RoundingModeRTZ";
case CapabilityStencilExportEXT: return "StencilExportEXT";
case CapabilityFloat16ImageAMD: return "Float16ImageAMD";

View File

@ -1003,6 +1003,7 @@ enum Capability {
CapabilityFragmentShaderShadingRateInterlockEXT = 5372,
CapabilityShaderSMBuiltinsNV = 5373,
CapabilityFragmentShaderPixelInterlockEXT = 5378,
CapabilityDemoteToHelperInvocation = 5379,
CapabilityDemoteToHelperInvocationEXT = 5379,
CapabilitySubgroupShuffleINTEL = 5568,
CapabilitySubgroupBufferBlockIOINTEL = 5569,
@ -2311,4 +2312,3 @@ inline FragmentShadingRateMask operator|(FragmentShadingRateMask a, FragmentShad
} // end namespace spv
#endif // #ifndef spirv_HPP

View File

@ -111,27 +111,23 @@ public:
void addStringOperand(const char* str)
{
unsigned int word;
char* wordString = (char*)&word;
char* wordPtr = wordString;
int charCount = 0;
unsigned int word = 0;
unsigned int shiftAmount = 0;
char c;
do {
c = *(str++);
*(wordPtr++) = c;
++charCount;
if (charCount == 4) {
word |= ((unsigned int)c) << shiftAmount;
shiftAmount += 8;
if (shiftAmount == 32) {
addImmediateOperand(word);
wordPtr = wordString;
charCount = 0;
word = 0;
shiftAmount = 0;
}
} while (c != 0);
// deal with partial last word
if (charCount > 0) {
// pad with 0s
for (; charCount < 4; ++charCount)
*(wordPtr++) = 0;
if (shiftAmount > 0) {
addImmediateOperand(word);
}
}

View File

@ -177,6 +177,7 @@ const char* shaderStageName = nullptr;
const char* variableName = nullptr;
bool HlslEnable16BitTypes = false;
bool HlslDX9compatible = false;
bool HlslDxPositionW = false;
bool DumpBuiltinSymbols = false;
std::vector<std::string> IncludeDirectoryList;
@ -662,6 +663,8 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
HlslEnable16BitTypes = true;
} else if (lowerword == "hlsl-dx9-compatible") {
HlslDX9compatible = true;
} else if (lowerword == "hlsl-dx-position-w") {
HlslDxPositionW = true;
} else if (lowerword == "auto-sampled-textures") {
autoSampledTextures = true;
} else if (lowerword == "invert-y" || // synonyms
@ -785,9 +788,13 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
} else if (strcmp(argv[1], "spirv1.5") == 0) {
TargetLanguage = glslang::EShTargetSpv;
TargetVersion = glslang::EShTargetSpv_1_5;
} else if (strcmp(argv[1], "spirv1.6") == 0) {
TargetLanguage = glslang::EShTargetSpv;
TargetVersion = glslang::EShTargetSpv_1_6;
} else
Error("--target-env expected one of: vulkan1.0, vulkan1.1, vulkan1.2, opengl,\n"
"spirv1.0, spirv1.1, spirv1.2, spirv1.3, spirv1.4, or spirv1.5");
Error("--target-env expected one of: vulkan1.0, vulkan1.1, vulkan1.2,\n"
"opengl, spirv1.0, spirv1.1, spirv1.2, spirv1.3,\n"
"spirv1.4, spirv1.5 or spirv1.6");
}
bumpArg();
} else if (lowerword == "undef-macro" ||
@ -1284,6 +1291,9 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
if (Options & EOptionInvertY)
shader->setInvertY(true);
if (HlslDxPositionW)
shader->setDxPositionW(true);
// Set up the environment, some subsettings take precedence over earlier
// ways of setting things.
if (Options & EOptionSpv) {
@ -1847,6 +1857,8 @@ void usage()
" --hlsl-dx9-compatible interprets sampler declarations as a\n"
" texture/sampler combo like DirectX9 would,\n"
" and recognizes DirectX9-specific semantics\n"
" --hlsl-dx-position-w W component of SV_Position in HLSL fragment\n"
" shaders compatible with DirectX\n"
" --invert-y | --iy invert position.Y output in vertex shader\n"
" --keep-uncalled | --ku don't eliminate uncalled functions\n"
" --nan-clamp favor non-NaN operand in min, max, and clamp\n"
@ -1922,8 +1934,9 @@ void usage()
" --sep synonym for --source-entrypoint\n"
" --stdin read from stdin instead of from a file;\n"
" requires providing the shader stage using -S\n"
" --target-env {vulkan1.0 | vulkan1.1 | vulkan1.2 | opengl | \n"
" spirv1.0 | spirv1.1 | spirv1.2 | spirv1.3 | spirv1.4 | spirv1.5}\n"
" --target-env {vulkan1.0 | vulkan1.1 | vulkan1.2 | opengl |\n"
" spirv1.0 | spirv1.1 | spirv1.2 | spirv1.3 | spirv1.4 |\n"
" spirv1.5 | spirv1.6}\n"
" Set the execution environment that the\n"
" generated code will be executed in.\n"
" Defaults to:\n"

View File

@ -244,6 +244,8 @@ c_shader_target_language_version(glslang_target_language_version_t target_langua
return glslang::EShTargetSpv_1_4;
case GLSLANG_TARGET_SPV_1_5:
return glslang::EShTargetSpv_1_5;
case GLSLANG_TARGET_SPV_1_6:
return glslang::EShTargetSpv_1_6;
default:
break;
}
@ -269,6 +271,8 @@ static glslang::EShTargetClientVersion c_shader_client_version(glslang_target_cl
switch (client_version) {
case GLSLANG_TARGET_VULKAN_1_1:
return glslang::EShTargetVulkan_1_1;
case GLSLANG_TARGET_VULKAN_1_2:
return glslang::EShTargetVulkan_1_2;
case GLSLANG_TARGET_OPENGL_450:
return glslang::EShTargetOpenGL_450;
default:
@ -344,6 +348,34 @@ GLSLANG_EXPORT glslang_shader_t* glslang_shader_create(const glslang_input_t* in
return shader;
}
GLSLANG_EXPORT void glslang_shader_shift_binding(glslang_shader_t* shader, glslang_resource_type_t res, unsigned int base)
{
const glslang::TResourceType res_type = glslang::TResourceType(res);
shader->shader->setShiftBinding(res_type, base);
}
GLSLANG_EXPORT void glslang_shader_shift_binding_for_set(glslang_shader_t* shader, glslang_resource_type_t res, unsigned int base, unsigned int set)
{
const glslang::TResourceType res_type = glslang::TResourceType(res);
shader->shader->setShiftBindingForSet(res_type, base, set);
}
GLSLANG_EXPORT void glslang_shader_set_options(glslang_shader_t* shader, int options)
{
if (options & GLSLANG_SHADER_AUTO_MAP_BINDINGS) {
shader->shader->setAutoMapBindings(true);
}
if (options & GLSLANG_SHADER_AUTO_MAP_LOCATIONS) {
shader->shader->setAutoMapLocations(true);
}
if (options & GLSLANG_SHADER_VULKAN_RULES_RELAXED) {
shader->shader->setEnvInputVulkanRulesRelaxed();
}
}
GLSLANG_EXPORT const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader)
{
return shader->preprocessedGLSL.c_str();
@ -417,6 +449,11 @@ GLSLANG_EXPORT int glslang_program_link(glslang_program_t* program, int messages
return (int)program->program->link((EShMessages)messages);
}
GLSLANG_EXPORT int glslang_program_map_io(glslang_program_t* program)
{
return (int)program->program->mapIO();
}
GLSLANG_EXPORT const char* glslang_program_get_info_log(glslang_program_t* program)
{
return program->program->getInfoLog();

View File

@ -36,19 +36,3 @@
// POSSIBILITY OF SUCH DAMAGE.
//
#extension GL_EXT_spirv_intrinsics : enable
#extension GL_ARB_gpu_shader_int64 : enable
uvec2 clockRealtime2x32EXT(void) {
spirv_instruction (extensions = ["SPV_KHR_shader_clock"], capabilities = [5055], id = 5056)
uvec2 clockRealtime2x32EXT_internal(uint scope);
return clockRealtime2x32EXT_internal(1 /*Device scope*/);
}
uint64_t clockRealtimeEXT(void) {
spirv_instruction (extensions = ["SPV_KHR_shader_clock"], capabilities = [5055], id = 5056)
uint64_t clockRealtimeEXT_internal(uint scope);
return clockRealtimeEXT_internal(1 /*Device scope*/);
}

View File

@ -2167,8 +2167,21 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
TIntermSymbol* arg = intermediate.addSymbol(*argVars.back());
handleFunctionArgument(&callee, callingArgs, arg);
if (param.type->getQualifier().isParamInput()) {
intermediate.growAggregate(synthBody, handleAssign(loc, EOpAssign, arg,
intermediate.addSymbol(**inputIt)));
TIntermTyped* input = intermediate.addSymbol(**inputIt);
if (input->getType().getQualifier().builtIn == EbvFragCoord && intermediate.getDxPositionW()) {
// Replace FragCoord W with reciprocal
auto pos_xyz = handleDotDereference(loc, input, "xyz");
auto pos_w = handleDotDereference(loc, input, "w");
auto one = intermediate.addConstantUnion(1.0, EbtFloat, loc);
auto recip_w = intermediate.addBinaryMath(EOpDiv, one, pos_w, loc);
TIntermAggregate* dst = new TIntermAggregate(EOpConstructVec4);
dst->getSequence().push_back(pos_xyz);
dst->getSequence().push_back(recip_w);
dst->setType(TType(EbtFloat, EvqTemporary, 4));
dst->setLoc(loc);
input = dst;
}
intermediate.growAggregate(synthBody, handleAssign(loc, EOpAssign, arg, input));
inputIt++;
}
if (param.type->getQualifier().storage == EvqUniform) {
@ -2452,6 +2465,62 @@ void HlslParseContext::handleFunctionArgument(TFunction* function,
arguments = newArg;
}
// FragCoord may require special loading: we can optionally reciprocate W.
TIntermTyped* HlslParseContext::assignFromFragCoord(const TSourceLoc& loc, TOperator op,
TIntermTyped* left, TIntermTyped* right)
{
// If we are not asked for reciprocal W, use a plain old assign.
if (!intermediate.getDxPositionW())
return intermediate.addAssign(op, left, right, loc);
// If we get here, we should reciprocate W.
TIntermAggregate* assignList = nullptr;
// If this is a complex rvalue, we don't want to dereference it many times. Create a temporary.
TVariable* rhsTempVar = nullptr;
rhsTempVar = makeInternalVariable("@fragcoord", right->getType());
rhsTempVar->getWritableType().getQualifier().makeTemporary();
{
TIntermTyped* rhsTempSym = intermediate.addSymbol(*rhsTempVar, loc);
assignList = intermediate.growAggregate(assignList,
intermediate.addAssign(EOpAssign, rhsTempSym, right, loc), loc);
}
// tmp.w = 1.0 / tmp.w
{
const int W = 3;
TIntermTyped* tempSymL = intermediate.addSymbol(*rhsTempVar, loc);
TIntermTyped* tempSymR = intermediate.addSymbol(*rhsTempVar, loc);
TIntermTyped* index = intermediate.addConstantUnion(W, loc);
TIntermTyped* lhsElement = intermediate.addIndex(EOpIndexDirect, tempSymL, index, loc);
TIntermTyped* rhsElement = intermediate.addIndex(EOpIndexDirect, tempSymR, index, loc);
const TType derefType(right->getType(), 0);
lhsElement->setType(derefType);
rhsElement->setType(derefType);
auto one = intermediate.addConstantUnion(1.0, EbtFloat, loc);
auto recip_w = intermediate.addBinaryMath(EOpDiv, one, rhsElement, loc);
assignList = intermediate.growAggregate(assignList, intermediate.addAssign(EOpAssign, lhsElement, recip_w, loc));
}
// Assign the rhs temp (now with W reciprocal) to the final output
{
TIntermTyped* rhsTempSym = intermediate.addSymbol(*rhsTempVar, loc);
assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, left, rhsTempSym, loc));
}
assert(assignList != nullptr);
assignList->setOperator(EOpSequence);
return assignList;
}
// Position may require special handling: we can optionally invert Y.
// See: https://github.com/KhronosGroup/glslang/issues/1173
// https://github.com/KhronosGroup/glslang/issues/494
@ -3071,6 +3140,10 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
subSplitLeft, subSplitRight);
assignList = intermediate.growAggregate(assignList, clipCullAssign, loc);
} else if (subSplitRight->getType().getQualifier().builtIn == EbvFragCoord) {
// FragCoord can require special handling: see comment above assignFromFragCoord
TIntermTyped* fragCoordAssign = assignFromFragCoord(loc, op, subSplitLeft, subSplitRight);
assignList = intermediate.growAggregate(assignList, fragCoordAssign, loc);
} else if (assignsClipPos(subSplitLeft)) {
// Position can require special handling: see comment above assignPosition
TIntermTyped* positionAssign = assignPosition(loc, op, subSplitLeft, subSplitRight);
@ -6935,6 +7008,9 @@ void HlslParseContext::shareStructBufferType(TType& type)
if (lhs.isStruct() != rhs.isStruct())
return false;
if (lhs.getQualifier().builtIn != rhs.getQualifier().builtIn)
return false;
if (lhs.isStruct() && rhs.isStruct()) {
if (lhs.getStruct()->size() != rhs.getStruct()->size())
return false;

View File

@ -94,6 +94,7 @@ public:
TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermTyped*);
TIntermAggregate* assignClipCullDistance(const TSourceLoc&, TOperator, int semanticId, TIntermTyped* left, TIntermTyped* right);
TIntermTyped* assignPosition(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right);
TIntermTyped* assignFromFragCoord(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right);
void decomposeIntrinsic(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
void decomposeSampleMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
void decomposeStructBufferMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);

View File

@ -39,6 +39,11 @@
#include <algorithm>
#include <cassert>
#ifdef _MSC_VER
#include <cfloat>
#else
#include <cmath>
#endif
#include <cstdio>
#include <cstdlib>
#include <list>
@ -302,6 +307,34 @@ template <class T> int IntLog2(T n)
return result;
}
inline bool IsInfinity(double x) {
#ifdef _MSC_VER
switch (_fpclass(x)) {
case _FPCLASS_NINF:
case _FPCLASS_PINF:
return true;
default:
return false;
}
#else
return std::isinf(x);
#endif
}
inline bool IsNan(double x) {
#ifdef _MSC_VER
switch (_fpclass(x)) {
case _FPCLASS_SNAN:
case _FPCLASS_QNAN:
return true;
default:
return false;
}
#else
return std::isnan(x);
#endif
}
} // end namespace glslang
#endif // _COMMON_INCLUDED_

View File

@ -1865,10 +1865,12 @@ public:
bool isAtomic() const { return false; }
bool isCoopMat() const { return false; }
bool isReference() const { return false; }
bool isSpirvType() const { return false; }
#else
bool isAtomic() const { return basicType == EbtAtomicUint; }
bool isCoopMat() const { return coopmat; }
bool isReference() const { return getBasicType() == EbtReference; }
bool isSpirvType() const { return getBasicType() == EbtSpirvType; }
#endif
// return true if this type contains any subtype which satisfies the given predicate.
@ -2444,11 +2446,15 @@ public:
//
bool sameStructType(const TType& right) const
{
// TODO: Why return true when neither types are structures?
// Most commonly, they are both nullptr, or the same pointer to the same actual structure
if ((!isStruct() && !right.isStruct()) ||
(isStruct() && right.isStruct() && structure == right.structure))
return true;
if (!isStruct() || !right.isStruct())
return false;
// Structure names have to match
if (*typeName != *right.typeName)
return false;
@ -2458,8 +2464,7 @@ public:
bool isGLPerVertex = *typeName == "gl_PerVertex";
// Both being nullptr was caught above, now they both have to be structures of the same number of elements
if (!isStruct() || !right.isStruct() ||
(structure->size() != right.structure->size() && !isGLPerVertex))
if (structure->size() != right.structure->size() && !isGLPerVertex)
return false;
// Compare the names and types of all the members, which have to match
@ -2469,6 +2474,14 @@ public:
if (*(*structure)[li].type != *(*right.structure)[ri].type)
return false;
} else {
// Skip hidden members
if ((*structure)[li].type->hiddenMember()) {
ri--;
continue;
} else if ((*right.structure)[ri].type->hiddenMember()) {
li--;
continue;
}
// If one of the members is something that's inconsistently declared, skip over it
// for now.
if (isGLPerVertex) {
@ -2485,10 +2498,10 @@ public:
}
// If we get here, then there should only be inconsistently declared members left
} else if (li < structure->size()) {
if (!isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName()))
if (!(*structure)[li].type->hiddenMember() && !isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName()))
return false;
} else {
if (!isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName()))
if (!(*right.structure)[ri].type->hiddenMember() && !isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName()))
return false;
}
}

View File

@ -224,6 +224,9 @@ GLSLANG_EXPORT void glslang_finalize_process();
GLSLANG_EXPORT glslang_shader_t* glslang_shader_create(const glslang_input_t* input);
GLSLANG_EXPORT void glslang_shader_delete(glslang_shader_t* shader);
GLSLANG_EXPORT void glslang_shader_shift_binding(glslang_shader_t* shader, glslang_resource_type_t res, unsigned int base);
GLSLANG_EXPORT void glslang_shader_shift_binding_for_set(glslang_shader_t* shader, glslang_resource_type_t res, unsigned int base, unsigned int set);
GLSLANG_EXPORT void glslang_shader_set_options(glslang_shader_t* shader, int options); // glslang_shader_options_t
GLSLANG_EXPORT int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input);
GLSLANG_EXPORT int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input);
GLSLANG_EXPORT const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader);
@ -234,6 +237,7 @@ GLSLANG_EXPORT glslang_program_t* glslang_program_create();
GLSLANG_EXPORT void glslang_program_delete(glslang_program_t* program);
GLSLANG_EXPORT void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader);
GLSLANG_EXPORT int glslang_program_link(glslang_program_t* program, int messages); // glslang_messages_t
GLSLANG_EXPORT int glslang_program_map_io(glslang_program_t* program);
GLSLANG_EXPORT void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage);
GLSLANG_EXPORT size_t glslang_program_SPIRV_get_size(glslang_program_t* program);
GLSLANG_EXPORT void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int*);

View File

@ -113,7 +113,8 @@ typedef enum {
GLSLANG_TARGET_SPV_1_3 = (1 << 16) | (3 << 8),
GLSLANG_TARGET_SPV_1_4 = (1 << 16) | (4 << 8),
GLSLANG_TARGET_SPV_1_5 = (1 << 16) | (5 << 8),
LAST_ELEMENT_MARKER(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT = 6),
GLSLANG_TARGET_SPV_1_6 = (1 << 16) | (6 << 8),
LAST_ELEMENT_MARKER(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT = 7),
} glslang_target_language_version_t;
/* EShExecutable counterpart */
@ -181,6 +182,26 @@ typedef enum {
LAST_ELEMENT_MARKER(GLSLANG_PROFILE_COUNT),
} glslang_profile_t;
/* Shader options */
typedef enum {
GLSLANG_SHADER_DEFAULT_BIT = 0,
GLSLANG_SHADER_AUTO_MAP_BINDINGS = (1 << 0),
GLSLANG_SHADER_AUTO_MAP_LOCATIONS = (1 << 1),
GLSLANG_SHADER_VULKAN_RULES_RELAXED = (1 << 2),
LAST_ELEMENT_MARKER(GLSLANG_SHADER_COUNT),
} glslang_shader_options_t;
/* TResourceType counterpart */
typedef enum {
GLSLANG_RESOURCE_TYPE_SAMPLER,
GLSLANG_RESOURCE_TYPE_TEXTURE,
GLSLANG_RESOURCE_TYPE_IMAGE,
GLSLANG_RESOURCE_TYPE_UBO,
GLSLANG_RESOURCE_TYPE_SSBO,
GLSLANG_RESOURCE_TYPE_UAV,
LAST_ELEMENT_MARKER(GLSLANG_RESOURCE_TYPE_COUNT),
} glslang_resource_type_t;
#undef LAST_ELEMENT_MARKER
#endif

View File

@ -46,35 +46,6 @@ namespace {
using namespace glslang;
typedef union {
double d;
int i[2];
} DoubleIntUnion;
// Some helper functions
bool isNan(double x)
{
DoubleIntUnion u;
// tough to find a platform independent library function, do it directly
u.d = x;
int bitPatternL = u.i[0];
int bitPatternH = u.i[1];
return (bitPatternH & 0x7ff80000) == 0x7ff80000 &&
((bitPatternH & 0xFFFFF) != 0 || bitPatternL != 0);
}
bool isInf(double x)
{
DoubleIntUnion u;
// tough to find a platform independent library function, do it directly
u.d = x;
int bitPatternL = u.i[0];
int bitPatternH = u.i[1];
return (bitPatternH & 0x7ff00000) == 0x7ff00000 &&
(bitPatternH & 0xFFFFF) == 0 && bitPatternL == 0;
}
const double pi = 3.1415926535897932384626433832795;
} // end anonymous namespace
@ -663,12 +634,12 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
case EOpIsNan:
{
newConstArray[i].setBConst(isNan(unionArray[i].getDConst()));
newConstArray[i].setBConst(IsNan(unionArray[i].getDConst()));
break;
}
case EOpIsInf:
{
newConstArray[i].setBConst(isInf(unionArray[i].getDConst()));
newConstArray[i].setBConst(IsInfinity(unionArray[i].getDConst()));
break;
}

View File

@ -316,6 +316,7 @@ const CustomFunction CustomFunctions[] = {
{ EOpTextureQuerySize, "textureSize", nullptr },
{ EOpTextureQueryLod, "textureQueryLod", nullptr },
{ EOpTextureQueryLod, "textureQueryLOD", nullptr }, // extension GL_ARB_texture_query_lod
{ EOpTextureQueryLevels, "textureQueryLevels", nullptr },
{ EOpTextureQuerySamples, "textureSamples", nullptr },
{ EOpTexture, "texture", nullptr },
@ -4553,11 +4554,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"\n");
}
// GL_ARB_shader_clock
// GL_ARB_shader_clock& GL_EXT_shader_realtime_clock
if (profile != EEsProfile && version >= 450) {
commonBuiltins.append(
"uvec2 clock2x32ARB();"
"uint64_t clockARB();"
"uvec2 clockRealtime2x32EXT();"
"uint64_t clockRealtimeEXT();"
"\n");
}
@ -6245,38 +6248,44 @@ void TBuiltIns::addQueryFunctions(TSampler sampler, const TString& typeName, int
//
// textureQueryLod(), fragment stage only
// Also enabled with extension GL_ARB_texture_query_lod
// Extension GL_ARB_texture_query_lod says that textureQueryLOD() also exist at extension.
if (profile != EEsProfile && version >= 150 && sampler.isCombined() && sampler.dim != EsdRect &&
! sampler.isMultiSample() && ! sampler.isBuffer()) {
for (int f16TexAddr = 0; f16TexAddr < 2; ++f16TexAddr) {
if (f16TexAddr && sampler.type != EbtFloat16)
continue;
stageBuiltins[EShLangFragment].append("vec2 textureQueryLod(");
stageBuiltins[EShLangFragment].append(typeName);
if (dimMap[sampler.dim] == 1)
if (f16TexAddr)
stageBuiltins[EShLangFragment].append(", float16_t");
else
stageBuiltins[EShLangFragment].append(", float");
else {
if (f16TexAddr)
stageBuiltins[EShLangFragment].append(", f16vec");
else
stageBuiltins[EShLangFragment].append(", vec");
stageBuiltins[EShLangFragment].append(postfixes[dimMap[sampler.dim]]);
}
stageBuiltins[EShLangFragment].append(");\n");
}
stageBuiltins[EShLangCompute].append("vec2 textureQueryLod(");
stageBuiltins[EShLangCompute].append(typeName);
if (dimMap[sampler.dim] == 1)
stageBuiltins[EShLangCompute].append(", float");
else {
stageBuiltins[EShLangCompute].append(", vec");
stageBuiltins[EShLangCompute].append(postfixes[dimMap[sampler.dim]]);
const TString funcName[2] = {"vec2 textureQueryLod(", "vec2 textureQueryLOD("};
for (int i = 0; i < 2; ++i){
for (int f16TexAddr = 0; f16TexAddr < 2; ++f16TexAddr) {
if (f16TexAddr && sampler.type != EbtFloat16)
continue;
stageBuiltins[EShLangFragment].append(funcName[i]);
stageBuiltins[EShLangFragment].append(typeName);
if (dimMap[sampler.dim] == 1)
if (f16TexAddr)
stageBuiltins[EShLangFragment].append(", float16_t");
else
stageBuiltins[EShLangFragment].append(", float");
else {
if (f16TexAddr)
stageBuiltins[EShLangFragment].append(", f16vec");
else
stageBuiltins[EShLangFragment].append(", vec");
stageBuiltins[EShLangFragment].append(postfixes[dimMap[sampler.dim]]);
}
stageBuiltins[EShLangFragment].append(");\n");
}
stageBuiltins[EShLangCompute].append(funcName[i]);
stageBuiltins[EShLangCompute].append(typeName);
if (dimMap[sampler.dim] == 1)
stageBuiltins[EShLangCompute].append(", float");
else {
stageBuiltins[EShLangCompute].append(", vec");
stageBuiltins[EShLangCompute].append(postfixes[dimMap[sampler.dim]]);
}
stageBuiltins[EShLangCompute].append(");\n");
}
stageBuiltins[EShLangCompute].append(");\n");
}
//
@ -8061,7 +8070,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
}
if (profile != EEsProfile && version < 400) {
symbolTable.setFunctionExtensions("textureQueryLod", 1, &E_GL_ARB_texture_query_lod);
symbolTable.setFunctionExtensions("textureQueryLOD", 1, &E_GL_ARB_texture_query_lod);
}
if (profile != EEsProfile && version >= 460) {
@ -8324,6 +8333,9 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
symbolTable.setFunctionExtensions("clockARB", 1, &E_GL_ARB_shader_clock);
symbolTable.setFunctionExtensions("clock2x32ARB", 1, &E_GL_ARB_shader_clock);
symbolTable.setFunctionExtensions("clockRealtimeEXT", 1, &E_GL_EXT_shader_realtime_clock);
symbolTable.setFunctionExtensions("clockRealtime2x32EXT", 1, &E_GL_EXT_shader_realtime_clock);
if (profile == EEsProfile && version < 320) {
symbolTable.setVariableExtensions("gl_PrimitiveID", Num_AEP_geometry_shader, AEP_geometry_shader);
symbolTable.setVariableExtensions("gl_Layer", Num_AEP_geometry_shader, AEP_geometry_shader);

View File

@ -3902,7 +3902,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
case EbtFloat16: PROMOTE(setDConst, double, Get); break; \
case EbtFloat: PROMOTE(setDConst, double, Get); break; \
case EbtDouble: PROMOTE(setDConst, double, Get); break; \
case EbtInt8: PROMOTE(setI8Const, char, Get); break; \
case EbtInt8: PROMOTE(setI8Const, signed char, Get); break; \
case EbtInt16: PROMOTE(setI16Const, short, Get); break; \
case EbtInt: PROMOTE(setIConst, int, Get); break; \
case EbtInt64: PROMOTE(setI64Const, long long, Get); break; \

View File

@ -1321,7 +1321,7 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction
// Find it in the symbol table.
//
const TFunction* fnCandidate;
bool builtIn;
bool builtIn {false};
fnCandidate = findFunction(loc, *function, builtIn);
if (fnCandidate) {
// This is a declared function that might map to
@ -6496,6 +6496,8 @@ void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier
error(loc, "can only be used with a uniform", "push_constant", "");
if (qualifier.hasSet())
error(loc, "cannot be used with push_constant", "set", "");
if (qualifier.hasBinding())
error(loc, "cannot be used with push_constant", "binding", "");
}
if (qualifier.hasBufferReference()) {
if (qualifier.storage != EvqBuffer)
@ -6650,8 +6652,10 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunct
: 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);
else if (version < 400) {
bool needfindFunction400 = extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) || extensionTurnedOn(E_GL_ARB_gpu_shader5);
function = needfindFunction400 ? findFunction400(loc, call, builtIn) : findFunction120(loc, call, builtIn);
}
else if (explicitTypesEnabled)
function = findFunctionExplicitTypes(loc, call, builtIn);
else

View File

@ -1343,7 +1343,6 @@ int ShInitialize()
glslang::GetGlobalLock();
++NumberOfClients;
glslang::ReleaseGlobalLock();
if (PerProcessGPA == nullptr)
PerProcessGPA = new TPoolAllocator();
@ -1353,6 +1352,7 @@ int ShInitialize()
glslang::HlslScanContext::fillInKeywordMap();
#endif
glslang::ReleaseGlobalLock();
return 1;
}
@ -1415,9 +1415,10 @@ int ShFinalize()
--NumberOfClients;
assert(NumberOfClients >= 0);
bool finalize = NumberOfClients == 0;
glslang::ReleaseGlobalLock();
if (! finalize)
if (! finalize) {
glslang::ReleaseGlobalLock();
return 1;
}
for (int version = 0; version < VersionCount; ++version) {
for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) {
@ -1455,6 +1456,7 @@ int ShFinalize()
glslang::HlslScanContext::deleteKeywordMap();
#endif
glslang::ReleaseGlobalLock();
return 1;
}
@ -1827,6 +1829,7 @@ void TShader::setUniqueId(unsigned long long id)
}
void TShader::setInvertY(bool invert) { intermediate->setInvertY(invert); }
void TShader::setDxPositionW(bool invert) { intermediate->setDxPositionW(invert); }
void TShader::setNanMinMaxClamp(bool useNonNan) { intermediate->setNanMinMaxClamp(useNonNan); }
#ifndef GLSLANG_WEB

View File

@ -426,12 +426,7 @@ TSymbolTableLevel* TSymbolTableLevel::clone() const
symTableLevel->thisLevel = thisLevel;
symTableLevel->retargetedSymbols.clear();
for (auto &s : retargetedSymbols) {
// Extra constructions to make sure they use the correct allocator pool
TString newFrom;
newFrom = s.first;
TString newTo;
newTo = s.second;
symTableLevel->retargetedSymbols.push_back({std::move(newFrom), std::move(newTo)});
symTableLevel->retargetedSymbols.push_back({s.first, s.second});
}
std::vector<bool> containerCopied(anonId, false);
tLevel::const_iterator iter;
@ -462,11 +457,7 @@ TSymbolTableLevel* TSymbolTableLevel::clone() const
TSymbol* sym = symTableLevel->find(s.second);
if (!sym)
continue;
// Need to declare and assign so newS is using the correct pool allocator
TString newS;
newS = s.first;
symTableLevel->insert(newS, sym);
symTableLevel->insert(s.first, sym);
}
return symTableLevel;

View File

@ -84,7 +84,7 @@ typedef TVector<const char*> TExtensionList;
class TSymbol {
public:
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
explicit TSymbol(const TString *n) : name(n), extensions(0), writable(true) { }
explicit TSymbol(const TString *n) : name(n), uniqueId(0), extensions(0), writable(true) { }
virtual TSymbol* clone() const = 0;
virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool

View File

@ -225,6 +225,9 @@ void TParseVersions::initializeExtensionBehavior()
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_ARB_draw_instanced] = EBhDisable;
extensionBehavior[E_GL_ARB_fragment_coord_conventions] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_basic] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_vote] = EBhDisable;
@ -465,6 +468,8 @@ void TParseVersions::getPreamble(std::string& preamble)
"#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_ARB_draw_instanced 1\n"
"#define GL_ARB_fragment_coord_conventions 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"

View File

@ -161,6 +161,8 @@ const char* const E_GL_ARB_shader_storage_buffer_object = "GL_ARB_shader_storage
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_ARB_draw_instanced = "GL_ARB_draw_instanced";
const char* const E_GL_ARB_fragment_coord_conventions = "GL_ARB_fragment_coord_conventions";
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";

View File

@ -48,37 +48,6 @@
#endif
#include <cstdint>
namespace {
bool IsInfinity(double x) {
#ifdef _MSC_VER
switch (_fpclass(x)) {
case _FPCLASS_NINF:
case _FPCLASS_PINF:
return true;
default:
return false;
}
#else
return std::isinf(x);
#endif
}
bool IsNan(double x) {
#ifdef _MSC_VER
switch (_fpclass(x)) {
case _FPCLASS_SNAN:
case _FPCLASS_QNAN:
return true;
default:
return false;
}
#else
return std::isnan(x);
#endif
}
}
namespace glslang {

View File

@ -514,6 +514,24 @@ struct TSymbolValidater
return;
}
else {
// Deal with input/output pairs where one is a block member but the other is loose,
// e.g. with ARB_separate_shader_objects
if (type1.getBasicType() == EbtBlock &&
type1.isStruct() && !type2.isStruct()) {
// Iterate through block members tracking layout
glslang::TString name;
type1.getStruct()->begin()->type->appendMangledName(name);
if (name == mangleName2
&& type1.getQualifier().layoutLocation == type2.getQualifier().layoutLocation) return;
}
if (type2.getBasicType() == EbtBlock &&
type2.isStruct() && !type1.isStruct()) {
// Iterate through block members tracking layout
glslang::TString name;
type2.getStruct()->begin()->type->appendMangledName(name);
if (name == mangleName1
&& type1.getQualifier().layoutLocation == type2.getQualifier().layoutLocation) return;
}
TString err = "Invalid In/Out variable type : " + entKey.first;
infoSink.info.message(EPrefixInternalError, err.c_str());
hadError = true;
@ -827,7 +845,7 @@ int TDefaultIoResolverBase::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
}
// no locations added if already present, a built-in variable, a block, or an opaque
if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getBasicType() == EbtBlock ||
type.isAtomic() || (type.containsOpaque() && referenceIntermediate.getSpv().openGl == 0)) {
type.isAtomic() || type.isSpirvType() || (type.containsOpaque() && referenceIntermediate.getSpv().openGl == 0)) {
return ent.newLocation = -1;
}
// no locations on blocks of built-in variables
@ -855,8 +873,8 @@ int TDefaultIoResolverBase::resolveInOutLocation(EShLanguage stage, TVarEntryInf
return ent.newLocation = -1;
}
// no locations added if already present, or a built-in variable
if (type.getQualifier().hasLocation() || type.isBuiltIn()) {
// no locations added if already present, a built-in variable, or a variable with SPIR-V decorate
if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getQualifier().hasSprivDecorate()) {
return ent.newLocation = -1;
}
@ -942,8 +960,8 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf
if (type.getQualifier().hasLocation()) {
return ent.newLocation = type.getQualifier().layoutLocation;
}
// no locations added if already present, or a built-in variable
if (type.isBuiltIn()) {
// no locations added if already present, a built-in variable, or a variable with SPIR-V decorate
if (type.isBuiltIn() || type.getQualifier().hasSprivDecorate()) {
return ent.newLocation = -1;
}
// no locations on blocks of built-in variables
@ -1024,7 +1042,8 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
} else {
// no locations added if already present, a built-in variable, a block, or an opaque
if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getBasicType() == EbtBlock ||
type.isAtomic() || (type.containsOpaque() && referenceIntermediate.getSpv().openGl == 0)) {
type.isAtomic() || type.isSpirvType() ||
(type.containsOpaque() && referenceIntermediate.getSpv().openGl == 0)) {
return ent.newLocation = -1;
}
// no locations on blocks of built-in variables

View File

@ -312,6 +312,7 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
MERGE_TRUE(autoMapBindings);
MERGE_TRUE(autoMapLocations);
MERGE_TRUE(invertY);
MERGE_TRUE(dxPositionW);
MERGE_TRUE(flattenUniformArrays);
MERGE_TRUE(useUnknownFormat);
MERGE_TRUE(hlslOffsets);
@ -759,7 +760,10 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
auto checkName = [this, unitSymbol, &infoSink](const TString& name) {
for (unsigned int i = 0; i < unitSymbol->getType().getStruct()->size(); ++i) {
if (name == (*unitSymbol->getType().getStruct())[i].type->getFieldName()) {
if (name == (*unitSymbol->getType().getStruct())[i].type->getFieldName()
&& !((*unitSymbol->getType().getStruct())[i].type->getQualifier().hasLocation()
|| unitSymbol->getType().getQualifier().hasLocation())
) {
error(infoSink, "Anonymous member name used for global variable or other anonymous member: ");
infoSink.info << (*unitSymbol->getType().getStruct())[i].type->getCompleteString() << "\n";
}
@ -858,9 +862,19 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
if (symbol.getType().getBasicType() == EbtBlock && unitSymbol.getType().getBasicType() == EbtBlock &&
symbol.getType().getStruct() && unitSymbol.getType().getStruct() &&
symbol.getType().sameStructType(unitSymbol.getType())) {
for (unsigned int i = 0; i < symbol.getType().getStruct()->size(); ++i) {
const TQualifier& qualifier = (*symbol.getType().getStruct())[i].type->getQualifier();
const TQualifier& unitQualifier = (*unitSymbol.getType().getStruct())[i].type->getQualifier();
unsigned int li = 0;
unsigned int ri = 0;
while (li < symbol.getType().getStruct()->size() && ri < unitSymbol.getType().getStruct()->size()) {
if ((*symbol.getType().getStruct())[li].type->hiddenMember()) {
++li;
continue;
}
if ((*unitSymbol.getType().getStruct())[ri].type->hiddenMember()) {
++ri;
continue;
}
const TQualifier& qualifier = (*symbol.getType().getStruct())[li].type->getQualifier();
const TQualifier & unitQualifier = (*unitSymbol.getType().getStruct())[ri].type->getQualifier();
if (qualifier.layoutMatrix != unitQualifier.layoutMatrix ||
qualifier.layoutOffset != unitQualifier.layoutOffset ||
qualifier.layoutAlign != unitQualifier.layoutAlign ||
@ -869,6 +883,8 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
error(infoSink, "Interface block member layout qualifiers must match:");
writeTypeComparison = true;
}
++li;
++ri;
}
}

View File

@ -290,6 +290,7 @@ public:
resources(TBuiltInResource{}),
numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
invertY(false),
dxPositionW(false),
useStorageBuffer(false),
invariantAll(false),
nanMinMaxClamp(false),
@ -397,6 +398,9 @@ public:
case EShTargetSpv_1_5:
processes.addProcess("target-env spirv1.5");
break;
case EShTargetSpv_1_6:
processes.addProcess("target-env spirv1.6");
break;
default:
processes.addProcess("target-env spirvUnknown");
break;
@ -460,6 +464,14 @@ public:
}
bool getInvertY() const { return invertY; }
void setDxPositionW(bool dxPosW)
{
dxPositionW = dxPosW;
if (dxPositionW)
processes.addProcess("dx-position-w");
}
bool getDxPositionW() const { return dxPositionW; }
#ifdef ENABLE_HLSL
void setSource(EShSource s) { source = s; }
EShSource getSource() const { return source; }
@ -1070,6 +1082,7 @@ protected:
int numPushConstants;
bool recursive;
bool invertY;
bool dxPositionW;
bool useStorageBuffer;
bool invariantAll;
bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN

View File

@ -172,7 +172,7 @@ namespace {
pthread_mutex_t gMutex;
}
void InitGlobalLock()
static void InitMutex(void)
{
pthread_mutexattr_t mutexattr;
pthread_mutexattr_init(&mutexattr);
@ -180,6 +180,12 @@ void InitGlobalLock()
pthread_mutex_init(&gMutex, &mutexattr);
}
void InitGlobalLock()
{
static pthread_once_t once = PTHREAD_ONCE_INIT;
pthread_once(&once, InitMutex);
}
void GetGlobalLock()
{
pthread_mutex_lock(&gMutex);

View File

@ -163,6 +163,7 @@ typedef enum {
} EShTargetLanguage;
typedef enum {
EShTargetUniversal = 0, // Universal
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
@ -179,7 +180,8 @@ 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 = 6),
EShTargetSpv_1_6 = (1 << 16) | (6 << 8), // SPIR-V 1.6
LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount = 7),
} EShTargetLanguageVersion;
struct TInputLanguage {
@ -485,6 +487,7 @@ public:
GLSLANG_EXPORT void addUniformLocationOverride(const char* name, int loc);
GLSLANG_EXPORT void setUniformLocationBase(int base);
GLSLANG_EXPORT void setInvertY(bool invert);
GLSLANG_EXPORT void setDxPositionW(bool dxPosW);
#ifdef ENABLE_HLSL
GLSLANG_EXPORT void setHlslIoMapping(bool hlslIoMap);
GLSLANG_EXPORT void setFlattenUniformArrays(bool flatten);