xref: /aosp_15_r20/external/angle/src/tests/gl_tests/ShaderBinaryTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2022 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker 
7*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/ANGLETest.h"
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include <vector>
10*8975f5c5SAndroid Build Coastguard Worker 
11*8975f5c5SAndroid Build Coastguard Worker #include "GLSLANG/ShaderLang.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/gl_raii.h"
13*8975f5c5SAndroid Build Coastguard Worker 
14*8975f5c5SAndroid Build Coastguard Worker using namespace angle;
15*8975f5c5SAndroid Build Coastguard Worker 
16*8975f5c5SAndroid Build Coastguard Worker class ShaderBinaryTest : public ANGLETest<>
17*8975f5c5SAndroid Build Coastguard Worker {
18*8975f5c5SAndroid Build Coastguard Worker   protected:
ShaderBinaryTest()19*8975f5c5SAndroid Build Coastguard Worker     ShaderBinaryTest()
20*8975f5c5SAndroid Build Coastguard Worker     {
21*8975f5c5SAndroid Build Coastguard Worker         setWindowWidth(128);
22*8975f5c5SAndroid Build Coastguard Worker         setWindowHeight(128);
23*8975f5c5SAndroid Build Coastguard Worker         setConfigRedBits(8);
24*8975f5c5SAndroid Build Coastguard Worker         setConfigGreenBits(8);
25*8975f5c5SAndroid Build Coastguard Worker         setConfigBlueBits(8);
26*8975f5c5SAndroid Build Coastguard Worker         setConfigAlphaBits(8);
27*8975f5c5SAndroid Build Coastguard Worker 
28*8975f5c5SAndroid Build Coastguard Worker         // Test flakiness was noticed when reusing displays.
29*8975f5c5SAndroid Build Coastguard Worker         forceNewDisplay();
30*8975f5c5SAndroid Build Coastguard Worker     }
31*8975f5c5SAndroid Build Coastguard Worker 
testSetUp()32*8975f5c5SAndroid Build Coastguard Worker     void testSetUp() override
33*8975f5c5SAndroid Build Coastguard Worker     {
34*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EQ(sh::Initialize(), true);
35*8975f5c5SAndroid Build Coastguard Worker 
36*8975f5c5SAndroid Build Coastguard Worker         if (!supported())
37*8975f5c5SAndroid Build Coastguard Worker         {
38*8975f5c5SAndroid Build Coastguard Worker             // Must return early because the initialization below will crash otherwise.
39*8975f5c5SAndroid Build Coastguard Worker             // Individal tests will skip themselves as well.
40*8975f5c5SAndroid Build Coastguard Worker             return;
41*8975f5c5SAndroid Build Coastguard Worker         }
42*8975f5c5SAndroid Build Coastguard Worker 
43*8975f5c5SAndroid Build Coastguard Worker         mCompileOptions.objectCode                    = true;
44*8975f5c5SAndroid Build Coastguard Worker         mCompileOptions.emulateGLDrawID               = true;
45*8975f5c5SAndroid Build Coastguard Worker         mCompileOptions.initializeUninitializedLocals = true;
46*8975f5c5SAndroid Build Coastguard Worker 
47*8975f5c5SAndroid Build Coastguard Worker         sh::InitBuiltInResources(&mResources);
48*8975f5c5SAndroid Build Coastguard Worker 
49*8975f5c5SAndroid Build Coastguard Worker         // Generate a shader binary:
50*8975f5c5SAndroid Build Coastguard Worker         ShShaderSpec spec     = SH_GLES2_SPEC;
51*8975f5c5SAndroid Build Coastguard Worker         ShShaderOutput output = SH_SPIRV_VULKAN_OUTPUT;
52*8975f5c5SAndroid Build Coastguard Worker 
53*8975f5c5SAndroid Build Coastguard Worker         // Vertex shader:
54*8975f5c5SAndroid Build Coastguard Worker         const char *source = essl1_shaders::vs::Simple();
55*8975f5c5SAndroid Build Coastguard Worker         ShHandle vertexCompiler =
56*8975f5c5SAndroid Build Coastguard Worker             sh::ConstructCompiler(GL_VERTEX_SHADER, spec, output, &mResources);
57*8975f5c5SAndroid Build Coastguard Worker         bool compileResult =
58*8975f5c5SAndroid Build Coastguard Worker             sh::GetShaderBinary(vertexCompiler, &source, 1, mCompileOptions, &mVertexShaderBinary);
59*8975f5c5SAndroid Build Coastguard Worker         ASSERT_TRUE(compileResult);
60*8975f5c5SAndroid Build Coastguard Worker 
61*8975f5c5SAndroid Build Coastguard Worker         if (mVertexShaderBinary.size() == 0)
62*8975f5c5SAndroid Build Coastguard Worker         {
63*8975f5c5SAndroid Build Coastguard Worker             FAIL() << "Creating vertex shader binary failed.";
64*8975f5c5SAndroid Build Coastguard Worker         }
65*8975f5c5SAndroid Build Coastguard Worker 
66*8975f5c5SAndroid Build Coastguard Worker         // Fragment shader:
67*8975f5c5SAndroid Build Coastguard Worker         source = essl1_shaders::fs::Red();
68*8975f5c5SAndroid Build Coastguard Worker         ShHandle fragmentCompiler =
69*8975f5c5SAndroid Build Coastguard Worker             sh::ConstructCompiler(GL_FRAGMENT_SHADER, spec, output, &mResources);
70*8975f5c5SAndroid Build Coastguard Worker         compileResult = sh::GetShaderBinary(fragmentCompiler, &source, 1, mCompileOptions,
71*8975f5c5SAndroid Build Coastguard Worker                                             &mFragmentShaderBinary);
72*8975f5c5SAndroid Build Coastguard Worker         ASSERT_TRUE(compileResult);
73*8975f5c5SAndroid Build Coastguard Worker 
74*8975f5c5SAndroid Build Coastguard Worker         if (mFragmentShaderBinary.size() == 0)
75*8975f5c5SAndroid Build Coastguard Worker         {
76*8975f5c5SAndroid Build Coastguard Worker             FAIL() << "Creating fragment shader binary failed.";
77*8975f5c5SAndroid Build Coastguard Worker         }
78*8975f5c5SAndroid Build Coastguard Worker     }
79*8975f5c5SAndroid Build Coastguard Worker 
testTearDown()80*8975f5c5SAndroid Build Coastguard Worker     void testTearDown() override
81*8975f5c5SAndroid Build Coastguard Worker     {
82*8975f5c5SAndroid Build Coastguard Worker         sh::Finalize();
83*8975f5c5SAndroid Build Coastguard Worker 
84*8975f5c5SAndroid Build Coastguard Worker         if (!supported())
85*8975f5c5SAndroid Build Coastguard Worker         {
86*8975f5c5SAndroid Build Coastguard Worker             // Return early because the initialization didn't complete.
87*8975f5c5SAndroid Build Coastguard Worker             return;
88*8975f5c5SAndroid Build Coastguard Worker         }
89*8975f5c5SAndroid Build Coastguard Worker 
90*8975f5c5SAndroid Build Coastguard Worker         glDeleteBuffers(1, &mBuffer);
91*8975f5c5SAndroid Build Coastguard Worker     }
92*8975f5c5SAndroid Build Coastguard Worker 
supported() const93*8975f5c5SAndroid Build Coastguard Worker     bool supported() const
94*8975f5c5SAndroid Build Coastguard Worker     {
95*8975f5c5SAndroid Build Coastguard Worker         GLint formatCount;
96*8975f5c5SAndroid Build Coastguard Worker         glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &formatCount);
97*8975f5c5SAndroid Build Coastguard Worker         if (formatCount == 0)
98*8975f5c5SAndroid Build Coastguard Worker         {
99*8975f5c5SAndroid Build Coastguard Worker             std::cout << "Test skipped because no program binary formats are available."
100*8975f5c5SAndroid Build Coastguard Worker                       << std::endl;
101*8975f5c5SAndroid Build Coastguard Worker             return false;
102*8975f5c5SAndroid Build Coastguard Worker         }
103*8975f5c5SAndroid Build Coastguard Worker         std::vector<GLint> formats(formatCount);
104*8975f5c5SAndroid Build Coastguard Worker         glGetIntegerv(GL_SHADER_BINARY_FORMATS, formats.data());
105*8975f5c5SAndroid Build Coastguard Worker 
106*8975f5c5SAndroid Build Coastguard Worker         ASSERT(formats[0] == GL_SHADER_BINARY_ANGLE);
107*8975f5c5SAndroid Build Coastguard Worker 
108*8975f5c5SAndroid Build Coastguard Worker         return true;
109*8975f5c5SAndroid Build Coastguard Worker     }
110*8975f5c5SAndroid Build Coastguard Worker 
111*8975f5c5SAndroid Build Coastguard Worker     ShCompileOptions mCompileOptions = {};
112*8975f5c5SAndroid Build Coastguard Worker     ShBuiltInResources mResources;
113*8975f5c5SAndroid Build Coastguard Worker     GLuint mBuffer;
114*8975f5c5SAndroid Build Coastguard Worker     sh::ShaderBinaryBlob mVertexShaderBinary;
115*8975f5c5SAndroid Build Coastguard Worker     sh::ShaderBinaryBlob mFragmentShaderBinary;
116*8975f5c5SAndroid Build Coastguard Worker };
117*8975f5c5SAndroid Build Coastguard Worker 
118*8975f5c5SAndroid Build Coastguard Worker // This tests the ability to successfully create and load a shader binary.
TEST_P(ShaderBinaryTest,CreateAndLoadBinary)119*8975f5c5SAndroid Build Coastguard Worker TEST_P(ShaderBinaryTest, CreateAndLoadBinary)
120*8975f5c5SAndroid Build Coastguard Worker {
121*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!supported());
122*8975f5c5SAndroid Build Coastguard Worker 
123*8975f5c5SAndroid Build Coastguard Worker     GLint compileResult;
124*8975f5c5SAndroid Build Coastguard Worker     // Create vertex shader and load binary
125*8975f5c5SAndroid Build Coastguard Worker     GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
126*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &vertShader, GL_SHADER_BINARY_ANGLE, mVertexShaderBinary.data(),
127*8975f5c5SAndroid Build Coastguard Worker                    mVertexShaderBinary.size());
128*8975f5c5SAndroid Build Coastguard Worker     glGetShaderiv(vertShader, GL_COMPILE_STATUS, &compileResult);
129*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_TRUE(compileResult);
130*8975f5c5SAndroid Build Coastguard Worker 
131*8975f5c5SAndroid Build Coastguard Worker     // Create fragment shader and load binary
132*8975f5c5SAndroid Build Coastguard Worker     GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
133*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &fragShader, GL_SHADER_BINARY_ANGLE, mFragmentShaderBinary.data(),
134*8975f5c5SAndroid Build Coastguard Worker                    mFragmentShaderBinary.size());
135*8975f5c5SAndroid Build Coastguard Worker     glGetShaderiv(fragShader, GL_COMPILE_STATUS, &compileResult);
136*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_TRUE(compileResult);
137*8975f5c5SAndroid Build Coastguard Worker 
138*8975f5c5SAndroid Build Coastguard Worker     // Create program from the shaders
139*8975f5c5SAndroid Build Coastguard Worker     GLuint newProgram = glCreateProgram();
140*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(newProgram, vertShader);
141*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(newProgram, fragShader);
142*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(newProgram);
143*8975f5c5SAndroid Build Coastguard Worker     newProgram = CheckLinkStatusAndReturnProgram(newProgram, true);
144*8975f5c5SAndroid Build Coastguard Worker 
145*8975f5c5SAndroid Build Coastguard Worker     // Test with a basic draw
146*8975f5c5SAndroid Build Coastguard Worker     drawQuad(newProgram, "a_position", 0.5f);
147*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
148*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
149*8975f5c5SAndroid Build Coastguard Worker }
150*8975f5c5SAndroid Build Coastguard Worker 
151*8975f5c5SAndroid Build Coastguard Worker // Check invalid gl call parameters, such as providing a GL type when a shader handle is expected.
TEST_P(ShaderBinaryTest,InvalidCallParams)152*8975f5c5SAndroid Build Coastguard Worker TEST_P(ShaderBinaryTest, InvalidCallParams)
153*8975f5c5SAndroid Build Coastguard Worker {
154*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!supported());
155*8975f5c5SAndroid Build Coastguard Worker 
156*8975f5c5SAndroid Build Coastguard Worker     GLuint vertShader[2];
157*8975f5c5SAndroid Build Coastguard Worker     vertShader[0]     = glCreateShader(GL_VERTEX_SHADER);
158*8975f5c5SAndroid Build Coastguard Worker     GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
159*8975f5c5SAndroid Build Coastguard Worker 
160*8975f5c5SAndroid Build Coastguard Worker     // Invalid shader
161*8975f5c5SAndroid Build Coastguard Worker     vertShader[1] = -1;
162*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &vertShader[1], GL_SHADER_BINARY_ANGLE, mVertexShaderBinary.data(),
163*8975f5c5SAndroid Build Coastguard Worker                    mVertexShaderBinary.size());
164*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
165*8975f5c5SAndroid Build Coastguard Worker 
166*8975f5c5SAndroid Build Coastguard Worker     // GL_INVALID_ENUM is generated if binaryFormat is not an accepted value.
167*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &vertShader[0], GL_INVALID_ENUM, mVertexShaderBinary.data(),
168*8975f5c5SAndroid Build Coastguard Worker                    mVertexShaderBinary.size());
169*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_ENUM);
170*8975f5c5SAndroid Build Coastguard Worker 
171*8975f5c5SAndroid Build Coastguard Worker     // GL_INVALID_VALUE is generated if n or length is negative
172*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(-1, &vertShader[0], GL_SHADER_BINARY_ANGLE, mVertexShaderBinary.data(),
173*8975f5c5SAndroid Build Coastguard Worker                    mVertexShaderBinary.size());
174*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
175*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &vertShader[0], GL_SHADER_BINARY_ANGLE, mVertexShaderBinary.data(), -1);
176*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
177*8975f5c5SAndroid Build Coastguard Worker 
178*8975f5c5SAndroid Build Coastguard Worker     // GL_INVALID_OPERATION is generated if any value in shaders is not a shader object.
179*8975f5c5SAndroid Build Coastguard Worker     GLuint program = glCreateProgram();
180*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &program, GL_SHADER_BINARY_ANGLE, mVertexShaderBinary.data(),
181*8975f5c5SAndroid Build Coastguard Worker                    mVertexShaderBinary.size());
182*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
183*8975f5c5SAndroid Build Coastguard Worker 
184*8975f5c5SAndroid Build Coastguard Worker     // GL_INVALID_OPERATION is generated if more than one of the handles in shaders refers to the
185*8975f5c5SAndroid Build Coastguard Worker     // same shader object.
186*8975f5c5SAndroid Build Coastguard Worker     vertShader[1] = vertShader[0];
187*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(2, &vertShader[0], GL_SHADER_BINARY_ANGLE, mVertexShaderBinary.data(),
188*8975f5c5SAndroid Build Coastguard Worker                    mVertexShaderBinary.size());
189*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
190*8975f5c5SAndroid Build Coastguard Worker 
191*8975f5c5SAndroid Build Coastguard Worker     // GL_INVALID_VALUE is generated if the data pointed to by binary does not match the format
192*8975f5c5SAndroid Build Coastguard Worker     // specified by binaryFormat.
193*8975f5c5SAndroid Build Coastguard Worker     std::string invalid("Invalid Shader Blob.");
194*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &vertShader[0], GL_SHADER_BINARY_ANGLE, invalid.data(), invalid.size());
195*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
196*8975f5c5SAndroid Build Coastguard Worker 
197*8975f5c5SAndroid Build Coastguard Worker     // Try loading vertex shader binary into fragment shader
198*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &fragShader, GL_SHADER_BINARY_ANGLE, mVertexShaderBinary.data(),
199*8975f5c5SAndroid Build Coastguard Worker                    mVertexShaderBinary.size());
200*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
201*8975f5c5SAndroid Build Coastguard Worker }
202*8975f5c5SAndroid Build Coastguard Worker 
203*8975f5c5SAndroid Build Coastguard Worker // Check attempting to get source code from a shader that was loaded with glShaderBinary.
TEST_P(ShaderBinaryTest,GetSourceFromBinaryShader)204*8975f5c5SAndroid Build Coastguard Worker TEST_P(ShaderBinaryTest, GetSourceFromBinaryShader)
205*8975f5c5SAndroid Build Coastguard Worker {
206*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!supported());
207*8975f5c5SAndroid Build Coastguard Worker 
208*8975f5c5SAndroid Build Coastguard Worker     GLint compileResult;
209*8975f5c5SAndroid Build Coastguard Worker     // Create vertex shader and load binary
210*8975f5c5SAndroid Build Coastguard Worker     GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
211*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &vertShader, GL_SHADER_BINARY_ANGLE, mVertexShaderBinary.data(),
212*8975f5c5SAndroid Build Coastguard Worker                    mVertexShaderBinary.size());
213*8975f5c5SAndroid Build Coastguard Worker     glGetShaderiv(vertShader, GL_COMPILE_STATUS, &compileResult);
214*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_TRUE(compileResult);
215*8975f5c5SAndroid Build Coastguard Worker 
216*8975f5c5SAndroid Build Coastguard Worker     GLsizei length = 0;
217*8975f5c5SAndroid Build Coastguard Worker     glGetShaderSource(vertShader, 0, &length, nullptr);
218*8975f5c5SAndroid Build Coastguard Worker 
219*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(length, 0);
220*8975f5c5SAndroid Build Coastguard Worker }
221*8975f5c5SAndroid Build Coastguard Worker 
222*8975f5c5SAndroid Build Coastguard Worker // Create a program from both shader source code and a binary blob.
TEST_P(ShaderBinaryTest,CombineSourceAndBinaryShaders)223*8975f5c5SAndroid Build Coastguard Worker TEST_P(ShaderBinaryTest, CombineSourceAndBinaryShaders)
224*8975f5c5SAndroid Build Coastguard Worker {
225*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!supported());
226*8975f5c5SAndroid Build Coastguard Worker 
227*8975f5c5SAndroid Build Coastguard Worker     GLint compileResult;
228*8975f5c5SAndroid Build Coastguard Worker     // Create vertex shader and load binary
229*8975f5c5SAndroid Build Coastguard Worker     GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
230*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &vertShader, GL_SHADER_BINARY_ANGLE, mVertexShaderBinary.data(),
231*8975f5c5SAndroid Build Coastguard Worker                    mVertexShaderBinary.size());
232*8975f5c5SAndroid Build Coastguard Worker     glGetShaderiv(vertShader, GL_COMPILE_STATUS, &compileResult);
233*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_TRUE(compileResult);
234*8975f5c5SAndroid Build Coastguard Worker 
235*8975f5c5SAndroid Build Coastguard Worker     // Create fragment shader
236*8975f5c5SAndroid Build Coastguard Worker     GLuint fragShader = CompileShader(GL_FRAGMENT_SHADER, essl1_shaders::fs::Red());
237*8975f5c5SAndroid Build Coastguard Worker 
238*8975f5c5SAndroid Build Coastguard Worker     GLuint newProgram = glCreateProgram();
239*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(newProgram, vertShader);
240*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(newProgram, fragShader);
241*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(newProgram);
242*8975f5c5SAndroid Build Coastguard Worker     newProgram = CheckLinkStatusAndReturnProgram(newProgram, true);
243*8975f5c5SAndroid Build Coastguard Worker 
244*8975f5c5SAndroid Build Coastguard Worker     // Test with a basic draw
245*8975f5c5SAndroid Build Coastguard Worker     drawQuad(newProgram, "a_position", 0.5f);
246*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
247*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
248*8975f5c5SAndroid Build Coastguard Worker }
249*8975f5c5SAndroid Build Coastguard Worker 
250*8975f5c5SAndroid Build Coastguard Worker // Test that shaders loaded with glShaderBinary do not cause false hits in the program cache.
TEST_P(ShaderBinaryTest,ProgramCacheWithShaderBinary)251*8975f5c5SAndroid Build Coastguard Worker TEST_P(ShaderBinaryTest, ProgramCacheWithShaderBinary)
252*8975f5c5SAndroid Build Coastguard Worker {
253*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!supported());
254*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_get_program_binary"));
255*8975f5c5SAndroid Build Coastguard Worker 
256*8975f5c5SAndroid Build Coastguard Worker     GLint compileResult;
257*8975f5c5SAndroid Build Coastguard Worker     // Create vertex shader that will be shared between the programs
258*8975f5c5SAndroid Build Coastguard Worker     GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
259*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &vertShader, GL_SHADER_BINARY_ANGLE, mVertexShaderBinary.data(),
260*8975f5c5SAndroid Build Coastguard Worker                    mVertexShaderBinary.size());
261*8975f5c5SAndroid Build Coastguard Worker     glGetShaderiv(vertShader, GL_COMPILE_STATUS, &compileResult);
262*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_TRUE(compileResult);
263*8975f5c5SAndroid Build Coastguard Worker 
264*8975f5c5SAndroid Build Coastguard Worker     // Create a program with a red vertex shader
265*8975f5c5SAndroid Build Coastguard Worker     GLuint fragShaderRed = glCreateShader(GL_FRAGMENT_SHADER);
266*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &fragShaderRed, GL_SHADER_BINARY_ANGLE, mFragmentShaderBinary.data(),
267*8975f5c5SAndroid Build Coastguard Worker                    mFragmentShaderBinary.size());
268*8975f5c5SAndroid Build Coastguard Worker     glGetShaderiv(fragShaderRed, GL_COMPILE_STATUS, &compileResult);
269*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_TRUE(compileResult);
270*8975f5c5SAndroid Build Coastguard Worker 
271*8975f5c5SAndroid Build Coastguard Worker     GLuint programRed = glCreateProgram();
272*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(programRed, vertShader);
273*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(programRed, fragShaderRed);
274*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(programRed);
275*8975f5c5SAndroid Build Coastguard Worker     programRed = CheckLinkStatusAndReturnProgram(programRed, true);
276*8975f5c5SAndroid Build Coastguard Worker 
277*8975f5c5SAndroid Build Coastguard Worker     // Test with a basic draw
278*8975f5c5SAndroid Build Coastguard Worker     drawQuad(programRed, "a_position", 0.5f);
279*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
280*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
281*8975f5c5SAndroid Build Coastguard Worker 
282*8975f5c5SAndroid Build Coastguard Worker     // Create a program with a blue fragment shader, also loaded from a binary
283*8975f5c5SAndroid Build Coastguard Worker     ShShaderSpec spec     = SH_GLES2_SPEC;
284*8975f5c5SAndroid Build Coastguard Worker     ShShaderOutput output = SH_SPIRV_VULKAN_OUTPUT;
285*8975f5c5SAndroid Build Coastguard Worker 
286*8975f5c5SAndroid Build Coastguard Worker     const char *source = essl1_shaders::fs::Blue();
287*8975f5c5SAndroid Build Coastguard Worker     sh::ShaderBinaryBlob fragShaderBlueData;
288*8975f5c5SAndroid Build Coastguard Worker     ShHandle fragmentCompiler =
289*8975f5c5SAndroid Build Coastguard Worker         sh::ConstructCompiler(GL_FRAGMENT_SHADER, spec, output, &mResources);
290*8975f5c5SAndroid Build Coastguard Worker     bool binaryCompileResult =
291*8975f5c5SAndroid Build Coastguard Worker         sh::GetShaderBinary(fragmentCompiler, &source, 1, mCompileOptions, &fragShaderBlueData);
292*8975f5c5SAndroid Build Coastguard Worker     ASSERT_TRUE(binaryCompileResult);
293*8975f5c5SAndroid Build Coastguard Worker     if (fragShaderBlueData.size() == 0)
294*8975f5c5SAndroid Build Coastguard Worker     {
295*8975f5c5SAndroid Build Coastguard Worker         FAIL() << "Creating fragment shader binary failed.";
296*8975f5c5SAndroid Build Coastguard Worker     }
297*8975f5c5SAndroid Build Coastguard Worker 
298*8975f5c5SAndroid Build Coastguard Worker     GLuint fragShaderBlue = glCreateShader(GL_FRAGMENT_SHADER);
299*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &fragShaderBlue, GL_SHADER_BINARY_ANGLE, fragShaderBlueData.data(),
300*8975f5c5SAndroid Build Coastguard Worker                    fragShaderBlueData.size());
301*8975f5c5SAndroid Build Coastguard Worker     glGetShaderiv(fragShaderBlue, GL_COMPILE_STATUS, &compileResult);
302*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_TRUE(compileResult);
303*8975f5c5SAndroid Build Coastguard Worker 
304*8975f5c5SAndroid Build Coastguard Worker     GLuint programBlue = glCreateProgram();
305*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(programBlue, vertShader);
306*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(programBlue, fragShaderBlue);
307*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(programBlue);
308*8975f5c5SAndroid Build Coastguard Worker     programBlue = CheckLinkStatusAndReturnProgram(programBlue, true);
309*8975f5c5SAndroid Build Coastguard Worker 
310*8975f5c5SAndroid Build Coastguard Worker     // The program cache should miss and create a new program
311*8975f5c5SAndroid Build Coastguard Worker     drawQuad(programBlue, "a_position", 0.5f);
312*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
313*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
314*8975f5c5SAndroid Build Coastguard Worker }
315*8975f5c5SAndroid Build Coastguard Worker 
316*8975f5c5SAndroid Build Coastguard Worker class ShaderBinaryTestES31 : public ShaderBinaryTest
317*8975f5c5SAndroid Build Coastguard Worker {
318*8975f5c5SAndroid Build Coastguard Worker   protected:
testSetUp()319*8975f5c5SAndroid Build Coastguard Worker     void testSetUp() override
320*8975f5c5SAndroid Build Coastguard Worker     {
321*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EQ(sh::Initialize(), true);
322*8975f5c5SAndroid Build Coastguard Worker 
323*8975f5c5SAndroid Build Coastguard Worker         mCompileOptions.objectCode                    = true;
324*8975f5c5SAndroid Build Coastguard Worker         mCompileOptions.emulateGLDrawID               = true;
325*8975f5c5SAndroid Build Coastguard Worker         mCompileOptions.initializeUninitializedLocals = true;
326*8975f5c5SAndroid Build Coastguard Worker 
327*8975f5c5SAndroid Build Coastguard Worker         sh::InitBuiltInResources(&mResources);
328*8975f5c5SAndroid Build Coastguard Worker         mResources.EXT_geometry_shader     = 1;
329*8975f5c5SAndroid Build Coastguard Worker         mResources.EXT_tessellation_shader = 1;
330*8975f5c5SAndroid Build Coastguard Worker 
331*8975f5c5SAndroid Build Coastguard Worker         // Generate a shader binary:
332*8975f5c5SAndroid Build Coastguard Worker         ShShaderSpec spec     = SH_GLES3_1_SPEC;
333*8975f5c5SAndroid Build Coastguard Worker         ShShaderOutput output = SH_SPIRV_VULKAN_OUTPUT;
334*8975f5c5SAndroid Build Coastguard Worker 
335*8975f5c5SAndroid Build Coastguard Worker         // Vertex shader:
336*8975f5c5SAndroid Build Coastguard Worker         const char *source = essl31_shaders::vs::Simple();
337*8975f5c5SAndroid Build Coastguard Worker         ShHandle vertexCompiler =
338*8975f5c5SAndroid Build Coastguard Worker             sh::ConstructCompiler(GL_VERTEX_SHADER, spec, output, &mResources);
339*8975f5c5SAndroid Build Coastguard Worker         bool compileResult =
340*8975f5c5SAndroid Build Coastguard Worker             sh::GetShaderBinary(vertexCompiler, &source, 1, mCompileOptions, &mVertexShaderBinary);
341*8975f5c5SAndroid Build Coastguard Worker         ASSERT_TRUE(compileResult);
342*8975f5c5SAndroid Build Coastguard Worker 
343*8975f5c5SAndroid Build Coastguard Worker         if (mVertexShaderBinary.size() == 0)
344*8975f5c5SAndroid Build Coastguard Worker         {
345*8975f5c5SAndroid Build Coastguard Worker             FAIL() << "Creating vertex shader binary failed.";
346*8975f5c5SAndroid Build Coastguard Worker         }
347*8975f5c5SAndroid Build Coastguard Worker 
348*8975f5c5SAndroid Build Coastguard Worker         // Fragment shader:
349*8975f5c5SAndroid Build Coastguard Worker         source = essl31_shaders::fs::Red();
350*8975f5c5SAndroid Build Coastguard Worker         ShHandle fragmentCompiler =
351*8975f5c5SAndroid Build Coastguard Worker             sh::ConstructCompiler(GL_FRAGMENT_SHADER, spec, output, &mResources);
352*8975f5c5SAndroid Build Coastguard Worker         compileResult = sh::GetShaderBinary(fragmentCompiler, &source, 1, mCompileOptions,
353*8975f5c5SAndroid Build Coastguard Worker                                             &mFragmentShaderBinary);
354*8975f5c5SAndroid Build Coastguard Worker         ASSERT_TRUE(compileResult);
355*8975f5c5SAndroid Build Coastguard Worker 
356*8975f5c5SAndroid Build Coastguard Worker         if (mFragmentShaderBinary.size() == 0)
357*8975f5c5SAndroid Build Coastguard Worker         {
358*8975f5c5SAndroid Build Coastguard Worker             FAIL() << "Creating fragment shader binary failed.";
359*8975f5c5SAndroid Build Coastguard Worker         }
360*8975f5c5SAndroid Build Coastguard Worker     }
361*8975f5c5SAndroid Build Coastguard Worker };
362*8975f5c5SAndroid Build Coastguard Worker 
363*8975f5c5SAndroid Build Coastguard Worker // Test all shader stages
TEST_P(ShaderBinaryTestES31,AllShaderStages)364*8975f5c5SAndroid Build Coastguard Worker TEST_P(ShaderBinaryTestES31, AllShaderStages)
365*8975f5c5SAndroid Build Coastguard Worker {
366*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!supported());
367*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
368*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
369*8975f5c5SAndroid Build Coastguard Worker 
370*8975f5c5SAndroid Build Coastguard Worker     const char *kGS = R"(#version 310 es
371*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
372*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
373*8975f5c5SAndroid Build Coastguard Worker 
374*8975f5c5SAndroid Build Coastguard Worker layout (triangles) in;
375*8975f5c5SAndroid Build Coastguard Worker layout (triangle_strip, max_vertices = 3) out;
376*8975f5c5SAndroid Build Coastguard Worker 
377*8975f5c5SAndroid Build Coastguard Worker void main() {
378*8975f5c5SAndroid Build Coastguard Worker     gl_Position = gl_in[0].gl_Position;
379*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
380*8975f5c5SAndroid Build Coastguard Worker 
381*8975f5c5SAndroid Build Coastguard Worker     gl_Position = gl_in[1].gl_Position;
382*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
383*8975f5c5SAndroid Build Coastguard Worker 
384*8975f5c5SAndroid Build Coastguard Worker     gl_Position = gl_in[2].gl_Position;
385*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
386*8975f5c5SAndroid Build Coastguard Worker 
387*8975f5c5SAndroid Build Coastguard Worker     EndPrimitive();
388*8975f5c5SAndroid Build Coastguard Worker }
389*8975f5c5SAndroid Build Coastguard Worker )";
390*8975f5c5SAndroid Build Coastguard Worker 
391*8975f5c5SAndroid Build Coastguard Worker     const char *kTCS = R"(#version 310 es
392*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_tessellation_shader : require
393*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
394*8975f5c5SAndroid Build Coastguard Worker 
395*8975f5c5SAndroid Build Coastguard Worker layout (vertices = 1) out;
396*8975f5c5SAndroid Build Coastguard Worker 
397*8975f5c5SAndroid Build Coastguard Worker void main()
398*8975f5c5SAndroid Build Coastguard Worker {
399*8975f5c5SAndroid Build Coastguard Worker     gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
400*8975f5c5SAndroid Build Coastguard Worker     gl_TessLevelInner[0] = 1.0;
401*8975f5c5SAndroid Build Coastguard Worker     gl_TessLevelInner[1] = 1.0;
402*8975f5c5SAndroid Build Coastguard Worker     gl_TessLevelOuter[0] = 1.0;
403*8975f5c5SAndroid Build Coastguard Worker     gl_TessLevelOuter[1] = 1.0;
404*8975f5c5SAndroid Build Coastguard Worker     gl_TessLevelOuter[2] = 1.0;
405*8975f5c5SAndroid Build Coastguard Worker     gl_TessLevelOuter[3] = 1.0;
406*8975f5c5SAndroid Build Coastguard Worker }
407*8975f5c5SAndroid Build Coastguard Worker 
408*8975f5c5SAndroid Build Coastguard Worker )";
409*8975f5c5SAndroid Build Coastguard Worker 
410*8975f5c5SAndroid Build Coastguard Worker     const char *kTES = R"(#version 310 es
411*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_tessellation_shader : require
412*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
413*8975f5c5SAndroid Build Coastguard Worker 
414*8975f5c5SAndroid Build Coastguard Worker layout (quads, cw, fractional_odd_spacing) in;
415*8975f5c5SAndroid Build Coastguard Worker 
416*8975f5c5SAndroid Build Coastguard Worker void main()
417*8975f5c5SAndroid Build Coastguard Worker {
418*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(gl_TessCoord.xy * 2. - 1., 0, 1);
419*8975f5c5SAndroid Build Coastguard Worker }
420*8975f5c5SAndroid Build Coastguard Worker )";
421*8975f5c5SAndroid Build Coastguard Worker 
422*8975f5c5SAndroid Build Coastguard Worker     // Generate a shader binary for geo, tcs, tes:
423*8975f5c5SAndroid Build Coastguard Worker     ShShaderSpec spec                  = SH_GLES3_1_SPEC;
424*8975f5c5SAndroid Build Coastguard Worker     ShShaderOutput output              = SH_SPIRV_VULKAN_OUTPUT;
425*8975f5c5SAndroid Build Coastguard Worker     mResources.EXT_geometry_shader     = 1;
426*8975f5c5SAndroid Build Coastguard Worker     mResources.EXT_tessellation_shader = 1;
427*8975f5c5SAndroid Build Coastguard Worker 
428*8975f5c5SAndroid Build Coastguard Worker     // Geometry shader:
429*8975f5c5SAndroid Build Coastguard Worker     sh::ShaderBinaryBlob geometryShaderBinary;
430*8975f5c5SAndroid Build Coastguard Worker     ShHandle geometryCompiler =
431*8975f5c5SAndroid Build Coastguard Worker         sh::ConstructCompiler(GL_GEOMETRY_SHADER, spec, output, &mResources);
432*8975f5c5SAndroid Build Coastguard Worker     bool compileResult =
433*8975f5c5SAndroid Build Coastguard Worker         sh::GetShaderBinary(geometryCompiler, &kGS, 1, mCompileOptions, &geometryShaderBinary);
434*8975f5c5SAndroid Build Coastguard Worker     ASSERT_TRUE(compileResult);
435*8975f5c5SAndroid Build Coastguard Worker     if (geometryShaderBinary.size() == 0)
436*8975f5c5SAndroid Build Coastguard Worker     {
437*8975f5c5SAndroid Build Coastguard Worker         FAIL() << "Creating geometry shader binary failed.";
438*8975f5c5SAndroid Build Coastguard Worker     }
439*8975f5c5SAndroid Build Coastguard Worker 
440*8975f5c5SAndroid Build Coastguard Worker     // tesselation control shader:
441*8975f5c5SAndroid Build Coastguard Worker     sh::ShaderBinaryBlob tessControlShaderBinary;
442*8975f5c5SAndroid Build Coastguard Worker     ShHandle tessControlCompiler =
443*8975f5c5SAndroid Build Coastguard Worker         sh::ConstructCompiler(GL_TESS_CONTROL_SHADER, spec, output, &mResources);
444*8975f5c5SAndroid Build Coastguard Worker     compileResult = sh::GetShaderBinary(tessControlCompiler, &kTCS, 1, mCompileOptions,
445*8975f5c5SAndroid Build Coastguard Worker                                         &tessControlShaderBinary);
446*8975f5c5SAndroid Build Coastguard Worker     ASSERT_TRUE(compileResult);
447*8975f5c5SAndroid Build Coastguard Worker     if (tessControlShaderBinary.size() == 0)
448*8975f5c5SAndroid Build Coastguard Worker     {
449*8975f5c5SAndroid Build Coastguard Worker         FAIL() << "Creating tesselation control shader binary failed.";
450*8975f5c5SAndroid Build Coastguard Worker     }
451*8975f5c5SAndroid Build Coastguard Worker 
452*8975f5c5SAndroid Build Coastguard Worker     // tesselation evaluation shader:
453*8975f5c5SAndroid Build Coastguard Worker     sh::ShaderBinaryBlob tessEvaluationShaderBinary;
454*8975f5c5SAndroid Build Coastguard Worker     ShHandle tessEvaluationCompiler =
455*8975f5c5SAndroid Build Coastguard Worker         sh::ConstructCompiler(GL_TESS_EVALUATION_SHADER, spec, output, &mResources);
456*8975f5c5SAndroid Build Coastguard Worker     compileResult = sh::GetShaderBinary(tessEvaluationCompiler, &kTES, 1, mCompileOptions,
457*8975f5c5SAndroid Build Coastguard Worker                                         &tessEvaluationShaderBinary);
458*8975f5c5SAndroid Build Coastguard Worker     ASSERT_TRUE(compileResult);
459*8975f5c5SAndroid Build Coastguard Worker     if (tessEvaluationShaderBinary.size() == 0)
460*8975f5c5SAndroid Build Coastguard Worker     {
461*8975f5c5SAndroid Build Coastguard Worker         FAIL() << "Creating tesselation evaluation shader binary failed.";
462*8975f5c5SAndroid Build Coastguard Worker     }
463*8975f5c5SAndroid Build Coastguard Worker 
464*8975f5c5SAndroid Build Coastguard Worker     GLint loadResult;
465*8975f5c5SAndroid Build Coastguard Worker     // Create vertex shader and load binary
466*8975f5c5SAndroid Build Coastguard Worker     GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
467*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &vertShader, GL_SHADER_BINARY_ANGLE, mVertexShaderBinary.data(),
468*8975f5c5SAndroid Build Coastguard Worker                    mVertexShaderBinary.size());
469*8975f5c5SAndroid Build Coastguard Worker     glGetShaderiv(vertShader, GL_COMPILE_STATUS, &loadResult);
470*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_TRUE(loadResult);
471*8975f5c5SAndroid Build Coastguard Worker 
472*8975f5c5SAndroid Build Coastguard Worker     // Create geometry shader and load binary
473*8975f5c5SAndroid Build Coastguard Worker     GLuint geoShader = glCreateShader(GL_GEOMETRY_SHADER);
474*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &geoShader, GL_SHADER_BINARY_ANGLE, geometryShaderBinary.data(),
475*8975f5c5SAndroid Build Coastguard Worker                    geometryShaderBinary.size());
476*8975f5c5SAndroid Build Coastguard Worker     glGetShaderiv(geoShader, GL_COMPILE_STATUS, &loadResult);
477*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_TRUE(loadResult);
478*8975f5c5SAndroid Build Coastguard Worker 
479*8975f5c5SAndroid Build Coastguard Worker     // Create tesselation control shader and load binary
480*8975f5c5SAndroid Build Coastguard Worker     GLuint tcShader = glCreateShader(GL_TESS_CONTROL_SHADER);
481*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &tcShader, GL_SHADER_BINARY_ANGLE, tessControlShaderBinary.data(),
482*8975f5c5SAndroid Build Coastguard Worker                    tessControlShaderBinary.size());
483*8975f5c5SAndroid Build Coastguard Worker     glGetShaderiv(tcShader, GL_COMPILE_STATUS, &loadResult);
484*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_TRUE(loadResult);
485*8975f5c5SAndroid Build Coastguard Worker 
486*8975f5c5SAndroid Build Coastguard Worker     // Create tesselation evaluation and load binary
487*8975f5c5SAndroid Build Coastguard Worker     GLuint teShader = glCreateShader(GL_TESS_EVALUATION_SHADER);
488*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &teShader, GL_SHADER_BINARY_ANGLE, tessEvaluationShaderBinary.data(),
489*8975f5c5SAndroid Build Coastguard Worker                    tessEvaluationShaderBinary.size());
490*8975f5c5SAndroid Build Coastguard Worker     glGetShaderiv(teShader, GL_COMPILE_STATUS, &loadResult);
491*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_TRUE(loadResult);
492*8975f5c5SAndroid Build Coastguard Worker 
493*8975f5c5SAndroid Build Coastguard Worker     // Create fragment shader and load binary
494*8975f5c5SAndroid Build Coastguard Worker     GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
495*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &fragShader, GL_SHADER_BINARY_ANGLE, mFragmentShaderBinary.data(),
496*8975f5c5SAndroid Build Coastguard Worker                    mFragmentShaderBinary.size());
497*8975f5c5SAndroid Build Coastguard Worker     glGetShaderiv(fragShader, GL_COMPILE_STATUS, &loadResult);
498*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_TRUE(loadResult);
499*8975f5c5SAndroid Build Coastguard Worker 
500*8975f5c5SAndroid Build Coastguard Worker     // Create program from the shaders
501*8975f5c5SAndroid Build Coastguard Worker     GLuint newProgram = glCreateProgram();
502*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(newProgram, vertShader);
503*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(newProgram, geoShader);
504*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(newProgram, tcShader);
505*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(newProgram, teShader);
506*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(newProgram, fragShader);
507*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(newProgram);
508*8975f5c5SAndroid Build Coastguard Worker     newProgram = CheckLinkStatusAndReturnProgram(newProgram, true);
509*8975f5c5SAndroid Build Coastguard Worker 
510*8975f5c5SAndroid Build Coastguard Worker     // Test with a basic draw
511*8975f5c5SAndroid Build Coastguard Worker     drawPatches(newProgram, "a_position", 0.5f, 1.0f, GL_FALSE);
512*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
513*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
514*8975f5c5SAndroid Build Coastguard Worker }
515*8975f5c5SAndroid Build Coastguard Worker 
516*8975f5c5SAndroid Build Coastguard Worker // Test glShaderBinary with complex shaders
TEST_P(ShaderBinaryTestES31,ComplexShader)517*8975f5c5SAndroid Build Coastguard Worker TEST_P(ShaderBinaryTestES31, ComplexShader)
518*8975f5c5SAndroid Build Coastguard Worker {
519*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!supported());
520*8975f5c5SAndroid Build Coastguard Worker 
521*8975f5c5SAndroid Build Coastguard Worker     const char *kVertexShader = R"(#version 310 es
522*8975f5c5SAndroid Build Coastguard Worker uniform vec2 table[4];
523*8975f5c5SAndroid Build Coastguard Worker 
524*8975f5c5SAndroid Build Coastguard Worker in vec2 position;
525*8975f5c5SAndroid Build Coastguard Worker in vec4 aTest;
526*8975f5c5SAndroid Build Coastguard Worker 
527*8975f5c5SAndroid Build Coastguard Worker out vec2 texCoord;
528*8975f5c5SAndroid Build Coastguard Worker out vec4 vTest;
529*8975f5c5SAndroid Build Coastguard Worker 
530*8975f5c5SAndroid Build Coastguard Worker void main()
531*8975f5c5SAndroid Build Coastguard Worker {
532*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(position + table[gl_InstanceID], 0, 1);
533*8975f5c5SAndroid Build Coastguard Worker     vTest       = aTest;
534*8975f5c5SAndroid Build Coastguard Worker     texCoord    = gl_Position.xy * 0.5 + vec2(0.5);
535*8975f5c5SAndroid Build Coastguard Worker })";
536*8975f5c5SAndroid Build Coastguard Worker 
537*8975f5c5SAndroid Build Coastguard Worker     const char *kFragmentShader = R"(#version 310 es
538*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
539*8975f5c5SAndroid Build Coastguard Worker 
540*8975f5c5SAndroid Build Coastguard Worker struct S { sampler2D sampler; };
541*8975f5c5SAndroid Build Coastguard Worker uniform S uStruct;
542*8975f5c5SAndroid Build Coastguard Worker 
543*8975f5c5SAndroid Build Coastguard Worker layout (binding = 0, std430) buffer Input {
544*8975f5c5SAndroid Build Coastguard Worker     float sampledInput;
545*8975f5c5SAndroid Build Coastguard Worker };
546*8975f5c5SAndroid Build Coastguard Worker 
547*8975f5c5SAndroid Build Coastguard Worker in vec2 texCoord;
548*8975f5c5SAndroid Build Coastguard Worker in vec4 vTest;
549*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
550*8975f5c5SAndroid Build Coastguard Worker 
551*8975f5c5SAndroid Build Coastguard Worker void main()
552*8975f5c5SAndroid Build Coastguard Worker {
553*8975f5c5SAndroid Build Coastguard Worker     if (sampledInput == 1.0)
554*8975f5c5SAndroid Build Coastguard Worker     {
555*8975f5c5SAndroid Build Coastguard Worker         my_FragColor = texture(uStruct.sampler, texCoord);
556*8975f5c5SAndroid Build Coastguard Worker     }
557*8975f5c5SAndroid Build Coastguard Worker     else
558*8975f5c5SAndroid Build Coastguard Worker     {
559*8975f5c5SAndroid Build Coastguard Worker         my_FragColor = vTest;
560*8975f5c5SAndroid Build Coastguard Worker     }
561*8975f5c5SAndroid Build Coastguard Worker })";
562*8975f5c5SAndroid Build Coastguard Worker 
563*8975f5c5SAndroid Build Coastguard Worker     // Generate shader binaries:
564*8975f5c5SAndroid Build Coastguard Worker     ShShaderSpec spec     = SH_GLES3_1_SPEC;
565*8975f5c5SAndroid Build Coastguard Worker     ShShaderOutput output = SH_SPIRV_VULKAN_OUTPUT;
566*8975f5c5SAndroid Build Coastguard Worker 
567*8975f5c5SAndroid Build Coastguard Worker     // Vertex shader:
568*8975f5c5SAndroid Build Coastguard Worker     sh::ShaderBinaryBlob vertexShaderBinary;
569*8975f5c5SAndroid Build Coastguard Worker     ShHandle vertexCompiler = sh::ConstructCompiler(GL_VERTEX_SHADER, spec, output, &mResources);
570*8975f5c5SAndroid Build Coastguard Worker     bool compileResult = sh::GetShaderBinary(vertexCompiler, &kVertexShader, 1, mCompileOptions,
571*8975f5c5SAndroid Build Coastguard Worker                                              &vertexShaderBinary);
572*8975f5c5SAndroid Build Coastguard Worker     ASSERT_TRUE(compileResult);
573*8975f5c5SAndroid Build Coastguard Worker 
574*8975f5c5SAndroid Build Coastguard Worker     if (vertexShaderBinary.size() == 0)
575*8975f5c5SAndroid Build Coastguard Worker     {
576*8975f5c5SAndroid Build Coastguard Worker         FAIL() << "Creating vertex shader binary failed.";
577*8975f5c5SAndroid Build Coastguard Worker     }
578*8975f5c5SAndroid Build Coastguard Worker 
579*8975f5c5SAndroid Build Coastguard Worker     // Fragment shader:
580*8975f5c5SAndroid Build Coastguard Worker     sh::ShaderBinaryBlob fragmentShaderBinary;
581*8975f5c5SAndroid Build Coastguard Worker     ShHandle fragmentCompiler =
582*8975f5c5SAndroid Build Coastguard Worker         sh::ConstructCompiler(GL_FRAGMENT_SHADER, spec, output, &mResources);
583*8975f5c5SAndroid Build Coastguard Worker     compileResult = sh::GetShaderBinary(fragmentCompiler, &kFragmentShader, 1, mCompileOptions,
584*8975f5c5SAndroid Build Coastguard Worker                                         &fragmentShaderBinary);
585*8975f5c5SAndroid Build Coastguard Worker     ASSERT_TRUE(compileResult);
586*8975f5c5SAndroid Build Coastguard Worker 
587*8975f5c5SAndroid Build Coastguard Worker     if (fragmentShaderBinary.size() == 0)
588*8975f5c5SAndroid Build Coastguard Worker     {
589*8975f5c5SAndroid Build Coastguard Worker         FAIL() << "Creating fragment shader binary failed.";
590*8975f5c5SAndroid Build Coastguard Worker     }
591*8975f5c5SAndroid Build Coastguard Worker 
592*8975f5c5SAndroid Build Coastguard Worker     GLint loadResult;
593*8975f5c5SAndroid Build Coastguard Worker     // Create vertex shader and load binary
594*8975f5c5SAndroid Build Coastguard Worker     GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
595*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &vertShader, GL_SHADER_BINARY_ANGLE, vertexShaderBinary.data(),
596*8975f5c5SAndroid Build Coastguard Worker                    vertexShaderBinary.size());
597*8975f5c5SAndroid Build Coastguard Worker     glGetShaderiv(vertShader, GL_COMPILE_STATUS, &loadResult);
598*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_TRUE(loadResult);
599*8975f5c5SAndroid Build Coastguard Worker 
600*8975f5c5SAndroid Build Coastguard Worker     // Create fragment shader and load binary
601*8975f5c5SAndroid Build Coastguard Worker     GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
602*8975f5c5SAndroid Build Coastguard Worker     glShaderBinary(1, &fragShader, GL_SHADER_BINARY_ANGLE, fragmentShaderBinary.data(),
603*8975f5c5SAndroid Build Coastguard Worker                    fragmentShaderBinary.size());
604*8975f5c5SAndroid Build Coastguard Worker     glGetShaderiv(fragShader, GL_COMPILE_STATUS, &loadResult);
605*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_TRUE(loadResult);
606*8975f5c5SAndroid Build Coastguard Worker 
607*8975f5c5SAndroid Build Coastguard Worker     // Create program from the shaders
608*8975f5c5SAndroid Build Coastguard Worker     GLuint newProgram = glCreateProgram();
609*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(newProgram, vertShader);
610*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(newProgram, fragShader);
611*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(newProgram);
612*8975f5c5SAndroid Build Coastguard Worker     newProgram = CheckLinkStatusAndReturnProgram(newProgram, true);
613*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(newProgram);
614*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
615*8975f5c5SAndroid Build Coastguard Worker 
616*8975f5c5SAndroid Build Coastguard Worker     // Setup instance offset table
617*8975f5c5SAndroid Build Coastguard Worker     constexpr GLfloat table[] = {-1, -1, -1, 1, 1, -1, 1, 1};
618*8975f5c5SAndroid Build Coastguard Worker     GLint tableMemberLoc      = glGetUniformLocation(newProgram, "table");
619*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, tableMemberLoc);
620*8975f5c5SAndroid Build Coastguard Worker     glUniform2fv(tableMemberLoc, 4, table);
621*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
622*8975f5c5SAndroid Build Coastguard Worker 
623*8975f5c5SAndroid Build Coastguard Worker     // Setup red testure and sampler uniform
624*8975f5c5SAndroid Build Coastguard Worker     GLTexture tex;
625*8975f5c5SAndroid Build Coastguard Worker     glActiveTexture(GL_TEXTURE0);
626*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D, tex);
627*8975f5c5SAndroid Build Coastguard Worker     GLubyte texData[] = {255u, 0u, 0u, 255u};
628*8975f5c5SAndroid Build Coastguard Worker     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
629*8975f5c5SAndroid Build Coastguard Worker 
630*8975f5c5SAndroid Build Coastguard Worker     GLint samplerMemberLoc = glGetUniformLocation(newProgram, "uStruct.sampler");
631*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, samplerMemberLoc);
632*8975f5c5SAndroid Build Coastguard Worker     glUniform1i(samplerMemberLoc, 0);
633*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
634*8975f5c5SAndroid Build Coastguard Worker 
635*8975f5c5SAndroid Build Coastguard Worker     // Setup the `aTest` attribute to blue
636*8975f5c5SAndroid Build Coastguard Worker     std::vector<Vector4> kInputAttribute(6, Vector4(0.0f, 0.0f, 1.0f, 1.0f));
637*8975f5c5SAndroid Build Coastguard Worker     GLint positionLocation = glGetAttribLocation(newProgram, "aTest");
638*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, kInputAttribute.data());
639*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(positionLocation);
640*8975f5c5SAndroid Build Coastguard Worker 
641*8975f5c5SAndroid Build Coastguard Worker     // Setup 'sampledInput' storage buffer to 1
642*8975f5c5SAndroid Build Coastguard Worker     constexpr GLfloat kInputDataOne = 1.0f;
643*8975f5c5SAndroid Build Coastguard Worker     GLBuffer input;
644*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
645*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputDataOne, GL_STATIC_COPY);
646*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
647*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
648*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
649*8975f5c5SAndroid Build Coastguard Worker 
650*8975f5c5SAndroid Build Coastguard Worker     // Test sampling texture with an instanced draw
651*8975f5c5SAndroid Build Coastguard Worker     drawQuadInstanced(newProgram, "position", 0.5f, 0.5f, GL_FALSE, 4);
652*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
653*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
654*8975f5c5SAndroid Build Coastguard Worker 
655*8975f5c5SAndroid Build Coastguard Worker     // Setup 'sampledInput' storage buffer to 0
656*8975f5c5SAndroid Build Coastguard Worker     constexpr GLfloat kInputDataZero = 0.0f;
657*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_SHADER_STORAGE_BUFFER, input);
658*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &kInputDataZero, GL_STATIC_COPY);
659*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input);
660*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
661*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
662*8975f5c5SAndroid Build Coastguard Worker 
663*8975f5c5SAndroid Build Coastguard Worker     // Test color attribute with an instanced draw
664*8975f5c5SAndroid Build Coastguard Worker     drawQuadInstanced(newProgram, "position", 0.5f, 0.5f, GL_FALSE, 4);
665*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
666*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
667*8975f5c5SAndroid Build Coastguard Worker }
668*8975f5c5SAndroid Build Coastguard Worker 
669*8975f5c5SAndroid Build Coastguard Worker // Use this to select which configurations (e.g. which renderer, which GLES major version) these
670*8975f5c5SAndroid Build Coastguard Worker // tests should be run against.
671*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31(ShaderBinaryTest);
672*8975f5c5SAndroid Build Coastguard Worker 
673*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ShaderBinaryTestES31);
674*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES31(ShaderBinaryTestES31);
675