From deec1933e907872eaff2647720b12634890540e2 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Tue, 13 Aug 2019 08:00:30 -0600 Subject: [PATCH] Web: Turn off includes, independent preprocessing path, fine tune all. Saved about 21K, size down to 380K of MSVC x86 code. Fixed one bug that needs to be looked at on the master branch: The test for needing a Vulkan binding has a bug in it, "!layoutAttachment" which does not mean "no layoutAttachment", because that is non-zero. This is why some test and test results changed. --- SPIRV/GlslangToSpv.cpp | 16 +-- SPIRV/SpvBuilder.cpp | 2 +- StandAlone/StandAlone.cpp | 2 + Test/baseResults/glspv.vert.out | 4 +- Test/baseResults/link1.vk.frag.out | 14 +-- Test/baseResults/size | 2 +- Test/baseResults/spv.debugInfo.1.1.frag.out | 3 +- Test/baseResults/spv.hlslOffsets.vert.out | 4 +- Test/baseResults/web.array.frag.out | 102 ++++++++++++++++++ Test/link1.vk.frag | 4 +- Test/link2.vk.frag | 4 +- Test/runtests | 2 +- Test/spv.hlslOffsets.vert | 2 +- Test/vulkan.vert | 4 +- Test/web.array.frag | 26 +++++ Test/web.testlist | 1 + glslang/Include/Types.h | 37 ++++--- glslang/Include/intermediate.h | 3 +- glslang/MachineIndependent/Intermediate.cpp | 43 ++++---- .../MachineIndependent/ParseContextBase.cpp | 4 +- glslang/MachineIndependent/ParseHelper.cpp | 93 ++++++++-------- glslang/MachineIndependent/ParseHelper.h | 6 +- glslang/MachineIndependent/Scan.cpp | 30 +++--- glslang/MachineIndependent/ShaderLang.cpp | 26 ++++- glslang/MachineIndependent/SymbolTable.cpp | 4 + glslang/MachineIndependent/SymbolTable.h | 13 +++ glslang/MachineIndependent/Versions.cpp | 83 +++++++------- glslang/MachineIndependent/iomapper.cpp | 4 +- glslang/MachineIndependent/iomapper.h | 2 +- glslang/MachineIndependent/limits.cpp | 2 + glslang/MachineIndependent/linkValidate.cpp | 11 +- glslang/MachineIndependent/parseVersions.h | 53 ++++++--- .../MachineIndependent/preprocessor/Pp.cpp | 13 ++- glslang/MachineIndependent/reflection.cpp | 2 +- 34 files changed, 423 insertions(+), 198 deletions(-) create mode 100644 Test/baseResults/web.array.frag.out create mode 100644 Test/web.array.frag diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 4a0732340..fb578f216 100644 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -390,9 +390,9 @@ void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector } if (qualifier.restrict) memory.push_back(spv::DecorationRestrict); - if (qualifier.readonly) + if (qualifier.isReadOnly()) memory.push_back(spv::DecorationNonWritable); - if (qualifier.writeonly) + if (qualifier.isWriteOnly()) memory.push_back(spv::DecorationNonReadable); #endif } @@ -1180,20 +1180,16 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T if (glslangIntermediate->getSource() != glslang::EShSourceHlsl || type.getQualifier().storage == glslang::EvqUniform) { -#ifndef GLSLANG_WEB - if (type.getBasicType() == glslang::EbtAtomicUint) + if (type.isAtomic()) return spv::StorageClassAtomicCounter; -#endif if (type.containsOpaque()) return spv::StorageClassUniformConstant; } -#ifndef GLSLANG_WEB if (type.getQualifier().isUniformOrBuffer() && - type.getQualifier().layoutShaderRecordNV) { + type.getQualifier().isShaderRecordNV()) { return spv::StorageClassShaderRecordBufferNV; } -#endif if (glslangIntermediate->usingStorageBuffer() && type.getQualifier().storage == glslang::EvqBuffer) { addPre13Extension(spv::E_SPV_KHR_storage_buffer_storage_class); @@ -1201,10 +1197,8 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T } if (type.getQualifier().isUniformOrBuffer()) { -#ifndef GLSLANG_WEB if (type.getQualifier().isPushConstant()) return spv::StorageClassPushConstant; -#endif if (type.getBasicType() == glslang::EbtBlock) return spv::StorageClassUniform; return spv::StorageClassUniformConstant; @@ -1215,7 +1209,7 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T case glslang::EvqConstReadOnly: return spv::StorageClassFunction; case glslang::EvqTemporary: return spv::StorageClassFunction; #ifndef GLSLANG_WEB - case glslang::EvqShared: return spv::StorageClassWorkgroup; + case glslang::EvqShared: return spv::StorageClassWorkgroup; case glslang::EvqPayloadNV: return spv::StorageClassRayPayloadNV; case glslang::EvqPayloadInNV: return spv::StorageClassIncomingRayPayloadNV; case glslang::EvqHitAttrNV: return spv::StorageClassHitAttributeNV; diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index 4a6f30bea..bd208952e 100644 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -2315,7 +2315,7 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector& Instruction* instr = module.getInstruction(componentTypeId); #ifdef GLSLANG_WEB const unsigned bitCount = 32; - assert(bitcount == instr->getImmediateOperand(0)); + assert(bitCount == instr->getImmediateOperand(0)); #else const unsigned bitCount = instr->getImmediateOperand(0); #endif diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index 44d3cccad..9fa311bce 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -1040,6 +1040,7 @@ void CompileAndLinkShaderUnits(std::vector compUnits) DirStackFileIncluder includer; std::for_each(IncludeDirectoryList.rbegin(), IncludeDirectoryList.rend(), [&includer](const std::string& dir) { includer.pushExternalLocalDirectory(dir); }); +#ifndef GLSLANG_WEB if (Options & EOptionOutputPreprocessed) { std::string str; if (shader->preprocess(&Resources, defaultVersion, ENoProfile, false, false, messages, &str, includer)) { @@ -1051,6 +1052,7 @@ void CompileAndLinkShaderUnits(std::vector compUnits) StderrIfNonEmpty(shader->getInfoDebugLog()); continue; } +#endif if (! shader->parse(&Resources, defaultVersion, false, messages, includer)) CompileFailed = true; diff --git a/Test/baseResults/glspv.vert.out b/Test/baseResults/glspv.vert.out index f2fe53b29..d51926284 100644 --- a/Test/baseResults/glspv.vert.out +++ b/Test/baseResults/glspv.vert.out @@ -2,12 +2,14 @@ glspv.vert ERROR: 0:3: 'push_constant' : only allowed when using GLSL for Vulkan ERROR: 0:6: 'descriptor set' : only allowed when using GLSL for Vulkan ERROR: 0:8: 'shared' : not allowed when generating SPIR-V +ERROR: 0:8: 'binding' : uniform/buffer blocks require layout(binding=X) ERROR: 0:9: 'packed' : not allowed when generating SPIR-V +ERROR: 0:9: 'binding' : uniform/buffer blocks require layout(binding=X) ERROR: 0:13: 'gl_VertexIndex' : undeclared identifier ERROR: 0:14: 'gl_InstanceIndex' : undeclared identifier ERROR: 0:17: 'gl_DepthRangeParameters' : undeclared identifier ERROR: 0:20: '' : syntax error, unexpected IDENTIFIER, expecting LEFT_BRACE or COMMA or SEMICOLON -ERROR: 8 compilation errors. No code generated. +ERROR: 10 compilation errors. No code generated. SPIR-V is not generated for failed compile or link diff --git a/Test/baseResults/link1.vk.frag.out b/Test/baseResults/link1.vk.frag.out index a24246a6e..094a50d8a 100644 --- a/Test/baseResults/link1.vk.frag.out +++ b/Test/baseResults/link1.vk.frag.out @@ -42,8 +42,8 @@ gl_FragCoord origin is upper left 0:? 'b' ( global 5-element array of highp int) 0:? 'c' ( global unsized 4-element array of highp int) 0:? 'i' ( global highp int) -0:? 'anon@0' (layout( column_major std430) buffer block{layout( column_major std430) buffer unsized 1-element array of highp float r}) -0:? 'anon@1' (layout( column_major std430) buffer block{layout( column_major std430) buffer unsized 1-element array of highp float m}) +0:? 'anon@0' (layout( binding=0 column_major std430) buffer block{layout( column_major std430) buffer unsized 1-element array of highp float r}) +0:? 'anon@1' (layout( binding=1 column_major std430) buffer block{layout( column_major std430) buffer unsized 1-element array of highp float m}) link2.vk.frag Shader version: 450 @@ -99,8 +99,8 @@ gl_FragCoord origin is upper left 0:? 'b' ( global unsized 3-element array of highp int) 0:? 'c' ( global 7-element array of highp int) 0:? 'i' ( global highp int) -0:? 'anon@0' (layout( column_major std430) buffer block{layout( column_major std430) buffer unsized 1-element array of highp float r}) -0:? 'anon@1' (layout( column_major std430) buffer block{layout( column_major std430) buffer 4-element array of highp float m}) +0:? 'anon@0' (layout( binding=0 column_major std430) buffer block{layout( column_major std430) buffer unsized 1-element array of highp float r}) +0:? 'anon@1' (layout( binding=1 column_major std430) buffer block{layout( column_major std430) buffer 4-element array of highp float m}) Linked fragment stage: @@ -192,8 +192,8 @@ gl_FragCoord origin is upper left 0:? 'b' ( global 5-element array of highp int) 0:? 'c' ( global 7-element array of highp int) 0:? 'i' ( global highp int) -0:? 'anon@0' (layout( column_major std430) buffer block{layout( column_major std430) buffer unsized 1-element array of highp float r}) -0:? 'anon@1' (layout( column_major std430) buffer block{layout( column_major std430) buffer 4-element array of highp float m}) +0:? 'anon@0' (layout( binding=0 column_major std430) buffer block{layout( column_major std430) buffer unsized 1-element array of highp float r}) +0:? 'anon@1' (layout( binding=1 column_major std430) buffer block{layout( column_major std430) buffer 4-element array of highp float m}) 0:? 's2D' (layout( binding=1) uniform highp sampler2D) // Module Version 10000 @@ -233,7 +233,7 @@ gl_FragCoord origin is upper left MemberDecorate 67(bnameImplicit) 0 Offset 0 Decorate 67(bnameImplicit) BufferBlock Decorate 69 DescriptorSet 0 - Decorate 69 Binding 0 + Decorate 69 Binding 1 2: TypeVoid 3: TypeFunction 2 6: TypeFloat 32 diff --git a/Test/baseResults/size b/Test/baseResults/size index c870190a8..484877654 100644 --- a/Test/baseResults/size +++ b/Test/baseResults/size @@ -1 +1 @@ -409600 ../build/install/bin/glslangValidator.exe +388096 ../build/install/bin/glslangValidator.exe diff --git a/Test/baseResults/spv.debugInfo.1.1.frag.out b/Test/baseResults/spv.debugInfo.1.1.frag.out index afd8cfdfe..e21208923 100644 --- a/Test/baseResults/spv.debugInfo.1.1.frag.out +++ b/Test/baseResults/spv.debugInfo.1.1.frag.out @@ -81,6 +81,7 @@ void main() Name 97 "i" ModuleProcessed "no-storage-format" ModuleProcessed "resource-set-binding 3" + ModuleProcessed "auto-map-bindings" ModuleProcessed "auto-map-locations" ModuleProcessed "client opengl100" ModuleProcessed "target-env spirv1.3" @@ -99,7 +100,7 @@ void main() Decorate 56 Binding 0 Decorate 67(s2d) Location 0 Decorate 67(s2d) DescriptorSet 3 - Decorate 67(s2d) Binding 0 + Decorate 67(s2d) Binding 1 3: TypeVoid 4: TypeFunction 3 7: TypeInt 32 1 diff --git a/Test/baseResults/spv.hlslOffsets.vert.out b/Test/baseResults/spv.hlslOffsets.vert.out index 84dc47b23..723675469 100644 --- a/Test/baseResults/spv.hlslOffsets.vert.out +++ b/Test/baseResults/spv.hlslOffsets.vert.out @@ -4,7 +4,7 @@ Shader version: 450 0:27 Function Definition: main( ( global void) 0:27 Function Parameters: 0:? Linker Objects -0:? 'anon@0' (layout( column_major std430) buffer block{layout( column_major std430) buffer highp float m0, layout( column_major std430) buffer highp 3-component vector of float m4, layout( column_major std430) buffer highp float m16, layout( column_major std430 offset=20) buffer highp 3-component vector of float m20, layout( column_major std430) buffer highp 3-component vector of float m32, layout( column_major std430) buffer highp 2-component vector of float m48, layout( column_major std430) buffer highp 2-component vector of float m56, layout( column_major std430) buffer highp float m64, layout( column_major std430) buffer highp 2-component vector of float m68, layout( column_major std430) buffer highp float m76, layout( column_major std430) buffer highp float m80, layout( column_major std430 offset=88) buffer highp 2-component vector of float m88, layout( column_major std430) buffer highp 2-component vector of float m96, layout( column_major std430) buffer 2-component vector of double m112}) +0:? 'anon@0' (layout( binding=0 column_major std430) buffer block{layout( column_major std430) buffer highp float m0, layout( column_major std430) buffer highp 3-component vector of float m4, layout( column_major std430) buffer highp float m16, layout( column_major std430 offset=20) buffer highp 3-component vector of float m20, layout( column_major std430) buffer highp 3-component vector of float m32, layout( column_major std430) buffer highp 2-component vector of float m48, layout( column_major std430) buffer highp 2-component vector of float m56, layout( column_major std430) buffer highp float m64, layout( column_major std430) buffer highp 2-component vector of float m68, layout( column_major std430) buffer highp float m76, layout( column_major std430) buffer highp float m80, layout( column_major std430 offset=88) buffer highp 2-component vector of float m88, layout( column_major std430) buffer highp 2-component vector of float m96, layout( column_major std430) buffer 2-component vector of double m112}) Linked vertex stage: @@ -15,7 +15,7 @@ Shader version: 450 0:27 Function Definition: main( ( global void) 0:27 Function Parameters: 0:? Linker Objects -0:? 'anon@0' (layout( column_major std430) buffer block{layout( column_major std430) buffer highp float m0, layout( column_major std430) buffer highp 3-component vector of float m4, layout( column_major std430) buffer highp float m16, layout( column_major std430 offset=20) buffer highp 3-component vector of float m20, layout( column_major std430) buffer highp 3-component vector of float m32, layout( column_major std430) buffer highp 2-component vector of float m48, layout( column_major std430) buffer highp 2-component vector of float m56, layout( column_major std430) buffer highp float m64, layout( column_major std430) buffer highp 2-component vector of float m68, layout( column_major std430) buffer highp float m76, layout( column_major std430) buffer highp float m80, layout( column_major std430 offset=88) buffer highp 2-component vector of float m88, layout( column_major std430) buffer highp 2-component vector of float m96, layout( column_major std430) buffer 2-component vector of double m112}) +0:? 'anon@0' (layout( binding=0 column_major std430) buffer block{layout( column_major std430) buffer highp float m0, layout( column_major std430) buffer highp 3-component vector of float m4, layout( column_major std430) buffer highp float m16, layout( column_major std430 offset=20) buffer highp 3-component vector of float m20, layout( column_major std430) buffer highp 3-component vector of float m32, layout( column_major std430) buffer highp 2-component vector of float m48, layout( column_major std430) buffer highp 2-component vector of float m56, layout( column_major std430) buffer highp float m64, layout( column_major std430) buffer highp 2-component vector of float m68, layout( column_major std430) buffer highp float m76, layout( column_major std430) buffer highp float m80, layout( column_major std430 offset=88) buffer highp 2-component vector of float m88, layout( column_major std430) buffer highp 2-component vector of float m96, layout( column_major std430) buffer 2-component vector of double m112}) // Module Version 10000 // Generated by (magic number): 80007 diff --git a/Test/baseResults/web.array.frag.out b/Test/baseResults/web.array.frag.out new file mode 100644 index 000000000..df70be126 --- /dev/null +++ b/Test/baseResults/web.array.frag.out @@ -0,0 +1,102 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 7 +; Bound: 74 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %colorOut + OpExecutionMode %main OriginUpperLeft + OpSource ESSL 310 + OpName %main "main" + OpName %foo_f1_5__ "foo(f1[5];" + OpName %a "a" + OpName %g4 "g4" + OpName %g5 "g5" + OpName %param "param" + OpName %u "u" + OpName %param_0 "param" + OpName %colorOut "colorOut" + OpDecorate %colorOut Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %uint = OpTypeInt 32 0 + %uint_5 = OpConstant %uint 5 +%_arr_float_uint_5 = OpTypeArray %float %uint_5 +%_ptr_Function__arr_float_uint_5 = OpTypePointer Function %_arr_float_uint_5 + %uint_4 = OpConstant %uint 4 +%_arr_float_uint_4 = OpTypeArray %float %uint_4 + %13 = OpTypeFunction %_arr_float_uint_4 %_ptr_Function__arr_float_uint_5 + %int = OpTypeInt 32 1 + %int_0 = OpConstant %int 0 +%_ptr_Function_float = OpTypePointer Function %float + %int_1 = OpConstant %int 1 + %int_2 = OpConstant %int 2 + %int_3 = OpConstant %int 3 +%_ptr_Private__arr_float_uint_4 = OpTypePointer Private %_arr_float_uint_4 + %g4 = OpVariable %_ptr_Private__arr_float_uint_4 Private +%_ptr_Private__arr_float_uint_5 = OpTypePointer Private %_arr_float_uint_5 + %g5 = OpVariable %_ptr_Private__arr_float_uint_5 Private + %float_1 = OpConstant %float 1 + %float_2 = OpConstant %float 2 + %float_3 = OpConstant %float 3 + %float_4 = OpConstant %float 4 + %45 = OpConstantComposite %_arr_float_uint_4 %float_1 %float_2 %float_3 %float_4 + %bool = OpTypeBool + %v2float = OpTypeVector %float 2 +%_ptr_Output_v2float = OpTypePointer Output %v2float + %colorOut = OpVariable %_ptr_Output_v2float Output + %float_5 = OpConstant %float 5 + %73 = OpConstantComposite %v2float %float_4 %float_5 + %main = OpFunction %void None %3 + %5 = OpLabel + %param = OpVariable %_ptr_Function__arr_float_uint_5 Function + %u = OpVariable %_ptr_Function__arr_float_uint_5 Function + %param_0 = OpVariable %_ptr_Function__arr_float_uint_5 Function + %39 = OpLoad %_arr_float_uint_5 %g5 + OpStore %param %39 + %40 = OpFunctionCall %_arr_float_uint_4 %foo_f1_5__ %param + OpStore %g4 %40 + %46 = OpLoad %_arr_float_uint_4 %g4 + %48 = OpCompositeExtract %float %45 0 + %49 = OpCompositeExtract %float %46 0 + %50 = OpFOrdEqual %bool %48 %49 + %51 = OpCompositeExtract %float %45 1 + %52 = OpCompositeExtract %float %46 1 + %53 = OpFOrdEqual %bool %51 %52 + %54 = OpLogicalAnd %bool %50 %53 + %55 = OpCompositeExtract %float %45 2 + %56 = OpCompositeExtract %float %46 2 + %57 = OpFOrdEqual %bool %55 %56 + %58 = OpLogicalAnd %bool %54 %57 + %59 = OpCompositeExtract %float %45 3 + %60 = OpCompositeExtract %float %46 3 + %61 = OpFOrdEqual %bool %59 %60 + %62 = OpLogicalAnd %bool %58 %61 + OpSelectionMerge %64 None + OpBranchConditional %62 %63 %64 + %63 = OpLabel + OpBranch %64 + %64 = OpLabel + %67 = OpLoad %_arr_float_uint_5 %u + OpStore %param_0 %67 + %68 = OpFunctionCall %_arr_float_uint_4 %foo_f1_5__ %param_0 + OpStore %colorOut %73 + OpReturn + OpFunctionEnd + %foo_f1_5__ = OpFunction %_arr_float_uint_4 None %13 + %a = OpFunctionParameter %_ptr_Function__arr_float_uint_5 + %16 = OpLabel + %20 = OpAccessChain %_ptr_Function_float %a %int_0 + %21 = OpLoad %float %20 + %23 = OpAccessChain %_ptr_Function_float %a %int_1 + %24 = OpLoad %float %23 + %26 = OpAccessChain %_ptr_Function_float %a %int_2 + %27 = OpLoad %float %26 + %29 = OpAccessChain %_ptr_Function_float %a %int_3 + %30 = OpLoad %float %29 + %31 = OpCompositeConstruct %_arr_float_uint_4 %21 %24 %27 %30 + OpReturnValue %31 + OpFunctionEnd diff --git a/Test/link1.vk.frag b/Test/link1.vk.frag index 167e78ee7..c860f6476 100644 --- a/Test/link1.vk.frag +++ b/Test/link1.vk.frag @@ -10,8 +10,8 @@ int b[5]; int c[]; int i; -buffer bnameRuntime { float r[]; }; -buffer bnameImplicit { float m[]; }; +layout (binding = 0) buffer bnameRuntime { float r[]; }; +layout (binding = 1) buffer bnameImplicit { float m[]; }; void main() { diff --git a/Test/link2.vk.frag b/Test/link2.vk.frag index b80402ca5..b83f8694f 100644 --- a/Test/link2.vk.frag +++ b/Test/link2.vk.frag @@ -8,8 +8,8 @@ int b[]; int c[7]; int i; -buffer bnameRuntime { float r[]; }; -buffer bnameImplicit { float m[4]; }; +layout (binding = 0) buffer bnameRuntime { float r[]; }; +layout (binding = 1) buffer bnameImplicit { float m[4]; }; vec4 getColor() { diff --git a/Test/runtests b/Test/runtests index cf947a6ba..8e31c0696 100755 --- a/Test/runtests +++ b/Test/runtests @@ -145,7 +145,7 @@ echo Testing SPV Debug Information $EXE -g --relaxed-errors --suppress-warnings --aml --amb --hlsl-offsets --nsf --spirv-val \ -G -H spv.debugInfo.frag --rsb frag 3 > $TARGETDIR/spv.debugInfo.frag.out diff -b $BASEDIR/spv.debugInfo.frag.out $TARGETDIR/spv.debugInfo.frag.out || HASERROR=1 -$EXE -g -Od --target-env vulkan1.1 --relaxed-errors --suppress-warnings --aml --hlsl-offsets --nsf --spirv-val \ +$EXE -g -Od --target-env vulkan1.1 --relaxed-errors --suppress-warnings --aml --amb --hlsl-offsets --nsf --spirv-val \ -G -H spv.debugInfo.frag --rsb frag 3 > $TARGETDIR/spv.debugInfo.1.1.frag.out diff -b $BASEDIR/spv.debugInfo.1.1.frag.out $TARGETDIR/spv.debugInfo.1.1.frag.out || HASERROR=1 $EXE -g -D -Od -e newMain -g --amb --aml --fua --hlsl-iomap --nsf --spirv-val --sib 1 --ssb 2 --sbb 3 --stb 4 --suavb 5 --sub 6 \ diff --git a/Test/spv.hlslOffsets.vert b/Test/spv.hlslOffsets.vert index 87e32a729..26950d93a 100644 --- a/Test/spv.hlslOffsets.vert +++ b/Test/spv.hlslOffsets.vert @@ -1,6 +1,6 @@ #version 450 -buffer block { +layout(binding = 0) buffer block { float m0; vec3 m4; ////// diff --git a/Test/vulkan.vert b/Test/vulkan.vert index 99456b9f0..7142691a9 100644 --- a/Test/vulkan.vert +++ b/Test/vulkan.vert @@ -21,8 +21,8 @@ void main() } layout(binding = 0) uniform atomic_uint aui; // ERROR, no atomics in Vulkan -layout(shared) uniform ub1n { int a; } ub1i; // ERROR, no shared -layout(packed) uniform ub2n { int a; } ub2i; // ERROR, no packed +layout(shared, binding = 1) uniform ub1n { int a; } ub1i; // ERROR, no shared +layout(packed, binding = 2) uniform ub2n { int a; } ub2i; // ERROR, no packed layout(constant_id=222) const int arraySize = 4; diff --git a/Test/web.array.frag b/Test/web.array.frag new file mode 100644 index 000000000..8b8acdf5d --- /dev/null +++ b/Test/web.array.frag @@ -0,0 +1,26 @@ +#version 310 es + +precision highp float; + +float g4[4]; +float g5[5]; + +layout(location = 0) out vec2 colorOut; + +float[4] foo(float a[5]) +{ + return float[](a[0], a[1], a[2], a[3]); +} + +void main() +{ + g4 = foo(g5); + + if (float[4](1.0, 2.0, 3.0, 4.0) == g4) + ; + + float u[5]; + foo(u); + + colorOut = vec2(g4.length(), g5.length()); +} diff --git a/Test/web.testlist b/Test/web.testlist index b2d147415..fba92127a 100644 --- a/Test/web.testlist +++ b/Test/web.testlist @@ -4,3 +4,4 @@ web.basic.vert web.controlFlow.frag web.operations.frag web.texture.frag +web.array.frag diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index fa26c8cbf..3720de7a4 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -578,6 +578,8 @@ public: bool nonUniform : 1; #ifdef GLSLANG_WEB + bool isWriteOnly() const { return false; } + bool isReadOnly() const { return false; } bool isSample() const { return false; } bool isMemory() const { return false; } bool isMemoryQualifierImageAndSSBOOnly() const { return false; } @@ -599,6 +601,8 @@ public: bool perTaskNV : 1; bool patch : 1; bool sample : 1; + bool isWriteOnly() const { return writeonly; } + bool isReadOnly() const { return readonly; } bool isSample() const { return sample; } bool isMemory() const { @@ -1035,11 +1039,13 @@ public: static const char* getLayoutPackingString(TLayoutPacking packing) { switch (packing) { + case ElpStd140: return "std140"; +#ifndef GLSLANG_WEB case ElpPacked: return "packed"; case ElpShared: return "shared"; - case ElpStd140: return "std140"; case ElpStd430: return "std430"; case ElpScalar: return "scalar"; +#endif default: return "none"; } } @@ -1332,6 +1338,12 @@ public: TSourceLoc loc; TArraySizes* typeParameters; +#ifdef GLSLANG_WEB + bool isCoopmat() const { return false; } +#else + bool isCoopmat() const { return coopmat; } +#endif + void initType(const TSourceLoc& l) { basicType = EbtVoid; @@ -1435,7 +1447,7 @@ public: } typeName = NewPoolTString(p.userDef->getTypeName().c_str()); } - if (p.coopmat && p.basicType == EbtFloat && + if (p.isCoopmat() && p.basicType == EbtFloat && p.typeParameters && p.typeParameters->getNumDims() > 0 && p.typeParameters->getDimSize(0) == 16) { basicType = EbtFloat16; @@ -1544,7 +1556,7 @@ public: referentType = copyOf.referentType; } typeParameters = copyOf.typeParameters; - coopmat = copyOf.coopmat; + coopmat = copyOf.isCoopMat(); } // Make complete copy of the whole type graph rooted at 'copyOf'. @@ -1658,9 +1670,11 @@ public: virtual bool isTexture() const { return basicType == EbtSampler && getSampler().isTexture(); } virtual bool isParameterized() const { return typeParameters != nullptr; } #ifdef GLSLANG_WEB + bool isAtomic() const { return false; } bool isCoopMat() const { return false; } bool isReference() const { return false; } #else + bool isAtomic() const { return basicType == EbtAtomicUint; } bool isCoopMat() const { return coopmat; } bool isReference() const { return getBasicType() == EbtReference; } #endif @@ -2240,7 +2254,7 @@ public: return true; } - bool sameReferenceType(const TType& right) const + bool sameReferenceType(const TType& right) const { if (isReference() != right.isReference()) return false; @@ -2257,7 +2271,7 @@ public: return *referentType == *right.referentType; } - // See if two types match, in all aspects except arrayness + // See if two types match, in all aspects except arrayness bool sameElementType(const TType& right) const { return basicType == right.basicType && sameElementShape(right); @@ -2292,7 +2306,7 @@ public: matrixCols == right.matrixCols && matrixRows == right.matrixRows && vector1 == right.vector1 && - coopmat == right.coopmat && + isCoopMat() == right.isCoopMat() && sameStructType(right) && sameReferenceType(right); } @@ -2301,7 +2315,7 @@ public: // an OK function parameter bool coopMatParameterOK(const TType& right) const { - return coopmat && right.coopmat && + return isCoopMat() && right.isCoopMat() && typeParameters == nullptr && right.typeParameters != nullptr; } @@ -2316,19 +2330,16 @@ public: return ! operator==(right); } -#ifdef GLSLANG_WEB - unsigned int getBufferReferenceAlignment() const { return 0; } -#else unsigned int getBufferReferenceAlignment() const { +#ifndef GLSLANG_WEB if (getBasicType() == glslang::EbtReference) { return getReferentType()->getQualifier().hasBufferReferenceAlign() ? (1u << getReferentType()->getQualifier().layoutBufferReferenceAlign) : 16u; - } else { - return 0; } - } #endif + return 0; + } protected: // Require consumer to pick between deep copy and shallow copy. diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h index f2a015ad0..3a7405ad6 100644 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -1089,7 +1089,8 @@ public: virtual bool isStruct() const { return type.isStruct(); } virtual bool isFloatingDomain() const { return type.isFloatingDomain(); } virtual bool isIntegerDomain() const { return type.isIntegerDomain(); } - virtual bool isReference() const { return type.isReference(); } + bool isAtomic() const { return type.isAtomic(); } + bool isReference() const { return type.isReference(); } TString getCompleteString() const { return type.getCompleteString(); } protected: diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index 966040bac..93d41f7da 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -383,18 +383,20 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo // TBasicType newType = EbtVoid; switch (op) { - case EOpConstructInt8: newType = EbtInt8; break; - case EOpConstructUint8: newType = EbtUint8; break; - case EOpConstructInt16: newType = EbtInt16; break; - case EOpConstructUint16: newType = EbtUint16; break; - case EOpConstructInt: newType = EbtInt; break; - case EOpConstructUint: newType = EbtUint; break; - case EOpConstructInt64: newType = EbtInt64; break; - case EOpConstructUint64: newType = EbtUint64; break; case EOpConstructBool: newType = EbtBool; break; case EOpConstructFloat: newType = EbtFloat; break; + case EOpConstructInt: newType = EbtInt; break; + case EOpConstructUint: newType = EbtUint; break; +#ifndef GLSLANG_WEB + case EOpConstructInt8: newType = EbtInt8; break; + case EOpConstructUint8: newType = EbtUint8; break; + case EOpConstructInt16: newType = EbtInt16; break; + case EOpConstructUint16: newType = EbtUint16; break; + case EOpConstructInt64: newType = EbtInt64; break; + case EOpConstructUint64: newType = EbtUint64; break; case EOpConstructDouble: newType = EbtDouble; break; case EOpConstructFloat16: newType = EbtFloat16; break; +#endif default: break; // some compilers want this } @@ -1562,6 +1564,17 @@ bool TIntermediate::isFPConversion(TBasicType from, TBasicType to) const bool TIntermediate::isFPIntegralConversion(TBasicType from, TBasicType to) const { switch (from) { + case EbtInt: + case EbtUint: + switch(to) { + case EbtFloat: + case EbtDouble: + return true; + default: + break; + } + break; +#ifndef GLSLANG_WEB case EbtInt8: case EbtUint8: case EbtInt16: @@ -1575,23 +1588,13 @@ bool TIntermediate::isFPIntegralConversion(TBasicType from, TBasicType to) const break; } break; - case EbtInt: - case EbtUint: - switch(to) { - case EbtFloat: - case EbtDouble: - return true; - default: - break; - } - break; case EbtInt64: case EbtUint64: if (to == EbtDouble) { return true; } break; - +#endif default: break; } @@ -1709,7 +1712,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat case EbtFloat: return true; case EbtBool: - return (getSource() == EShSourceHlsl); + return getSource() == EShSourceHlsl; case EbtInt16: case EbtUint16: return extensionRequested(E_GL_AMD_gpu_shader_int16); diff --git a/glslang/MachineIndependent/ParseContextBase.cpp b/glslang/MachineIndependent/ParseContextBase.cpp index ccf010e3a..282ecca0e 100644 --- a/glslang/MachineIndependent/ParseContextBase.cpp +++ b/glslang/MachineIndependent/ParseContextBase.cpp @@ -155,7 +155,7 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, case EvqUniform: message = "can't modify a uniform"; break; #ifndef GLSLANG_WEB case EvqBuffer: - if (node->getQualifier().readonly) + if (node->getQualifier().isReadOnly()) message = "can't modify a readonly buffer"; if (node->getQualifier().isShaderRecordNV()) message = "can't modify a shaderrecordnv qualified buffer"; @@ -236,7 +236,7 @@ void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, } TIntermSymbol* symNode = node->getAsSymbolNode(); - if (symNode && symNode->getQualifier().writeonly) + if (symNode && symNode->getQualifier().isWriteOnly()) error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str()); } diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 1db615a20..9e19b2791 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -56,8 +56,11 @@ TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, b infoSink, forwardCompatible, messages, entryPoint), inMain(false), blockName(nullptr), - limits(resources.limits), + limits(resources.limits) +#ifndef GLSLANG_WEB + , atomicUintOffsets(nullptr), anyIndexLimits(false) +#endif { // decide whether precision qualifiers should be ignored or respected if (isEsProfile() || spvVersion.vulkan > 0) { @@ -103,7 +106,9 @@ TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, b TParseContext::~TParseContext() { +#ifndef GLSLANG_WEB delete [] atomicUintOffsets; +#endif } // Set up all default precisions as needed by the current environment. @@ -855,8 +860,8 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm } } else if (base->isStruct() || base->isReference()) { const TTypeList* fields = base->isReference() ? - base->getType().getReferentType()->getStruct() : - base->getType().getStruct(); + base->getType().getReferentType()->getStruct() : + base->getType().getStruct(); bool fieldFound = false; int member; for (member = 0; member < (int)fields->size(); ++member) { @@ -1089,12 +1094,9 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction { TIntermTyped* result = nullptr; -#ifndef GLSLANG_WEB if (function->getBuiltInOp() == EOpArrayLength) result = handleLengthMethod(loc, function, arguments); - else -#endif - if (function->getBuiltInOp() != EOpNull) { + else if (function->getBuiltInOp() != EOpNull) { // // Then this should be a constructor. // Don't go through the symbol table for constructors. @@ -1147,7 +1149,6 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction error(arguments->getLoc(), "Non-L-value cannot be passed for 'out' or 'inout' parameters.", "out", ""); } TQualifier& argQualifier = arg->getAsTyped()->getQualifier(); -#ifndef GLSLANG_WEB if (argQualifier.isMemory()) { const char* message = "argument cannot drop memory qualifier when passed to formal parameter"; if (argQualifier.volatil && ! formalQualifier.volatil) @@ -1173,11 +1174,10 @@ TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction if (!builtIn && argQualifier.getFormat() != formalQualifier.getFormat()) { // we have mismatched formats, which should only be allowed if writeonly // and at least one format is unknown - if (!formalQualifier.writeonly || (formalQualifier.getFormat() != ElfNone && - argQualifier.getFormat() != ElfNone)) + if (!formalQualifier.isWriteOnly() || (formalQualifier.getFormat() != ElfNone && + argQualifier.getFormat() != ElfNone)) error(arguments->getLoc(), "image formats must match", "format", ""); } -#endif if (builtIn && arg->getAsTyped()->getType().contains16BitFloat()) requireFloat16Arithmetic(arguments->getLoc(), "built-in function", "float16 types can only be in uniform block or buffer storage"); if (builtIn && arg->getAsTyped()->getType().contains16BitInt()) @@ -1457,8 +1457,6 @@ void TParseContext::checkLocation(const TSourceLoc& loc, TOperator op) #endif } -#ifndef GLSLANG_WEB - // Finish processing object.length(). This started earlier in handleDotDereference(), where // the ".length" part was recognized and semantically checked, and finished here where the // function syntax "()" is recognized. @@ -1474,6 +1472,7 @@ TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction const TType& type = intermNode->getAsTyped()->getType(); if (type.isArray()) { if (type.isUnsizedArray()) { +#ifndef GLSLANG_WEB if (intermNode->getAsSymbolNode() && isIoResizeArray(type)) { // We could be between a layout declaration that gives a built-in io array implicit size and // a user redeclaration of that array, meaning we have to substitute its implicit size here @@ -1485,13 +1484,16 @@ TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction length = getIoArrayImplicitSize(type.getQualifier()); } } +#endif if (length == 0) { +#ifndef GLSLANG_WEB if (intermNode->getAsSymbolNode() && isIoResizeArray(type)) error(loc, "", function->getName().c_str(), "array must first be sized by a redeclaration or layout qualifier"); else if (isRuntimeLength(*intermNode->getAsTyped())) { // Create a unary op and let the back end handle it return intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, intermNode, TType(EbtInt)); } else +#endif error(loc, "", function->getName().c_str(), "array must be declared with a size before using this method"); } } else if (type.getOuterArrayNode()) { @@ -1519,8 +1521,6 @@ TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction return intermediate.addConstantUnion(length, loc); } -#endif - // // Add any needed implicit conversions for function-call arguments to input parameters. // @@ -1804,7 +1804,6 @@ void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction& } } - // // Do additional checking of built-in function calls that is not caught // by normal semantic checks on argument type, extension tagging, etc. @@ -2583,12 +2582,10 @@ void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TInt // Let the base class check errors TParseContextBase::rValueErrorCheck(loc, op, node); -#ifndef GLSLANG_WEB TIntermSymbol* symNode = node->getAsSymbolNode(); - if (!(symNode && symNode->getQualifier().writeonly)) // base class checks - if (symNode && symNode->getQualifier().explicitInterp) + if (!(symNode && symNode->getQualifier().isWriteOnly())) // base class checks + if (symNode && symNode->getQualifier().isExplicitInterpolation()) error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str()); -#endif } // @@ -3035,7 +3032,7 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T error(loc, "cannot convert a sampler", "constructor", ""); return true; } - if (op != EOpConstructStruct && typed->getBasicType() == EbtAtomicUint) { + if (op != EOpConstructStruct && typed->isAtomic()) { error(loc, "cannot convert an atomic_uint", "constructor", ""); return true; } @@ -3529,14 +3526,12 @@ void TParseContext::setDefaultPrecision(const TSourceLoc& loc, TPublicType& publ } } -#ifndef GLSLANG_WEB if (basicType == EbtAtomicUint) { if (qualifier != EpqHigh) error(loc, "can only apply highp to atomic_uint", "precision", ""); return; } -#endif error(loc, "cannot apply precision statement to this type; use 'float', 'int' or a sampler type", TType::getBasicString(basicType), ""); } @@ -3573,8 +3568,10 @@ void TParseContext::precisionQualifierCheck(const TSourceLoc& loc, TBasicType ba if (! obeyPrecisionQualifiers() || parsingBuiltins) return; +#ifndef GLSLANG_WEB if (baseType == EbtAtomicUint && qualifier.precision != EpqNone && qualifier.precision != EpqHigh) error(loc, "atomic counters can only be highp", "atomic_uint", ""); +#endif if (baseType == EbtFloat || baseType == EbtUint || baseType == EbtInt || baseType == EbtSampler || baseType == EbtAtomicUint) { if (qualifier.precision == EpqNone) { @@ -3756,16 +3753,15 @@ void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qua (qualifier.storage != EvqTemporary && qualifier.storage != EvqGlobal && qualifier.storage != EvqShared && qualifier.storage != EvqConst)) error(loc, "only outermost dimension of an array of arrays can be a specialization constant", "[]", ""); - // desktop always allows outer-dimension-unsized variable arrays, +#ifndef GLSLANG_WEB + // desktop always allows outer-dimension-unsized variable arrays, if (!isEsProfile()) return; // for ES, if size isn't coming from an initializer, it has to be explicitly declared now, // with very few exceptions -#ifndef GLSLANG_WEB - // last member of ssbo block exception: if (qualifier.storage == EvqBuffer && lastMember) return; @@ -3780,13 +3776,13 @@ void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qua break; case EShLangTessControl: if ( qualifier.storage == EvqVaryingIn || - (qualifier.storage == EvqVaryingOut && ! qualifier.patch)) + (qualifier.storage == EvqVaryingOut && ! qualifier.isPatch())) if ((isEsProfile() && version >= 320) || extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader)) return; break; case EShLangTessEvaluation: - if ((qualifier.storage == EvqVaryingIn && ! qualifier.patch) || + if ((qualifier.storage == EvqVaryingIn && ! qualifier.isPatch()) || qualifier.storage == EvqVaryingOut) if ((isEsProfile() && version >= 320) || extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader)) @@ -4491,12 +4487,15 @@ void TParseContext::opaqueCheck(const TSourceLoc& loc, const TType& type, const void TParseContext::referenceCheck(const TSourceLoc& loc, const TType& type, const char* op) { +#ifndef GLSLANG_WEB if (containsFieldWithBasicType(type, EbtReference)) error(loc, "can't use with reference types", op, ""); +#endif } void TParseContext::storage16BitAssignmentCheck(const TSourceLoc& loc, const TType& type, const char* op) { +#ifndef GLSLANG_WEB if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtFloat16)) requireFloat16Arithmetic(loc, op, "can't use with structs containing float16"); @@ -4526,6 +4525,7 @@ void TParseContext::storage16BitAssignmentCheck(const TSourceLoc& loc, const TTy if (type.isArray() && type.getBasicType() == EbtUint8) requireInt8Arithmetic(loc, op, "can't use with arrays containing uint8"); +#endif } void TParseContext::specializationCheck(const TSourceLoc& loc, const TType& type, const char* op) @@ -5117,8 +5117,10 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi error(loc, "needs a literal integer", "set", ""); return; } else if (id == "binding") { +#ifndef GLSLANG_WEB profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, "binding"); profileRequires(loc, EEsProfile, 310, nullptr, "binding"); +#endif if ((unsigned int)value >= TQualifier::layoutBindingEnd) error(loc, "binding is too large", id.c_str(), ""); else @@ -5517,7 +5519,7 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb if (qualifier.hasPacking()) error(loc, "cannot specify packing on a variable declaration", "layout", ""); // "The offset qualifier can only be used on block members of blocks..." - if (qualifier.hasOffset() && type.getBasicType() != EbtAtomicUint) + if (qualifier.hasOffset() && !type.isAtomic()) error(loc, "cannot specify on a variable declaration", "offset", ""); // "The align qualifier can only be used on blocks or block members..." if (qualifier.hasAlign()) @@ -5675,32 +5677,30 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) } } } +#ifndef GLSLANG_WEB if (spvVersion.vulkan == 0 && lastBinding >= resources.maxCombinedTextureImageUnits) error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : ""); +#endif } -#ifndef GLSLANG_WEB - if (type.getBasicType() == EbtAtomicUint) { + if (type.isAtomic()) { if (qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) { error(loc, "atomic_uint binding is too large; see gl_MaxAtomicCounterBindings", "binding", ""); return; } } -#endif } else if (!intermediate.getAutoMapBindings()) { // some types require bindings -#ifndef GLSLANG_WEB // atomic_uint - if (type.getBasicType() == EbtAtomicUint) + if (type.isAtomic()) error(loc, "layout(binding=X) is required", "atomic_uint", ""); -#endif // SPIR-V if (spvVersion.spv > 0) { if (qualifier.isUniformOrBuffer()) { if (type.getBasicType() == EbtBlock && !qualifier.isPushConstant() && !qualifier.isShaderRecordNV() && - !qualifier.layoutAttachment && + !qualifier.hasAttachment() && !qualifier.hasBufferReference()) error(loc, "uniform/buffer blocks require layout(binding=X)", "binding", ""); else if (spvVersion.vulkan > 0 && type.getBasicType() == EbtSampler) @@ -5739,12 +5739,12 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) // "Except for image variables qualified with the format qualifiers r32f, r32i, and r32ui, image variables must // specify either memory qualifier readonly or the memory qualifier writeonly." if (! (qualifier.getFormat() == ElfR32f || qualifier.getFormat() == ElfR32i || qualifier.getFormat() == ElfR32ui)) { - if (! qualifier.readonly && ! qualifier.writeonly) + if (! qualifier.isReadOnly() && ! qualifier.isWriteOnly()) error(loc, "format requires readonly or writeonly memory qualifier", TQualifier::getLayoutFormatString(qualifier.getFormat()), ""); } } } - } else if (type.isImage() && ! qualifier.writeonly) { + } else if (type.isImage() && ! qualifier.isWriteOnly()) { const char *explanation = "image variables not declared 'writeonly' and without a format layout qualifier"; requireProfile(loc, ECoreProfile | ECompatibilityProfile, explanation); profileRequires(loc, ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shader_image_load_formatted, explanation); @@ -5966,9 +5966,9 @@ void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQua // Correct and/or advance an object's offset layout qualifier. void TParseContext::fixOffset(const TSourceLoc& loc, TSymbol& symbol) { -#ifndef GLSLANG_WEB const TQualifier& qualifier = symbol.getType().getQualifier(); - if (symbol.getType().getBasicType() == EbtAtomicUint) { +#ifndef GLSLANG_WEB + if (symbol.getType().isAtomic()) { if (qualifier.hasBinding() && (int)qualifier.layoutBinding < resources.maxAtomicCounterBindings) { // Set the offset @@ -6545,7 +6545,9 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp TType skeletalType; skeletalType.shallowCopy(variable->getType()); skeletalType.getQualifier().makeTemporary(); +#ifndef GLSLANG_WEB initializer = convertInitializerList(loc, skeletalType, initializer); +#endif if (! initializer) { // error recovery; don't leave const without constant values if (qualifier == EvqConst) @@ -7420,7 +7422,6 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q if (currentBlockQualifier.layoutPacking == ElpStd430 && ! currentBlockQualifier.isPushConstant()) requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "std430 requires the buffer storage qualifier"); break; -#ifndef GLSLANG_WEB case EvqBuffer: requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "buffer block"); profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, "buffer block"); @@ -7434,8 +7435,7 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q EShLangFragmentMask|EShLangMeshNVMask), "input block"); if (language == EShLangFragment) { profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "fragment input block"); - } - else if (language == EShLangMeshNV && ! qualifier.isTaskMemory()) { + } else if (language == EShLangMeshNV && ! qualifier.isTaskMemory()) { error(loc, "input blocks cannot be used in a mesh shader", "out", ""); } break; @@ -7446,14 +7446,13 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q // ES 310 can have a block before shader_io is turned on, so skip this test for built-ins if (language == EShLangVertex && ! parsingBuiltins) { profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "vertex output block"); - } - else if (language == EShLangMeshNV && qualifier.isTaskMemory()) { + } else if (language == EShLangMeshNV && qualifier.isTaskMemory()) { error(loc, "can only use on input blocks in mesh shader", "taskNV", ""); - } - else if (language == EShLangTaskNV && ! qualifier.isTaskMemory()) { + } else if (language == EShLangTaskNV && ! qualifier.isTaskMemory()) { error(loc, "output blocks cannot be used in a task shader", "out", ""); } break; +#ifndef GLSLANG_WEB case EvqPayloadNV: profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV block"); requireStage(loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangAnyHitNVMask | EShLangClosestHitNVMask | EShLangMissNVMask), diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 9e74a6961..1f63e84d5 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -476,10 +476,11 @@ protected: TQualifier globalUniformDefaults; TQualifier globalInputDefaults; TQualifier globalOutputDefaults; - int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point TString currentCaller; // name of last function body entered (not valid when at global scope) - TIdSetType inductiveLoopIds; +#ifndef GLSLANG_WEB + int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point bool anyIndexLimits; + TIdSetType inductiveLoopIds; TVector needsIndexLimitationChecking; // @@ -515,6 +516,7 @@ protected: // array-sizing declarations // TVector ioArraySymbolResizeList; +#endif }; } // end namespace glslang diff --git a/glslang/MachineIndependent/Scan.cpp b/glslang/MachineIndependent/Scan.cpp index ad0c12c97..b4d8dc0d2 100644 --- a/glslang/MachineIndependent/Scan.cpp +++ b/glslang/MachineIndependent/Scan.cpp @@ -324,7 +324,9 @@ struct str_hash // A single global usable by all threads, by all versions, by all languages. // After a single process-level initialization, this is read only and thread safe std::unordered_map* KeywordMap = nullptr; +#ifndef GLSLANG_WEB std::unordered_set* ReservedSet = nullptr; +#endif }; @@ -758,8 +760,10 @@ void TScanContext::deleteKeywordMap() { delete KeywordMap; KeywordMap = nullptr; +#ifndef GLSLANG_WEB delete ReservedSet; ReservedSet = nullptr; +#endif } // Called by yylex to get the next token. @@ -1051,6 +1055,11 @@ int TScanContext::tokenizeIdentifier() case SUBROUTINE: return es30ReservedFromGLSL(400); + case SHARED: + if ((parseContext.isEsProfile() && parseContext.version < 300) || + (!parseContext.isEsProfile() && parseContext.version < 140)) + return identifierOrType(); + return keyword; #endif case LAYOUT: @@ -1064,11 +1073,6 @@ int TScanContext::tokenizeIdentifier() return identifierOrType(); return keyword; } - case SHARED: - if ((parseContext.isEsProfile() && parseContext.version < 300) || - (!parseContext.isEsProfile() && parseContext.version < 140)) - return identifierOrType(); - return keyword; case HIGH_PRECISION: case MEDIUM_PRECISION: @@ -1649,7 +1653,7 @@ int TScanContext::identifierOrReserved(bool reserved) return 0; } - if (parseContext.forwardCompatible) + if (parseContext.isForwardCompatible()) parseContext.warn(loc, "using future reserved keyword", tokenText, ""); return identifierOrType(); @@ -1664,7 +1668,7 @@ int TScanContext::es30ReservedFromGLSL(int version) if ((parseContext.isEsProfile() && parseContext.version < 300) || (!parseContext.isEsProfile() && parseContext.version < version)) { - if (parseContext.forwardCompatible) + if (parseContext.isForwardCompatible()) parseContext.warn(loc, "future reserved word in ES 300 and keyword in GLSL", tokenText, ""); return identifierOrType(); @@ -1680,7 +1684,7 @@ int TScanContext::nonreservedKeyword(int esVersion, int nonEsVersion) { if ((parseContext.isEsProfile() && parseContext.version < esVersion) || (!parseContext.isEsProfile() && parseContext.version < nonEsVersion)) { - if (parseContext.forwardCompatible) + if (parseContext.isForwardCompatible()) parseContext.warn(loc, "using future keyword", tokenText, ""); return identifierOrType(); @@ -1694,7 +1698,7 @@ int TScanContext::precisionKeyword() if (parseContext.isEsProfile() || parseContext.version >= 130) return keyword; - if (parseContext.forwardCompatible) + if (parseContext.isForwardCompatible()) parseContext.warn(loc, "using ES precision qualifier keyword", tokenText, ""); return identifierOrType(); @@ -1707,7 +1711,7 @@ int TScanContext::matNxM() if (parseContext.version > 110) return keyword; - if (parseContext.forwardCompatible) + if (parseContext.isForwardCompatible()) parseContext.warn(loc, "using future non-square matrix type keyword", tokenText, ""); return identifierOrType(); @@ -1726,7 +1730,7 @@ int TScanContext::dMat() if (!parseContext.isEsProfile() && parseContext.version >= 400) return keyword; - if (parseContext.forwardCompatible) + if (parseContext.isForwardCompatible()) parseContext.warn(loc, "using future type keyword", tokenText, ""); return identifierOrType(); @@ -1747,7 +1751,7 @@ int TScanContext::firstGenerationImage(bool inEs310) return keyword; } - if (parseContext.forwardCompatible) + if (parseContext.isForwardCompatible()) parseContext.warn(loc, "using future type keyword", tokenText, ""); return identifierOrType(); @@ -1765,7 +1769,7 @@ int TScanContext::secondGenerationImage() (parseContext.version >= 420 || parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store)))) return keyword; - if (parseContext.forwardCompatible) + if (parseContext.isForwardCompatible()) parseContext.warn(loc, "using future type keyword", tokenText, ""); return identifierOrType(); diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index bced5d72d..a51c0c4ce 100755 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -477,11 +477,13 @@ void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& sp // Function to Print all builtins void DumpBuiltinSymbolTable(TInfoSink& infoSink, const TSymbolTable& symbolTable) { +#ifndef GLSLANG_WEB infoSink.debug << "BuiltinSymbolTable {\n"; symbolTable.dump(infoSink, true); infoSink.debug << "}\n"; +#endif } // Return true if the shader was correctly specified for version/profile/stage. @@ -634,7 +636,6 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo default: break; } -#endif if (profile == EEsProfile && version >= 300 && versionNotFirst) { correct = false; @@ -644,7 +645,7 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo // Check for SPIR-V compatibility if (spvVersion.spv != 0) { switch (profile) { - case EEsProfile: + case EEsProfile: if (spvVersion.vulkan > 0 && version < 310) { correct = false; infoSink.info.message(EPrefixError, "#version: ES shaders for Vulkan SPIR-V require version 310 or higher"); @@ -673,6 +674,7 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo break; } } +#endif return correct; } @@ -854,6 +856,7 @@ bool ProcessDeferred( : userInput.scanVersion(version, profile, versionNotFirstToken); bool versionNotFound = version == 0; if (forceDefaultVersionAndProfile && source == EShSourceGlsl) { +#ifndef GLSLANG_WEB if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound && (version != defaultVersion || profile != defaultProfile)) { compiler->infoSink.info << "Warning, (version, profile) forced to be (" @@ -861,7 +864,7 @@ bool ProcessDeferred( << "), while in source code it is (" << version << ", " << ProfileName(profile) << ")\n"; } - +#endif if (versionNotFound) { versionNotFirstToken = false; versionNotFirst = false; @@ -874,6 +877,7 @@ bool ProcessDeferred( bool goodVersion = DeduceVersionProfile(compiler->infoSink, stage, versionNotFirst, defaultVersion, source, version, profile, spvVersion); bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst)); +#ifndef GLSLANG_WEB bool warnVersionNotFirst = false; if (! versionWillBeError && versionNotFirstToken) { if (messages & EShMsgRelaxedErrors) @@ -881,6 +885,7 @@ bool ProcessDeferred( else versionWillBeError = true; } +#endif intermediate.setSource(source); intermediate.setVersion(version); @@ -942,11 +947,13 @@ bool ProcessDeferred( parseContext->setLimits(*resources); if (! goodVersion) parseContext->addError(); +#ifndef GLSLANG_WEB if (warnVersionNotFirst) { TSourceLoc loc; loc.init(); parseContext->warn(loc, "Illegal to have non-comment, non-whitespace tokens before #version", "#version", ""); } +#endif parseContext->initializeExtensionBehavior(); @@ -977,6 +984,8 @@ bool ProcessDeferred( return success; } +#ifndef GLSLANG_WEB + // Responsible for keeping track of the most recent source string and line in // the preprocessor and outputting newlines appropriately if the source string // or line changes. @@ -1173,6 +1182,8 @@ struct DoPreprocessing { std::string* outputString; }; +#endif + // DoFullParse is a valid ProcessingConext template argument for fully // parsing the shader. It populates the "intermediate" with the AST. struct DoFullParse{ @@ -1203,6 +1214,7 @@ struct DoFullParse{ } }; +#ifndef GLSLANG_WEB // Take a single compilation unit, and run the preprocessor on it. // Return: True if there were no issues found in preprocessing, // False if during preprocessing any unknown version, pragmas or @@ -1235,6 +1247,7 @@ bool PreprocessDeferred( forwardCompatible, messages, intermediate, parser, false, includer); } +#endif // // do a partial compile on the given strings for a single compilation unit @@ -1829,6 +1842,7 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion &environment); } +#ifndef GLSLANG_WEB // Fill in a string with the result of preprocessing ShaderStrings // Returns true if all extensions, pragmas and version strings were valid. // @@ -1853,6 +1867,7 @@ bool TShader::preprocess(const TBuiltInResource* builtInResources, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, message, includer, *intermediate, output_string); } +#endif const char* TShader::getInfoLog() { @@ -1928,6 +1943,7 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages) if (stages[stage].size() == 0) return true; +#ifndef GLSLANG_WEB int numEsShaders = 0, numNonEsShaders = 0; for (auto it = stages[stage].begin(); it != stages[stage].end(); ++it) { if ((*it)->intermediate->getProfile() == EEsProfile) { @@ -1976,7 +1992,9 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages) for (it = stages[stage].begin(); it != stages[stage].end(); ++it) intermediate[stage]->merge(*infoSink, *(*it)->intermediate); } - +#else + intermediate[stage] = stages[stage].front()->intermediate; +#endif intermediate[stage]->finalCheck(*infoSink, (messages & EShMsgKeepUncalled) != 0); if (messages & EShMsgAST) diff --git a/glslang/MachineIndependent/SymbolTable.cpp b/glslang/MachineIndependent/SymbolTable.cpp index 2f72a3646..2ea14af28 100755 --- a/glslang/MachineIndependent/SymbolTable.cpp +++ b/glslang/MachineIndependent/SymbolTable.cpp @@ -174,6 +174,8 @@ void TType::buildMangledName(TString& mangledName) const } } +#ifndef GLSLANG_WEB + // // Dump functions. // @@ -252,6 +254,8 @@ void TSymbolTable::dump(TInfoSink& infoSink, bool complete) const } } +#endif + // // Functions have buried pointers to delete. // diff --git a/glslang/MachineIndependent/SymbolTable.h b/glslang/MachineIndependent/SymbolTable.h index f3873cff0..40ca3da53 100755 --- a/glslang/MachineIndependent/SymbolTable.h +++ b/glslang/MachineIndependent/SymbolTable.h @@ -116,8 +116,11 @@ public: } virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); } virtual const char** getExtensions() const { return extensions->data(); } + +#ifndef GLSLANG_WEB virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0; void dumpExtensions(TInfoSink& infoSink) const; +#endif virtual bool isReadOnly() const { return ! writable; } virtual void makeReadOnly() { writable = false; } @@ -193,7 +196,9 @@ public: } virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); } +#ifndef GLSLANG_WEB virtual void dump(TInfoSink& infoSink, bool complete = false) const; +#endif protected: explicit TVariable(const TVariable&); @@ -314,7 +319,9 @@ public: virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; } virtual const TParameter& operator[](int i) const { return parameters[i]; } +#ifndef GLSLANG_WEB virtual void dump(TInfoSink& infoSink, bool complete = false) const override; +#endif protected: explicit TFunction(const TFunction&); @@ -374,7 +381,9 @@ public: virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); } virtual int getAnonId() const { return anonId; } +#ifndef GLSLANG_WEB virtual void dump(TInfoSink& infoSink, bool complete = false) const override; +#endif protected: explicit TAnonMember(const TAnonMember&); @@ -542,7 +551,9 @@ public: void relateToOperator(const char* name, TOperator op); void setFunctionExtensions(const char* name, int num, const char* const extensions[]); +#ifndef GLSLANG_WEB void dump(TInfoSink& infoSink, bool complete = false) const; +#endif TSymbolTableLevel* clone() const; void readOnly(); @@ -843,7 +854,9 @@ public: } int getMaxSymbolId() { return uniqueId; } +#ifndef GLSLANG_WEB void dump(TInfoSink& infoSink, bool complete = false) const; +#endif void copyTable(const TSymbolTable& copyOf); void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); } diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp index f65921858..e96a95292 100644 --- a/glslang/MachineIndependent/Versions.cpp +++ b/glslang/MachineIndependent/Versions.cpp @@ -502,21 +502,6 @@ void TParseVersions::getPreamble(std::string& preamble) #endif } -// -// When to use requireProfile(): -// -// Use if only some profiles support a feature. However, if within a profile the feature -// is version or extension specific, follow this call with calls to profileRequires(). -// -// Operation: If the current profile is not one of the profileMask, -// give an error message. -// -void TParseVersions::requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc) -{ - if (! (profile & profileMask)) - error(loc, "not supported with this profile:", featureDesc, ProfileName(profile)); -} - // // Map from stage enum to externally readable text name. // @@ -543,6 +528,42 @@ const char* StageName(EShLanguage stage) } } +// +// When to use requireStage() +// +// If only some stages support a feature. +// +// Operation: If the current stage is not present, give an error message. +// +void TParseVersions::requireStage(const TSourceLoc& loc, EShLanguageMask languageMask, const char* featureDesc) +{ + if (((1 << language) & languageMask) == 0) + error(loc, "not supported in this stage:", featureDesc, StageName(language)); +} + +// If only one stage supports a feature, this can be called. But, all supporting stages +// must be specified with one call. +void TParseVersions::requireStage(const TSourceLoc& loc, EShLanguage stage, const char* featureDesc) +{ + requireStage(loc, static_cast(1 << stage), featureDesc); +} + +#ifndef GLSLANG_WEB +// +// When to use requireProfile(): +// +// Use if only some profiles support a feature. However, if within a profile the feature +// is version or extension specific, follow this call with calls to profileRequires(). +// +// Operation: If the current profile is not one of the profileMask, +// give an error message. +// +void TParseVersions::requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc) +{ + if (! (profile & profileMask)) + error(loc, "not supported with this profile:", featureDesc, ProfileName(profile)); +} + // // When to use profileRequires(): // @@ -560,7 +581,8 @@ const char* StageName(EShLanguage stage) // // entry point that takes multiple extensions -void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, const char* const extensions[], const char* featureDesc) +void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, + const char* const extensions[], const char* featureDesc) { if (profile & profileMask) { bool okay = minVersion > 0 && version >= minVersion; @@ -584,33 +606,12 @@ void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int } // entry point for the above that takes a single extension -void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, const char* featureDesc) +void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, + const char* featureDesc) { profileRequires(loc, profileMask, minVersion, extension ? 1 : 0, &extension, featureDesc); } -// -// When to use requireStage() -// -// If only some stages support a feature. -// -// Operation: If the current stage is not present, give an error message. -// -void TParseVersions::requireStage(const TSourceLoc& loc, EShLanguageMask languageMask, const char* featureDesc) -{ - if (((1 << language) & languageMask) == 0) - error(loc, "not supported in this stage:", featureDesc, StageName(language)); -} - -// If only one stage supports a feature, this can be called. But, all supporting stages -// must be specified with one call. -void TParseVersions::requireStage(const TSourceLoc& loc, EShLanguage stage, const char* featureDesc) -{ - requireStage(loc, static_cast(1 << stage), featureDesc); -} - -#ifndef GLSLANG_WEB - void TParseVersions::unimplemented(const TSourceLoc& loc, const char* featureDesc) { error(loc, "feature not yet implemented", featureDesc, ""); @@ -1106,15 +1107,19 @@ void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op) // Call for any operation that requires Vulkan. void TParseVersions::requireVulkan(const TSourceLoc& loc, const char* op) { +#ifndef GLSLANG_WEB if (spvVersion.vulkan == 0) error(loc, "only allowed when using GLSL for Vulkan", op, ""); +#endif } // Call for any operation that requires SPIR-V. void TParseVersions::requireSpv(const TSourceLoc& loc, const char* op) { +#ifndef GLSLANG_WEB if (spvVersion.spv == 0) error(loc, "only allowed when generating SPIR-V", op, ""); +#endif } } // end namespace glslang diff --git a/glslang/MachineIndependent/iomapper.cpp b/glslang/MachineIndependent/iomapper.cpp index 8a6ea3c62..26b830e4f 100644 --- a/glslang/MachineIndependent/iomapper.cpp +++ b/glslang/MachineIndependent/iomapper.cpp @@ -477,7 +477,7 @@ int TDefaultIoResolverBase::resolveUniformLocation(EShLanguage /*stage*/, TVarEn } // no locations added if already present, a built-in variable, a block, or an opaque if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getBasicType() == EbtBlock || - type.getBasicType() == EbtAtomicUint || (type.containsOpaque() && intermediate.getSpv().openGl == 0)) { + type.isAtomic() || (type.containsOpaque() && intermediate.getSpv().openGl == 0)) { return ent.newLocation = -1; } // no locations on blocks of built-in variables @@ -674,7 +674,7 @@ int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEn } else { // no locations added if already present, a built-in variable, a block, or an opaque if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getBasicType() == EbtBlock || - type.getBasicType() == EbtAtomicUint || (type.containsOpaque() && intermediate.getSpv().openGl == 0)) { + type.isAtomic() || (type.containsOpaque() && intermediate.getSpv().openGl == 0)) { return ent.newLocation = -1; } // no locations on blocks of built-in variables diff --git a/glslang/MachineIndependent/iomapper.h b/glslang/MachineIndependent/iomapper.h index a95238bbc..01afc5a21 100644 --- a/glslang/MachineIndependent/iomapper.h +++ b/glslang/MachineIndependent/iomapper.h @@ -178,7 +178,7 @@ protected: // Return true if this is a UAV (unordered access view) type: static bool isUavType(const glslang::TType& type) { - if (type.getQualifier().readonly) + if (type.getQualifier().isReadOnly()) return false; return (type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage()) || (type.getQualifier().storage == EvqBuffer); diff --git a/glslang/MachineIndependent/limits.cpp b/glslang/MachineIndependent/limits.cpp index 64d191b47..51d930034 100644 --- a/glslang/MachineIndependent/limits.cpp +++ b/glslang/MachineIndependent/limits.cpp @@ -187,12 +187,14 @@ bool TIndexTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node) // void TParseContext::constantIndexExpressionCheck(TIntermNode* index) { +#ifndef GLSLANG_WEB TIndexTraverser it(inductiveLoopIds); index->traverse(&it); if (it.bad) error(it.badLoc, "Non-constant-index-expression", "limitations", ""); +#endif } } // end namespace glslang diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp index 45f45091a..5b920f2d5 100644 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -89,8 +89,6 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) #endif } -#ifndef GLSLANG_WEB - void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit) { if (unit.getNumEntryPoints() > 0) { @@ -106,6 +104,8 @@ void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit) callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end()); } +#ifndef GLSLANG_WEB + #define MERGE_MAX(member) member = std::max(member, unit.member) #define MERGE_TRUE(member) if (unit.member) member = unit.member; @@ -307,6 +307,8 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit) ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end()); } +#endif + // Traverser that seeds an ID map with all built-ins, and tracks the // maximum ID used. // (It would be nice to put this in a function, but that causes warnings @@ -485,7 +487,6 @@ void TIntermediate::mergeImplicitArraySizes(TType& type, const TType& unitType) for (int i = 0; i < (int)type.getStruct()->size(); ++i) mergeImplicitArraySizes(*(*type.getStruct())[i].type, *(*unitType.getStruct())[i].type); } -#endif // not GLSLANG_WEB // // Compare two global objects from two compilation units and see if they match @@ -1258,6 +1259,7 @@ int TIntermediate::computeTypeUniformLocationSize(const TType& type) } #ifndef GLSLANG_WEB + // Accumulate xfb buffer ranges and check for collisions as the accumulation is done. // // Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value. @@ -1374,7 +1376,8 @@ unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains return 4 * numComponents; } } -#endif // not GLSLANG_WEB + +#endif const int baseAlignmentVec4Std140 = 16; diff --git a/glslang/MachineIndependent/parseVersions.h b/glslang/MachineIndependent/parseVersions.h index ea34f4153..bed64743a 100755 --- a/glslang/MachineIndependent/parseVersions.h +++ b/glslang/MachineIndependent/parseVersions.h @@ -57,17 +57,37 @@ public: TParseVersions(TIntermediate& interm, int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink, bool forwardCompatible, EShMessages messages) - : infoSink(infoSink), version(version), profile(profile), language(language), - spvVersion(spvVersion), forwardCompatible(forwardCompatible), - intermediate(interm), messages(messages), numErrors(0), currentScanner(0) { } + : +#ifndef GLSLANG_WEB + forwardCompatible(forwardCompatible), + profile(profile), +#endif + infoSink(infoSink), version(version), + language(language), + spvVersion(spvVersion), + intermediate(interm), messages(messages), numErrors(0), currentScanner(0) { } virtual ~TParseVersions() { } - virtual void requireProfile(const TSourceLoc&, int queryProfiles, const char* featureDesc); - virtual void profileRequires(const TSourceLoc&, int queryProfiles, int minVersion, int numExtensions, const char* const extensions[], const char* featureDesc); - virtual void profileRequires(const TSourceLoc&, int queryProfiles, int minVersion, const char* const extension, const char* featureDesc); - virtual void requireStage(const TSourceLoc&, EShLanguageMask, const char* featureDesc); - virtual void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc); + void requireStage(const TSourceLoc&, EShLanguageMask, const char* featureDesc); + void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc); #ifdef GLSLANG_WEB + const EProfile profile = EEsProfile; bool isEsProfile() const { return true; } + void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc) + { + if (! (EEsProfile & profileMask)) + error(loc, "not supported with this profile:", featureDesc, ProfileName(profile)); + } + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, + const char* const extensions[], const char* featureDesc) + { + if ((EEsProfile & profileMask) && (minVersion == 0 || version < minVersion)) + error(loc, "not supported for this version or the enabled extensions", featureDesc, ""); + } + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, + const char* featureDesc) + { + profileRequires(loc, profileMask, minVersion, extension ? 1 : 0, &extension, featureDesc); + } void initializeExtensionBehavior() { } void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc) { } void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc) { } @@ -92,8 +112,18 @@ public: void int64Check(const TSourceLoc&, const char* op, bool builtIn = false) { } void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false) { } void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false) { } + bool relaxedErrors() const { return false; } + bool suppressWarnings() const { return true; } + bool isForwardCompatible() const { return false; } #else + bool forwardCompatible; // true if errors are to be given for use of deprecated features + EProfile profile; // the declared profile in the shader (core by default) bool isEsProfile() const { return profile == EEsProfile; } + void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc); + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, + const char* const extensions[], const char* featureDesc); + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, + const char* featureDesc); virtual void initializeExtensionBehavior(); virtual void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc); virtual void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc); @@ -131,6 +161,9 @@ public: virtual void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false); virtual void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false); virtual void fcoopmatCheck(const TSourceLoc&, const char* op, bool builtIn = false); + bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; } + bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; } + bool isForwardCompatible() const { return forwardCompatible; } #endif // GLSLANG_WEB virtual void spvRemoved(const TSourceLoc&, const char* op); virtual void vulkanRemoved(const TSourceLoc&, const char* op); @@ -170,8 +203,6 @@ public: void setCurrentString(int string) { currentScanner->setString(string); } void getPreamble(std::string&); - bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; } - bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; } #ifdef ENABLE_HLSL bool isReadingHLSL() const { return (messages & EShMsgReadHlsl) == EShMsgReadHlsl; } bool hlslEnable16BitTypes() const { return (messages & EShMsgHlslEnable16BitTypes) != 0; } @@ -184,10 +215,8 @@ public: // compilation mode int version; // version, updated by #version in the shader - EProfile profile; // the declared profile in the shader (core by default) EShLanguage language; // really the stage SpvVersion spvVersion; - bool forwardCompatible; // true if errors are to be given for use of deprecated features TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree protected: diff --git a/glslang/MachineIndependent/preprocessor/Pp.cpp b/glslang/MachineIndependent/preprocessor/Pp.cpp index fc23c0475..d7ff485c0 100755 --- a/glslang/MachineIndependent/preprocessor/Pp.cpp +++ b/glslang/MachineIndependent/preprocessor/Pp.cpp @@ -722,6 +722,7 @@ int TPpContext::CPPline(TPpToken* ppToken) parseContext.setCurrentLine(lineRes); if (token != '\n') { +#ifndef GLSLANG_WEB if (token == PpAtomConstString) { parseContext.ppRequireExtensions(directiveLoc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based #line"); // We need to save a copy of the string instead of pointing @@ -731,7 +732,9 @@ int TPpContext::CPPline(TPpToken* ppToken) parseContext.setCurrentSourceName(sourceName); hasFile = true; token = scanToken(ppToken); - } else { + } else +#endif + { token = eval(token, MIN_PRECEDENCE, false, fileRes, fileErr, ppToken); if (! fileErr) { parseContext.setCurrentString(fileRes); @@ -952,16 +955,16 @@ int TPpContext::readCPPline(TPpToken* ppToken) case PpAtomIfndef: token = CPPifdef(0, ppToken); break; + case PpAtomLine: + token = CPPline(ppToken); + break; +#ifndef GLSLANG_WEB case PpAtomInclude: if(!parseContext.isReadingHLSL()) { parseContext.ppRequireExtensions(ppToken->loc, 1, &E_GL_GOOGLE_include_directive, "#include"); } token = CPPinclude(ppToken); break; - case PpAtomLine: - token = CPPline(ppToken); - break; -#ifndef GLSLANG_WEB case PpAtomPragma: token = CPPpragma(ppToken); break; diff --git a/glslang/MachineIndependent/reflection.cpp b/glslang/MachineIndependent/reflection.cpp index fe36a76e2..e35498ff7 100644 --- a/glslang/MachineIndependent/reflection.cpp +++ b/glslang/MachineIndependent/reflection.cpp @@ -398,7 +398,7 @@ public: topLevelArrayStride = variables.back().arrayStride; } - if ((reflection.options & EShReflectionSeparateBuffers) && terminalType->getBasicType() == EbtAtomicUint) + if ((reflection.options & EShReflectionSeparateBuffers) && terminalType->isAtomic()) reflection.atomicCounterUniformIndices.push_back(uniformIndex); variables.back().topLevelArrayStride = topLevelArrayStride;