mirror of
https://github.com/love2d/love.git
synced 2026-08-17 11:00:31 +02:00
Update glslang
This commit is contained in:
@@ -1292,7 +1292,8 @@ bool IsDescriptorResource(const glslang::TType& type)
|
|||||||
// basically samplerXXX/subpass/sampler/texture are all included
|
// basically samplerXXX/subpass/sampler/texture are all included
|
||||||
// if they are the global-scope-class, not the function parameter
|
// if they are the global-scope-class, not the function parameter
|
||||||
// (or local, if they ever exist) class.
|
// (or local, if they ever exist) class.
|
||||||
if (type.getBasicType() == glslang::EbtSampler)
|
if (type.getBasicType() == glslang::EbtSampler ||
|
||||||
|
type.getBasicType() == glslang::EbtAccStruct)
|
||||||
return type.getQualifier().isUniformOrBuffer();
|
return type.getQualifier().isUniformOrBuffer();
|
||||||
|
|
||||||
// None of the above.
|
// None of the above.
|
||||||
@@ -1439,7 +1440,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
|
|||||||
// Add the source extensions
|
// Add the source extensions
|
||||||
const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions();
|
const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions();
|
||||||
for (auto it = sourceExtensions.begin(); it != sourceExtensions.end(); ++it)
|
for (auto it = sourceExtensions.begin(); it != sourceExtensions.end(); ++it)
|
||||||
builder.addSourceExtension(it->c_str());
|
builder.addSourceExtension(it->first.c_str());
|
||||||
|
|
||||||
// Add the top-level modes for this shader.
|
// Add the top-level modes for this shader.
|
||||||
|
|
||||||
@@ -1448,7 +1449,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
|
|||||||
builder.addExecutionMode(shaderEntry, spv::ExecutionModeXfb);
|
builder.addExecutionMode(shaderEntry, spv::ExecutionModeXfb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sourceExtensions.find("GL_EXT_ray_flags_primitive_culling") != sourceExtensions.end()) {
|
if (glslangIntermediate->getLayoutPrimitiveCulling()) {
|
||||||
builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingProvisionalKHR);
|
builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingProvisionalKHR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3524,7 +3525,18 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol*
|
|||||||
if (glslang::IsAnonymous(name))
|
if (glslang::IsAnonymous(name))
|
||||||
name = "";
|
name = "";
|
||||||
|
|
||||||
return builder.createVariable(storageClass, spvType, name);
|
spv::Id initializer = spv::NoResult;
|
||||||
|
|
||||||
|
if (node->getType().getQualifier().storage == glslang::EvqUniform &&
|
||||||
|
!node->getConstArray().empty()) {
|
||||||
|
int nextConst = 0;
|
||||||
|
initializer = createSpvConstantFromConstUnionArray(node->getType(),
|
||||||
|
node->getConstArray(),
|
||||||
|
nextConst,
|
||||||
|
false /* specConst */);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.createVariable(storageClass, spvType, name, initializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return type Id of the sampled type.
|
// Return type Id of the sampled type.
|
||||||
@@ -4388,8 +4400,10 @@ bool TGlslangToSpvTraverser::writableParam(glslang::TStorageQualifier qualifier)
|
|||||||
assert(qualifier == glslang::EvqIn ||
|
assert(qualifier == glslang::EvqIn ||
|
||||||
qualifier == glslang::EvqOut ||
|
qualifier == glslang::EvqOut ||
|
||||||
qualifier == glslang::EvqInOut ||
|
qualifier == glslang::EvqInOut ||
|
||||||
|
qualifier == glslang::EvqUniform ||
|
||||||
qualifier == glslang::EvqConstReadOnly);
|
qualifier == glslang::EvqConstReadOnly);
|
||||||
return qualifier != glslang::EvqConstReadOnly;
|
return qualifier != glslang::EvqConstReadOnly &&
|
||||||
|
qualifier != glslang::EvqUniform;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is parameter pass-by-original?
|
// Is parameter pass-by-original?
|
||||||
@@ -8270,6 +8284,18 @@ spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& n
|
|||||||
|
|
||||||
// We now know we have a specialization constant to build
|
// We now know we have a specialization constant to build
|
||||||
|
|
||||||
|
// Extra capabilities may be needed.
|
||||||
|
if (node.getType().contains8BitInt())
|
||||||
|
builder.addCapability(spv::CapabilityInt8);
|
||||||
|
if (node.getType().contains16BitFloat())
|
||||||
|
builder.addCapability(spv::CapabilityFloat16);
|
||||||
|
if (node.getType().contains16BitInt())
|
||||||
|
builder.addCapability(spv::CapabilityInt16);
|
||||||
|
if (node.getType().contains64BitInt())
|
||||||
|
builder.addCapability(spv::CapabilityInt64);
|
||||||
|
if (node.getType().containsDouble())
|
||||||
|
builder.addCapability(spv::CapabilityFloat64);
|
||||||
|
|
||||||
// gl_WorkGroupSize is a special case until the front-end handles hierarchical specialization constants,
|
// gl_WorkGroupSize is a special case until the front-end handles hierarchical specialization constants,
|
||||||
// even then, it's specialization ids are handled by special case syntax in GLSL: layout(local_size_x = ...
|
// even then, it's specialization ids are handled by special case syntax in GLSL: layout(local_size_x = ...
|
||||||
if (node.getType().getQualifier().builtIn == glslang::EbvWorkGroupSize) {
|
if (node.getType().getQualifier().builtIn == glslang::EbvWorkGroupSize) {
|
||||||
|
|||||||
@@ -50,11 +50,11 @@ namespace spv {
|
|||||||
typedef unsigned int Id;
|
typedef unsigned int Id;
|
||||||
|
|
||||||
#define SPV_VERSION 0x10500
|
#define SPV_VERSION 0x10500
|
||||||
#define SPV_REVISION 1
|
#define SPV_REVISION 3
|
||||||
|
|
||||||
static const unsigned int MagicNumber = 0x07230203;
|
static const unsigned int MagicNumber = 0x07230203;
|
||||||
static const unsigned int Version = 0x00010500;
|
static const unsigned int Version = 0x00010500;
|
||||||
static const unsigned int Revision = 1;
|
static const unsigned int Revision = 3;
|
||||||
static const unsigned int OpCodeMask = 0xffff;
|
static const unsigned int OpCodeMask = 0xffff;
|
||||||
static const unsigned int WordCountShift = 16;
|
static const unsigned int WordCountShift = 16;
|
||||||
|
|
||||||
|
|||||||
@@ -231,6 +231,9 @@ enum TBuiltInVariable {
|
|||||||
EbvFragSizeEXT,
|
EbvFragSizeEXT,
|
||||||
EbvFragInvocationCountEXT,
|
EbvFragInvocationCountEXT,
|
||||||
|
|
||||||
|
EbvSecondaryFragDataEXT,
|
||||||
|
EbvSecondaryFragColorEXT,
|
||||||
|
|
||||||
EbvViewportMaskNV,
|
EbvViewportMaskNV,
|
||||||
EbvSecondaryPositionNV,
|
EbvSecondaryPositionNV,
|
||||||
EbvSecondaryViewportMaskNV,
|
EbvSecondaryViewportMaskNV,
|
||||||
@@ -433,6 +436,9 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
|
|||||||
case EbvFragSizeEXT: return "FragSizeEXT";
|
case EbvFragSizeEXT: return "FragSizeEXT";
|
||||||
case EbvFragInvocationCountEXT: return "FragInvocationCountEXT";
|
case EbvFragInvocationCountEXT: return "FragInvocationCountEXT";
|
||||||
|
|
||||||
|
case EbvSecondaryFragDataEXT: return "SecondaryFragDataEXT";
|
||||||
|
case EbvSecondaryFragColorEXT: return "SecondaryFragColorEXT";
|
||||||
|
|
||||||
case EbvViewportMaskNV: return "ViewportMaskNV";
|
case EbvViewportMaskNV: return "ViewportMaskNV";
|
||||||
case EbvSecondaryPositionNV: return "SecondaryPositionNV";
|
case EbvSecondaryPositionNV: return "SecondaryPositionNV";
|
||||||
case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
|
case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ struct TBuiltInResource {
|
|||||||
int maxTaskWorkGroupSizeY_NV;
|
int maxTaskWorkGroupSizeY_NV;
|
||||||
int maxTaskWorkGroupSizeZ_NV;
|
int maxTaskWorkGroupSizeZ_NV;
|
||||||
int maxMeshViewCountNV;
|
int maxMeshViewCountNV;
|
||||||
|
int maxDualSourceDrawBuffersEXT;
|
||||||
|
|
||||||
TLimits limits;
|
TLimits limits;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1235,6 +1235,7 @@ struct TShaderQualifiers {
|
|||||||
bool layoutDerivativeGroupQuads; // true if layout derivative_group_quadsNV set
|
bool layoutDerivativeGroupQuads; // true if layout derivative_group_quadsNV set
|
||||||
bool layoutDerivativeGroupLinear; // true if layout derivative_group_linearNV set
|
bool layoutDerivativeGroupLinear; // true if layout derivative_group_linearNV set
|
||||||
int primitives; // mesh shader "max_primitives"DerivativeGroupLinear; // 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; }
|
TLayoutDepth getDepth() const { return layoutDepth; }
|
||||||
#else
|
#else
|
||||||
TLayoutDepth getDepth() const { return EldNone; }
|
TLayoutDepth getDepth() const { return EldNone; }
|
||||||
@@ -1268,6 +1269,7 @@ struct TShaderQualifiers {
|
|||||||
layoutOverrideCoverage = false;
|
layoutOverrideCoverage = false;
|
||||||
layoutDerivativeGroupQuads = false;
|
layoutDerivativeGroupQuads = false;
|
||||||
layoutDerivativeGroupLinear = false;
|
layoutDerivativeGroupLinear = false;
|
||||||
|
layoutPrimitiveCulling = false;
|
||||||
primitives = TQualifier::layoutNotSet;
|
primitives = TQualifier::layoutNotSet;
|
||||||
interlockOrdering = EioNone;
|
interlockOrdering = EioNone;
|
||||||
#endif
|
#endif
|
||||||
@@ -1331,6 +1333,8 @@ struct TShaderQualifiers {
|
|||||||
primitives = src.primitives;
|
primitives = src.primitives;
|
||||||
if (src.interlockOrdering != EioNone)
|
if (src.interlockOrdering != EioNone)
|
||||||
interlockOrdering = src.interlockOrdering;
|
interlockOrdering = src.interlockOrdering;
|
||||||
|
if (src.layoutPrimitiveCulling)
|
||||||
|
layoutPrimitiveCulling = src.layoutPrimitiveCulling;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ typedef struct glslang_resource_s {
|
|||||||
int max_task_work_group_size_y_nv;
|
int max_task_work_group_size_y_nv;
|
||||||
int max_task_work_group_size_z_nv;
|
int max_task_work_group_size_z_nv;
|
||||||
int max_mesh_view_count_nv;
|
int max_mesh_view_count_nv;
|
||||||
|
int maxDualSourceDrawBuffersEXT;
|
||||||
|
|
||||||
glslang_limits_t limits;
|
glslang_limits_t limits;
|
||||||
} glslang_resource_t;
|
} glslang_resource_t;
|
||||||
|
|||||||
@@ -164,6 +164,9 @@ typedef enum {
|
|||||||
GLSLANG_REFLECTION_SEPARATE_BUFFERS_BIT = (1 << 3),
|
GLSLANG_REFLECTION_SEPARATE_BUFFERS_BIT = (1 << 3),
|
||||||
GLSLANG_REFLECTION_ALL_BLOCK_VARIABLES_BIT = (1 << 4),
|
GLSLANG_REFLECTION_ALL_BLOCK_VARIABLES_BIT = (1 << 4),
|
||||||
GLSLANG_REFLECTION_UNWRAP_IO_BLOCKS_BIT = (1 << 5),
|
GLSLANG_REFLECTION_UNWRAP_IO_BLOCKS_BIT = (1 << 5),
|
||||||
|
GLSLANG_REFLECTION_ALL_IO_VARIABLES_BIT = (1 << 6),
|
||||||
|
GLSLANG_REFLECTION_SHARED_STD140_SSBO_BIT = (1 << 7),
|
||||||
|
GLSLANG_REFLECTION_SHARED_STD140_UBO_BIT = (1 << 8),
|
||||||
LAST_ELEMENT_MARKER(GLSLANG_REFLECTION_COUNT),
|
LAST_ELEMENT_MARKER(GLSLANG_REFLECTION_COUNT),
|
||||||
} glslang_reflection_options_t;
|
} glslang_reflection_options_t;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
// This header is generated by the make-revision script.
|
// This header is generated by the make-revision script.
|
||||||
|
|
||||||
#define GLSLANG_PATCH_LEVEL 3741
|
#define GLSLANG_PATCH_LEVEL 3766
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ EProfile EDesktopProfile = static_cast<EProfile>(ENoProfile | ECoreProfile | ECo
|
|||||||
// Declare pointers to put into the table for versioning.
|
// Declare pointers to put into the table for versioning.
|
||||||
#ifdef GLSLANG_WEB
|
#ifdef GLSLANG_WEB
|
||||||
const Versioning* Es300Desktop130 = nullptr;
|
const Versioning* Es300Desktop130 = nullptr;
|
||||||
const Versioning* Es310Desktop430 = nullptr;
|
const Versioning* Es310Desktop420 = nullptr;
|
||||||
#else
|
#else
|
||||||
const Versioning Es300Desktop130Version[] = { { EEsProfile, 0, 300, 0, nullptr },
|
const Versioning Es300Desktop130Version[] = { { EEsProfile, 0, 300, 0, nullptr },
|
||||||
{ EDesktopProfile, 0, 130, 0, nullptr },
|
{ EDesktopProfile, 0, 130, 0, nullptr },
|
||||||
@@ -158,11 +158,6 @@ EProfile EDesktopProfile = static_cast<EProfile>(ENoProfile | ECoreProfile | ECo
|
|||||||
{ EBadProfile } };
|
{ EBadProfile } };
|
||||||
const Versioning* Es310Desktop420 = &Es310Desktop420Version[0];
|
const Versioning* Es310Desktop420 = &Es310Desktop420Version[0];
|
||||||
|
|
||||||
const Versioning Es310Desktop430Version[] = { { EEsProfile, 0, 310, 0, nullptr },
|
|
||||||
{ EDesktopProfile, 0, 430, 0, nullptr },
|
|
||||||
{ EBadProfile } };
|
|
||||||
const Versioning* Es310Desktop430 = &Es310Desktop430Version[0];
|
|
||||||
|
|
||||||
const Versioning Es310Desktop450Version[] = { { EEsProfile, 0, 310, 0, nullptr },
|
const Versioning Es310Desktop450Version[] = { { EEsProfile, 0, 310, 0, nullptr },
|
||||||
{ EDesktopProfile, 0, 450, 0, nullptr },
|
{ EDesktopProfile, 0, 450, 0, nullptr },
|
||||||
{ EBadProfile } };
|
{ EBadProfile } };
|
||||||
@@ -1349,7 +1344,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((profile == EEsProfile && version >= 300) ||
|
if ((profile == EEsProfile && version >= 300) ||
|
||||||
(profile != EEsProfile && version >= 400)) {
|
(profile != EEsProfile && version >= 150)) {
|
||||||
commonBuiltins.append(
|
commonBuiltins.append(
|
||||||
"highp uint packUnorm2x16(vec2);"
|
"highp uint packUnorm2x16(vec2);"
|
||||||
"vec2 unpackUnorm2x16(highp uint);"
|
"vec2 unpackUnorm2x16(highp uint);"
|
||||||
@@ -1357,7 +1352,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((profile == EEsProfile && version >= 300) ||
|
if ((profile == EEsProfile && version >= 300) ||
|
||||||
(profile != EEsProfile && version >= 420)) {
|
(profile != EEsProfile && version >= 150)) {
|
||||||
commonBuiltins.append(
|
commonBuiltins.append(
|
||||||
"highp uint packSnorm2x16(vec2);"
|
"highp uint packSnorm2x16(vec2);"
|
||||||
" vec2 unpackSnorm2x16(highp uint);"
|
" vec2 unpackSnorm2x16(highp uint);"
|
||||||
@@ -1369,7 +1364,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
commonBuiltins.append(
|
commonBuiltins.append(
|
||||||
"mediump vec2 unpackHalf2x16(highp uint);"
|
"mediump vec2 unpackHalf2x16(highp uint);"
|
||||||
"\n");
|
"\n");
|
||||||
} else if (profile != EEsProfile && version >= 420) {
|
} else if (profile != EEsProfile && version >= 150) {
|
||||||
commonBuiltins.append(
|
commonBuiltins.append(
|
||||||
" vec2 unpackHalf2x16(highp uint);"
|
" vec2 unpackHalf2x16(highp uint);"
|
||||||
"\n");
|
"\n");
|
||||||
@@ -1377,7 +1372,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
if ((profile == EEsProfile && version >= 310) ||
|
if ((profile == EEsProfile && version >= 310) ||
|
||||||
(profile != EEsProfile && version >= 400)) {
|
(profile != EEsProfile && version >= 150)) {
|
||||||
commonBuiltins.append(
|
commonBuiltins.append(
|
||||||
"highp uint packSnorm4x8(vec4);"
|
"highp uint packSnorm4x8(vec4);"
|
||||||
"highp uint packUnorm4x8(vec4);"
|
"highp uint packUnorm4x8(vec4);"
|
||||||
@@ -1389,7 +1384,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
"mediump vec4 unpackSnorm4x8(highp uint);"
|
"mediump vec4 unpackSnorm4x8(highp uint);"
|
||||||
"mediump vec4 unpackUnorm4x8(highp uint);"
|
"mediump vec4 unpackUnorm4x8(highp uint);"
|
||||||
"\n");
|
"\n");
|
||||||
} else if (profile != EEsProfile && version >= 400) {
|
} else if (profile != EEsProfile && version >= 150) {
|
||||||
commonBuiltins.append(
|
commonBuiltins.append(
|
||||||
"vec4 unpackSnorm4x8(highp uint);"
|
"vec4 unpackSnorm4x8(highp uint);"
|
||||||
"vec4 unpackUnorm4x8(highp uint);"
|
"vec4 unpackUnorm4x8(highp uint);"
|
||||||
@@ -3072,6 +3067,24 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
|
|||||||
"\n");
|
"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((profile == EEsProfile && version >= 300 && version < 310) ||
|
||||||
|
(profile != EEsProfile && version >= 150 && version < 450)) { // GL_EXT_shader_integer_mix
|
||||||
|
commonBuiltins.append("int mix(int, int, bool);"
|
||||||
|
"ivec2 mix(ivec2, ivec2, bvec2);"
|
||||||
|
"ivec3 mix(ivec3, ivec3, bvec3);"
|
||||||
|
"ivec4 mix(ivec4, ivec4, bvec4);"
|
||||||
|
"uint mix(uint, uint, bool );"
|
||||||
|
"uvec2 mix(uvec2, uvec2, bvec2);"
|
||||||
|
"uvec3 mix(uvec3, uvec3, bvec3);"
|
||||||
|
"uvec4 mix(uvec4, uvec4, bvec4);"
|
||||||
|
"bool mix(bool, bool, bool );"
|
||||||
|
"bvec2 mix(bvec2, bvec2, bvec2);"
|
||||||
|
"bvec3 mix(bvec3, bvec3, bvec3);"
|
||||||
|
"bvec4 mix(bvec4, bvec4, bvec4);"
|
||||||
|
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
|
||||||
// GL_AMD_gpu_shader_half_float/Explicit types
|
// GL_AMD_gpu_shader_half_float/Explicit types
|
||||||
if (profile != EEsProfile && version >= 450) {
|
if (profile != EEsProfile && version >= 450) {
|
||||||
commonBuiltins.append(
|
commonBuiltins.append(
|
||||||
@@ -5864,9 +5877,9 @@ void TBuiltIns::addQueryFunctions(TSampler sampler, const TString& typeName, int
|
|||||||
|
|
||||||
//
|
//
|
||||||
// textureQueryLod(), fragment stage only
|
// textureQueryLod(), fragment stage only
|
||||||
//
|
// Also enabled with extension GL_ARB_texture_query_lod
|
||||||
|
|
||||||
if (profile != EEsProfile && version >= 400 && sampler.isCombined() && sampler.dim != EsdRect &&
|
if (profile != EEsProfile && version >= 150 && sampler.isCombined() && sampler.dim != EsdRect &&
|
||||||
! sampler.isMultiSample() && ! sampler.isBuffer()) {
|
! sampler.isMultiSample() && ! sampler.isBuffer()) {
|
||||||
for (int f16TexAddr = 0; f16TexAddr < 2; ++f16TexAddr) {
|
for (int f16TexAddr = 0; f16TexAddr < 2; ++f16TexAddr) {
|
||||||
if (f16TexAddr && sampler.type != EbtFloat16)
|
if (f16TexAddr && sampler.type != EbtFloat16)
|
||||||
@@ -6758,6 +6771,18 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf
|
|||||||
s.append(builtInConstant);
|
s.append(builtInConstant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version >= 100) {
|
||||||
|
// GL_EXT_blend_func_extended
|
||||||
|
snprintf(builtInConstant, maxSize, "const mediump int gl_MaxDualSourceDrawBuffersEXT = %d;", resources.maxDualSourceDrawBuffersEXT);
|
||||||
|
s.append(builtInConstant);
|
||||||
|
// this is here instead of with the others in initialize(version, profile) due to the dependence on gl_MaxDualSourceDrawBuffersEXT
|
||||||
|
if (language == EShLangFragment) {
|
||||||
|
s.append(
|
||||||
|
"mediump vec4 gl_SecondaryFragColorEXT;"
|
||||||
|
"mediump vec4 gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT];"
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// non-ES profile
|
// non-ES profile
|
||||||
|
|
||||||
@@ -7570,6 +7595,10 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
BuiltInVariable("gl_FragStencilRefARB", EbvFragStencilRef, symbolTable);
|
BuiltInVariable("gl_FragStencilRefARB", EbvFragStencilRef, symbolTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (profile != EEsProfile && version < 400) {
|
||||||
|
symbolTable.setFunctionExtensions("textureQueryLod", 1, &E_GL_ARB_texture_query_lod);
|
||||||
|
}
|
||||||
|
|
||||||
if (profile != EEsProfile && version >= 460) {
|
if (profile != EEsProfile && version >= 460) {
|
||||||
symbolTable.setFunctionExtensions("rayQueryInitializeEXT", 1, &E_GL_EXT_ray_query);
|
symbolTable.setFunctionExtensions("rayQueryInitializeEXT", 1, &E_GL_EXT_ray_query);
|
||||||
symbolTable.setFunctionExtensions("rayQueryTerminateEXT", 1, &E_GL_EXT_ray_query);
|
symbolTable.setFunctionExtensions("rayQueryTerminateEXT", 1, &E_GL_EXT_ray_query);
|
||||||
@@ -7880,6 +7909,22 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
symbolTable.setFunctionExtensions("atomicCompSwap", 1, &E_GL_ARB_shader_storage_buffer_object);
|
symbolTable.setFunctionExtensions("atomicCompSwap", 1, &E_GL_ARB_shader_storage_buffer_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GL_ARB_shading_language_packing
|
||||||
|
if (profile != EEsProfile && version < 400 ) {
|
||||||
|
symbolTable.setFunctionExtensions("packUnorm2x16", 1, &E_GL_ARB_shading_language_packing);
|
||||||
|
symbolTable.setFunctionExtensions("unpackUnorm2x16", 1, &E_GL_ARB_shading_language_packing);
|
||||||
|
symbolTable.setFunctionExtensions("packSnorm4x8", 1, &E_GL_ARB_shading_language_packing);
|
||||||
|
symbolTable.setFunctionExtensions("packUnorm4x8", 1, &E_GL_ARB_shading_language_packing);
|
||||||
|
symbolTable.setFunctionExtensions("unpackSnorm4x8", 1, &E_GL_ARB_shading_language_packing);
|
||||||
|
symbolTable.setFunctionExtensions("unpackUnorm4x8", 1, &E_GL_ARB_shading_language_packing);
|
||||||
|
}
|
||||||
|
if (profile != EEsProfile && version < 420 ) {
|
||||||
|
symbolTable.setFunctionExtensions("packSnorm2x16", 1, &E_GL_ARB_shading_language_packing);
|
||||||
|
symbolTable.setFunctionExtensions("unpackSnorm2x16", 1, &E_GL_ARB_shading_language_packing);
|
||||||
|
symbolTable.setFunctionExtensions("unpackHalf2x16", 1, &E_GL_ARB_shading_language_packing);
|
||||||
|
symbolTable.setFunctionExtensions("packHalf2x16", 1, &E_GL_ARB_shading_language_packing);
|
||||||
|
}
|
||||||
|
|
||||||
symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group);
|
symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group);
|
||||||
BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
|
BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
|
||||||
symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview);
|
symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview);
|
||||||
@@ -8091,6 +8136,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
symbolTable.setFunctionExtensions("groupMemoryBarrier", 1, &E_GL_ARB_compute_shader);
|
symbolTable.setFunctionExtensions("groupMemoryBarrier", 1, &E_GL_ARB_compute_shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
symbolTable.setFunctionExtensions("controlBarrier", 1, &E_GL_KHR_memory_scope_semantics);
|
symbolTable.setFunctionExtensions("controlBarrier", 1, &E_GL_KHR_memory_scope_semantics);
|
||||||
symbolTable.setFunctionExtensions("debugPrintfEXT", 1, &E_GL_EXT_debug_printf);
|
symbolTable.setFunctionExtensions("debugPrintfEXT", 1, &E_GL_EXT_debug_printf);
|
||||||
|
|
||||||
@@ -9131,6 +9177,16 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
|
|||||||
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData));
|
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData));
|
||||||
SpecialQualifier("gl_FragData", EvqFragColor, EbvFragData, symbolTable);
|
SpecialQualifier("gl_FragData", EvqFragColor, EbvFragData, symbolTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GL_EXT_blend_func_extended
|
||||||
|
if (profile == EEsProfile && version >= 100) {
|
||||||
|
symbolTable.setVariableExtensions("gl_MaxDualSourceDrawBuffersEXT", 1, &E_GL_EXT_blend_func_extended);
|
||||||
|
symbolTable.setVariableExtensions("gl_SecondaryFragColorEXT", 1, &E_GL_EXT_blend_func_extended);
|
||||||
|
symbolTable.setVariableExtensions("gl_SecondaryFragDataEXT", 1, &E_GL_EXT_blend_func_extended);
|
||||||
|
SpecialQualifier("gl_SecondaryFragColorEXT", EvqVaryingOut, EbvSecondaryFragColorEXT, symbolTable);
|
||||||
|
SpecialQualifier("gl_SecondaryFragDataEXT", EvqVaryingOut, EbvSecondaryFragDataEXT, symbolTable);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EShLangTessControl:
|
case EShLangTessControl:
|
||||||
|
|||||||
@@ -1620,7 +1620,7 @@ bool TIntermediate::isFPIntegralConversion(TBasicType from, TBasicType to) const
|
|||||||
//
|
//
|
||||||
bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op) const
|
bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op) const
|
||||||
{
|
{
|
||||||
if (isEsProfile() || version == 110)
|
if ((isEsProfile() && version < 310 ) || version == 110)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (from == to)
|
if (from == to)
|
||||||
@@ -1699,6 +1699,30 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
|
|||||||
if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat))
|
if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
} else if (isEsProfile()) {
|
||||||
|
switch (to) {
|
||||||
|
case EbtFloat:
|
||||||
|
switch (from) {
|
||||||
|
case EbtInt:
|
||||||
|
case EbtUint:
|
||||||
|
return extensionRequested(E_GL_EXT_shader_implicit_conversions);
|
||||||
|
case EbtFloat:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case EbtUint:
|
||||||
|
switch (from) {
|
||||||
|
case EbtInt:
|
||||||
|
return extensionRequested(E_GL_EXT_shader_implicit_conversions);
|
||||||
|
case EbtUint:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (to) {
|
switch (to) {
|
||||||
case EbtDouble:
|
case EbtDouble:
|
||||||
@@ -1709,12 +1733,14 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
|
|||||||
case EbtUint64:
|
case EbtUint64:
|
||||||
case EbtFloat:
|
case EbtFloat:
|
||||||
case EbtDouble:
|
case EbtDouble:
|
||||||
return true;
|
return version >= 400 || extensionRequested(E_GL_ARB_gpu_shader_fp64);
|
||||||
case EbtInt16:
|
case EbtInt16:
|
||||||
case EbtUint16:
|
case EbtUint16:
|
||||||
return extensionRequested(E_GL_AMD_gpu_shader_int16);
|
return (version >= 400 || extensionRequested(E_GL_ARB_gpu_shader_fp64)) &&
|
||||||
|
extensionRequested(E_GL_AMD_gpu_shader_int16);
|
||||||
case EbtFloat16:
|
case EbtFloat16:
|
||||||
return extensionRequested(E_GL_AMD_gpu_shader_half_float);
|
return (version >= 400 || extensionRequested(E_GL_ARB_gpu_shader_fp64)) &&
|
||||||
|
extensionRequested(E_GL_AMD_gpu_shader_half_float);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1731,15 +1757,14 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
|
|||||||
return extensionRequested(E_GL_AMD_gpu_shader_int16);
|
return extensionRequested(E_GL_AMD_gpu_shader_int16);
|
||||||
case EbtFloat16:
|
case EbtFloat16:
|
||||||
return
|
return
|
||||||
extensionRequested(E_GL_AMD_gpu_shader_half_float) ||
|
extensionRequested(E_GL_AMD_gpu_shader_half_float) || getSource() == EShSourceHlsl;
|
||||||
getSource() == EShSourceHlsl;
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case EbtUint:
|
case EbtUint:
|
||||||
switch (from) {
|
switch (from) {
|
||||||
case EbtInt:
|
case EbtInt:
|
||||||
return version >= 400 || getSource() == EShSourceHlsl;
|
return version >= 400 || getSource() == EShSourceHlsl;
|
||||||
case EbtUint:
|
case EbtUint:
|
||||||
return true;
|
return true;
|
||||||
case EbtBool:
|
case EbtBool:
|
||||||
@@ -1931,7 +1956,9 @@ std::tuple<TBasicType, TBasicType> TIntermediate::getConversionDestinatonType(TB
|
|||||||
TBasicType res0 = EbtNumTypes;
|
TBasicType res0 = EbtNumTypes;
|
||||||
TBasicType res1 = EbtNumTypes;
|
TBasicType res1 = EbtNumTypes;
|
||||||
|
|
||||||
if (isEsProfile() || version == 110)
|
if ((isEsProfile() &&
|
||||||
|
(version < 310 || !extensionRequested(E_GL_EXT_shader_implicit_conversions))) ||
|
||||||
|
version == 110)
|
||||||
return std::make_tuple(res0, res1);
|
return std::make_tuple(res0, res1);
|
||||||
|
|
||||||
if (getSource() == EShSourceHlsl) {
|
if (getSource() == EShSourceHlsl) {
|
||||||
|
|||||||
@@ -428,8 +428,18 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
|
|||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
if (base->isReference() && ! base->isArray()) {
|
if (base->isReference() && ! base->isArray()) {
|
||||||
requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "buffer reference indexing");
|
requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "buffer reference indexing");
|
||||||
result = intermediate.addBinaryMath(EOpAdd, base, index, loc);
|
if (base->getType().getReferentType()->containsUnsizedArray()) {
|
||||||
result->setType(base->getType());
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
|
if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
|
||||||
@@ -822,50 +832,7 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
|
|||||||
TIntermTyped* result = base;
|
TIntermTyped* result = base;
|
||||||
if ((base->isVector() || base->isScalar()) &&
|
if ((base->isVector() || base->isScalar()) &&
|
||||||
(base->isFloatingDomain() || base->isIntegerDomain() || base->getBasicType() == EbtBool)) {
|
(base->isFloatingDomain() || base->isIntegerDomain() || base->getBasicType() == EbtBool)) {
|
||||||
if (base->isScalar()) {
|
result = handleDotSwizzle(loc, base, field);
|
||||||
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();
|
|
||||||
}
|
|
||||||
} else if (base->isStruct() || base->isReference()) {
|
} else if (base->isStruct() || base->isReference()) {
|
||||||
const TTypeList* fields = base->isReference() ?
|
const TTypeList* fields = base->isReference() ?
|
||||||
base->getType().getReferentType()->getStruct() :
|
base->getType().getReferentType()->getStruct() :
|
||||||
@@ -906,6 +873,60 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
|
|||||||
return result;
|
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)
|
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,
|
// a block that needs extension checking is either 'base', or if arrayed,
|
||||||
@@ -2198,6 +2219,28 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
|
|||||||
memorySemanticsCheck(loc, fnCandidate, callNode);
|
memorySemanticsCheck(loc, fnCandidate, callNode);
|
||||||
}
|
}
|
||||||
break;
|
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
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -3354,6 +3397,11 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
|
|||||||
!qualifier.hasBufferReference())
|
!qualifier.hasBufferReference())
|
||||||
error(loc, "buffers can be declared only as blocks", "buffer", "");
|
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)
|
if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -3404,7 +3452,7 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
|
|||||||
profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays");
|
profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays");
|
||||||
}
|
}
|
||||||
if (publicType.basicType == EbtDouble)
|
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)
|
if (qualifier.isAuxiliary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.invariant)
|
||||||
error(loc, "vertex input cannot be further qualified", "", "");
|
error(loc, "vertex input cannot be further qualified", "", "");
|
||||||
break;
|
break;
|
||||||
@@ -5125,6 +5173,12 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (id == "primitive_culling") {
|
||||||
|
requireExtensions(loc, 1, &E_GL_EXT_ray_flags_primitive_culling, "primitive culling");
|
||||||
|
publicType.shaderQualifiers.layoutPrimitiveCulling = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), "");
|
error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), "");
|
||||||
@@ -5385,10 +5439,10 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
|
|||||||
|
|
||||||
case EShLangFragment:
|
case EShLangFragment:
|
||||||
if (id == "index") {
|
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 };
|
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, 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."
|
// "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) {
|
if (value < 0 || value > 1) {
|
||||||
value = 0;
|
value = 0;
|
||||||
@@ -6056,6 +6110,8 @@ void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQua
|
|||||||
error(loc, message, "num_views", "");
|
error(loc, message, "num_views", "");
|
||||||
if (shaderQualifiers.interlockOrdering != EioNone)
|
if (shaderQualifiers.interlockOrdering != EioNone)
|
||||||
error(loc, message, TQualifier::getInterlockOrderingString(shaderQualifiers.interlockOrdering), "");
|
error(loc, message, TQualifier::getInterlockOrderingString(shaderQualifiers.interlockOrdering), "");
|
||||||
|
if (shaderQualifiers.layoutPrimitiveCulling)
|
||||||
|
error(loc, "can only be applied as standalone", "primitive_culling", "");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6135,7 +6191,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_float32) ||
|
||||||
extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64);
|
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);
|
function = findFunctionExact(loc, call, builtIn);
|
||||||
else if (version < 400)
|
else if (version < 400)
|
||||||
function = extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) ? findFunction400(loc, call, builtIn) : findFunction120(loc, call, builtIn);
|
function = extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) ? findFunction400(loc, call, builtIn) : findFunction120(loc, call, builtIn);
|
||||||
@@ -7542,6 +7601,8 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
|
|||||||
fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation);
|
fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation);
|
||||||
fixXfbOffsets(currentBlockQualifier, typeList);
|
fixXfbOffsets(currentBlockQualifier, typeList);
|
||||||
fixBlockUniformOffsets(currentBlockQualifier, typeList);
|
fixBlockUniformOffsets(currentBlockQualifier, typeList);
|
||||||
|
fixBlockUniformLayoutMatrix(currentBlockQualifier, &typeList, nullptr);
|
||||||
|
fixBlockUniformLayoutPacking(currentBlockQualifier, &typeList, nullptr);
|
||||||
for (unsigned int member = 0; member < typeList.size(); ++member)
|
for (unsigned int member = 0; member < typeList.size(); ++member)
|
||||||
layoutTypeCheck(typeList[member].loc, *typeList[member].type);
|
layoutTypeCheck(typeList[member].loc, *typeList[member].type);
|
||||||
|
|
||||||
@@ -7912,6 +7973,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.
|
// For an identifier that is already declared, add more qualification to it.
|
||||||
void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, const TString& identifier)
|
void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, const TString& identifier)
|
||||||
{
|
{
|
||||||
@@ -8220,6 +8376,16 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con
|
|||||||
{
|
{
|
||||||
checkIoArraysConsistency(loc);
|
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
|
#endif
|
||||||
const TQualifier& qualifier = publicType.qualifier;
|
const TQualifier& qualifier = publicType.qualifier;
|
||||||
|
|
||||||
@@ -8370,5 +8536,43 @@ TIntermNode* TParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expre
|
|||||||
return switchNode;
|
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
|
} // end namespace glslang
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ class TScanContext;
|
|||||||
class TPpContext;
|
class TPpContext;
|
||||||
|
|
||||||
typedef std::set<int> TIdSetType;
|
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
|
// Sharable code (as well as what's in TParseVersions) across
|
||||||
@@ -315,6 +316,7 @@ public:
|
|||||||
TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
|
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* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
|
||||||
TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
|
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);
|
void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName);
|
||||||
TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
|
TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
|
||||||
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
|
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
|
||||||
@@ -417,12 +419,15 @@ public:
|
|||||||
void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
|
void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
|
||||||
void fixXfbOffsets(TQualifier&, TTypeList&);
|
void fixXfbOffsets(TQualifier&, TTypeList&);
|
||||||
void fixBlockUniformOffsets(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, const TString& identifier);
|
||||||
void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
|
void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
|
||||||
void invariantCheck(const TSourceLoc&, const TQualifier&);
|
void invariantCheck(const TSourceLoc&, const TQualifier&);
|
||||||
void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
|
void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
|
||||||
void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
|
void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
|
||||||
TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
|
TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
|
||||||
|
const TTypeList* recordStructCopy(TStructRecord&, const TType*, const TType*);
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
#ifndef GLSLANG_WEB
|
||||||
TAttributeType attributeFromName(const TString& name) const;
|
TAttributeType attributeFromName(const TString& name) const;
|
||||||
@@ -483,6 +488,8 @@ protected:
|
|||||||
bool anyIndexLimits;
|
bool anyIndexLimits;
|
||||||
TIdSetType inductiveLoopIds;
|
TIdSetType inductiveLoopIds;
|
||||||
TVector<TIntermTyped*> needsIndexLimitationChecking;
|
TVector<TIntermTyped*> needsIndexLimitationChecking;
|
||||||
|
TStructRecord matrixFixRecord;
|
||||||
|
TStructRecord packingFixRecord;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Geometry shader input arrays:
|
// Geometry shader input arrays:
|
||||||
|
|||||||
@@ -1196,8 +1196,8 @@ int TScanContext::tokenizeIdentifier()
|
|||||||
afterType = true;
|
afterType = true;
|
||||||
if (parseContext.isEsProfile() || parseContext.version < 150 ||
|
if (parseContext.isEsProfile() || parseContext.version < 150 ||
|
||||||
(!parseContext.symbolTable.atBuiltInLevel() &&
|
(!parseContext.symbolTable.atBuiltInLevel() &&
|
||||||
parseContext.version < 400 &&
|
(parseContext.version < 400 && !parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) &&
|
||||||
!parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64)))
|
(parseContext.version < 410 && !parseContext.extensionTurnedOn(E_GL_ARB_vertex_attrib_64bit)))))
|
||||||
reservedWord();
|
reservedWord();
|
||||||
return keyword;
|
return keyword;
|
||||||
|
|
||||||
@@ -1792,7 +1792,9 @@ int TScanContext::dMat()
|
|||||||
|
|
||||||
if (!parseContext.isEsProfile() && (parseContext.version >= 400 ||
|
if (!parseContext.isEsProfile() && (parseContext.version >= 400 ||
|
||||||
parseContext.symbolTable.atBuiltInLevel() ||
|
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;
|
return keyword;
|
||||||
|
|
||||||
if (parseContext.isForwardCompatible())
|
if (parseContext.isForwardCompatible())
|
||||||
|
|||||||
@@ -64,6 +64,7 @@
|
|||||||
// checkDeprecated()
|
// checkDeprecated()
|
||||||
// requireNotRemoved()
|
// requireNotRemoved()
|
||||||
// requireExtensions()
|
// requireExtensions()
|
||||||
|
// extensionRequires()
|
||||||
//
|
//
|
||||||
// Typically, only the first two calls are needed. They go into a code path that
|
// 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
|
// implements Feature F, and will log the proper error/warning messages. Parsing
|
||||||
@@ -78,9 +79,11 @@
|
|||||||
// const char* const XXX_extension_X = "XXX_extension_X";
|
// const char* const XXX_extension_X = "XXX_extension_X";
|
||||||
//
|
//
|
||||||
// 2) Add extension initialization to TParseVersions::initializeExtensionBehavior(),
|
// 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;
|
// 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():
|
// 3) Add any preprocessor directives etc. in the next function, TParseVersions::getPreamble():
|
||||||
//
|
//
|
||||||
@@ -140,6 +143,8 @@
|
|||||||
// set of extensions that both enable them and are necessary, given the version of the symbol
|
// 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.)
|
// 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 "parseVersions.h"
|
||||||
#include "localintermediate.h"
|
#include "localintermediate.h"
|
||||||
@@ -155,6 +160,20 @@ namespace glslang {
|
|||||||
//
|
//
|
||||||
void TParseVersions::initializeExtensionBehavior()
|
void TParseVersions::initializeExtensionBehavior()
|
||||||
{
|
{
|
||||||
|
typedef struct {
|
||||||
|
const char *const extensionName;
|
||||||
|
EShTargetLanguageVersion minSpvVersion;
|
||||||
|
} extensionData;
|
||||||
|
|
||||||
|
const extensionData exts[] = { {E_GL_EXT_ray_tracing, EShTargetSpv_1_4} };
|
||||||
|
|
||||||
|
for (int 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_texture_3D] = EBhDisable;
|
||||||
extensionBehavior[E_GL_OES_standard_derivatives] = EBhDisable;
|
extensionBehavior[E_GL_OES_standard_derivatives] = EBhDisable;
|
||||||
extensionBehavior[E_GL_EXT_frag_depth] = EBhDisable;
|
extensionBehavior[E_GL_EXT_frag_depth] = EBhDisable;
|
||||||
@@ -201,6 +220,9 @@ void TParseVersions::initializeExtensionBehavior()
|
|||||||
extensionBehavior[E_GL_ARB_shader_bit_encoding] = EBhDisable;
|
extensionBehavior[E_GL_ARB_shader_bit_encoding] = EBhDisable;
|
||||||
extensionBehavior[E_GL_ARB_shader_image_size] = EBhDisable;
|
extensionBehavior[E_GL_ARB_shader_image_size] = EBhDisable;
|
||||||
extensionBehavior[E_GL_ARB_shader_storage_buffer_object] = 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_basic] = EBhDisable;
|
||||||
extensionBehavior[E_GL_KHR_shader_subgroup_vote] = EBhDisable;
|
extensionBehavior[E_GL_KHR_shader_subgroup_vote] = EBhDisable;
|
||||||
@@ -295,6 +317,7 @@ void TParseVersions::initializeExtensionBehavior()
|
|||||||
extensionBehavior[E_GL_OES_tessellation_point_size] = EBhDisable;
|
extensionBehavior[E_GL_OES_tessellation_point_size] = EBhDisable;
|
||||||
extensionBehavior[E_GL_OES_texture_buffer] = EBhDisable;
|
extensionBehavior[E_GL_OES_texture_buffer] = EBhDisable;
|
||||||
extensionBehavior[E_GL_OES_texture_cube_map_array] = EBhDisable;
|
extensionBehavior[E_GL_OES_texture_cube_map_array] = EBhDisable;
|
||||||
|
extensionBehavior[E_GL_EXT_shader_integer_mix] = EBhDisable;
|
||||||
|
|
||||||
// EXT extensions
|
// EXT extensions
|
||||||
extensionBehavior[E_GL_EXT_device_group] = EBhDisable;
|
extensionBehavior[E_GL_EXT_device_group] = EBhDisable;
|
||||||
@@ -303,6 +326,8 @@ void TParseVersions::initializeExtensionBehavior()
|
|||||||
extensionBehavior[E_GL_EXT_ray_tracing] = EBhDisable;
|
extensionBehavior[E_GL_EXT_ray_tracing] = EBhDisable;
|
||||||
extensionBehavior[E_GL_EXT_ray_query] = EBhDisable;
|
extensionBehavior[E_GL_EXT_ray_query] = EBhDisable;
|
||||||
extensionBehavior[E_GL_EXT_ray_flags_primitive_culling] = 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
|
// OVR extensions
|
||||||
extensionBehavior[E_GL_OVR_multiview] = EBhDisable;
|
extensionBehavior[E_GL_OVR_multiview] = EBhDisable;
|
||||||
@@ -324,6 +349,7 @@ void TParseVersions::initializeExtensionBehavior()
|
|||||||
extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int64] = 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_subgroup_extended_types_float16] = EBhDisable;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GLSLANG_WEB
|
#endif // GLSLANG_WEB
|
||||||
|
|
||||||
// Get code that is not part of a shared symbol table, is specific to this shader,
|
// Get code that is not part of a shared symbol table, is specific to this shader,
|
||||||
@@ -362,6 +388,9 @@ void TParseVersions::getPreamble(std::string& preamble)
|
|||||||
"#define GL_EXT_tessellation_point_size 1\n"
|
"#define GL_EXT_tessellation_point_size 1\n"
|
||||||
"#define GL_EXT_texture_buffer 1\n"
|
"#define GL_EXT_texture_buffer 1\n"
|
||||||
"#define GL_EXT_texture_cube_map_array 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
|
// OES matching AEP
|
||||||
"#define GL_OES_geometry_shader 1\n"
|
"#define GL_OES_geometry_shader 1\n"
|
||||||
@@ -412,12 +441,15 @@ void TParseVersions::getPreamble(std::string& preamble)
|
|||||||
"#define GL_ARB_shader_stencil_export 1\n"
|
"#define GL_ARB_shader_stencil_export 1\n"
|
||||||
"#define GL_ARB_sample_shading 1\n"
|
"#define GL_ARB_sample_shading 1\n"
|
||||||
"#define GL_ARB_shader_image_size 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_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_post_depth_coverage 1\n"
|
||||||
"#define GL_ARB_fragment_shader_interlock 1\n"
|
"#define GL_ARB_fragment_shader_interlock 1\n"
|
||||||
"#define GL_ARB_uniform_buffer_object 1\n"
|
"#define GL_ARB_uniform_buffer_object 1\n"
|
||||||
"#define GL_ARB_shader_bit_encoding 1\n"
|
"#define GL_ARB_shader_bit_encoding 1\n"
|
||||||
"#define GL_ARB_shader_storage_buffer_object 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_non_constant_global_initializers 1\n"
|
||||||
"#define GL_EXT_shader_image_load_formatted 1\n"
|
"#define GL_EXT_shader_image_load_formatted 1\n"
|
||||||
"#define GL_EXT_post_depth_coverage 1\n"
|
"#define GL_EXT_post_depth_coverage 1\n"
|
||||||
@@ -819,6 +851,9 @@ void TParseVersions::updateExtensionBehavior(int line, const char* extension, co
|
|||||||
// check if extension is used with correct shader stage
|
// check if extension is used with correct shader stage
|
||||||
checkExtensionStage(getCurrentLoc(), extension);
|
checkExtensionStage(getCurrentLoc(), extension);
|
||||||
|
|
||||||
|
// check if extension has additional requirements
|
||||||
|
extensionRequires(getCurrentLoc(), extension ,behaviorString);
|
||||||
|
|
||||||
// update the requested extension
|
// update the requested extension
|
||||||
updateExtensionBehavior(extension, behavior);
|
updateExtensionBehavior(extension, behavior);
|
||||||
|
|
||||||
@@ -916,8 +951,8 @@ void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBe
|
|||||||
} else {
|
} else {
|
||||||
if (iter->second == EBhDisablePartial)
|
if (iter->second == EBhDisablePartial)
|
||||||
warn(getCurrentLoc(), "extension is only partially supported:", "#extension", extension);
|
warn(getCurrentLoc(), "extension is only partially supported:", "#extension", extension);
|
||||||
if (behavior == EBhEnable || behavior == EBhRequire)
|
if (behavior == EBhEnable || behavior == EBhRequire || behavior == EBhDisable)
|
||||||
intermediate.addRequestedExtension(extension);
|
intermediate.updateRequestedExtension(extension, behavior);
|
||||||
iter->second = behavior;
|
iter->second = behavior;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -935,6 +970,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.
|
// Call for any operation needing full GLSL integer data-type support.
|
||||||
void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
|
void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
|
||||||
{
|
{
|
||||||
@@ -945,8 +998,13 @@ void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
|
|||||||
// Call for any operation needing GLSL double data-type support.
|
// Call for any operation needing GLSL double data-type support.
|
||||||
void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op)
|
void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op)
|
||||||
{
|
{
|
||||||
|
|
||||||
//requireProfile(loc, ECoreProfile | ECompatibilityProfile, 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.
|
// Call for any operation needing GLSL float16 data-type support.
|
||||||
@@ -1187,5 +1245,12 @@ void TParseVersions::requireSpv(const TSourceLoc& loc, const char* op)
|
|||||||
error(loc, "only allowed when generating SPIR-V", op, "");
|
error(loc, "only allowed when generating SPIR-V", op, "");
|
||||||
#endif
|
#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
|
} // end namespace glslang
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef _VERSIONS_INCLUDED_
|
#ifndef _VERSIONS_INCLUDED_
|
||||||
#define _VERSIONS_INCLUDED_
|
#define _VERSIONS_INCLUDED_
|
||||||
|
|
||||||
@@ -52,7 +53,7 @@
|
|||||||
// Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible
|
// Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible
|
||||||
// defects from mixing the two different forms.
|
// defects from mixing the two different forms.
|
||||||
//
|
//
|
||||||
typedef enum {
|
typedef enum : unsigned {
|
||||||
EBadProfile = 0,
|
EBadProfile = 0,
|
||||||
ENoProfile = (1 << 0), // only for desktop, before profiles showed up
|
ENoProfile = (1 << 0), // only for desktop, before profiles showed up
|
||||||
ECoreProfile = (1 << 1),
|
ECoreProfile = (1 << 1),
|
||||||
@@ -156,6 +157,9 @@ 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_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_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_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_basic = "GL_KHR_shader_subgroup_basic";
|
||||||
const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote";
|
const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote";
|
||||||
@@ -194,6 +198,8 @@ const char* const E_GL_EXT_debug_printf = "GL_EXT_debug_prin
|
|||||||
const char* const E_GL_EXT_ray_tracing = "GL_EXT_ray_tracing";
|
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_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_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
|
// Arrays of extensions for the above viewportEXTs duplications
|
||||||
|
|
||||||
@@ -265,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_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_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_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
|
// OES matching AEP
|
||||||
const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader";
|
const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader";
|
||||||
|
|||||||
@@ -1466,7 +1466,7 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
|
|||||||
infoSink.debug << "Shader version: " << version << "\n";
|
infoSink.debug << "Shader version: " << version << "\n";
|
||||||
if (requestedExtensions.size() > 0) {
|
if (requestedExtensions.size() > 0) {
|
||||||
for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt)
|
for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt)
|
||||||
infoSink.debug << "Requested " << *extIt << "\n";
|
infoSink.debug << "Requested " << extIt->first << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xfbMode)
|
if (xfbMode)
|
||||||
|
|||||||
@@ -309,26 +309,43 @@ struct TSymbolValidater
|
|||||||
TIntermSymbol* base = ent1.symbol;
|
TIntermSymbol* base = ent1.symbol;
|
||||||
const TType& type = ent1.symbol->getType();
|
const TType& type = ent1.symbol->getType();
|
||||||
const TString& name = entKey.first;
|
const TString& name = entKey.first;
|
||||||
TString mangleName1, mangleName2;
|
|
||||||
type.appendMangledName(mangleName1);
|
|
||||||
EShLanguage stage = ent1.stage;
|
EShLanguage stage = ent1.stage;
|
||||||
|
TString mangleName1, mangleName2;
|
||||||
if (currentStage != stage) {
|
if (currentStage != stage) {
|
||||||
preStage = currentStage;
|
preStage = currentStage;
|
||||||
currentStage = stage;
|
currentStage = stage;
|
||||||
nextStage = EShLangCount;
|
nextStage = EShLangCount;
|
||||||
for (int i = currentStage + 1; i < EShLangCount; i++) {
|
for (int i = currentStage + 1; i < EShLangCount; i++) {
|
||||||
if (inVarMaps[i] != nullptr)
|
if (inVarMaps[i] != nullptr) {
|
||||||
nextStage = static_cast<EShLanguage>(i);
|
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) {
|
if (base->getQualifier().storage == EvqVaryingIn) {
|
||||||
// validate stage in;
|
// validate stage in;
|
||||||
if (preStage == EShLangCount)
|
if (preStage == EShLangCount)
|
||||||
return;
|
return;
|
||||||
|
if (name == "gl_PerVertex")
|
||||||
|
return;
|
||||||
if (outVarMaps[preStage] != nullptr) {
|
if (outVarMaps[preStage] != nullptr) {
|
||||||
auto ent2 = outVarMaps[preStage]->find(name);
|
auto ent2 = outVarMaps[preStage]->find(name);
|
||||||
if (ent2 != outVarMaps[preStage]->end()) {
|
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)
|
if (mangleName1 == mangleName2)
|
||||||
return;
|
return;
|
||||||
else {
|
else {
|
||||||
@@ -343,10 +360,18 @@ struct TSymbolValidater
|
|||||||
// validate stage out;
|
// validate stage out;
|
||||||
if (nextStage == EShLangCount)
|
if (nextStage == EShLangCount)
|
||||||
return;
|
return;
|
||||||
|
if (name == "gl_PerVertex")
|
||||||
|
return;
|
||||||
if (outVarMaps[nextStage] != nullptr) {
|
if (outVarMaps[nextStage] != nullptr) {
|
||||||
auto ent2 = inVarMaps[nextStage]->find(name);
|
auto ent2 = inVarMaps[nextStage]->find(name);
|
||||||
if (ent2 != inVarMaps[nextStage]->end()) {
|
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)
|
if (mangleName1 == mangleName2)
|
||||||
return;
|
return;
|
||||||
else {
|
else {
|
||||||
@@ -579,10 +604,7 @@ TDefaultGlslIoResolver::TDefaultGlslIoResolver(const TIntermediate& intermediate
|
|||||||
|
|
||||||
int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) {
|
int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) {
|
||||||
const TType& type = ent.symbol->getType();
|
const TType& type = ent.symbol->getType();
|
||||||
const TString& name = IsAnonymous(ent.symbol->getName()) ?
|
const TString& name = getAccessName(ent.symbol);
|
||||||
ent.symbol->getType().getTypeName()
|
|
||||||
:
|
|
||||||
ent.symbol->getName();
|
|
||||||
if (currentStage != stage) {
|
if (currentStage != stage) {
|
||||||
preStage = currentStage;
|
preStage = currentStage;
|
||||||
currentStage = stage;
|
currentStage = stage;
|
||||||
@@ -630,7 +652,7 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf
|
|||||||
TVarSlotMap::iterator iter = storageSlotMap[resourceKey].find(name);
|
TVarSlotMap::iterator iter = storageSlotMap[resourceKey].find(name);
|
||||||
if (iter != storageSlotMap[resourceKey].end()) {
|
if (iter != storageSlotMap[resourceKey].end()) {
|
||||||
// If interface resource be found, set it has location and this symbol's new location
|
// 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;
|
// vs: out vec4 a;
|
||||||
// fs: layout(..., location = 3,...) in vec4 a;
|
// fs: layout(..., location = 3,...) in vec4 a;
|
||||||
@@ -666,10 +688,7 @@ int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInf
|
|||||||
|
|
||||||
int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
|
int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
|
||||||
const TType& type = ent.symbol->getType();
|
const TType& type = ent.symbol->getType();
|
||||||
const TString& name = IsAnonymous(ent.symbol->getName()) ?
|
const TString& name = getAccessName(ent.symbol);
|
||||||
ent.symbol->getType().getTypeName()
|
|
||||||
:
|
|
||||||
ent.symbol->getName();
|
|
||||||
// kick out of not doing this
|
// kick out of not doing this
|
||||||
if (! doAutoLocationMapping()) {
|
if (! doAutoLocationMapping()) {
|
||||||
return ent.newLocation = -1;
|
return ent.newLocation = -1;
|
||||||
@@ -712,7 +731,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
|
|||||||
TVarSlotMap::iterator iter = slotMap.find(name);
|
TVarSlotMap::iterator iter = slotMap.find(name);
|
||||||
if (iter != slotMap.end()) {
|
if (iter != slotMap.end()) {
|
||||||
// If uniform resource be found, set it has location and this symbol's new location
|
// 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;
|
// vs: uniform vec4 a;
|
||||||
// fs: layout(..., location = 3,...) uniform vec4 a;
|
// fs: layout(..., location = 3,...) uniform vec4 a;
|
||||||
@@ -720,7 +739,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
|
|||||||
location = iter->second;
|
location = iter->second;
|
||||||
}
|
}
|
||||||
if (! hasLocation) {
|
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.
|
// So we should find a new slot for this uniform.
|
||||||
//
|
//
|
||||||
// vs: uniform vec4 a;
|
// vs: uniform vec4 a;
|
||||||
@@ -729,7 +748,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
|
|||||||
storageSlotMap[resourceKey][name] = location;
|
storageSlotMap[resourceKey][name] = location;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// the first uniform declarated in a program.
|
// the first uniform declaration in a program.
|
||||||
TVarSlotMap varSlotMap;
|
TVarSlotMap varSlotMap;
|
||||||
location = getFreeSlot(resourceKey, 0, size);
|
location = getFreeSlot(resourceKey, 0, size);
|
||||||
varSlotMap[name] = location;
|
varSlotMap[name] = location;
|
||||||
@@ -740,11 +759,8 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn
|
|||||||
|
|
||||||
int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) {
|
int TDefaultGlslIoResolver::resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) {
|
||||||
const TType& type = ent.symbol->getType();
|
const TType& type = ent.symbol->getType();
|
||||||
const TString& name = IsAnonymous(ent.symbol->getName()) ?
|
const TString& name = getAccessName(ent.symbol);
|
||||||
ent.symbol->getType().getTypeName()
|
// On OpenGL arrays of opaque types take a separate binding for each element
|
||||||
:
|
|
||||||
ent.symbol->getName();
|
|
||||||
// On OpenGL arrays of opaque types take a seperate binding for each element
|
|
||||||
int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
|
int numBindings = intermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
|
||||||
TResourceType resource = getResourceType(type);
|
TResourceType resource = getResourceType(type);
|
||||||
// don't need to handle uniform symbol, it will be handled in resolveUniformLocation
|
// don't need to handle uniform symbol, it will be handled in resolveUniformLocation
|
||||||
@@ -818,10 +834,7 @@ void TDefaultGlslIoResolver::endCollect(EShLanguage /*stage*/) {
|
|||||||
|
|
||||||
void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
|
void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
|
||||||
const TType& type = ent.symbol->getType();
|
const TType& type = ent.symbol->getType();
|
||||||
const TString& name = IsAnonymous(ent.symbol->getName()) ?
|
const TString& name = getAccessName(ent.symbol);
|
||||||
ent.symbol->getType().getTypeName()
|
|
||||||
:
|
|
||||||
ent.symbol->getName();
|
|
||||||
TStorageQualifier storage = type.getQualifier().storage;
|
TStorageQualifier storage = type.getQualifier().storage;
|
||||||
EShLanguage stage(EShLangCount);
|
EShLanguage stage(EShLangCount);
|
||||||
switch (storage) {
|
switch (storage) {
|
||||||
@@ -881,10 +894,7 @@ void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink&
|
|||||||
|
|
||||||
void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
|
void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
|
||||||
const TType& type = ent.symbol->getType();
|
const TType& type = ent.symbol->getType();
|
||||||
const TString& name = IsAnonymous(ent.symbol->getName()) ?
|
const TString& name = getAccessName(ent.symbol);
|
||||||
ent.symbol->getType().getTypeName()
|
|
||||||
:
|
|
||||||
ent.symbol->getName();
|
|
||||||
int resource = getResourceType(type);
|
int resource = getResourceType(type);
|
||||||
if (type.getQualifier().hasBinding()) {
|
if (type.getQualifier().hasBinding()) {
|
||||||
TVarSlotMap& varSlotMap = resourceSlotMap[resource];
|
TVarSlotMap& varSlotMap = resourceSlotMap[resource];
|
||||||
@@ -907,6 +917,13 @@ void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TString& TDefaultGlslIoResolver::getAccessName(const TIntermSymbol* symbol)
|
||||||
|
{
|
||||||
|
return symbol->getBasicType() == EbtBlock ?
|
||||||
|
symbol->getType().getTypeName() :
|
||||||
|
symbol->getName();
|
||||||
|
}
|
||||||
|
|
||||||
//TDefaultGlslIoResolver end
|
//TDefaultGlslIoResolver end
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -203,6 +203,7 @@ public:
|
|||||||
void endCollect(EShLanguage) override;
|
void endCollect(EShLanguage) override;
|
||||||
void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
|
void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
|
||||||
void reserverResourceSlot(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.
|
// 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.
|
// 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.
|
// 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.
|
||||||
@@ -238,12 +239,13 @@ typedef std::map<TString, TVarEntryInfo> TVarLiveMap;
|
|||||||
// In the future, if the vc++ compiler can handle such a situation,
|
// In the future, if the vc++ compiler can handle such a situation,
|
||||||
// this part of the code will be removed.
|
// this part of the code will be removed.
|
||||||
struct TVarLivePair : std::pair<const TString, TVarEntryInfo> {
|
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) {
|
TVarLivePair& operator=(const TVarLivePair& _Right) {
|
||||||
const_cast<TString&>(first) = _Right.first;
|
const_cast<TString&>(first) = _Right.first;
|
||||||
second = _Right.second;
|
second = _Right.second;
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
|
TVarLivePair(const TVarLivePair& src) : pair(src) { }
|
||||||
};
|
};
|
||||||
typedef std::vector<TVarLivePair> TVarLiveVector;
|
typedef std::vector<TVarLivePair> TVarLiveVector;
|
||||||
|
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
|
|||||||
|
|
||||||
if (vertices == TQualifier::layoutNotSet)
|
if (vertices == TQualifier::layoutNotSet)
|
||||||
vertices = unit.vertices;
|
vertices = unit.vertices;
|
||||||
else if (vertices != unit.vertices) {
|
else if (unit.vertices != TQualifier::layoutNotSet && vertices != unit.vertices) {
|
||||||
if (language == EShLangGeometry || language == EShLangMeshNV)
|
if (language == EShLangGeometry || language == EShLangMeshNV)
|
||||||
error(infoSink, "Contradictory layout max_vertices values");
|
error(infoSink, "Contradictory layout max_vertices values");
|
||||||
else if (language == EShLangTessControl)
|
else if (language == EShLangTessControl)
|
||||||
@@ -172,12 +172,12 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
|
|||||||
|
|
||||||
if (inputPrimitive == ElgNone)
|
if (inputPrimitive == ElgNone)
|
||||||
inputPrimitive = unit.inputPrimitive;
|
inputPrimitive = unit.inputPrimitive;
|
||||||
else if (inputPrimitive != unit.inputPrimitive)
|
else if (unit.inputPrimitive != ElgNone && inputPrimitive != unit.inputPrimitive)
|
||||||
error(infoSink, "Contradictory input layout primitives");
|
error(infoSink, "Contradictory input layout primitives");
|
||||||
|
|
||||||
if (outputPrimitive == ElgNone)
|
if (outputPrimitive == ElgNone)
|
||||||
outputPrimitive = unit.outputPrimitive;
|
outputPrimitive = unit.outputPrimitive;
|
||||||
else if (outputPrimitive != unit.outputPrimitive)
|
else if (unit.outputPrimitive != ElgNone && outputPrimitive != unit.outputPrimitive)
|
||||||
error(infoSink, "Contradictory output layout primitives");
|
error(infoSink, "Contradictory output layout primitives");
|
||||||
|
|
||||||
if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger)
|
if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger)
|
||||||
@@ -1550,7 +1550,9 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, T
|
|||||||
RoundToPow2(size, alignment);
|
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)
|
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
|
// 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;
|
return alignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -265,6 +265,7 @@ public:
|
|||||||
computeDerivativeMode(LayoutDerivativeNone),
|
computeDerivativeMode(LayoutDerivativeNone),
|
||||||
primitives(TQualifier::layoutNotSet),
|
primitives(TQualifier::layoutNotSet),
|
||||||
numTaskNVBlocks(0),
|
numTaskNVBlocks(0),
|
||||||
|
layoutPrimitiveCulling(false),
|
||||||
autoMapBindings(false),
|
autoMapBindings(false),
|
||||||
autoMapLocations(false),
|
autoMapLocations(false),
|
||||||
flattenUniformArrays(false),
|
flattenUniformArrays(false),
|
||||||
@@ -356,8 +357,15 @@ public:
|
|||||||
}
|
}
|
||||||
const SpvVersion& getSpv() const { return spvVersion; }
|
const SpvVersion& getSpv() const { return spvVersion; }
|
||||||
EShLanguage getStage() const { return language; }
|
EShLanguage getStage() const { return language; }
|
||||||
void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
|
void updateRequestedExtension(const char* extension, TExtensionBehavior behavior) {
|
||||||
const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; }
|
if(requestedExtensions.find(extension) != requestedExtensions.end()) {
|
||||||
|
requestedExtensions[extension] = behavior;
|
||||||
|
} else {
|
||||||
|
requestedExtensions.insert(std::make_pair(extension, behavior));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::map<std::string, TExtensionBehavior>& getRequestedExtensions() const { return requestedExtensions; }
|
||||||
|
|
||||||
void setTreeRoot(TIntermNode* r) { treeRoot = r; }
|
void setTreeRoot(TIntermNode* r) { treeRoot = r; }
|
||||||
TIntermNode* getTreeRoot() const { return treeRoot; }
|
TIntermNode* getTreeRoot() const { return treeRoot; }
|
||||||
@@ -392,7 +400,7 @@ public:
|
|||||||
void setSource(EShSource s) { source = s; }
|
void setSource(EShSource s) { source = s; }
|
||||||
EShSource getSource() const { return source; }
|
EShSource getSource() const { return source; }
|
||||||
#else
|
#else
|
||||||
void setSource(EShSource s) { assert(s == EShSourceGlsl); }
|
void setSource(EShSource s) { assert(s == EShSourceGlsl); (void)s; }
|
||||||
EShSource getSource() const { return EShSourceGlsl; }
|
EShSource getSource() const { return EShSourceGlsl; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -735,6 +743,8 @@ public:
|
|||||||
void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; }
|
void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; }
|
||||||
bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; }
|
bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; }
|
||||||
ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; }
|
ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; }
|
||||||
|
void setLayoutPrimitiveCulling() { layoutPrimitiveCulling = true; }
|
||||||
|
bool getLayoutPrimitiveCulling() const { return layoutPrimitiveCulling; }
|
||||||
bool setPrimitives(int m)
|
bool setPrimitives(int m)
|
||||||
{
|
{
|
||||||
if (primitives != TQualifier::layoutNotSet)
|
if (primitives != TQualifier::layoutNotSet)
|
||||||
@@ -902,7 +912,13 @@ protected:
|
|||||||
#ifdef GLSLANG_WEB
|
#ifdef GLSLANG_WEB
|
||||||
bool extensionRequested(const char *extension) const { return false; }
|
bool extensionRequested(const char *extension) const { return false; }
|
||||||
#else
|
#else
|
||||||
bool extensionRequested(const char *extension) const {return requestedExtensions.find(extension) != requestedExtensions.end();}
|
bool extensionRequested(const char *extension) const {
|
||||||
|
auto it = requestedExtensions.find(extension);
|
||||||
|
if (it != requestedExtensions.end()) {
|
||||||
|
return (it->second == EBhDisable) ? false : true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char* getResourceName(TResourceType);
|
static const char* getResourceName(TResourceType);
|
||||||
@@ -917,7 +933,7 @@ protected:
|
|||||||
int version; // source version
|
int version; // source version
|
||||||
SpvVersion spvVersion;
|
SpvVersion spvVersion;
|
||||||
TIntermNode* treeRoot;
|
TIntermNode* treeRoot;
|
||||||
std::set<std::string> requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
|
std::map<std::string, TExtensionBehavior> requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
|
||||||
TBuiltInResource resources;
|
TBuiltInResource resources;
|
||||||
int numEntryPoints;
|
int numEntryPoints;
|
||||||
int numErrors;
|
int numErrors;
|
||||||
@@ -961,6 +977,7 @@ protected:
|
|||||||
ComputeDerivativeMode computeDerivativeMode;
|
ComputeDerivativeMode computeDerivativeMode;
|
||||||
int primitives;
|
int primitives;
|
||||||
int numTaskNVBlocks;
|
int numTaskNVBlocks;
|
||||||
|
bool layoutPrimitiveCulling;
|
||||||
|
|
||||||
// Base shift values
|
// Base shift values
|
||||||
std::array<unsigned int, EResCount> shiftBinding;
|
std::array<unsigned int, EResCount> shiftBinding;
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ public:
|
|||||||
void updateExtensionBehavior(int line, const char* const extension, const char* behavior) { }
|
void updateExtensionBehavior(int line, const char* const extension, const char* behavior) { }
|
||||||
void updateExtensionBehavior(const char* const extension, TExtensionBehavior) { }
|
void updateExtensionBehavior(const char* const extension, TExtensionBehavior) { }
|
||||||
void checkExtensionStage(const TSourceLoc&, const char* const extension) { }
|
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 fullIntegerCheck(const TSourceLoc&, const char* op) { }
|
||||||
void doubleCheck(const TSourceLoc&, const char* op) { }
|
void doubleCheck(const TSourceLoc&, const char* op) { }
|
||||||
bool float16Arithmetic() { return false; }
|
bool float16Arithmetic() { return false; }
|
||||||
@@ -139,6 +140,7 @@ public:
|
|||||||
virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[],
|
virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[],
|
||||||
const char* featureDesc);
|
const char* featureDesc);
|
||||||
virtual void checkExtensionStage(const TSourceLoc&, const char* const extension);
|
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 fullIntegerCheck(const TSourceLoc&, const char* op);
|
||||||
|
|
||||||
virtual void unimplemented(const TSourceLoc&, const char* featureDesc);
|
virtual void unimplemented(const TSourceLoc&, const char* featureDesc);
|
||||||
@@ -170,6 +172,7 @@ public:
|
|||||||
virtual void vulkanRemoved(const TSourceLoc&, const char* op);
|
virtual void vulkanRemoved(const TSourceLoc&, const char* op);
|
||||||
virtual void requireVulkan(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);
|
||||||
|
virtual void requireSpv(const TSourceLoc&, const char *op, unsigned int version);
|
||||||
|
|
||||||
|
|
||||||
#if defined(GLSLANG_WEB) && !defined(GLSLANG_WEB_DEVEL)
|
#if defined(GLSLANG_WEB) && !defined(GLSLANG_WEB_DEVEL)
|
||||||
@@ -222,6 +225,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
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 set to
|
||||||
|
TMap<TString, unsigned int> extensionMinSpv; // for each extension string, store minimum spirv required
|
||||||
EShMessages messages; // errors/warnings/rule-sets
|
EShMessages messages; // errors/warnings/rule-sets
|
||||||
int numErrors; // number of compile-time errors encountered
|
int numErrors; // number of compile-time errors encountered
|
||||||
TInputScanner* currentScanner;
|
TInputScanner* currentScanner;
|
||||||
|
|||||||
@@ -77,10 +77,10 @@ namespace glslang {
|
|||||||
// This is in the glslang namespace directly so it can be a friend of TReflection.
|
// This is in the glslang namespace directly so it can be a friend of TReflection.
|
||||||
//
|
//
|
||||||
|
|
||||||
class TReflectionTraverser : public TLiveTraverser {
|
class TReflectionTraverser : public TIntermTraverser {
|
||||||
public:
|
public:
|
||||||
TReflectionTraverser(const TIntermediate& i, TReflection& r) :
|
TReflectionTraverser(const TIntermediate& i, TReflection& r) :
|
||||||
TLiveTraverser(i), reflection(r) { }
|
TIntermTraverser(), intermediate(i), reflection(r), updateStageMasks(true) { }
|
||||||
|
|
||||||
virtual bool visitBinary(TVisit, TIntermBinary* node);
|
virtual bool visitBinary(TVisit, TIntermBinary* node);
|
||||||
virtual void visitSymbol(TIntermSymbol* base);
|
virtual void visitSymbol(TIntermSymbol* base);
|
||||||
@@ -92,11 +92,28 @@ public:
|
|||||||
if (processedDerefs.find(&base) == processedDerefs.end()) {
|
if (processedDerefs.find(&base) == processedDerefs.end()) {
|
||||||
processedDerefs.insert(&base);
|
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
|
// Use a degenerate (empty) set of dereferences to immediately put as at the end of
|
||||||
// the dereference change expected by blowUpActiveAggregate.
|
// the dereference change expected by blowUpActiveAggregate.
|
||||||
TList<TIntermBinary*> derefs;
|
blowUpActiveAggregate(base.getType(), baseName, derefs, derefs.end(), offset, blockIndex, 0, -1, 0,
|
||||||
blowUpActiveAggregate(base.getType(), base.getName(), derefs, derefs.end(), -1, -1, 0, 0,
|
base.getQualifier().storage, updateStageMasks);
|
||||||
base.getQualifier().storage, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,9 +172,9 @@ public:
|
|||||||
void getOffsets(const TType& type, TVector<int>& offsets)
|
void getOffsets(const TType& type, TVector<int>& offsets)
|
||||||
{
|
{
|
||||||
const TTypeList& memberList = *type.getStruct();
|
const TTypeList& memberList = *type.getStruct();
|
||||||
|
|
||||||
int memberSize = 0;
|
int memberSize = 0;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
for (size_t m = 0; m < offsets.size(); ++m) {
|
for (size_t m = 0; m < offsets.size(); ++m) {
|
||||||
// if the user supplied an offset, snap to it now
|
// if the user supplied an offset, snap to it now
|
||||||
if (memberList[m].type->getQualifier().hasOffset())
|
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.
|
// 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,
|
void blowUpActiveAggregate(const TType& baseType, const TString& baseName, const TList<TIntermBinary*>& derefs,
|
||||||
TList<TIntermBinary*>::const_iterator deref, int offset, int blockIndex, int arraySize,
|
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.
|
// when strictArraySuffix is enabled, we closely follow the rules from ARB_program_interface_query.
|
||||||
// Broadly:
|
// Broadly:
|
||||||
@@ -262,14 +279,15 @@ public:
|
|||||||
// Visit all the indices of this array, and for each one add on the remaining dereferencing
|
// 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) {
|
for (int i = 0; i < std::max(visitNode->getLeft()->getType().getOuterArraySize(), 1); ++i) {
|
||||||
TString newBaseName = name;
|
TString newBaseName = name;
|
||||||
if (strictArraySuffix && blockParent)
|
if (terminalType->getBasicType() == EbtBlock) {}
|
||||||
|
else if (strictArraySuffix && blockParent)
|
||||||
newBaseName.append(TString("[0]"));
|
newBaseName.append(TString("[0]"));
|
||||||
else if (strictArraySuffix || baseType.getBasicType() != EbtBlock)
|
else if (strictArraySuffix || baseType.getBasicType() != EbtBlock)
|
||||||
newBaseName.append(TString("[") + String(i) + "]");
|
newBaseName.append(TString("[") + String(i) + "]");
|
||||||
TList<TIntermBinary*>::const_iterator nextDeref = deref;
|
TList<TIntermBinary*>::const_iterator nextDeref = deref;
|
||||||
++nextDeref;
|
++nextDeref;
|
||||||
blowUpActiveAggregate(*terminalType, newBaseName, derefs, nextDeref, offset, blockIndex, arraySize,
|
blowUpActiveAggregate(*terminalType, newBaseName, derefs, nextDeref, offset, blockIndex, arraySize,
|
||||||
topLevelArrayStride, baseStorage, active);
|
topLevelArraySize, topLevelArrayStride, baseStorage, active);
|
||||||
|
|
||||||
if (offset >= 0)
|
if (offset >= 0)
|
||||||
offset += stride;
|
offset += stride;
|
||||||
@@ -282,9 +300,10 @@ public:
|
|||||||
int stride = getArrayStride(baseType, visitNode->getLeft()->getType());
|
int stride = getArrayStride(baseType, visitNode->getLeft()->getType());
|
||||||
|
|
||||||
index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
|
index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
|
||||||
if (strictArraySuffix && blockParent) {
|
if (terminalType->getBasicType() == EbtBlock) {}
|
||||||
|
else if (strictArraySuffix && blockParent)
|
||||||
name.append(TString("[0]"));
|
name.append(TString("[0]"));
|
||||||
} else if (strictArraySuffix || baseType.getBasicType() != EbtBlock) {
|
else if (strictArraySuffix || baseType.getBasicType() != EbtBlock) {
|
||||||
name.append(TString("[") + String(index) + "]");
|
name.append(TString("[") + String(index) + "]");
|
||||||
|
|
||||||
if (offset >= 0)
|
if (offset >= 0)
|
||||||
@@ -294,7 +313,10 @@ public:
|
|||||||
if (topLevelArrayStride == 0)
|
if (topLevelArrayStride == 0)
|
||||||
topLevelArrayStride = stride;
|
topLevelArrayStride = stride;
|
||||||
|
|
||||||
blockParent = false;
|
// expand top-level arrays in blocks with [0] suffix
|
||||||
|
if (topLevelArrayStride != 0 && visitNode->getLeft()->getType().isArray()) {
|
||||||
|
blockParent = false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EOpIndexDirectStruct:
|
case EOpIndexDirectStruct:
|
||||||
@@ -304,6 +326,12 @@ public:
|
|||||||
if (name.size() > 0)
|
if (name.size() > 0)
|
||||||
name.append(".");
|
name.append(".");
|
||||||
name.append((*visitNode->getLeft()->getType().getStruct())[index].type->getFieldName());
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -323,24 +351,27 @@ public:
|
|||||||
if (offset >= 0)
|
if (offset >= 0)
|
||||||
stride = getArrayStride(baseType, *terminalType);
|
stride = getArrayStride(baseType, *terminalType);
|
||||||
|
|
||||||
if (topLevelArrayStride == 0)
|
|
||||||
topLevelArrayStride = stride;
|
|
||||||
|
|
||||||
int arrayIterateSize = std::max(terminalType->getOuterArraySize(), 1);
|
int arrayIterateSize = std::max(terminalType->getOuterArraySize(), 1);
|
||||||
|
|
||||||
// for top-level arrays in blocks, only expand [0] to avoid explosion of items
|
// 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;
|
arrayIterateSize = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (topLevelArrayStride == 0)
|
||||||
|
topLevelArrayStride = stride;
|
||||||
|
|
||||||
for (int i = 0; i < arrayIterateSize; ++i) {
|
for (int i = 0; i < arrayIterateSize; ++i) {
|
||||||
TString newBaseName = name;
|
TString newBaseName = name;
|
||||||
newBaseName.append(TString("[") + String(i) + "]");
|
if (terminalType->getBasicType() != EbtBlock)
|
||||||
|
newBaseName.append(TString("[") + String(i) + "]");
|
||||||
TType derefType(*terminalType, 0);
|
TType derefType(*terminalType, 0);
|
||||||
if (offset >= 0)
|
if (offset >= 0)
|
||||||
offset = baseOffset + stride * i;
|
offset = baseOffset + stride * i;
|
||||||
|
|
||||||
blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
|
blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
|
||||||
topLevelArrayStride, baseStorage, active);
|
topLevelArraySize, topLevelArrayStride, baseStorage, active);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Visit all members of this aggregate, and for each one,
|
// Visit all members of this aggregate, and for each one,
|
||||||
@@ -369,8 +400,31 @@ public:
|
|||||||
arrayStride = getArrayStride(baseType, derefType);
|
arrayStride = getArrayStride(baseType, derefType);
|
||||||
}
|
}
|
||||||
|
|
||||||
blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0,
|
if (topLevelArraySize == -1 && arrayStride == 0 && blockParent)
|
||||||
arrayStride, baseStorage, active);
|
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())
|
if ((reflection.options & EShReflectionSeparateBuffers) && terminalType->isAtomic())
|
||||||
reflection.atomicCounterUniformIndices.push_back(uniformIndex);
|
reflection.atomicCounterUniformIndices.push_back(uniformIndex);
|
||||||
|
|
||||||
|
variables.back().topLevelArraySize = topLevelArraySize;
|
||||||
variables.back().topLevelArrayStride = topLevelArrayStride;
|
variables.back().topLevelArrayStride = topLevelArrayStride;
|
||||||
|
|
||||||
if ((reflection.options & EShReflectionAllBlockVariables) && active) {
|
if ((reflection.options & EShReflectionAllBlockVariables) && active) {
|
||||||
@@ -537,65 +592,17 @@ public:
|
|||||||
if (! anonymous)
|
if (! anonymous)
|
||||||
baseName = blockName;
|
baseName = blockName;
|
||||||
|
|
||||||
if (base->getType().isArray()) {
|
blockIndex = addBlockName(blockName, base->getType(), intermediate.getBlockSize(base->getType()));
|
||||||
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()));
|
|
||||||
|
|
||||||
if (reflection.options & EShReflectionAllBlockVariables) {
|
if (reflection.options & EShReflectionAllBlockVariables) {
|
||||||
// Use a degenerate (empty) set of dereferences to immediately put as at the end of
|
// Use a degenerate (empty) set of dereferences to immediately put as at the end of
|
||||||
// the dereference change expected by blowUpActiveAggregate.
|
// the dereference change expected by blowUpActiveAggregate.
|
||||||
TList<TIntermBinary*> derefs;
|
TList<TIntermBinary*> derefs;
|
||||||
|
|
||||||
// because we don't have any derefs, the first thing blowUpActiveAggregate will do is iterate over each
|
// otherwise - if we're not using strict array suffix rules, or this isn't a block so we are
|
||||||
// member in the struct definition. This will lose any information about whether the parent was a buffer
|
// expanding root arrays anyway, just start the iteration from the base block type.
|
||||||
// block. So if we're using strict array rules which don't expand the first child of a buffer block we
|
blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.end(), 0, blockIndex, 0, -1, 0,
|
||||||
// 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,
|
|
||||||
base->getQualifier().storage, false);
|
base->getQualifier().storage, false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,30 +633,40 @@ public:
|
|||||||
else
|
else
|
||||||
baseName = base->getName();
|
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);
|
base->getQualifier().storage, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int addBlockName(const TString& name, const TType& type, int size)
|
int addBlockName(const TString& name, const TType& type, int size)
|
||||||
{
|
{
|
||||||
TReflection::TMapIndexToReflection& blocks = reflection.GetBlockMapForStorage(type.getQualifier().storage);
|
|
||||||
|
|
||||||
int blockIndex;
|
int blockIndex;
|
||||||
TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
|
if (type.isArray()) {
|
||||||
if (reflection.nameToIndex.find(name.c_str()) == reflection.nameToIndex.end()) {
|
TType derefType(type, 0);
|
||||||
blockIndex = (int)blocks.size();
|
for (int e = 0; e < type.getOuterArraySize(); ++e) {
|
||||||
reflection.nameToIndex[name.c_str()] = blockIndex;
|
uint32_t memberBlockIndex = addBlockName(name + "[" + String(e) + "]", derefType, size);
|
||||||
blocks.push_back(TObjectReflection(name.c_str(), type, -1, -1, size, -1));
|
if (e == 0)
|
||||||
|
blockIndex = memberBlockIndex;
|
||||||
blocks.back().numMembers = countAggregateMembers(type);
|
}
|
||||||
|
|
||||||
EShLanguageMask& stages = blocks.back().stages;
|
|
||||||
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
|
|
||||||
} else {
|
} else {
|
||||||
blockIndex = it->second;
|
TReflection::TMapIndexToReflection& blocks = reflection.GetBlockMapForStorage(type.getQualifier().storage);
|
||||||
|
|
||||||
EShLanguageMask& stages = blocks[blockIndex].stages;
|
TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
|
||||||
stages = static_cast<EShLanguageMask>(stages | 1 << intermediate.getStage());
|
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;
|
return blockIndex;
|
||||||
@@ -995,8 +1012,10 @@ public:
|
|||||||
return type.isArray() ? type.getOuterArraySize() : 1;
|
return type.isArray() ? type.getOuterArraySize() : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TIntermediate& intermediate;
|
||||||
TReflection& reflection;
|
TReflection& reflection;
|
||||||
std::set<const TIntermNode*> processedDerefs;
|
std::set<const TIntermNode*> processedDerefs;
|
||||||
|
bool updateStageMasks;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TReflectionTraverser(TReflectionTraverser&);
|
TReflectionTraverser(TReflectionTraverser&);
|
||||||
@@ -1029,7 +1048,21 @@ bool TReflectionTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
|
|||||||
// To reflect non-dereferenced objects.
|
// To reflect non-dereferenced objects.
|
||||||
void TReflectionTraverser::visitSymbol(TIntermSymbol* base)
|
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);
|
addUniform(*base);
|
||||||
|
|
||||||
if ((intermediate.getStage() == reflection.firstStage && base->getQualifier().isPipeInput()) ||
|
if ((intermediate.getStage() == reflection.firstStage && base->getQualifier().isPipeInput()) ||
|
||||||
@@ -1135,15 +1168,47 @@ bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate)
|
|||||||
|
|
||||||
TReflectionTraverser it(intermediate, *this);
|
TReflectionTraverser it(intermediate, *this);
|
||||||
|
|
||||||
// put the entry point on the list of functions to process
|
for (auto& sequnence : intermediate.getTreeRoot()->getAsAggregate()->getSequence()) {
|
||||||
it.pushFunction(intermediate.getEntryPointMangledName().c_str());
|
if (sequnence->getAsAggregate() != nullptr) {
|
||||||
|
if (sequnence->getAsAggregate()->getOp() == glslang::EOpLinkerObjects) {
|
||||||
// process all the functions
|
it.updateStageMasks = false;
|
||||||
while (! it.functions.empty()) {
|
TIntermAggregate* linkerObjects = sequnence->getAsAggregate();
|
||||||
TIntermNode* function = it.functions.back();
|
for (auto& sequnence : linkerObjects->getSequence()) {
|
||||||
it.functions.pop_back();
|
auto pNode = sequnence->getAsSymbolNode();
|
||||||
function->traverse(&it);
|
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);
|
buildCounterIndices(intermediate);
|
||||||
buildUniformStageMask(intermediate);
|
buildUniformStageMask(intermediate);
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ const TBuiltInResource DefaultTBuiltInResource = {
|
|||||||
/* .maxTaskWorkGroupSizeY_NV = */ 1,
|
/* .maxTaskWorkGroupSizeY_NV = */ 1,
|
||||||
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
|
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
|
||||||
/* .maxMeshViewCountNV = */ 4,
|
/* .maxMeshViewCountNV = */ 4,
|
||||||
|
/* .maxDualSourceDrawBuffersEXT = */ 1,
|
||||||
|
|
||||||
/* .limits = */ {
|
/* .limits = */ {
|
||||||
/* .nonInductiveForLoops = */ 1,
|
/* .nonInductiveForLoops = */ 1,
|
||||||
|
|||||||
Executable → Regular
+16
-11
@@ -68,7 +68,7 @@
|
|||||||
// This should always increase, as some paths to do not consume
|
// This should always increase, as some paths to do not consume
|
||||||
// a more major number.
|
// a more major number.
|
||||||
// It should increment by one when new functionality is added.
|
// It should increment by one when new functionality is added.
|
||||||
#define GLSLANG_MINOR_VERSION 13
|
#define GLSLANG_MINOR_VERSION 14
|
||||||
|
|
||||||
//
|
//
|
||||||
// Call before doing any other compiler/linker operations.
|
// Call before doing any other compiler/linker operations.
|
||||||
@@ -109,7 +109,7 @@ typedef enum {
|
|||||||
LAST_ELEMENT_MARKER(EShLangCount),
|
LAST_ELEMENT_MARKER(EShLangCount),
|
||||||
} EShLanguage; // would be better as stage, but this is ancient now
|
} EShLanguage; // would be better as stage, but this is ancient now
|
||||||
|
|
||||||
typedef enum {
|
typedef enum : unsigned {
|
||||||
EShLangVertexMask = (1 << EShLangVertex),
|
EShLangVertexMask = (1 << EShLangVertex),
|
||||||
EShLangTessControlMask = (1 << EShLangTessControl),
|
EShLangTessControlMask = (1 << EShLangTessControl),
|
||||||
EShLangTessEvaluationMask = (1 << EShLangTessEvaluation),
|
EShLangTessEvaluationMask = (1 << EShLangTessEvaluation),
|
||||||
@@ -240,7 +240,7 @@ typedef enum {
|
|||||||
//
|
//
|
||||||
// Message choices for what errors and warnings are given.
|
// 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
|
EShMsgDefault = 0, // default is to give all required errors and extra warnings
|
||||||
EShMsgRelaxedErrors = (1 << 0), // be liberal in accepting input
|
EShMsgRelaxedErrors = (1 << 0), // be liberal in accepting input
|
||||||
EShMsgSuppressWarnings = (1 << 1), // suppress all warnings, except those required by the specification
|
EShMsgSuppressWarnings = (1 << 1), // suppress all warnings, except those required by the specification
|
||||||
@@ -255,7 +255,7 @@ enum EShMessages {
|
|||||||
EShMsgDebugInfo = (1 << 10), // save debug information
|
EShMsgDebugInfo = (1 << 10), // save debug information
|
||||||
EShMsgHlslEnable16BitTypes = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL
|
EShMsgHlslEnable16BitTypes = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL
|
||||||
EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages
|
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
|
EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table
|
||||||
LAST_ELEMENT_MARKER(EShMsgCount),
|
LAST_ELEMENT_MARKER(EShMsgCount),
|
||||||
};
|
};
|
||||||
@@ -264,13 +264,16 @@ enum EShMessages {
|
|||||||
// Options for building reflection
|
// Options for building reflection
|
||||||
//
|
//
|
||||||
typedef enum {
|
typedef enum {
|
||||||
EShReflectionDefault = 0, // default is original behaviour before options were added
|
EShReflectionDefault = 0, // default is original behaviour before options were added
|
||||||
EShReflectionStrictArraySuffix = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes
|
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
|
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
|
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
|
EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately
|
||||||
EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive
|
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
|
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),
|
LAST_ELEMENT_MARKER(EShReflectionCount),
|
||||||
} EShReflectionOptions;
|
} EShReflectionOptions;
|
||||||
|
|
||||||
@@ -412,6 +415,7 @@ enum TResourceType {
|
|||||||
EResCount
|
EResCount
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Make one TShader per shader that you will link into a program. Then
|
// Make one TShader per shader that you will link into a program. Then
|
||||||
// - provide the shader through setStrings() or setStringsWithLengths()
|
// - provide the shader through setStrings() or setStringsWithLengths()
|
||||||
// - optionally call setEnv*(), see below for more detail
|
// - optionally call setEnv*(), see below for more detail
|
||||||
@@ -694,6 +698,7 @@ public:
|
|||||||
int counterIndex;
|
int counterIndex;
|
||||||
int numMembers;
|
int numMembers;
|
||||||
int arrayStride; // stride of an array variable
|
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
|
int topLevelArrayStride; // stride of the top-level variable in a storage buffer member
|
||||||
EShLanguageMask stages;
|
EShLanguageMask stages;
|
||||||
|
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ static const TBuiltInResource defaultTBuiltInResource = {
|
|||||||
/* .maxTaskWorkGroupSizeY_NV = */ 1,
|
/* .maxTaskWorkGroupSizeY_NV = */ 1,
|
||||||
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
|
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
|
||||||
/* .maxMeshViewCountNV = */ 4,
|
/* .maxMeshViewCountNV = */ 4,
|
||||||
|
/* .maxDualSourceDrawBuffersEXT = */ 1,
|
||||||
/* .limits = */ {
|
/* .limits = */ {
|
||||||
/* .nonInductiveForLoops = */ 1,
|
/* .nonInductiveForLoops = */ 1,
|
||||||
/* .whileLoops = */ 1,
|
/* .whileLoops = */ 1,
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ static const TBuiltInResource defaultTBuiltInResource = {
|
|||||||
/* .maxTaskWorkGroupSizeY_NV = */ 1,
|
/* .maxTaskWorkGroupSizeY_NV = */ 1,
|
||||||
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
|
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
|
||||||
/* .maxMeshViewCountNV = */ 4,
|
/* .maxMeshViewCountNV = */ 4,
|
||||||
|
/* .maxDualSourceDrawBuffersEXT = */ 1,
|
||||||
/* .limits = */ {
|
/* .limits = */ {
|
||||||
/* .nonInductiveForLoops = */ 1,
|
/* .nonInductiveForLoops = */ 1,
|
||||||
/* .whileLoops = */ 1,
|
/* .whileLoops = */ 1,
|
||||||
|
|||||||
Reference in New Issue
Block a user