mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-02-17 20:52:36 +01:00
Updated glslang.
This commit is contained in:
2
3rdparty/glslang/SPIRV/GlslangToSpv.cpp
vendored
2
3rdparty/glslang/SPIRV/GlslangToSpv.cpp
vendored
@@ -1439,7 +1439,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.
|
||||||
|
|
||||||
|
|||||||
4
3rdparty/glslang/SPIRV/spirv.hpp
vendored
4
3rdparty/glslang/SPIRV/spirv.hpp
vendored
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -134,6 +134,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,
|
||||||
@@ -243,6 +244,7 @@ std::string GetDefaultTBuiltInResourceString()
|
|||||||
<< "MaxTaskWorkGroupSizeY_NV " << DefaultTBuiltInResource.maxTaskWorkGroupSizeY_NV << "\n"
|
<< "MaxTaskWorkGroupSizeY_NV " << DefaultTBuiltInResource.maxTaskWorkGroupSizeY_NV << "\n"
|
||||||
<< "MaxTaskWorkGroupSizeZ_NV " << DefaultTBuiltInResource.maxTaskWorkGroupSizeZ_NV << "\n"
|
<< "MaxTaskWorkGroupSizeZ_NV " << DefaultTBuiltInResource.maxTaskWorkGroupSizeZ_NV << "\n"
|
||||||
<< "MaxMeshViewCountNV " << DefaultTBuiltInResource.maxMeshViewCountNV << "\n"
|
<< "MaxMeshViewCountNV " << DefaultTBuiltInResource.maxMeshViewCountNV << "\n"
|
||||||
|
<< "MaxDualSourceDrawBuffersEXT " << DefaultTBuiltInResource.maxDualSourceDrawBuffersEXT << "\n"
|
||||||
<< "nonInductiveForLoops " << DefaultTBuiltInResource.limits.nonInductiveForLoops << "\n"
|
<< "nonInductiveForLoops " << DefaultTBuiltInResource.limits.nonInductiveForLoops << "\n"
|
||||||
<< "whileLoops " << DefaultTBuiltInResource.limits.whileLoops << "\n"
|
<< "whileLoops " << DefaultTBuiltInResource.limits.whileLoops << "\n"
|
||||||
<< "doWhileLoops " << DefaultTBuiltInResource.limits.doWhileLoops << "\n"
|
<< "doWhileLoops " << DefaultTBuiltInResource.limits.doWhileLoops << "\n"
|
||||||
|
|||||||
6
3rdparty/glslang/glslang/Include/BaseTypes.h
vendored
6
3rdparty/glslang/glslang/Include/BaseTypes.h
vendored
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
2
3rdparty/glslang/glslang/Include/revision.h
vendored
2
3rdparty/glslang/glslang/Include/revision.h
vendored
@@ -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 3743
|
||||||
|
|||||||
@@ -146,7 +146,6 @@ 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;
|
|
||||||
#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 +157,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 +1343,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 +1351,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 +1363,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 +1371,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 +1383,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);"
|
||||||
@@ -3066,6 +3060,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(
|
||||||
@@ -5849,9 +5861,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)
|
||||||
@@ -6743,6 +6755,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
|
||||||
|
|
||||||
@@ -7555,6 +7579,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);
|
||||||
@@ -7844,6 +7872,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);
|
||||||
@@ -8055,6 +8099,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);
|
||||||
|
|
||||||
@@ -9086,6 +9131,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)
|
||||||
@@ -1667,7 +1667,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
|
|||||||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16) ||
|
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16) ||
|
||||||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float32) ||
|
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float32) ||
|
||||||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float64);
|
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float64);
|
||||||
|
|
||||||
if (explicitTypesEnabled) {
|
if (explicitTypesEnabled) {
|
||||||
// integral promotions
|
// integral promotions
|
||||||
if (isIntegralPromotion(from, to)) {
|
if (isIntegralPromotion(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:
|
||||||
@@ -1731,15 +1755,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 +1954,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;
|
||||||
@@ -5385,10 +5433,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;
|
||||||
@@ -6135,7 +6183,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);
|
||||||
|
|||||||
@@ -315,6 +315,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&);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
@@ -1774,7 +1774,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())
|
||||||
|
|||||||
@@ -200,6 +200,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;
|
||||||
@@ -294,6 +297,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;
|
||||||
@@ -302,6 +306,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;
|
||||||
@@ -360,6 +366,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"
|
||||||
@@ -409,12 +418,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"
|
||||||
@@ -913,8 +925,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -942,8 +954,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.
|
||||||
|
|||||||
@@ -155,6 +155,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";
|
||||||
@@ -193,6 +196,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
|
||||||
|
|
||||||
@@ -264,6 +269,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)
|
||||||
|
|||||||
@@ -238,12 +238,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) { *this = src; }
|
||||||
};
|
};
|
||||||
typedef std::vector<TVarLivePair> TVarLiveVector;
|
typedef std::vector<TVarLivePair> TVarLiveVector;
|
||||||
|
|
||||||
|
|||||||
@@ -356,8 +356,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; }
|
||||||
@@ -902,7 +909,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 +930,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;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -126,15 +126,16 @@ namespace bgfx { namespace metal
|
|||||||
8, // MaxCullDistances
|
8, // MaxCullDistances
|
||||||
8, // MaxCombinedClipAndCullDistances
|
8, // MaxCombinedClipAndCullDistances
|
||||||
4, // MaxSamples
|
4, // MaxSamples
|
||||||
0, // maxMeshOutputVerticesNV;
|
0, // maxMeshOutputVerticesNV
|
||||||
0, // maxMeshOutputPrimitivesNV;
|
0, // maxMeshOutputPrimitivesNV
|
||||||
0, // maxMeshWorkGroupSizeX_NV;
|
0, // maxMeshWorkGroupSizeX_NV
|
||||||
0, // maxMeshWorkGroupSizeY_NV;
|
0, // maxMeshWorkGroupSizeY_NV
|
||||||
0, // maxMeshWorkGroupSizeZ_NV;
|
0, // maxMeshWorkGroupSizeZ_NV
|
||||||
0, // maxTaskWorkGroupSizeX_NV;
|
0, // maxTaskWorkGroupSizeX_NV
|
||||||
0, // maxTaskWorkGroupSizeY_NV;
|
0, // maxTaskWorkGroupSizeY_NV
|
||||||
0, // maxTaskWorkGroupSizeZ_NV;
|
0, // maxTaskWorkGroupSizeZ_NV
|
||||||
0, // maxMeshViewCountNV
|
0, // maxMeshViewCountNV
|
||||||
|
0, // maxDualSourceDrawBuffersEXT
|
||||||
|
|
||||||
{ // limits
|
{ // limits
|
||||||
true, // nonInductiveForLoops
|
true, // nonInductiveForLoops
|
||||||
|
|||||||
@@ -142,15 +142,16 @@ namespace bgfx { namespace spirv
|
|||||||
8, // MaxCullDistances
|
8, // MaxCullDistances
|
||||||
8, // MaxCombinedClipAndCullDistances
|
8, // MaxCombinedClipAndCullDistances
|
||||||
4, // MaxSamples
|
4, // MaxSamples
|
||||||
0, // maxMeshOutputVerticesNV;
|
0, // maxMeshOutputVerticesNV
|
||||||
0, // maxMeshOutputPrimitivesNV;
|
0, // maxMeshOutputPrimitivesNV
|
||||||
0, // maxMeshWorkGroupSizeX_NV;
|
0, // maxMeshWorkGroupSizeX_NV
|
||||||
0, // maxMeshWorkGroupSizeY_NV;
|
0, // maxMeshWorkGroupSizeY_NV
|
||||||
0, // maxMeshWorkGroupSizeZ_NV;
|
0, // maxMeshWorkGroupSizeZ_NV
|
||||||
0, // maxTaskWorkGroupSizeX_NV;
|
0, // maxTaskWorkGroupSizeX_NV
|
||||||
0, // maxTaskWorkGroupSizeY_NV;
|
0, // maxTaskWorkGroupSizeY_NV
|
||||||
0, // maxTaskWorkGroupSizeZ_NV;
|
0, // maxTaskWorkGroupSizeZ_NV
|
||||||
0, // maxMeshViewCountNV
|
0, // maxMeshViewCountNV
|
||||||
|
0, // maxDualSourceDrawBuffersEXT
|
||||||
|
|
||||||
{ // limits
|
{ // limits
|
||||||
true, // nonInductiveForLoops
|
true, // nonInductiveForLoops
|
||||||
@@ -803,7 +804,7 @@ namespace bgfx { namespace spirv
|
|||||||
uniforms.push_back(uniform);
|
uniforms.push_back(uniform);
|
||||||
moved = true;
|
moved = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!moved)
|
if (!moved)
|
||||||
|
|||||||
Reference in New Issue
Block a user