xref: /aosp_15_r20/external/angle/src/tests/gl_tests/ParallelShaderCompileTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2018 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 // ParallelShaderCompileTest.cpp : Tests of the GL_KHR_parallel_shader_compile extension.
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/ANGLETest.h"
10*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/gl_raii.h"
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker #include "util/random_utils.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "util/test_utils.h"
14*8975f5c5SAndroid Build Coastguard Worker 
15*8975f5c5SAndroid Build Coastguard Worker using namespace angle;
16*8975f5c5SAndroid Build Coastguard Worker 
17*8975f5c5SAndroid Build Coastguard Worker namespace
18*8975f5c5SAndroid Build Coastguard Worker {
19*8975f5c5SAndroid Build Coastguard Worker 
20*8975f5c5SAndroid Build Coastguard Worker namespace
21*8975f5c5SAndroid Build Coastguard Worker {
22*8975f5c5SAndroid Build Coastguard Worker 
23*8975f5c5SAndroid Build Coastguard Worker constexpr int kTaskCount             = 32;
24*8975f5c5SAndroid Build Coastguard Worker constexpr unsigned int kPollInterval = 100;
25*8975f5c5SAndroid Build Coastguard Worker 
26*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
27*8975f5c5SAndroid Build Coastguard Worker 
28*8975f5c5SAndroid Build Coastguard Worker class ParallelShaderCompileTest : public ANGLETest<>
29*8975f5c5SAndroid Build Coastguard Worker {
30*8975f5c5SAndroid Build Coastguard Worker   protected:
ParallelShaderCompileTest()31*8975f5c5SAndroid Build Coastguard Worker     ParallelShaderCompileTest()
32*8975f5c5SAndroid Build Coastguard Worker     {
33*8975f5c5SAndroid Build Coastguard Worker         setWindowWidth(128);
34*8975f5c5SAndroid Build Coastguard Worker         setWindowHeight(128);
35*8975f5c5SAndroid Build Coastguard Worker         setConfigRedBits(8);
36*8975f5c5SAndroid Build Coastguard Worker         setConfigGreenBits(8);
37*8975f5c5SAndroid Build Coastguard Worker         setConfigBlueBits(8);
38*8975f5c5SAndroid Build Coastguard Worker         setConfigAlphaBits(8);
39*8975f5c5SAndroid Build Coastguard Worker     }
40*8975f5c5SAndroid Build Coastguard Worker 
ensureParallelShaderCompileExtensionAvailable()41*8975f5c5SAndroid Build Coastguard Worker     bool ensureParallelShaderCompileExtensionAvailable()
42*8975f5c5SAndroid Build Coastguard Worker     {
43*8975f5c5SAndroid Build Coastguard Worker         if (IsGLExtensionRequestable("GL_KHR_parallel_shader_compile"))
44*8975f5c5SAndroid Build Coastguard Worker         {
45*8975f5c5SAndroid Build Coastguard Worker             glRequestExtensionANGLE("GL_KHR_parallel_shader_compile");
46*8975f5c5SAndroid Build Coastguard Worker         }
47*8975f5c5SAndroid Build Coastguard Worker 
48*8975f5c5SAndroid Build Coastguard Worker         if (!IsGLExtensionEnabled("GL_KHR_parallel_shader_compile"))
49*8975f5c5SAndroid Build Coastguard Worker         {
50*8975f5c5SAndroid Build Coastguard Worker             return false;
51*8975f5c5SAndroid Build Coastguard Worker         }
52*8975f5c5SAndroid Build Coastguard Worker         return true;
53*8975f5c5SAndroid Build Coastguard Worker     }
54*8975f5c5SAndroid Build Coastguard Worker 
55*8975f5c5SAndroid Build Coastguard Worker     class Task
56*8975f5c5SAndroid Build Coastguard Worker     {
57*8975f5c5SAndroid Build Coastguard Worker       public:
Task(int id)58*8975f5c5SAndroid Build Coastguard Worker         Task(int id) : mID(id) {}
~Task()59*8975f5c5SAndroid Build Coastguard Worker         virtual ~Task() {}
60*8975f5c5SAndroid Build Coastguard Worker 
61*8975f5c5SAndroid Build Coastguard Worker         virtual bool compile()            = 0;
62*8975f5c5SAndroid Build Coastguard Worker         virtual bool isCompileCompleted() = 0;
63*8975f5c5SAndroid Build Coastguard Worker         virtual bool link()               = 0;
postLink()64*8975f5c5SAndroid Build Coastguard Worker         virtual void postLink() {}
65*8975f5c5SAndroid Build Coastguard Worker         virtual void runAndVerify(ParallelShaderCompileTest *test) = 0;
66*8975f5c5SAndroid Build Coastguard Worker 
isLinkCompleted()67*8975f5c5SAndroid Build Coastguard Worker         bool isLinkCompleted()
68*8975f5c5SAndroid Build Coastguard Worker         {
69*8975f5c5SAndroid Build Coastguard Worker             GLint status;
70*8975f5c5SAndroid Build Coastguard Worker             glGetProgramiv(mProgram, GL_COMPLETION_STATUS_KHR, &status);
71*8975f5c5SAndroid Build Coastguard Worker             return (status == GL_TRUE);
72*8975f5c5SAndroid Build Coastguard Worker         }
73*8975f5c5SAndroid Build Coastguard Worker 
74*8975f5c5SAndroid Build Coastguard Worker       protected:
InsertRandomString(const std::string & source)75*8975f5c5SAndroid Build Coastguard Worker         static std::string InsertRandomString(const std::string &source)
76*8975f5c5SAndroid Build Coastguard Worker         {
77*8975f5c5SAndroid Build Coastguard Worker             RNG rng;
78*8975f5c5SAndroid Build Coastguard Worker             std::ostringstream ostream;
79*8975f5c5SAndroid Build Coastguard Worker             ostream << source << "\n// Random string to fool program cache: " << rng.randomInt()
80*8975f5c5SAndroid Build Coastguard Worker                     << "\n";
81*8975f5c5SAndroid Build Coastguard Worker             return ostream.str();
82*8975f5c5SAndroid Build Coastguard Worker         }
83*8975f5c5SAndroid Build Coastguard Worker 
CompileShader(GLenum type,const std::string & source)84*8975f5c5SAndroid Build Coastguard Worker         static GLuint CompileShader(GLenum type, const std::string &source)
85*8975f5c5SAndroid Build Coastguard Worker         {
86*8975f5c5SAndroid Build Coastguard Worker             GLuint shader = glCreateShader(type);
87*8975f5c5SAndroid Build Coastguard Worker 
88*8975f5c5SAndroid Build Coastguard Worker             const char *sourceArray[1] = {source.c_str()};
89*8975f5c5SAndroid Build Coastguard Worker             glShaderSource(shader, 1, sourceArray, nullptr);
90*8975f5c5SAndroid Build Coastguard Worker             glCompileShader(shader);
91*8975f5c5SAndroid Build Coastguard Worker             return shader;
92*8975f5c5SAndroid Build Coastguard Worker         }
93*8975f5c5SAndroid Build Coastguard Worker 
RecompileShader(GLuint shader,const std::string & source)94*8975f5c5SAndroid Build Coastguard Worker         static void RecompileShader(GLuint shader, const std::string &source)
95*8975f5c5SAndroid Build Coastguard Worker         {
96*8975f5c5SAndroid Build Coastguard Worker             const char *sourceArray[1] = {source.c_str()};
97*8975f5c5SAndroid Build Coastguard Worker             glShaderSource(shader, 1, sourceArray, nullptr);
98*8975f5c5SAndroid Build Coastguard Worker             glCompileShader(shader);
99*8975f5c5SAndroid Build Coastguard Worker         }
100*8975f5c5SAndroid Build Coastguard Worker 
CheckShader(GLuint shader)101*8975f5c5SAndroid Build Coastguard Worker         static bool CheckShader(GLuint shader)
102*8975f5c5SAndroid Build Coastguard Worker         {
103*8975f5c5SAndroid Build Coastguard Worker             GLint compileResult;
104*8975f5c5SAndroid Build Coastguard Worker             glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
105*8975f5c5SAndroid Build Coastguard Worker 
106*8975f5c5SAndroid Build Coastguard Worker             if (compileResult == 0)
107*8975f5c5SAndroid Build Coastguard Worker             {
108*8975f5c5SAndroid Build Coastguard Worker                 GLint infoLogLength;
109*8975f5c5SAndroid Build Coastguard Worker                 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
110*8975f5c5SAndroid Build Coastguard Worker 
111*8975f5c5SAndroid Build Coastguard Worker                 // Info log length includes the null terminator, so 1 means that the info log is an
112*8975f5c5SAndroid Build Coastguard Worker                 // empty string.
113*8975f5c5SAndroid Build Coastguard Worker                 if (infoLogLength > 1)
114*8975f5c5SAndroid Build Coastguard Worker                 {
115*8975f5c5SAndroid Build Coastguard Worker                     std::vector<GLchar> infoLog(infoLogLength);
116*8975f5c5SAndroid Build Coastguard Worker                     glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr,
117*8975f5c5SAndroid Build Coastguard Worker                                        &infoLog[0]);
118*8975f5c5SAndroid Build Coastguard Worker                     std::cerr << "shader compilation failed: " << &infoLog[0];
119*8975f5c5SAndroid Build Coastguard Worker                 }
120*8975f5c5SAndroid Build Coastguard Worker                 else
121*8975f5c5SAndroid Build Coastguard Worker                 {
122*8975f5c5SAndroid Build Coastguard Worker                     std::cerr << "shader compilation failed. <Empty log message>";
123*8975f5c5SAndroid Build Coastguard Worker                 }
124*8975f5c5SAndroid Build Coastguard Worker                 std::cerr << std::endl;
125*8975f5c5SAndroid Build Coastguard Worker             }
126*8975f5c5SAndroid Build Coastguard Worker             return (compileResult == GL_TRUE);
127*8975f5c5SAndroid Build Coastguard Worker         }
128*8975f5c5SAndroid Build Coastguard Worker 
129*8975f5c5SAndroid Build Coastguard Worker         GLuint mProgram;
130*8975f5c5SAndroid Build Coastguard Worker         int mID;
131*8975f5c5SAndroid Build Coastguard Worker     };
132*8975f5c5SAndroid Build Coastguard Worker 
133*8975f5c5SAndroid Build Coastguard Worker     template <typename T>
134*8975f5c5SAndroid Build Coastguard Worker     class TaskRunner
135*8975f5c5SAndroid Build Coastguard Worker     {
136*8975f5c5SAndroid Build Coastguard Worker       public:
TaskRunner()137*8975f5c5SAndroid Build Coastguard Worker         TaskRunner() {}
~TaskRunner()138*8975f5c5SAndroid Build Coastguard Worker         ~TaskRunner() {}
139*8975f5c5SAndroid Build Coastguard Worker 
run(ParallelShaderCompileTest * test,unsigned int pollInterval)140*8975f5c5SAndroid Build Coastguard Worker         void run(ParallelShaderCompileTest *test, unsigned int pollInterval)
141*8975f5c5SAndroid Build Coastguard Worker         {
142*8975f5c5SAndroid Build Coastguard Worker 
143*8975f5c5SAndroid Build Coastguard Worker             std::vector<std::unique_ptr<T>> compileTasks;
144*8975f5c5SAndroid Build Coastguard Worker             for (int i = 0; i < kTaskCount; ++i)
145*8975f5c5SAndroid Build Coastguard Worker             {
146*8975f5c5SAndroid Build Coastguard Worker                 std::unique_ptr<T> task(new T(i));
147*8975f5c5SAndroid Build Coastguard Worker                 bool isCompiling = task->compile();
148*8975f5c5SAndroid Build Coastguard Worker                 ASSERT_TRUE(isCompiling);
149*8975f5c5SAndroid Build Coastguard Worker                 compileTasks.push_back(std::move(task));
150*8975f5c5SAndroid Build Coastguard Worker             }
151*8975f5c5SAndroid Build Coastguard Worker 
152*8975f5c5SAndroid Build Coastguard Worker             std::vector<std::unique_ptr<T>> linkTasks;
153*8975f5c5SAndroid Build Coastguard Worker             while (!compileTasks.empty())
154*8975f5c5SAndroid Build Coastguard Worker             {
155*8975f5c5SAndroid Build Coastguard Worker                 for (unsigned int i = 0; i < compileTasks.size();)
156*8975f5c5SAndroid Build Coastguard Worker                 {
157*8975f5c5SAndroid Build Coastguard Worker                     auto &task = compileTasks[i];
158*8975f5c5SAndroid Build Coastguard Worker 
159*8975f5c5SAndroid Build Coastguard Worker                     if (task->isCompileCompleted())
160*8975f5c5SAndroid Build Coastguard Worker                     {
161*8975f5c5SAndroid Build Coastguard Worker                         bool isLinking = task->link();
162*8975f5c5SAndroid Build Coastguard Worker                         task->postLink();
163*8975f5c5SAndroid Build Coastguard Worker                         ASSERT_TRUE(isLinking);
164*8975f5c5SAndroid Build Coastguard Worker                         linkTasks.push_back(std::move(task));
165*8975f5c5SAndroid Build Coastguard Worker                         compileTasks.erase(compileTasks.begin() + i);
166*8975f5c5SAndroid Build Coastguard Worker                         continue;
167*8975f5c5SAndroid Build Coastguard Worker                     }
168*8975f5c5SAndroid Build Coastguard Worker                     ++i;
169*8975f5c5SAndroid Build Coastguard Worker                 }
170*8975f5c5SAndroid Build Coastguard Worker                 if (pollInterval != 0)
171*8975f5c5SAndroid Build Coastguard Worker                 {
172*8975f5c5SAndroid Build Coastguard Worker                     angle::Sleep(pollInterval);
173*8975f5c5SAndroid Build Coastguard Worker                 }
174*8975f5c5SAndroid Build Coastguard Worker             }
175*8975f5c5SAndroid Build Coastguard Worker 
176*8975f5c5SAndroid Build Coastguard Worker             while (!linkTasks.empty())
177*8975f5c5SAndroid Build Coastguard Worker             {
178*8975f5c5SAndroid Build Coastguard Worker                 for (unsigned int i = 0; i < linkTasks.size();)
179*8975f5c5SAndroid Build Coastguard Worker                 {
180*8975f5c5SAndroid Build Coastguard Worker                     auto &task = linkTasks[i];
181*8975f5c5SAndroid Build Coastguard Worker 
182*8975f5c5SAndroid Build Coastguard Worker                     if (task->isLinkCompleted())
183*8975f5c5SAndroid Build Coastguard Worker                     {
184*8975f5c5SAndroid Build Coastguard Worker                         task->runAndVerify(test);
185*8975f5c5SAndroid Build Coastguard Worker                         linkTasks.erase(linkTasks.begin() + i);
186*8975f5c5SAndroid Build Coastguard Worker                         continue;
187*8975f5c5SAndroid Build Coastguard Worker                     }
188*8975f5c5SAndroid Build Coastguard Worker                     else
189*8975f5c5SAndroid Build Coastguard Worker                     {
190*8975f5c5SAndroid Build Coastguard Worker                         task->postLink();
191*8975f5c5SAndroid Build Coastguard Worker                     }
192*8975f5c5SAndroid Build Coastguard Worker                     ++i;
193*8975f5c5SAndroid Build Coastguard Worker                 }
194*8975f5c5SAndroid Build Coastguard Worker                 if (pollInterval != 0)
195*8975f5c5SAndroid Build Coastguard Worker                 {
196*8975f5c5SAndroid Build Coastguard Worker                     angle::Sleep(pollInterval);
197*8975f5c5SAndroid Build Coastguard Worker                 }
198*8975f5c5SAndroid Build Coastguard Worker             }
199*8975f5c5SAndroid Build Coastguard Worker         }
200*8975f5c5SAndroid Build Coastguard Worker     };
201*8975f5c5SAndroid Build Coastguard Worker 
202*8975f5c5SAndroid Build Coastguard Worker     class ClearColorWithDraw : public Task
203*8975f5c5SAndroid Build Coastguard Worker     {
204*8975f5c5SAndroid Build Coastguard Worker       public:
ClearColorWithDraw(int taskID)205*8975f5c5SAndroid Build Coastguard Worker         ClearColorWithDraw(int taskID) : Task(taskID)
206*8975f5c5SAndroid Build Coastguard Worker         {
207*8975f5c5SAndroid Build Coastguard Worker             auto color = static_cast<GLubyte>(taskID * 255 / kTaskCount);
208*8975f5c5SAndroid Build Coastguard Worker             mColor     = {color, color, color, 255};
209*8975f5c5SAndroid Build Coastguard Worker         }
210*8975f5c5SAndroid Build Coastguard Worker 
compile()211*8975f5c5SAndroid Build Coastguard Worker         bool compile() override
212*8975f5c5SAndroid Build Coastguard Worker         {
213*8975f5c5SAndroid Build Coastguard Worker             mVertexShader =
214*8975f5c5SAndroid Build Coastguard Worker                 CompileShader(GL_VERTEX_SHADER, InsertRandomString(essl1_shaders::vs::Simple()));
215*8975f5c5SAndroid Build Coastguard Worker             mFragmentShader = CompileShader(GL_FRAGMENT_SHADER,
216*8975f5c5SAndroid Build Coastguard Worker                                             InsertRandomString(essl1_shaders::fs::UniformColor()));
217*8975f5c5SAndroid Build Coastguard Worker             return (mVertexShader != 0 && mFragmentShader != 0);
218*8975f5c5SAndroid Build Coastguard Worker         }
219*8975f5c5SAndroid Build Coastguard Worker 
isCompileCompleted()220*8975f5c5SAndroid Build Coastguard Worker         bool isCompileCompleted() override
221*8975f5c5SAndroid Build Coastguard Worker         {
222*8975f5c5SAndroid Build Coastguard Worker             GLint status;
223*8975f5c5SAndroid Build Coastguard Worker             glGetShaderiv(mVertexShader, GL_COMPLETION_STATUS_KHR, &status);
224*8975f5c5SAndroid Build Coastguard Worker             if (status == GL_TRUE)
225*8975f5c5SAndroid Build Coastguard Worker             {
226*8975f5c5SAndroid Build Coastguard Worker                 glGetShaderiv(mFragmentShader, GL_COMPLETION_STATUS_KHR, &status);
227*8975f5c5SAndroid Build Coastguard Worker                 return (status == GL_TRUE);
228*8975f5c5SAndroid Build Coastguard Worker             }
229*8975f5c5SAndroid Build Coastguard Worker             return false;
230*8975f5c5SAndroid Build Coastguard Worker         }
231*8975f5c5SAndroid Build Coastguard Worker 
link()232*8975f5c5SAndroid Build Coastguard Worker         bool link() override
233*8975f5c5SAndroid Build Coastguard Worker         {
234*8975f5c5SAndroid Build Coastguard Worker             mProgram = 0;
235*8975f5c5SAndroid Build Coastguard Worker             if (CheckShader(mVertexShader) && CheckShader(mFragmentShader))
236*8975f5c5SAndroid Build Coastguard Worker             {
237*8975f5c5SAndroid Build Coastguard Worker                 mProgram = glCreateProgram();
238*8975f5c5SAndroid Build Coastguard Worker                 glAttachShader(mProgram, mVertexShader);
239*8975f5c5SAndroid Build Coastguard Worker                 glAttachShader(mProgram, mFragmentShader);
240*8975f5c5SAndroid Build Coastguard Worker                 glLinkProgram(mProgram);
241*8975f5c5SAndroid Build Coastguard Worker             }
242*8975f5c5SAndroid Build Coastguard Worker             glDeleteShader(mVertexShader);
243*8975f5c5SAndroid Build Coastguard Worker             glDeleteShader(mFragmentShader);
244*8975f5c5SAndroid Build Coastguard Worker             return (mProgram != 0);
245*8975f5c5SAndroid Build Coastguard Worker         }
246*8975f5c5SAndroid Build Coastguard Worker 
runAndVerify(ParallelShaderCompileTest * test)247*8975f5c5SAndroid Build Coastguard Worker         void runAndVerify(ParallelShaderCompileTest *test) override
248*8975f5c5SAndroid Build Coastguard Worker         {
249*8975f5c5SAndroid Build Coastguard Worker             glClearColor(0, 0, 0, 0);
250*8975f5c5SAndroid Build Coastguard Worker             glClear(GL_COLOR_BUFFER_BIT);
251*8975f5c5SAndroid Build Coastguard Worker             glDisable(GL_DEPTH_TEST);
252*8975f5c5SAndroid Build Coastguard Worker             glUseProgram(mProgram);
253*8975f5c5SAndroid Build Coastguard Worker             ASSERT_GL_NO_ERROR();
254*8975f5c5SAndroid Build Coastguard Worker             GLint colorUniformLocation =
255*8975f5c5SAndroid Build Coastguard Worker                 glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
256*8975f5c5SAndroid Build Coastguard Worker             ASSERT_NE(colorUniformLocation, -1);
257*8975f5c5SAndroid Build Coastguard Worker             auto normalizeColor = mColor.toNormalizedVector();
258*8975f5c5SAndroid Build Coastguard Worker             glUniform4fv(colorUniformLocation, 1, normalizeColor.data());
259*8975f5c5SAndroid Build Coastguard Worker             test->drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
260*8975f5c5SAndroid Build Coastguard Worker             EXPECT_PIXEL_COLOR_EQ(test->getWindowWidth() / 2, test->getWindowHeight() / 2, mColor);
261*8975f5c5SAndroid Build Coastguard Worker             glUseProgram(0);
262*8975f5c5SAndroid Build Coastguard Worker             glDeleteProgram(mProgram);
263*8975f5c5SAndroid Build Coastguard Worker             ASSERT_GL_NO_ERROR();
264*8975f5c5SAndroid Build Coastguard Worker         }
265*8975f5c5SAndroid Build Coastguard Worker 
266*8975f5c5SAndroid Build Coastguard Worker       protected:
recompile()267*8975f5c5SAndroid Build Coastguard Worker         void recompile()
268*8975f5c5SAndroid Build Coastguard Worker         {
269*8975f5c5SAndroid Build Coastguard Worker             RecompileShader(mVertexShader, essl1_shaders::vs::Simple());
270*8975f5c5SAndroid Build Coastguard Worker             RecompileShader(mFragmentShader, essl1_shaders::fs::UniformColor());
271*8975f5c5SAndroid Build Coastguard Worker         }
272*8975f5c5SAndroid Build Coastguard Worker 
273*8975f5c5SAndroid Build Coastguard Worker       private:
274*8975f5c5SAndroid Build Coastguard Worker         GLuint mVertexShader;
275*8975f5c5SAndroid Build Coastguard Worker         GLuint mFragmentShader;
276*8975f5c5SAndroid Build Coastguard Worker         GLColor mColor;
277*8975f5c5SAndroid Build Coastguard Worker     };
278*8975f5c5SAndroid Build Coastguard Worker 
279*8975f5c5SAndroid Build Coastguard Worker     class ClearColorWithDrawRecompile : public ClearColorWithDraw
280*8975f5c5SAndroid Build Coastguard Worker     {
281*8975f5c5SAndroid Build Coastguard Worker       public:
ClearColorWithDrawRecompile(int taskID)282*8975f5c5SAndroid Build Coastguard Worker         ClearColorWithDrawRecompile(int taskID) : ClearColorWithDraw(taskID) {}
283*8975f5c5SAndroid Build Coastguard Worker 
postLink()284*8975f5c5SAndroid Build Coastguard Worker         void postLink() override { recompile(); }
285*8975f5c5SAndroid Build Coastguard Worker     };
286*8975f5c5SAndroid Build Coastguard Worker 
287*8975f5c5SAndroid Build Coastguard Worker     class ImageLoadStore : public Task
288*8975f5c5SAndroid Build Coastguard Worker     {
289*8975f5c5SAndroid Build Coastguard Worker       public:
ImageLoadStore(int taskID)290*8975f5c5SAndroid Build Coastguard Worker         ImageLoadStore(int taskID) : Task(taskID) {}
~ImageLoadStore()291*8975f5c5SAndroid Build Coastguard Worker         ~ImageLoadStore() {}
292*8975f5c5SAndroid Build Coastguard Worker 
compile()293*8975f5c5SAndroid Build Coastguard Worker         bool compile() override
294*8975f5c5SAndroid Build Coastguard Worker         {
295*8975f5c5SAndroid Build Coastguard Worker             const char kCSSource[] = R"(#version 310 es
296*8975f5c5SAndroid Build Coastguard Worker layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
297*8975f5c5SAndroid Build Coastguard Worker layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
298*8975f5c5SAndroid Build Coastguard Worker layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
299*8975f5c5SAndroid Build Coastguard Worker void main()
300*8975f5c5SAndroid Build Coastguard Worker {
301*8975f5c5SAndroid Build Coastguard Worker     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
302*8975f5c5SAndroid Build Coastguard Worker     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
303*8975f5c5SAndroid Build Coastguard Worker })";
304*8975f5c5SAndroid Build Coastguard Worker 
305*8975f5c5SAndroid Build Coastguard Worker             mShader = CompileShader(GL_COMPUTE_SHADER, InsertRandomString(kCSSource));
306*8975f5c5SAndroid Build Coastguard Worker             return mShader != 0;
307*8975f5c5SAndroid Build Coastguard Worker         }
308*8975f5c5SAndroid Build Coastguard Worker 
isCompileCompleted()309*8975f5c5SAndroid Build Coastguard Worker         bool isCompileCompleted() override
310*8975f5c5SAndroid Build Coastguard Worker         {
311*8975f5c5SAndroid Build Coastguard Worker             GLint status;
312*8975f5c5SAndroid Build Coastguard Worker             glGetShaderiv(mShader, GL_COMPLETION_STATUS_KHR, &status);
313*8975f5c5SAndroid Build Coastguard Worker             return status == GL_TRUE;
314*8975f5c5SAndroid Build Coastguard Worker         }
315*8975f5c5SAndroid Build Coastguard Worker 
link()316*8975f5c5SAndroid Build Coastguard Worker         bool link() override
317*8975f5c5SAndroid Build Coastguard Worker         {
318*8975f5c5SAndroid Build Coastguard Worker             mProgram = 0;
319*8975f5c5SAndroid Build Coastguard Worker             if (CheckShader(mShader))
320*8975f5c5SAndroid Build Coastguard Worker             {
321*8975f5c5SAndroid Build Coastguard Worker                 mProgram = glCreateProgram();
322*8975f5c5SAndroid Build Coastguard Worker                 glAttachShader(mProgram, mShader);
323*8975f5c5SAndroid Build Coastguard Worker                 glLinkProgram(mProgram);
324*8975f5c5SAndroid Build Coastguard Worker             }
325*8975f5c5SAndroid Build Coastguard Worker             glDeleteShader(mShader);
326*8975f5c5SAndroid Build Coastguard Worker             return mProgram != 0;
327*8975f5c5SAndroid Build Coastguard Worker         }
328*8975f5c5SAndroid Build Coastguard Worker 
runAndVerify(ParallelShaderCompileTest * test)329*8975f5c5SAndroid Build Coastguard Worker         void runAndVerify(ParallelShaderCompileTest *test) override
330*8975f5c5SAndroid Build Coastguard Worker         {
331*8975f5c5SAndroid Build Coastguard Worker             // Taken from ComputeShaderTest.StoreImageThenLoad.
332*8975f5c5SAndroid Build Coastguard Worker             constexpr GLuint kInputValues[3][1] = {{300}, {200}, {100}};
333*8975f5c5SAndroid Build Coastguard Worker             GLTexture texture[3];
334*8975f5c5SAndroid Build Coastguard Worker             glBindTexture(GL_TEXTURE_2D, texture[0]);
335*8975f5c5SAndroid Build Coastguard Worker             glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
336*8975f5c5SAndroid Build Coastguard Worker             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
337*8975f5c5SAndroid Build Coastguard Worker                             kInputValues[0]);
338*8975f5c5SAndroid Build Coastguard Worker             EXPECT_GL_NO_ERROR();
339*8975f5c5SAndroid Build Coastguard Worker 
340*8975f5c5SAndroid Build Coastguard Worker             glBindTexture(GL_TEXTURE_2D, texture[1]);
341*8975f5c5SAndroid Build Coastguard Worker             glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
342*8975f5c5SAndroid Build Coastguard Worker             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
343*8975f5c5SAndroid Build Coastguard Worker                             kInputValues[1]);
344*8975f5c5SAndroid Build Coastguard Worker             EXPECT_GL_NO_ERROR();
345*8975f5c5SAndroid Build Coastguard Worker 
346*8975f5c5SAndroid Build Coastguard Worker             glBindTexture(GL_TEXTURE_2D, texture[2]);
347*8975f5c5SAndroid Build Coastguard Worker             glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
348*8975f5c5SAndroid Build Coastguard Worker             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT,
349*8975f5c5SAndroid Build Coastguard Worker                             kInputValues[2]);
350*8975f5c5SAndroid Build Coastguard Worker             EXPECT_GL_NO_ERROR();
351*8975f5c5SAndroid Build Coastguard Worker 
352*8975f5c5SAndroid Build Coastguard Worker             glUseProgram(mProgram);
353*8975f5c5SAndroid Build Coastguard Worker 
354*8975f5c5SAndroid Build Coastguard Worker             glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
355*8975f5c5SAndroid Build Coastguard Worker             glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
356*8975f5c5SAndroid Build Coastguard Worker 
357*8975f5c5SAndroid Build Coastguard Worker             glDispatchCompute(1, 1, 1);
358*8975f5c5SAndroid Build Coastguard Worker             glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
359*8975f5c5SAndroid Build Coastguard Worker             EXPECT_GL_NO_ERROR();
360*8975f5c5SAndroid Build Coastguard Worker 
361*8975f5c5SAndroid Build Coastguard Worker             glBindImageTexture(0, texture[1], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
362*8975f5c5SAndroid Build Coastguard Worker             glBindImageTexture(1, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
363*8975f5c5SAndroid Build Coastguard Worker 
364*8975f5c5SAndroid Build Coastguard Worker             glDispatchCompute(1, 1, 1);
365*8975f5c5SAndroid Build Coastguard Worker             glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
366*8975f5c5SAndroid Build Coastguard Worker             EXPECT_GL_NO_ERROR();
367*8975f5c5SAndroid Build Coastguard Worker 
368*8975f5c5SAndroid Build Coastguard Worker             GLuint outputValue;
369*8975f5c5SAndroid Build Coastguard Worker             GLFramebuffer framebuffer;
370*8975f5c5SAndroid Build Coastguard Worker             glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
371*8975f5c5SAndroid Build Coastguard Worker             glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
372*8975f5c5SAndroid Build Coastguard Worker                                    texture[2], 0);
373*8975f5c5SAndroid Build Coastguard Worker             glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);
374*8975f5c5SAndroid Build Coastguard Worker             EXPECT_GL_NO_ERROR();
375*8975f5c5SAndroid Build Coastguard Worker 
376*8975f5c5SAndroid Build Coastguard Worker             EXPECT_EQ(300u, outputValue);
377*8975f5c5SAndroid Build Coastguard Worker 
378*8975f5c5SAndroid Build Coastguard Worker             glUseProgram(0);
379*8975f5c5SAndroid Build Coastguard Worker             glDeleteProgram(mProgram);
380*8975f5c5SAndroid Build Coastguard Worker             ASSERT_GL_NO_ERROR();
381*8975f5c5SAndroid Build Coastguard Worker         }
382*8975f5c5SAndroid Build Coastguard Worker 
383*8975f5c5SAndroid Build Coastguard Worker       private:
384*8975f5c5SAndroid Build Coastguard Worker         GLuint mShader;
385*8975f5c5SAndroid Build Coastguard Worker     };
386*8975f5c5SAndroid Build Coastguard Worker };
387*8975f5c5SAndroid Build Coastguard Worker 
388*8975f5c5SAndroid Build Coastguard Worker // Test basic functionality of GL_KHR_parallel_shader_compile
TEST_P(ParallelShaderCompileTest,Basic)389*8975f5c5SAndroid Build Coastguard Worker TEST_P(ParallelShaderCompileTest, Basic)
390*8975f5c5SAndroid Build Coastguard Worker {
391*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!ensureParallelShaderCompileExtensionAvailable());
392*8975f5c5SAndroid Build Coastguard Worker 
393*8975f5c5SAndroid Build Coastguard Worker     GLint count = 0;
394*8975f5c5SAndroid Build Coastguard Worker     glMaxShaderCompilerThreadsKHR(8);
395*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
396*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_SHADER_COMPILER_THREADS_KHR, &count);
397*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
398*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(8, count);
399*8975f5c5SAndroid Build Coastguard Worker }
400*8975f5c5SAndroid Build Coastguard Worker 
401*8975f5c5SAndroid Build Coastguard Worker // Test to compile and link many programs in parallel.
TEST_P(ParallelShaderCompileTest,LinkAndDrawManyPrograms)402*8975f5c5SAndroid Build Coastguard Worker TEST_P(ParallelShaderCompileTest, LinkAndDrawManyPrograms)
403*8975f5c5SAndroid Build Coastguard Worker {
404*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!ensureParallelShaderCompileExtensionAvailable());
405*8975f5c5SAndroid Build Coastguard Worker 
406*8975f5c5SAndroid Build Coastguard Worker     TaskRunner<ClearColorWithDraw> runner;
407*8975f5c5SAndroid Build Coastguard Worker     runner.run(this, kPollInterval);
408*8975f5c5SAndroid Build Coastguard Worker }
409*8975f5c5SAndroid Build Coastguard Worker 
410*8975f5c5SAndroid Build Coastguard Worker // Tests no crash in case that the Shader starts another compile while the Program being attached
411*8975f5c5SAndroid Build Coastguard Worker // to is still linking.
412*8975f5c5SAndroid Build Coastguard Worker // crbug.com/1317673
TEST_P(ParallelShaderCompileTest,LinkProgramAndRecompileShader)413*8975f5c5SAndroid Build Coastguard Worker TEST_P(ParallelShaderCompileTest, LinkProgramAndRecompileShader)
414*8975f5c5SAndroid Build Coastguard Worker {
415*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!ensureParallelShaderCompileExtensionAvailable());
416*8975f5c5SAndroid Build Coastguard Worker 
417*8975f5c5SAndroid Build Coastguard Worker     TaskRunner<ClearColorWithDrawRecompile> runner;
418*8975f5c5SAndroid Build Coastguard Worker     runner.run(this, 0);
419*8975f5c5SAndroid Build Coastguard Worker }
420*8975f5c5SAndroid Build Coastguard Worker 
421*8975f5c5SAndroid Build Coastguard Worker class ParallelShaderCompileTestES31 : public ParallelShaderCompileTest
422*8975f5c5SAndroid Build Coastguard Worker {};
423*8975f5c5SAndroid Build Coastguard Worker 
424*8975f5c5SAndroid Build Coastguard Worker // Test to compile and link many computing programs in parallel.
TEST_P(ParallelShaderCompileTestES31,LinkAndDispatchManyPrograms)425*8975f5c5SAndroid Build Coastguard Worker TEST_P(ParallelShaderCompileTestES31, LinkAndDispatchManyPrograms)
426*8975f5c5SAndroid Build Coastguard Worker {
427*8975f5c5SAndroid Build Coastguard Worker     // Flaky on Win NVIDIA D3D11. http://anglebug.com/40096580
428*8975f5c5SAndroid Build Coastguard Worker     // Suspectable to the flakyness of http://anglebug.com/40096579.
429*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11());
430*8975f5c5SAndroid Build Coastguard Worker 
431*8975f5c5SAndroid Build Coastguard Worker     // TODO(http://anglebug.com/42264192): Fails on Linux+Intel+OpenGL
432*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsOpenGL());
433*8975f5c5SAndroid Build Coastguard Worker 
434*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!ensureParallelShaderCompileExtensionAvailable());
435*8975f5c5SAndroid Build Coastguard Worker 
436*8975f5c5SAndroid Build Coastguard Worker     TaskRunner<ImageLoadStore> runner;
437*8975f5c5SAndroid Build Coastguard Worker     runner.run(this, kPollInterval);
438*8975f5c5SAndroid Build Coastguard Worker }
439*8975f5c5SAndroid Build Coastguard Worker 
440*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES2(ParallelShaderCompileTest);
441*8975f5c5SAndroid Build Coastguard Worker 
442*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ParallelShaderCompileTestES31);
443*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES31(ParallelShaderCompileTestES31);
444*8975f5c5SAndroid Build Coastguard Worker 
445*8975f5c5SAndroid Build Coastguard Worker }  // namespace
446