From 63d4794e8ef11a0ea0832b578c8c37da805c51cb Mon Sep 17 00:00:00 2001 From: Thomas Perl Date: Tue, 24 May 2016 13:15:01 +0200 Subject: [PATCH 1/4] Add test case: Link 2 ESSL fragment shader units --- Test/baseResults/es-link1.frag.out | 48 ++++++++++++++++++++++++++++++ Test/es-link1.frag | 8 +++++ Test/es-link2.frag | 8 +++++ Test/runtests | 1 + 4 files changed, 65 insertions(+) create mode 100644 Test/baseResults/es-link1.frag.out create mode 100644 Test/es-link1.frag create mode 100644 Test/es-link2.frag diff --git a/Test/baseResults/es-link1.frag.out b/Test/baseResults/es-link1.frag.out new file mode 100644 index 00000000..c033e210 --- /dev/null +++ b/Test/baseResults/es-link1.frag.out @@ -0,0 +1,48 @@ +es-link1.frag +Shader version: 100 +0:? Sequence +0:5 Function Definition: main( (global void) +0:5 Function Parameters: +0:7 Sequence +0:7 move second child to first child (temp mediump 4-component vector of float) +0:7 'gl_FragColor' (fragColor mediump 4-component vector of float FragColor) +0:7 Function Call: calculateColor( (global mediump 4-component vector of float) +0:? Linker Objects + +es-link2.frag +Shader version: 100 +0:? Sequence +0:5 Function Definition: calculateColor( (global mediump 4-component vector of float) +0:5 Function Parameters: +0:7 Sequence +0:7 Branch: Return with expression +0:7 vector-scale (temp mediump 4-component vector of float) +0:7 'varyingColor' (smooth in mediump 4-component vector of float) +0:7 Constant: +0:7 0.500000 +0:? Linker Objects +0:? 'varyingColor' (smooth in mediump 4-component vector of float) + + +Linked fragment stage: + + +Shader version: 100 +0:? Sequence +0:5 Function Definition: main( (global void) +0:5 Function Parameters: +0:7 Sequence +0:7 move second child to first child (temp mediump 4-component vector of float) +0:7 'gl_FragColor' (fragColor mediump 4-component vector of float FragColor) +0:7 Function Call: calculateColor( (global mediump 4-component vector of float) +0:5 Function Definition: calculateColor( (global mediump 4-component vector of float) +0:5 Function Parameters: +0:7 Sequence +0:7 Branch: Return with expression +0:7 vector-scale (temp mediump 4-component vector of float) +0:7 'varyingColor' (smooth in mediump 4-component vector of float) +0:7 Constant: +0:7 0.500000 +0:? Linker Objects +0:? 'varyingColor' (smooth in mediump 4-component vector of float) + diff --git a/Test/es-link1.frag b/Test/es-link1.frag new file mode 100644 index 00000000..fe4da41d --- /dev/null +++ b/Test/es-link1.frag @@ -0,0 +1,8 @@ +#version 100 + +mediump vec4 calculateColor(); + +void main() +{ + gl_FragColor = calculateColor(); +} diff --git a/Test/es-link2.frag b/Test/es-link2.frag new file mode 100644 index 00000000..e7b5a477 --- /dev/null +++ b/Test/es-link2.frag @@ -0,0 +1,8 @@ +#version 100 + +varying mediump vec4 varyingColor; + +mediump vec4 calculateColor() +{ + return varyingColor * 0.5; +} diff --git a/Test/runtests b/Test/runtests index 6e6524ab..d54fb580 100755 --- a/Test/runtests +++ b/Test/runtests @@ -96,6 +96,7 @@ function runBulkTest { runBulkTest mains1.frag mains2.frag noMain1.geom noMain2.geom runBulkTest noMain.vert mains.frag runBulkTest link1.frag link2.frag link3.frag +runBulkTest es-link1.frag es-link2.frag runBulkTest recurse1.vert recurse1.frag recurse2.frag runBulkTest 300link.frag runBulkTest 300link2.frag From b40a6d6b40a46c1206a9a309885a7e1fbbc1cf93 Mon Sep 17 00:00:00 2001 From: Thomas Perl Date: Tue, 24 May 2016 13:16:08 +0200 Subject: [PATCH 2/4] Use version/profile from first compilation stage When linking multiple compilation units per shader stage, the code creates a new intermediate, but fails to set its version and profile. This change makes it so that the new intermediate inherits the version and profile of the first compilation unit, so that two ES SL compilation units can be combined. --- glslang/MachineIndependent/ShaderLang.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index 3a3bd58c..2c5a1ca7 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -1530,10 +1530,13 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages) // Be efficient for the common single compilation unit per stage case, // reusing it's TIntermediate instead of merging into a new one. // + TIntermediate *firstIntermediate = stages[stage].front()->intermediate; if (stages[stage].size() == 1) - intermediate[stage] = stages[stage].front()->intermediate; + intermediate[stage] = firstIntermediate; else { - intermediate[stage] = new TIntermediate(stage); + intermediate[stage] = new TIntermediate(stage, + firstIntermediate->getVersion(), + firstIntermediate->getProfile()); newedIntermediate[stage] = true; } From 0bb546f8ae76a595fb08c288a0a868930f222d77 Mon Sep 17 00:00:00 2001 From: Thomas Perl Date: Tue, 24 May 2016 13:18:31 +0200 Subject: [PATCH 3/4] Fix test case for the "empty" linker test case The test result should only give one error about linking ES and non-ES shading language compilation units: - empty.frag: No version info, interpreted as 100, ES - empty2.frag: No version info, interpreted as 100, ES - empty3.frag: Version declared as 110, non-ES Previously, because the new intermediate is always created without version/profile information, there would be two linker errors: 1.) When merging the new intermediate with empty.frag 2.) When merging (new intermediate + empty.frag + empty2.frag) with empty3.frag Now, there is only one error; as the error with merging the new intermediate with empty.frag has been removed. --- Test/baseResults/empty.frag.out | 2 -- 1 file changed, 2 deletions(-) diff --git a/Test/baseResults/empty.frag.out b/Test/baseResults/empty.frag.out index d3c244a5..95db9ef8 100644 --- a/Test/baseResults/empty.frag.out +++ b/Test/baseResults/empty.frag.out @@ -18,8 +18,6 @@ Linked fragment stage: ERROR: Linking fragment stage: Cannot mix ES profile with non-ES profile shaders -ERROR: Linking fragment stage: Cannot mix ES profile with non-ES profile shaders - ERROR: Linking fragment stage: Missing entry point: Each stage requires one "void main()" entry point Shader version: 110 From 7bfd08d21c449c75d56022d0e9b7022d227aac47 Mon Sep 17 00:00:00 2001 From: Thomas Perl Date: Wed, 25 May 2016 09:26:43 +0200 Subject: [PATCH 4/4] Check for linking multiple ES shaders to the same stage --- Test/baseResults/empty.frag.out | 11 +- Test/baseResults/es-link1.frag.out | 23 +--- Test/baseResults/link1.frag.out | 133 +------------------- glslang/MachineIndependent/ShaderLang.cpp | 17 +++ glslang/MachineIndependent/linkValidate.cpp | 4 - gtests/Link.FromFile.cpp | 1 + 6 files changed, 21 insertions(+), 168 deletions(-) diff --git a/Test/baseResults/empty.frag.out b/Test/baseResults/empty.frag.out index 95db9ef8..be186bb9 100644 --- a/Test/baseResults/empty.frag.out +++ b/Test/baseResults/empty.frag.out @@ -13,14 +13,5 @@ Shader version: 110 0:? Sequence 0:? Linker Objects - -Linked fragment stage: - -ERROR: Linking fragment stage: Cannot mix ES profile with non-ES profile shaders - -ERROR: Linking fragment stage: Missing entry point: Each stage requires one "void main()" entry point - -Shader version: 110 -0:? Sequence -0:? Linker Objects +ERROR: Cannot mix ES profile with non-ES profile shaders diff --git a/Test/baseResults/es-link1.frag.out b/Test/baseResults/es-link1.frag.out index c033e210..41ce9a0f 100644 --- a/Test/baseResults/es-link1.frag.out +++ b/Test/baseResults/es-link1.frag.out @@ -23,26 +23,5 @@ Shader version: 100 0:? Linker Objects 0:? 'varyingColor' (smooth in mediump 4-component vector of float) - -Linked fragment stage: - - -Shader version: 100 -0:? Sequence -0:5 Function Definition: main( (global void) -0:5 Function Parameters: -0:7 Sequence -0:7 move second child to first child (temp mediump 4-component vector of float) -0:7 'gl_FragColor' (fragColor mediump 4-component vector of float FragColor) -0:7 Function Call: calculateColor( (global mediump 4-component vector of float) -0:5 Function Definition: calculateColor( (global mediump 4-component vector of float) -0:5 Function Parameters: -0:7 Sequence -0:7 Branch: Return with expression -0:7 vector-scale (temp mediump 4-component vector of float) -0:7 'varyingColor' (smooth in mediump 4-component vector of float) -0:7 Constant: -0:7 0.500000 -0:? Linker Objects -0:? 'varyingColor' (smooth in mediump 4-component vector of float) +ERROR: Cannot attach multiple ES shaders of the same type to a single program diff --git a/Test/baseResults/link1.frag.out b/Test/baseResults/link1.frag.out index bc6cf5c8..51d7475a 100644 --- a/Test/baseResults/link1.frag.out +++ b/Test/baseResults/link1.frag.out @@ -158,136 +158,5 @@ Requested GL_OES_texture_3D 0:? Linker Objects 0:? 'iv3' (smooth in highp 2-component vector of float) - -Linked fragment stage: - -ERROR: Linking fragment stage: Types must match: - glass: "uniform 3-component vector of float" versus "uniform 2-component vector of float" -ERROR: Linking fragment stage: Interpolation and auxiliary storage qualifiers must match: - cup: "smooth in 4-component vector of float" versus "flat in 4-component vector of float" -ERROR: Linking fragment stage: Initializers must match: - cv3e -ERROR: Linking fragment stage: Initializers must match: - um2e -ERROR: Linking fragment stage: Initializers must match: - se -ERROR: Linking fragment stage: Cannot mix ES profile with non-ES profile shaders - -ERROR: Linking fragment stage: Types must match: -ERROR: Linking fragment stage: Precision qualifiers must match: - iv3: "smooth in 3-component vector of float" versus "smooth in highp 2-component vector of float" - -Shader version: 300 -Requested GL_OES_EGL_image_external -Requested GL_OES_standard_derivatives -Requested GL_OES_texture_3D -0:? Sequence -0:8 Sequence -0:8 move second child to first child (temp 4-component vector of float) -0:8 'a' (global 4-component vector of float) -0:8 vector-scale (temp 4-component vector of float) -0:8 Constant: -0:8 8.000000 -0:8 'uv4' (uniform 4-component vector of float) -0:13 Function Definition: main( (global void) -0:13 Function Parameters: -0:17 Sequence -0:17 move second child to first child (temp 4-component vector of float) -0:17 'b' (global 4-component vector of float) -0:17 vector-scale (temp 4-component vector of float) -0:17 Constant: -0:17 8.000000 -0:17 'a' (global 4-component vector of float) -0:19 Function Definition: foo(mf22; (global 2-component vector of int) -0:19 Function Parameters: -0:19 'm' (in 2X2 matrix of float) -0:21 Sequence -0:21 Branch: Return with expression -0:21 Convert float to int (temp 2-component vector of int) -0:21 direct index (temp 2-component vector of float) -0:21 'm' (in 2X2 matrix of float) -0:21 Constant: -0:21 0 (const int) -0:24 Sequence -0:24 move second child to first child (temp 4-component vector of float) -0:24 'c' (global 4-component vector of float) -0:24 component-wise multiply (temp 4-component vector of float) -0:24 'b' (global 4-component vector of float) -0:24 'b' (global 4-component vector of float) -0:8 Sequence -0:8 move second child to first child (temp 4-component vector of float) -0:8 'd' (global 4-component vector of float) -0:8 vector-scale (temp 4-component vector of float) -0:8 Constant: -0:8 8.000000 -0:8 'uv4' (uniform 4-component vector of float) -0:13 Sequence -0:13 move second child to first child (temp 4-component vector of float) -0:13 'e' (global 4-component vector of float) -0:13 vector-scale (temp 4-component vector of float) -0:13 Constant: -0:13 8.000000 -0:13 'd' (global 4-component vector of float) -0:15 Function Definition: foo( (global 2-component vector of int) -0:15 Function Parameters: -0:17 Sequence -0:17 Branch: Return with expression -0:17 Constant: -0:17 2 (const int) -0:17 2 (const int) -0:20 Sequence -0:20 move second child to first child (temp 4-component vector of float) -0:20 'f' (global 4-component vector of float) -0:20 component-wise multiply (temp 4-component vector of float) -0:20 'e' (global 4-component vector of float) -0:20 'e' (global 4-component vector of float) -0:? Linker Objects -0:? 'uv4' (uniform 4-component vector of float) -0:? 'glass' (uniform 3-component vector of float) -0:? 'ci' (const int) -0:? 8 (const int) -0:? 'a' (global 4-component vector of float) -0:? 'iv3' (smooth in 3-component vector of float) -0:? 'cup' (smooth in 4-component vector of float) -0:? 'b' (global 4-component vector of float) -0:? 'c' (global 4-component vector of float) -0:? 'cv3' (const 3-component vector of float) -0:? 43.000000 -0:? 0.340000 -0:? 9.900000 -0:? 'cv3n' (const 3-component vector of float) -0:? 43.000000 -0:? 0.340000 -0:? 9.900000 -0:? 'cv3e' (const 3-component vector of float) -0:? 43.000000 -0:? 0.340000 -0:? 9.900000 -0:? 'um2' (uniform 2X2 matrix of float) -0:? 4.000000 -0:? 0.000000 -0:? 0.000000 -0:? 4.000000 -0:? 'um2n' (uniform 2X2 matrix of float) -0:? 4.000000 -0:? 0.000000 -0:? 0.000000 -0:? 4.000000 -0:? 'um2e' (uniform 2X2 matrix of float) -0:? 4.000000 -0:? 0.000000 -0:? 0.000000 -0:? 4.000000 -0:? 's' (uniform structure{global int a, global float b}) -0:? 82 (const int) -0:? 3.900000 -0:? 'sn' (uniform structure{global int a, global float b}) -0:? 82 (const int) -0:? 3.900000 -0:? 'se' (uniform structure{global int a, global float b}) -0:? 82 (const int) -0:? 3.900000 -0:? 'd' (global 4-component vector of float) -0:? 'e' (global 4-component vector of float) -0:? 'f' (global 4-component vector of float) +ERROR: Cannot mix ES profile with non-ES profile shaders diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index 2c5a1ca7..1446298c 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -1526,6 +1526,23 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages) if (stages[stage].size() == 0) return true; + int numEsShaders = 0, numNonEsShaders = 0; + for (auto it = stages[stage].begin(); it != stages[stage].end(); ++it) { + if ((*it)->intermediate->getProfile() == EEsProfile) { + numEsShaders++; + } else { + numNonEsShaders++; + } + } + + if (numEsShaders > 0 && numNonEsShaders > 0) { + infoSink->info.message(EPrefixError, "Cannot mix ES profile with non-ES profile shaders"); + return false; + } else if (numEsShaders > 1) { + infoSink->info.message(EPrefixError, "Cannot attach multiple ES shaders of the same type to a single program"); + return false; + } + // // Be efficient for the common single compilation unit per stage case, // reusing it's TIntermediate instead of merging into a new one. diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp index c48e7bff..1cda57d3 100644 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -86,10 +86,6 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) numPushConstants += unit.numPushConstants; callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end()); - if ((profile != EEsProfile && unit.profile == EEsProfile) || - (profile == EEsProfile && unit.profile != EEsProfile)) - error(infoSink, "Cannot mix ES profile with non-ES profile shaders\n"); - if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger) error(infoSink, "gl_FragCoord redeclarations must match across shaders\n"); diff --git a/gtests/Link.FromFile.cpp b/gtests/Link.FromFile.cpp index 6db43d9c..331c5b27 100644 --- a/gtests/Link.FromFile.cpp +++ b/gtests/Link.FromFile.cpp @@ -99,6 +99,7 @@ INSTANTIATE_TEST_CASE_P( {"empty.frag", "empty2.frag", "empty3.frag"}, {"150.tesc", "150.tese", "400.tesc", "400.tese", "410.tesc", "420.tesc", "420.tese"}, {"max_vertices_0.geom"}, + {"es-link1.frag", "es-link2.frag"}, })), ); // clang-format on