• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2022 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 #include <regex>
8 #include <sstream>
9 #include <string>
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12 
13 using namespace angle;
14 
15 #define ASSERT_GL_INTEGER(pname, expected) \
16     {                                      \
17         GLint value;                       \
18         glGetIntegerv(pname, &value);      \
19         ASSERT_EQ(value, GLint(expected)); \
20     }
21 
22 #define EXPECT_GL_INTEGER(pname, expected) \
23     {                                      \
24         GLint value;                       \
25         glGetIntegerv(pname, &value);      \
26         EXPECT_EQ(value, GLint(expected)); \
27     }
28 
29 #define EXPECT_PLS_INTEGER(plane, pname, expected)                                                 \
30     {                                                                                              \
31         GLint value = 0xbaadc0de;                                                                  \
32         glGetFramebufferPixelLocalStorageParameterivRobustANGLE(plane, pname, 1, nullptr, &value); \
33         EXPECT_EQ(value, GLint(expected));                                                         \
34         value = 0xbaadc0de;                                                                        \
35         glGetFramebufferPixelLocalStorageParameterivANGLE(plane, pname, &value);                   \
36         EXPECT_EQ(value, GLint(expected));                                                         \
37     }
38 
39 #define EXPECT_GL_SINGLE_ERROR(err)                \
40     EXPECT_GL_ERROR(err);                          \
41     while (GLenum nextError = glGetError())        \
42     {                                              \
43         EXPECT_EQ(nextError, GLenum(GL_NO_ERROR)); \
44     }
45 
46 #define EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(plane, rgba)                             \
47     {                                                                                 \
48         std::array<GLfloat, 4> expected rgba;                                         \
49         std::array<GLfloat, 4> value;                                                 \
50         value.fill(std::numeric_limits<GLfloat>::quiet_NaN());                        \
51         glGetFramebufferPixelLocalStorageParameterfvANGLE(                            \
52             plane, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, value.data());             \
53         EXPECT_EQ(value, expected);                                                   \
54         value.fill(std::numeric_limits<GLfloat>::quiet_NaN());                        \
55         glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(                      \
56             plane, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, 4, nullptr, value.data()); \
57         EXPECT_EQ(value, expected);                                                   \
58     }
59 
60 #define EXPECT_PIXEL_LOCAL_CLEAR_VALUE_INT(plane, rgba)                             \
61     {                                                                               \
62         std::array<GLint, 4> expected rgba;                                         \
63         std::array<GLint, 4> value;                                                 \
64         value.fill(0xbaadc0de);                                                     \
65         glGetFramebufferPixelLocalStorageParameterivANGLE(                          \
66             plane, GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE, value.data());             \
67         EXPECT_EQ(value, expected);                                                 \
68         value.fill(0xbaadc0de);                                                     \
69         glGetFramebufferPixelLocalStorageParameterivRobustANGLE(                    \
70             plane, GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE, 4, nullptr, value.data()); \
71         EXPECT_EQ(value, expected);                                                 \
72     }
73 
74 #define EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(plane, rgba)                              \
75     {                                                                                         \
76         std::array<GLuint, 4> expected rgba;                                                  \
77         std::array<GLuint, 4> value;                                                          \
78         std::array<GLint, 4> valuei;                                                          \
79         valuei.fill(0xbaadc0de);                                                              \
80         glGetFramebufferPixelLocalStorageParameterivANGLE(                                    \
81             plane, GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE, valuei.data());             \
82         memcpy(value.data(), valuei.data(), sizeof(value));                                   \
83         EXPECT_EQ(value, expected);                                                           \
84         valuei.fill(0xbaadc0de);                                                              \
85         glGetFramebufferPixelLocalStorageParameterivRobustANGLE(                              \
86             plane, GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE, 4, nullptr, valuei.data()); \
87         memcpy(value.data(), valuei.data(), sizeof(value));                                   \
88         EXPECT_EQ(value, expected);                                                           \
89     }
90 
91 #define EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(framebuffer, attachment, value)                    \
92     {                                                                                         \
93         GLint attachmentName = 0xbaadc0de;                                                    \
94         glGetFramebufferAttachmentParameteriv(                                                \
95             framebuffer, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &attachmentName); \
96         EXPECT_EQ(attachmentName, static_cast<GLint>(value));                                 \
97     }
98 
99 constexpr static int W = 128, H = 128;
100 constexpr static std::array<float, 4> FULLSCREEN = {0, 0, W, H};
101 
102 // For building the <loadops> parameter of glBeginPixelLocalStorageANGLE.
103 template <typename T>
104 struct Array
105 {
ArrayArray106     Array(const std::initializer_list<T> &list) : mVec(list) {}
operator const T*Array107     operator const T *() const { return mVec.data(); }
108     std::vector<T> mVec;
109 };
110 
111 template <typename T>
MakeArray(const std::initializer_list<T> & list)112 static Array<T> MakeArray(const std::initializer_list<T> &list)
113 {
114     return Array<T>(list);
115 }
116 
GLenumArray(const std::initializer_list<GLenum> & list)117 static Array<GLenum> GLenumArray(const std::initializer_list<GLenum> &list)
118 {
119     return Array<GLenum>(list);
120 }
121 
ClearF(GLfloat r,GLfloat g,GLfloat b,GLfloat a)122 static Array<GLfloat> ClearF(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
123 {
124     return MakeArray({r, g, b, a});
125 }
126 
ClearI(GLint r,GLint g,GLint b,GLint a)127 static Array<GLint> ClearI(GLint r, GLint g, GLint b, GLint a)
128 {
129     return MakeArray({r, g, b, a});
130 }
131 
ClearUI(GLuint r,GLuint g,GLuint b,GLuint a)132 static Array<GLuint> ClearUI(GLuint r, GLuint g, GLuint b, GLuint a)
133 {
134     return MakeArray({r, g, b, a});
135 }
136 
137 class PLSTestTexture
138 {
139   public:
PLSTestTexture(GLenum internalformat)140     PLSTestTexture(GLenum internalformat) { reset(internalformat); }
PLSTestTexture(GLenum internalformat,int w,int h)141     PLSTestTexture(GLenum internalformat, int w, int h) { reset(internalformat, w, h); }
PLSTestTexture(PLSTestTexture && that)142     PLSTestTexture(PLSTestTexture &&that) : mID(std::exchange(that.mID, 0)) {}
reset()143     void reset()
144     {
145         glDeleteTextures(1, &mID);
146         mID = 0;
147     }
reset(GLenum internalformat)148     void reset(GLenum internalformat) { reset(internalformat, W, H); }
reset(GLenum internalformat,int w,int h)149     void reset(GLenum internalformat, int w, int h)
150     {
151         GLuint id;
152         glGenTextures(1, &id);
153         glBindTexture(GL_TEXTURE_2D, id);
154         glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, w, h);
155         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
156         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
157         if (mID)
158         {
159             glDeleteTextures(1, &mID);
160         }
161         mID = id;
162     }
~PLSTestTexture()163     ~PLSTestTexture()
164     {
165         if (mID)
166         {
167             glDeleteTextures(1, &mID);
168         }
169     }
operator GLuint() const170     operator GLuint() const { return mID; }
171 
172   private:
173     PLSTestTexture &operator=(const PLSTestTexture &) = delete;
174     PLSTestTexture(const PLSTestTexture &)            = delete;
175     GLuint mID                                        = 0;
176 };
177 
178 struct Box
179 {
180     using float4 = std::array<float, 4>;
BoxBox181     constexpr Box(float4 rect) : rect(rect), color{}, aux1{}, aux2{} {}
BoxBox182     constexpr Box(float4 rect, float4 incolor) : rect(rect), color(incolor), aux1{}, aux2{} {}
BoxBox183     constexpr Box(float4 rect, float4 incolor, float4 inaux1)
184         : rect(rect), color(incolor), aux1(inaux1), aux2{}
185     {}
BoxBox186     constexpr Box(float4 rect, float4 incolor, float4 inaux1, float4 inaux2)
187         : rect(rect), color(incolor), aux1(inaux1), aux2(inaux2)
188     {}
189     float4 rect;
190     float4 color;
191     float4 aux1;
192     float4 aux2;
193 };
194 
195 enum class UseBarriers : bool
196 {
197     No = false,
198     IfNotCoherent
199 };
200 
201 class PLSProgram
202 {
203   public:
204     enum class VertexArray
205     {
206         Default,
207         VAO
208     };
209 
PLSProgram(VertexArray vertexArray=VertexArray::VAO)210     PLSProgram(VertexArray vertexArray = VertexArray::VAO)
211     {
212         if (vertexArray == VertexArray::VAO)
213         {
214             glGenVertexArrays(1, &mVertexArray);
215             glGenBuffers(1, &mVertexBuffer);
216         }
217     }
218 
~PLSProgram()219     ~PLSProgram() { reset(); }
220 
reset()221     void reset()
222     {
223         if (mVertexArray != 0)
224         {
225             glDeleteVertexArrays(1, &mVertexArray);
226             mVertexArray = 0;
227         }
228         if (mVertexBuffer != 0)
229         {
230             glDeleteBuffers(1, &mVertexBuffer);
231             mVertexBuffer = 0;
232         }
233     }
234 
widthUniform() const235     int widthUniform() const { return mWidthUniform; }
heightUniform() const236     int heightUniform() const { return mHeightUniform; }
237 
compile(std::string fsMain)238     void compile(std::string fsMain) { compile("", fsMain); }
239 
compile(std::string extensions,std::string fsMain)240     void compile(std::string extensions, std::string fsMain)
241     {
242         glBindVertexArray(mVertexArray);
243         glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
244 
245         if (mVertexArray == 0)
246         {
247             if (mLTRBLocation >= 0)
248             {
249                 glDisableVertexAttribArray(mLTRBLocation);
250             }
251             if (mRGBALocation >= 0)
252             {
253                 glDisableVertexAttribArray(mRGBALocation);
254             }
255             if (mAux1Location >= 0)
256             {
257                 glDisableVertexAttribArray(mAux1Location);
258             }
259             if (mAux2Location >= 0)
260             {
261                 glDisableVertexAttribArray(mAux2Location);
262             }
263         }
264 
265         mProgram.makeRaster(
266             R"(#version 300 es
267             precision highp float;
268 
269             uniform float W, H;
270             in vec4 rect;
271             in vec4 incolor;
272             in vec4 inaux1;
273             in vec4 inaux2;
274             out vec4 color;
275             out vec4 aux1;
276             out vec4 aux2;
277 
278             void main()
279             {
280                 color = incolor;
281                 aux1 = inaux1;
282                 aux2 = inaux2;
283                 gl_Position.x = ((gl_VertexID & 1) == 0 ? rect.x : rect.z) * 2.0/W - 1.0;
284                 gl_Position.y = ((gl_VertexID & 2) == 0 ? rect.y : rect.w) * 2.0/H - 1.0;
285                 gl_Position.zw = vec2(0, 1);
286             })",
287 
288             std::string(R"(#version 300 es
289             #extension GL_ANGLE_shader_pixel_local_storage : require
290             )")
291                 .append(extensions)
292                 .append(R"(
293             precision highp float;
294             in vec4 color;
295             in vec4 aux1;
296             in vec4 aux2;)")
297                 .append(fsMain)
298                 .c_str());
299 
300         EXPECT_TRUE(mProgram.valid());
301 
302         glUseProgram(mProgram);
303 
304         mWidthUniform = glGetUniformLocation(mProgram, "W");
305         glUniform1f(mWidthUniform, W);
306 
307         mHeightUniform = glGetUniformLocation(mProgram, "H");
308         glUniform1f(mHeightUniform, H);
309 
310         mLTRBLocation = glGetAttribLocation(mProgram, "rect");
311         glEnableVertexAttribArray(mLTRBLocation);
312         glVertexAttribDivisor(mLTRBLocation, 1);
313 
314         mRGBALocation = glGetAttribLocation(mProgram, "incolor");
315         glEnableVertexAttribArray(mRGBALocation);
316         glVertexAttribDivisor(mRGBALocation, 1);
317 
318         mAux1Location = glGetAttribLocation(mProgram, "inaux1");
319         glEnableVertexAttribArray(mAux1Location);
320         glVertexAttribDivisor(mAux1Location, 1);
321 
322         mAux2Location = glGetAttribLocation(mProgram, "inaux2");
323         glEnableVertexAttribArray(mAux2Location);
324         glVertexAttribDivisor(mAux2Location, 1);
325     }
326 
get() const327     GLuint get() const { return mProgram; }
operator GLuint()328     operator GLuint() { return get(); }
operator GLuint() const329     operator GLuint() const { return get(); }
330 
bind()331     void bind()
332     {
333         glUseProgram(mProgram);
334         glBindVertexArray(mVertexArray);
335         glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
336     }
337 
drawBoxes(std::vector<Box> boxes,UseBarriers useBarriers=UseBarriers::IfNotCoherent)338     void drawBoxes(std::vector<Box> boxes, UseBarriers useBarriers = UseBarriers::IfNotCoherent)
339     {
340         uintptr_t base;
341         if (mVertexBuffer == 0)
342         {
343             base = reinterpret_cast<uintptr_t>(boxes.data());
344         }
345         else
346         {
347             glBufferData(GL_ARRAY_BUFFER, boxes.size() * sizeof(Box), boxes.data(), GL_STATIC_DRAW);
348             base = 0;
349         }
350         if (useBarriers == UseBarriers::IfNotCoherent &&
351             !IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent"))
352         {
353             for (size_t i = 0; i < boxes.size(); ++i)
354             {
355                 glVertexAttribPointer(
356                     mLTRBLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Box),
357                     reinterpret_cast<void *>(base + i * sizeof(Box) + offsetof(Box, rect)));
358                 glVertexAttribPointer(
359                     mRGBALocation, 4, GL_FLOAT, GL_FALSE, sizeof(Box),
360                     reinterpret_cast<void *>(base + i * sizeof(Box) + offsetof(Box, color)));
361                 glVertexAttribPointer(
362                     mAux1Location, 4, GL_FLOAT, GL_FALSE, sizeof(Box),
363                     reinterpret_cast<void *>(base + i * sizeof(Box) + offsetof(Box, aux1)));
364                 glVertexAttribPointer(
365                     mAux2Location, 4, GL_FLOAT, GL_FALSE, sizeof(Box),
366                     reinterpret_cast<void *>(base + i * sizeof(Box) + offsetof(Box, aux2)));
367                 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
368                 glPixelLocalStorageBarrierANGLE();
369             }
370         }
371         else
372         {
373             glVertexAttribPointer(mLTRBLocation, 4, GL_FLOAT, GL_FALSE, sizeof(Box),
374                                   reinterpret_cast<void *>(base + offsetof(Box, rect)));
375             glVertexAttribPointer(mRGBALocation, 4, GL_FLOAT, GL_FALSE, sizeof(Box),
376                                   reinterpret_cast<void *>(base + offsetof(Box, color)));
377             glVertexAttribPointer(mAux1Location, 4, GL_FLOAT, GL_FALSE, sizeof(Box),
378                                   reinterpret_cast<void *>(base + offsetof(Box, aux1)));
379             glVertexAttribPointer(mAux2Location, 4, GL_FLOAT, GL_FALSE, sizeof(Box),
380                                   reinterpret_cast<void *>(base + offsetof(Box, aux2)));
381             glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, boxes.size());
382         }
383     }
384 
385   private:
386     GLProgram mProgram;
387     GLuint mVertexArray  = 0;
388     GLuint mVertexBuffer = 0;
389 
390     GLint mWidthUniform  = -1;
391     GLint mHeightUniform = -1;
392 
393     GLint mLTRBLocation = -1;
394     GLint mRGBALocation = -1;
395     GLint mAux1Location = -1;
396     GLint mAux2Location = -1;
397 };
398 
399 class ShaderInfoLog
400 {
401   public:
compileFragmentShader(const char * source)402     bool compileFragmentShader(const char *source)
403     {
404         return compileShader(source, GL_FRAGMENT_SHADER);
405     }
406 
compileShader(const char * source,GLenum shaderType)407     bool compileShader(const char *source, GLenum shaderType)
408     {
409         mInfoLog.clear();
410 
411         GLuint shader = glCreateShader(shaderType);
412         glShaderSource(shader, 1, &source, nullptr);
413         glCompileShader(shader);
414 
415         GLint compileResult;
416         glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
417 
418         if (compileResult == 0)
419         {
420             GLint infoLogLength;
421             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
422             // Info log length includes the null terminator; std::string::reserve does not.
423             mInfoLog.resize(std::max(infoLogLength - 1, 0));
424             glGetShaderInfoLog(shader, infoLogLength, nullptr, mInfoLog.data());
425         }
426 
427         glDeleteShader(shader);
428         return compileResult != 0;
429     }
430 
has(const char * subStr) const431     bool has(const char *subStr) const { return strstr(mInfoLog.c_str(), subStr); }
432 
433   private:
434     std::string mInfoLog;
435 };
436 
437 class PixelLocalStorageTest : public ANGLETest<>
438 {
439   public:
PixelLocalStorageTest()440     PixelLocalStorageTest()
441     {
442         setWindowWidth(W);
443         setWindowHeight(H);
444         setConfigRedBits(8);
445         setConfigGreenBits(8);
446         setConfigBlueBits(8);
447         setConfigAlphaBits(8);
448         setExtensionsEnabled(false);
449     }
450 
testTearDown()451     void testTearDown() override
452     {
453         mProgram.reset();
454         mRenderTextureProgram.reset();
455         if (mScratchFBO)
456         {
457             glDeleteFramebuffers(1, &mScratchFBO);
458         }
459     }
460 
testSetUp()461     void testSetUp() override
462     {
463         if (EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"))
464         {
465             glGetIntegerv(GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE, &MAX_PIXEL_LOCAL_STORAGE_PLANES);
466             glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE,
467                           &MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE);
468             glGetIntegerv(GL_MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE,
469                           &MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES);
470             glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &MAX_COLOR_ATTACHMENTS);
471             glGetIntegerv(GL_MAX_DRAW_BUFFERS, &MAX_DRAW_BUFFERS);
472         }
473 
474         // INVALID_OPERATION is generated if DITHER is enabled.
475         glDisable(GL_DITHER);
476 
477         ANGLETest::testSetUp();
478     }
479 
isContextVersionAtLeast(int major,int minor)480     int isContextVersionAtLeast(int major, int minor)
481     {
482         return getClientMajorVersion() > major ||
483                (getClientMajorVersion() == major && getClientMinorVersion() >= minor);
484     }
485 
attachTexture2DToScratchFBO(GLuint tex,GLint level=0)486     void attachTexture2DToScratchFBO(GLuint tex, GLint level = 0)
487     {
488         if (!mScratchFBO)
489         {
490             glGenFramebuffers(1, &mScratchFBO);
491         }
492         glBindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
493         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, level);
494         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
495     }
496 
attachTextureLayerToScratchFBO(GLuint tex,int level,int layer)497     void attachTextureLayerToScratchFBO(GLuint tex, int level, int layer)
498     {
499         if (!mScratchFBO)
500         {
501             glGenFramebuffers(1, &mScratchFBO);
502         }
503         glBindFramebuffer(GL_FRAMEBUFFER, mScratchFBO);
504         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, level, layer);
505         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
506     }
507 
508     // Access texture contents by rendering them into FBO 0, rather than just grabbing them with
509     // glReadPixels.
renderTextureToDefaultFramebuffer(GLuint tex)510     void renderTextureToDefaultFramebuffer(GLuint tex)
511     {
512         glBindFramebuffer(GL_FRAMEBUFFER, 0);
513         // Reset the framebuffer contents to some value that might help debugging.
514         glClearColor(.1f, .4f, .6f, .9f);
515         glClear(GL_COLOR_BUFFER_BIT);
516 
517         GLint linked = 0;
518         glGetProgramiv(mRenderTextureProgram, GL_LINK_STATUS, &linked);
519         if (!linked)
520         {
521             constexpr char kVS[] =
522                 R"(#version 300 es
523                 precision highp float;
524                 out vec2 texcoord;
525                 void main()
526                 {
527                     texcoord.x = (gl_VertexID & 1) == 0 ? 0.0 : 1.0;
528                     texcoord.y = (gl_VertexID & 2) == 0 ? 0.0 : 1.0;
529                     gl_Position = vec4(texcoord * 2.0 - 1.0, 0, 1);
530                 })";
531 
532             constexpr char kFS[] =
533                 R"(#version 300 es
534                 precision highp float;
535                 uniform highp sampler2D tex;  // FIXME! layout(binding=0) causes an ANGLE crash!
536                 in vec2 texcoord;
537                 out vec4 fragcolor;
538                 void main()
539                 {
540                     fragcolor = texture(tex, texcoord);
541                 })";
542 
543             mRenderTextureProgram.makeRaster(kVS, kFS);
544             ASSERT_TRUE(mRenderTextureProgram.valid());
545             glUseProgram(mRenderTextureProgram);
546             glUniform1i(glGetUniformLocation(mRenderTextureProgram, "tex"), 0);
547         }
548 
549         glUseProgram(mRenderTextureProgram);
550         glBindTexture(GL_TEXTURE_2D, tex);
551         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
552     }
553 
554     // Implemented as a class members so we can run the test on ES3 and ES31 both.
555     void doStateRestorationTest();
556     void doDrawStateTest();
557 
558     GLint MAX_PIXEL_LOCAL_STORAGE_PLANES                           = 0;
559     GLint MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE    = 0;
560     GLint MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES = 0;
561     GLint MAX_COLOR_ATTACHMENTS                                    = 0;
562     GLint MAX_DRAW_BUFFERS                                         = 0;
563 
564     PLSProgram mProgram{PLSProgram::VertexArray::Default};
565 
566     GLuint mScratchFBO = 0;
567     GLProgram mRenderTextureProgram;
568 };
569 
570 // Verify conformant implementation-dependent PLS limits.
TEST_P(PixelLocalStorageTest,ImplementationDependentLimits)571 TEST_P(PixelLocalStorageTest, ImplementationDependentLimits)
572 {
573     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
574 
575     // Table 6.X: Impementation Dependent Pixel Local Storage Limits.
576     EXPECT_TRUE(MAX_PIXEL_LOCAL_STORAGE_PLANES >= 4);
577     EXPECT_TRUE(MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE >= 0);
578     EXPECT_TRUE(MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES >= 4);
579 
580     // Logical deductions based on 6.X.
581     EXPECT_TRUE(MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES >=
582                 MAX_PIXEL_LOCAL_STORAGE_PLANES);
583     EXPECT_TRUE(MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES >=
584                 MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE);
585     EXPECT_TRUE(MAX_COLOR_ATTACHMENTS + MAX_PIXEL_LOCAL_STORAGE_PLANES >=
586                 MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES);
587     EXPECT_TRUE(MAX_DRAW_BUFFERS + MAX_PIXEL_LOCAL_STORAGE_PLANES >=
588                 MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES);
589 }
590 
591 // Verify that rgba8, rgba8i, and rgba8ui pixel local storage behaves as specified.
TEST_P(PixelLocalStorageTest,RGBA8)592 TEST_P(PixelLocalStorageTest, RGBA8)
593 {
594     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
595 
596     mProgram.compile(R"(
597         layout(binding=0, rgba8) uniform lowp pixelLocalANGLE plane1;
598         layout(rgba8i, binding=1) uniform lowp ipixelLocalANGLE plane2;
599         layout(binding=2, rgba8ui) uniform lowp upixelLocalANGLE plane3;
600         void main()
601         {
602             pixelLocalStoreANGLE(plane1, color + pixelLocalLoadANGLE(plane1));
603             pixelLocalStoreANGLE(plane2, ivec4(aux1) + pixelLocalLoadANGLE(plane2));
604             pixelLocalStoreANGLE(plane3, uvec4(aux2) + pixelLocalLoadANGLE(plane3));
605         })");
606 
607     PLSTestTexture tex1(GL_RGBA8);
608     PLSTestTexture tex2(GL_RGBA8I);
609     PLSTestTexture tex3(GL_RGBA8UI);
610 
611     GLFramebuffer fbo;
612     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
613     glFramebufferTexturePixelLocalStorageANGLE(0, tex1, 0, 0);
614     glFramebufferTexturePixelLocalStorageANGLE(1, tex2, 0, 0);
615     glFramebufferTexturePixelLocalStorageANGLE(2, tex3, 0, 0);
616     glViewport(0, 0, W, H);
617     glDrawBuffers(0, nullptr);
618 
619     glBeginPixelLocalStorageANGLE(
620         3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE}));
621 
622     // Accumulate R, G, B, A in 4 separate passes.
623     // Store out-of-range values to ensure they are properly clamped upon storage.
624     mProgram.drawBoxes({{FULLSCREEN, {2, -1, -2, -3}, {-500, 0, 0, 0}, {1, 0, 0, 0}},
625                         {FULLSCREEN, {0, 1, 0, 100}, {0, -129, 0, 0}, {0, 50, 0, 0}},
626                         {FULLSCREEN, {0, 0, 1, 0}, {0, 0, -70, 0}, {0, 0, 100, 0}},
627                         {FULLSCREEN, {0, 0, 0, -1}, {128, 0, 0, 500}, {0, 0, 0, 300}}});
628 
629     glEndPixelLocalStorageANGLE(3, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE,
630                                                 GL_STORE_OP_STORE_ANGLE}));
631 
632     attachTexture2DToScratchFBO(tex1);
633     EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor(255, 255, 255, 0));
634 
635     attachTexture2DToScratchFBO(tex2);
636     EXPECT_PIXEL_RECT32I_EQ(0, 0, W, H, GLColor32I(0, -128, -70, 127));
637 
638     attachTexture2DToScratchFBO(tex3);
639     EXPECT_PIXEL_RECT32UI_EQ(0, 0, W, H, GLColor32UI(1, 50, 100, 255));
640 
641     ASSERT_GL_NO_ERROR();
642 }
643 
644 // Verify that r32f and r32ui pixel local storage behaves as specified.
TEST_P(PixelLocalStorageTest,R32)645 TEST_P(PixelLocalStorageTest, R32)
646 {
647     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
648 
649     mProgram.compile(R"(
650         layout(r32f, binding=0) uniform highp pixelLocalANGLE plane1;
651         layout(binding=1, r32ui) uniform highp upixelLocalANGLE plane2;
652         void main()
653         {
654             pixelLocalStoreANGLE(plane1, color + pixelLocalLoadANGLE(plane1));
655             pixelLocalStoreANGLE(plane2, uvec4(aux1) + pixelLocalLoadANGLE(plane2));
656         })");
657 
658     PLSTestTexture tex1(GL_R32F);
659     PLSTestTexture tex2(GL_R32UI);
660 
661     GLFramebuffer fbo;
662     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
663     glFramebufferTexturePixelLocalStorageANGLE(0, tex1, 0, 0);
664     glFramebufferTexturePixelLocalStorageANGLE(1, tex2, 0, 0);
665     glViewport(0, 0, W, H);
666     glDrawBuffers(0, nullptr);
667 
668     glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE}));
669 
670     // Accumulate R in 4 separate passes.
671     mProgram.drawBoxes({{FULLSCREEN, {-1.5, 0, 0, 0}, {0x000000ff, 0, 0, 0}},
672                         {FULLSCREEN, {-10.25, 0, 0, 0}, {0x0000ff00, 0, 0, 0}},
673                         {FULLSCREEN, {-100, 0, 0, 0}, {0x00ff0000, 0, 0, 0}},
674                         {FULLSCREEN, {.25, 0, 0, 0}, {0xff000000, 0, 0, 22}}});
675 
676     glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE}));
677 
678     // These values should be exact matches.
679     //
680     // GL_R32F is spec'd as a 32-bit IEEE float, and GL_R32UI is a 32-bit unsigned integer.
681     // There is some affordance for fp32 fused operations, but "a + b" is required to be
682     // correctly rounded.
683     //
684     // From the GLSL ES 3.0 spec:
685     //
686     //   "Highp unsigned integers have exactly 32 bits of precision. Highp signed integers use
687     //    32 bits, including a sign bit, in two's complement form."
688     //
689     //   "Highp floating-point variables within a shader are encoded according to the IEEE 754
690     //    specification for single-precision floating-point values (logically, not necessarily
691     //    physically)."
692     //
693     //   "Operation: a + b, a - b, a * b
694     //    Precision: Correctly rounded."
695     attachTexture2DToScratchFBO(tex1);
696     EXPECT_PIXEL_RECT32F_EQ(0, 0, W, H, GLColor32F(-111.5, 0, 0, 1));
697 
698     attachTexture2DToScratchFBO(tex2);
699     EXPECT_PIXEL_RECT32UI_EQ(0, 0, W, H, GLColor32UI(0xffffffff, 0, 0, 1));
700 
701     ASSERT_GL_NO_ERROR();
702 }
703 
704 // Check proper functioning of the clear value state.
TEST_P(PixelLocalStorageTest,ClearValues_rgba8)705 TEST_P(PixelLocalStorageTest, ClearValues_rgba8)
706 {
707     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
708 
709     PLSTestTexture tex8f(GL_RGBA8, 1, 1);
710     PLSTestTexture tex8i(GL_RGBA8I, 1, 1);
711     PLSTestTexture tex8ui(GL_RGBA8UI, 1, 1);
712 
713     GLFramebuffer fbo;
714     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
715     glFramebufferTexturePixelLocalStorageANGLE(0, tex8f, 0, 0);
716     glFramebufferTexturePixelLocalStorageANGLE(1, tex8i, 0, 0);
717     glFramebufferTexturePixelLocalStorageANGLE(2, tex8ui, 0, 0);
718     auto clearLoads =
719         GLenumArray({GL_LOAD_OP_CLEAR_ANGLE, GL_LOAD_OP_CLEAR_ANGLE, GL_LOAD_OP_CLEAR_ANGLE});
720     auto storeStores =
721         GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE});
722 
723     // Clear values are initially zero.
724     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(0, ({0, 0, 0, 0}));
725     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_INT(1, ({0, 0, 0, 0}));
726     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(2, ({0, 0, 0, 0}));
727     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
728     glBeginPixelLocalStorageANGLE(3, clearLoads);
729     glEndPixelLocalStorageANGLE(3, storeStores);
730     attachTexture2DToScratchFBO(tex8f);
731     EXPECT_PIXEL_RECT_EQ(0, 0, 1, 1, GLColor(0, 0, 0, 0));
732     attachTexture2DToScratchFBO(tex8i);
733     EXPECT_PIXEL_RECT32I_EQ(0, 0, 1, 1, GLColor32I(0, 0, 0, 0));
734     attachTexture2DToScratchFBO(tex8ui);
735     EXPECT_PIXEL_RECT32UI_EQ(0, 0, 1, 1, GLColor32UI(0, 0, 0, 0));
736 
737     // Test custom RGBA8 clear values.
738     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
739     glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(100.5, 0, 0, 0));
740     glFramebufferPixelLocalClearValueivANGLE(1, ClearI(-1, 2, -3, 4));
741     glFramebufferPixelLocalClearValueuivANGLE(2, ClearUI(5, 6, 7, 8));
742     glBeginPixelLocalStorageANGLE(3, clearLoads);
743     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(0, ({100.5, 0, 0, 0}));
744     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_INT(1, ({-1, 2, -3, 4}));
745     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(2, ({5, 6, 7, 8}));
746     glEndPixelLocalStorageANGLE(3, storeStores);
747     attachTexture2DToScratchFBO(tex8f);
748     EXPECT_PIXEL_RECT_EQ(0, 0, 1, 1, GLColor(255, 0, 0, 0));
749     attachTexture2DToScratchFBO(tex8i);
750     EXPECT_PIXEL_RECT32I_EQ(0, 0, 1, 1, GLColor32I(-1, 2, -3, 4));
751     attachTexture2DToScratchFBO(tex8ui);
752     EXPECT_PIXEL_RECT32UI_EQ(0, 0, 1, 1, GLColor32UI(5, 6, 7, 8));
753 
754     // Rotate and test again.
755     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
756     glFramebufferTexturePixelLocalStorageANGLE(0, tex8ui, 0, 0);
757     glFramebufferTexturePixelLocalStorageANGLE(1, tex8f, 0, 0);
758     glFramebufferTexturePixelLocalStorageANGLE(2, tex8i, 0, 0);
759     glBeginPixelLocalStorageANGLE(3, clearLoads);
760     // Since each clear value type is separate state, these should all be zero again.
761     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(0, ({0, 0, 0, 0}));
762     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(1, ({0, 0, 0, 0}));
763     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_INT(2, ({0, 0, 0, 0}));
764     glEndPixelLocalStorageANGLE(3, storeStores);
765     attachTexture2DToScratchFBO(tex8ui);
766     EXPECT_PIXEL_RECT32UI_EQ(0, 0, 1, 1, GLColor32UI(0, 0, 0, 0));
767     attachTexture2DToScratchFBO(tex8f);
768     EXPECT_PIXEL_RECT_EQ(0, 0, 1, 1, GLColor(0, 0, 0, 0));
769     attachTexture2DToScratchFBO(tex8i);
770     EXPECT_PIXEL_RECT32I_EQ(0, 0, 1, 1, GLColor32I(0, 0, 0, 0));
771     // If any component of the clear value is larger than can be represented in plane's
772     // internalformat, it is clamped.
773     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
774     glFramebufferPixelLocalClearValueuivANGLE(0, ClearUI(254, 255, 256, 257));
775     glFramebufferPixelLocalClearValuefvANGLE(1, ClearF(-1, 0, 1, 2));
776     glFramebufferPixelLocalClearValueivANGLE(2, ClearI(-129, -128, 127, 128));
777     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(0, ({254, 255, 256, 257}));
778     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(1, ({-1, 0, 1, 2}));
779     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_INT(2, ({-129, -128, 127, 128}));
780     glBeginPixelLocalStorageANGLE(3, clearLoads);
781     glEndPixelLocalStorageANGLE(3, storeStores);
782     attachTexture2DToScratchFBO(tex8ui);
783     EXPECT_PIXEL_RECT32UI_EQ(0, 0, 1, 1, GLColor32UI(254, 255, 255, 255));
784     attachTexture2DToScratchFBO(tex8f);
785     EXPECT_PIXEL_RECT_EQ(0, 0, 1, 1, GLColor(0, 0, 255, 255));
786     attachTexture2DToScratchFBO(tex8i);
787     EXPECT_PIXEL_RECT32I_EQ(0, 0, 1, 1, GLColor32I(-128, -128, 127, 127));
788 
789     // Final rotation.
790     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
791     glFramebufferTexturePixelLocalStorageANGLE(0, tex8i, 0, 0);
792     glFramebufferTexturePixelLocalStorageANGLE(1, tex8ui, 0, 0);
793     glFramebufferTexturePixelLocalStorageANGLE(2, tex8f, 0, 0);
794     // Since each clear value type is separate state, these should all be zero yet again.
795     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_INT(0, ({0, 0, 0, 0}));
796     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(1, ({0, 0, 0, 0}));
797     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(2, ({0, 0, 0, 0}));
798     glBeginPixelLocalStorageANGLE(3, clearLoads);
799     glEndPixelLocalStorageANGLE(3, storeStores);
800     attachTexture2DToScratchFBO(tex8i);
801     EXPECT_PIXEL_RECT32I_EQ(0, 0, 1, 1, GLColor32I(0, 0, 0, 0));
802     attachTexture2DToScratchFBO(tex8ui);
803     EXPECT_PIXEL_RECT32UI_EQ(0, 0, 1, 1, GLColor32UI(0, 0, 0, 0));
804     attachTexture2DToScratchFBO(tex8f);
805     EXPECT_PIXEL_RECT_EQ(0, 0, 1, 1, GLColor(0, 0, 0, 0));
806     // If any component of the clear value is larger than can be represented in plane's
807     // internalformat, it is clamped.
808     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
809     glFramebufferPixelLocalClearValueivANGLE(0, ClearI(999, 999, -999, -999));
810     glFramebufferPixelLocalClearValueuivANGLE(1, ClearUI(0, 0, 999, 999));
811     glFramebufferPixelLocalClearValuefvANGLE(2, ClearF(999, 999, -999, -999));
812     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_INT(0, ({999, 999, -999, -999}));
813     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(1, ({0, 0, 999, 999}));
814     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(2, ({999, 999, -999, -999}));
815     glBeginPixelLocalStorageANGLE(3, clearLoads);
816     glEndPixelLocalStorageANGLE(3, storeStores);
817     attachTexture2DToScratchFBO(tex8i);
818     EXPECT_PIXEL_RECT32I_EQ(0, 0, 1, 1, GLColor32I(127, 127, -128, -128));
819     attachTexture2DToScratchFBO(tex8ui);
820     EXPECT_PIXEL_RECT32UI_EQ(0, 0, 1, 1, GLColor32UI(0, 0, 255, 255));
821     attachTexture2DToScratchFBO(tex8f);
822     EXPECT_PIXEL_RECT_EQ(0, 0, 1, 1, GLColor(255, 255, 0, 0));
823 
824     // GL_LOAD_OP_ZERO_ANGLE shouldn't be affected by previous clear colors.
825     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
826     glBeginPixelLocalStorageANGLE(
827         3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE}));
828     glEndPixelLocalStorageANGLE(3, storeStores);
829     attachTexture2DToScratchFBO(tex8f);
830     EXPECT_PIXEL_RECT_EQ(0, 0, 1, 1, GLColor(0, 0, 0, 0));
831     attachTexture2DToScratchFBO(tex8i);
832     EXPECT_PIXEL_RECT32I_EQ(0, 0, 1, 1, GLColor32I(0, 0, 0, 0));
833     attachTexture2DToScratchFBO(tex8ui);
834     EXPECT_PIXEL_RECT32UI_EQ(0, 0, 1, 1, GLColor32UI(0, 0, 0, 0));
835 
836     // Cycle back to the original configuration and ensure that clear state hasn't changed.
837     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
838     glFramebufferTexturePixelLocalStorageANGLE(0, tex8f, 0, 0);
839     glFramebufferTexturePixelLocalStorageANGLE(1, tex8i, 0, 0);
840     glFramebufferTexturePixelLocalStorageANGLE(2, tex8ui, 0, 0);
841     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(0, ({100.5f, 0, 0, 0}));
842     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_INT(1, ({-1, 2, -3, 4}));
843     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(2, ({5, 6, 7, 8}));
844     glBeginPixelLocalStorageANGLE(3, clearLoads);
845     glEndPixelLocalStorageANGLE(3, storeStores);
846     attachTexture2DToScratchFBO(tex8f);
847     EXPECT_PIXEL_RECT_EQ(0, 0, 1, 1, GLColor(255, 0, 0, 0));
848     attachTexture2DToScratchFBO(tex8i);
849     EXPECT_PIXEL_RECT32I_EQ(0, 0, 1, 1, GLColor32I(-1, 2, -3, 4));
850     attachTexture2DToScratchFBO(tex8ui);
851     EXPECT_PIXEL_RECT32UI_EQ(0, 0, 1, 1, GLColor32UI(5, 6, 7, 8));
852 
853     // Clear state is specific to the draw framebuffer; clear values on one framebuffer do not
854     // affect clear values on another.
855     GLFramebuffer fbo2;
856     glBindFramebuffer(GL_FRAMEBUFFER, fbo2);
857     glFramebufferTexturePixelLocalStorageANGLE(0, tex8f, 0, 0);
858     glFramebufferTexturePixelLocalStorageANGLE(1, tex8i, 0, 0);
859     glFramebufferTexturePixelLocalStorageANGLE(2, tex8ui, 0, 0);
860     glBeginPixelLocalStorageANGLE(3, clearLoads);
861     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(0, ({0, 0, 0, 0}));
862     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_INT(1, ({0, 0, 0, 0}));
863     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(2, ({0, 0, 0, 0}));
864     glEndPixelLocalStorageANGLE(3, storeStores);
865     attachTexture2DToScratchFBO(tex8f);
866     EXPECT_PIXEL_RECT_EQ(0, 0, 1, 1, GLColor(0, 0, 0, 0));
867     attachTexture2DToScratchFBO(tex8i);
868     EXPECT_PIXEL_RECT32I_EQ(0, 0, 1, 1, GLColor32I(0, 0, 0, 0));
869     attachTexture2DToScratchFBO(tex8ui);
870     EXPECT_PIXEL_RECT32UI_EQ(0, 0, 1, 1, GLColor32UI(0, 0, 0, 0));
871 }
872 
873 // Check clear values for r32f and r32ui PLS format.
TEST_P(PixelLocalStorageTest,ClearValues_r32)874 TEST_P(PixelLocalStorageTest, ClearValues_r32)
875 {
876     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
877 
878     GLFramebuffer fbo;
879     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
880 
881     // Test custom R32 clear values.
882     PLSTestTexture tex32f(GL_R32F);
883     PLSTestTexture tex32ui(GL_R32UI);
884     glFramebufferTexturePixelLocalStorageANGLE(0, tex32f, 0, 0);
885     glFramebufferTexturePixelLocalStorageANGLE(1, tex32ui, 0, 0);
886     glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(100.5, 0, 0, 0));
887     glFramebufferPixelLocalClearValueuivANGLE(1, ClearUI(0xbaadbeef, 1, 1, 0));
888     glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE, GL_LOAD_OP_CLEAR_ANGLE}));
889     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(0, ({100.5f, 0, 0, 0}));
890     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(1, ({0xbaadbeef, 1, 1, 0}));
891     glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE}));
892     attachTexture2DToScratchFBO(tex32f);
893     EXPECT_PIXEL_RECT32F_EQ(0, 0, 1, 1, GLColor32F(100.5f, 0, 0, 1));
894     attachTexture2DToScratchFBO(tex32ui);
895     EXPECT_PIXEL_RECT32UI_EQ(0, 0, 1, 1, GLColor32UI(0xbaadbeef, 0, 0, 1));
896 }
897 
898 // Check proper support of GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_LOAD_ANGLE, and GL_LOAD_OP_CLEAR_ANGLE
899 // loadOps. Also verify that it works do draw with GL_MAX_LOCAL_STORAGE_PLANES_ANGLE planes.
TEST_P(PixelLocalStorageTest,LoadOps)900 TEST_P(PixelLocalStorageTest, LoadOps)
901 {
902     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
903 
904     std::stringstream fs;
905     for (int i = 0; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i)
906     {
907         fs << "layout(binding=" << i << ", rgba8) uniform highp pixelLocalANGLE pls" << i << ";\n";
908     }
909     fs << "void main() {\n";
910     for (int i = 0; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i)
911     {
912         fs << "pixelLocalStoreANGLE(pls" << i << ", color + pixelLocalLoadANGLE(pls" << i
913            << "));\n";
914     }
915     fs << "}";
916     mProgram.compile(fs.str().c_str());
917 
918     // Create pls textures and clear them to red.
919     glClearColor(1, 0, 0, 1);
920     std::vector<PLSTestTexture> texs;
921     for (int i = 0; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i)
922     {
923         texs.emplace_back(GL_RGBA8);
924         attachTexture2DToScratchFBO(texs[i]);
925         glClear(GL_COLOR_BUFFER_BIT);
926     }
927 
928     // Turn on scissor to try and confuse the local storage clear step.
929     glEnable(GL_SCISSOR_TEST);
930     glScissor(0, 0, 20, H);
931 
932     // Set up pls color planes with a clear color of black. Odd units load with
933     // GL_LOAD_OP_CLEAR_ANGLE (cleared to black) and even load with GL_LOAD_OP_LOAD_ANGLE (preserved
934     // red).
935     GLFramebuffer fbo;
936     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
937     std::vector<GLenum> loadOps(MAX_PIXEL_LOCAL_STORAGE_PLANES);
938     for (int i = 0; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i)
939     {
940         glFramebufferTexturePixelLocalStorageANGLE(i, texs[i], 0, 0);
941         glFramebufferPixelLocalClearValuefvANGLE(i, ClearF(0, 0, 0, 1));
942         loadOps[i] = (i & 1) ? GL_LOAD_OP_CLEAR_ANGLE : GL_LOAD_OP_LOAD_ANGLE;
943     }
944     std::vector<GLenum> storeOps(MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_STORE_OP_STORE_ANGLE);
945     glViewport(0, 0, W, H);
946     glDrawBuffers(0, nullptr);
947 
948     // Draw transparent green into all pls attachments.
949     glBeginPixelLocalStorageANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES, loadOps.data());
950     mProgram.drawBoxes({{{FULLSCREEN}, {0, 1, 0, 0}}});
951     glEndPixelLocalStorageANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES, storeOps.data());
952 
953     for (int i = 0; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i)
954     {
955         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texs[i], 0);
956         // Check that the draw buffers didn't get perturbed by local storage -- GL_COLOR_ATTACHMENT0
957         // is currently off, so glClear has no effect. This also verifies that local storage planes
958         // didn't get left attached to the framebuffer somewhere with draw buffers on.
959         glClear(GL_COLOR_BUFFER_BIT);
960         EXPECT_PIXEL_RECT_EQ(0, 0, 20, H,
961                              loadOps[i] == GL_LOAD_OP_CLEAR_ANGLE
962                                  ? GLColor(0, 255, 0, 255)
963                                  : /*GL_LOAD_OP_LOAD_ANGLE*/ GLColor(255, 255, 0, 255));
964         // Check that the scissor didn't get perturbed by local storage.
965         EXPECT_PIXEL_RECT_EQ(20, 0, W - 20, H,
966                              loadOps[i] == GL_LOAD_OP_CLEAR_ANGLE
967                                  ? GLColor(0, 0, 0, 255)
968                                  : /*GL_LOAD_OP_LOAD_ANGLE*/ GLColor(255, 0, 0, 255));
969     }
970 
971     // Detach the last read pls texture from the framebuffer.
972     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
973 
974     // Now test GL_LOAD_OP_ZERO_ANGLE, and leaving a plane deinitialized.
975     for (int i = 0; i < 2; ++i)
976     {
977         loadOps[i] = GL_LOAD_OP_ZERO_ANGLE;
978     }
979 
980     // Execute a pls pass without a draw.
981     glBeginPixelLocalStorageANGLE(3, loadOps.data());
982     glEndPixelLocalStorageANGLE(3, storeOps.data());
983 
984     for (int i = 0; i < 3; ++i)
985     {
986         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texs[i], 0);
987         if (i < 2)
988         {
989             ASSERT(loadOps[i] == GL_LOAD_OP_ZERO_ANGLE);
990             EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor(0, 0, 0, 0));
991         }
992         else
993         {
994             // Should have been left unchanged.
995             EXPECT_PIXEL_RECT_EQ(0, 0, 20, H, GLColor(255, 255, 0, 255));
996             EXPECT_PIXEL_RECT_EQ(20, 0, W - 20, H, GLColor(255, 0, 0, 255));
997         }
998     }
999 
1000     // Now turn GL_COLOR_ATTACHMENT0 back on and check that the clear color and scissor didn't get
1001     // perturbed by local storage.
1002     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texs[1], 0);
1003     glDrawBuffers(1, GLenumArray({GL_COLOR_ATTACHMENT0}));
1004     glClear(GL_COLOR_BUFFER_BIT);
1005     EXPECT_PIXEL_RECT_EQ(0, 0, 20, H, GLColor(255, 0, 0, 255));
1006     EXPECT_PIXEL_RECT_EQ(20, 0, W - 20, H, GLColor(0, 0, 0, 0));
1007 
1008     ASSERT_GL_NO_ERROR();
1009 }
1010 
1011 // This next series of tests checks that GL utilities for rejecting fragments prevent stores to PLS:
1012 //
1013 //   * stencil test
1014 //   * depth test
1015 //   * viewport
1016 //
1017 // Some utilities are not legal in ANGLE_shader_pixel_local_storage:
1018 //
1019 //   * gl_SampleMask is disallowed by the spec
1020 //   * discard, after potential calls to pixelLocalLoadANGLE/Store, is disallowed by the spec
1021 //   * pixelLocalLoadANGLE/Store after a return from main is disallowed by the spec
1022 //
1023 // To run the tests, bind a FragmentRejectTestFBO and draw {FRAG_REJECT_TEST_BOX}:
1024 //
1025 //   * {0, 0, FRAG_REJECT_TEST_WIDTH, FRAG_REJECT_TEST_HEIGHT} should be green
1026 //   * Fragments outside should have been rejected, leaving the pixels black
1027 //
1028 struct FragmentRejectTestFBO : GLFramebuffer
1029 {
FragmentRejectTestFBOFragmentRejectTestFBO1030     FragmentRejectTestFBO(GLuint tex)
1031     {
1032         glBindFramebuffer(GL_FRAMEBUFFER, *this);
1033         glFramebufferTexturePixelLocalStorageANGLE(0, tex, 0, 0);
1034         glFramebufferPixelLocalClearValuefvANGLE(0, MakeArray<float>({0, 0, 0, 1}));
1035         glViewport(0, 0, W, H);
1036         glDrawBuffers(0, nullptr);
1037     }
1038 };
1039 constexpr static int FRAG_REJECT_TEST_WIDTH  = 64;
1040 constexpr static int FRAG_REJECT_TEST_HEIGHT = 64;
1041 constexpr static Box FRAG_REJECT_TEST_BOX(FULLSCREEN,
1042                                           {0, 1, 0, 0},  // draw color
1043                                           {0, 0, FRAG_REJECT_TEST_WIDTH,
1044                                            FRAG_REJECT_TEST_HEIGHT});  // reject pixels outside aux1
1045 
1046 // Check that the stencil test prevents stores to PLS.
TEST_P(PixelLocalStorageTest,FragmentReject_stencil)1047 TEST_P(PixelLocalStorageTest, FragmentReject_stencil)
1048 {
1049     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
1050 
1051     PLSTestTexture tex(GL_RGBA8);
1052     FragmentRejectTestFBO fbo(tex);
1053 
1054     mProgram.compile(R"(
1055     layout(binding=0, rgba8) uniform highp pixelLocalANGLE pls;
1056     void main()
1057     {
1058         pixelLocalStoreANGLE(pls, color + pixelLocalLoadANGLE(pls));
1059     })");
1060     GLuint depthStencil;
1061     glGenRenderbuffers(1, &depthStencil);
1062     glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
1063     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, W, H);
1064     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
1065                               depthStencil);
1066 
1067     // glStencilFunc(GL_NEVER, ...) should not update pls.
1068     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE}));
1069     glEnable(GL_STENCIL_TEST);
1070     glStencilFunc(GL_NEVER, 1, ~0u);
1071     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1072     GLint zero = 0;
1073     glClearBufferiv(GL_STENCIL, 0, &zero);
1074     mProgram.drawBoxes({{{0, 0, FRAG_REJECT_TEST_WIDTH, FRAG_REJECT_TEST_HEIGHT}}});
1075     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE}));
1076     glDisable(GL_STENCIL_TEST);
1077     attachTexture2DToScratchFBO(tex);
1078     EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::black);
1079 
1080     // Stencil should be preserved after PLS, and only pixels that pass the stencil test should
1081     // update PLS next.
1082     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1083     glEnable(GL_STENCIL_TEST);
1084     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_LOAD_ANGLE}));
1085     glStencilFunc(GL_NOTEQUAL, 0, ~0u);
1086     glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
1087     mProgram.drawBoxes({FRAG_REJECT_TEST_BOX});
1088     glDisable(GL_STENCIL_TEST);
1089     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE}));
1090     renderTextureToDefaultFramebuffer(tex);
1091     EXPECT_PIXEL_RECT_EQ(0, 0, FRAG_REJECT_TEST_WIDTH, FRAG_REJECT_TEST_HEIGHT, GLColor::green);
1092     EXPECT_PIXEL_RECT_EQ(FRAG_REJECT_TEST_WIDTH, 0, W - FRAG_REJECT_TEST_WIDTH,
1093                          FRAG_REJECT_TEST_HEIGHT, GLColor::black);
1094     EXPECT_PIXEL_RECT_EQ(0, FRAG_REJECT_TEST_HEIGHT, W, H - FRAG_REJECT_TEST_HEIGHT,
1095                          GLColor::black);
1096 
1097     ASSERT_GL_NO_ERROR();
1098 }
1099 
1100 // Check that the depth test prevents stores to PLS.
TEST_P(PixelLocalStorageTest,FragmentReject_depth)1101 TEST_P(PixelLocalStorageTest, FragmentReject_depth)
1102 {
1103     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
1104 
1105     PLSTestTexture tex(GL_RGBA8);
1106     FragmentRejectTestFBO fbo(tex);
1107 
1108     mProgram.compile(R"(
1109     layout(binding=0, rgba8) uniform highp pixelLocalANGLE pls;
1110     void main()
1111     {
1112         pixelLocalStoreANGLE(pls, pixelLocalLoadANGLE(pls) + color);
1113     })");
1114     GLuint depth;
1115     glGenRenderbuffers(1, &depth);
1116     glBindRenderbuffer(GL_RENDERBUFFER, depth);
1117     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, W, H);
1118     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
1119     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE}));
1120     GLfloat zero = 0;
1121     glClearBufferfv(GL_DEPTH, 0, &zero);
1122     glEnable(GL_DEPTH_TEST);
1123     glEnable(GL_SCISSOR_TEST);
1124     glScissor(0, 0, FRAG_REJECT_TEST_WIDTH, FRAG_REJECT_TEST_HEIGHT);
1125     GLfloat one = 1;
1126     glClearBufferfv(GL_DEPTH, 0, &one);
1127     glDisable(GL_SCISSOR_TEST);
1128     glDepthFunc(GL_LESS);
1129     mProgram.drawBoxes({FRAG_REJECT_TEST_BOX});
1130     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE}));
1131     glDisable(GL_DEPTH_TEST);
1132 
1133     renderTextureToDefaultFramebuffer(tex);
1134     EXPECT_PIXEL_RECT_EQ(0, 0, FRAG_REJECT_TEST_WIDTH, FRAG_REJECT_TEST_HEIGHT, GLColor::green);
1135     EXPECT_PIXEL_RECT_EQ(FRAG_REJECT_TEST_WIDTH, 0, W - FRAG_REJECT_TEST_WIDTH,
1136                          FRAG_REJECT_TEST_HEIGHT, GLColor::black);
1137     EXPECT_PIXEL_RECT_EQ(0, FRAG_REJECT_TEST_HEIGHT, W, H - FRAG_REJECT_TEST_HEIGHT,
1138                          GLColor::black);
1139     ASSERT_GL_NO_ERROR();
1140 }
1141 
1142 // Check that restricting the viewport also restricts stores to PLS.
TEST_P(PixelLocalStorageTest,FragmentReject_viewport)1143 TEST_P(PixelLocalStorageTest, FragmentReject_viewport)
1144 {
1145     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
1146 
1147     PLSTestTexture tex(GL_RGBA8);
1148     FragmentRejectTestFBO fbo(tex);
1149 
1150     mProgram.compile(R"(
1151     layout(binding=0, rgba8) uniform highp pixelLocalANGLE pls;
1152     void main()
1153     {
1154         vec4 dst = pixelLocalLoadANGLE(pls);
1155         pixelLocalStoreANGLE(pls, color + dst);
1156     })");
1157     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE}));
1158     glViewport(0, 0, FRAG_REJECT_TEST_WIDTH, FRAG_REJECT_TEST_HEIGHT);
1159     mProgram.drawBoxes({FRAG_REJECT_TEST_BOX});
1160     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE}));
1161     glViewport(0, 0, W, H);
1162 
1163     renderTextureToDefaultFramebuffer(tex);
1164     EXPECT_PIXEL_RECT_EQ(0, 0, FRAG_REJECT_TEST_WIDTH, FRAG_REJECT_TEST_HEIGHT, GLColor::green);
1165     EXPECT_PIXEL_RECT_EQ(FRAG_REJECT_TEST_WIDTH, 0, W - FRAG_REJECT_TEST_WIDTH,
1166                          FRAG_REJECT_TEST_HEIGHT, GLColor::black);
1167     EXPECT_PIXEL_RECT_EQ(0, FRAG_REJECT_TEST_HEIGHT, W, H - FRAG_REJECT_TEST_HEIGHT,
1168                          GLColor::black);
1169     ASSERT_GL_NO_ERROR();
1170 }
1171 
1172 // Check that results are only nondeterministic within predictable constraints, and that no data is
1173 // random or leaked from other contexts when we forget to insert a barrier.
TEST_P(PixelLocalStorageTest,ForgetBarrier)1174 TEST_P(PixelLocalStorageTest, ForgetBarrier)
1175 {
1176     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
1177 
1178     mProgram.compile(R"(
1179     layout(binding=0, r32f) uniform highp pixelLocalANGLE framebuffer;
1180     void main()
1181     {
1182         vec4 dst = pixelLocalLoadANGLE(framebuffer);
1183         pixelLocalStoreANGLE(framebuffer, color + dst * 2.0);
1184     })");
1185 
1186     // Draw r=100, one pixel at a time, in random order.
1187     constexpr static int NUM_PIXELS = H * W;
1188     std::vector<Box> boxesA_100;
1189     int pixelIdx = 0;
1190     for (int i = 0; i < NUM_PIXELS; ++i)
1191     {
1192         int iy  = pixelIdx / W;
1193         float y = iy;
1194         int ix  = pixelIdx % W;
1195         float x = ix;
1196         pixelIdx =
1197             (pixelIdx + 69484171) % NUM_PIXELS;  // Prime numbers guarantee we hit every pixel once.
1198         boxesA_100.push_back(Box{{x, y, x + 1, y + 1}, {100, 0, 0, 0}});
1199     }
1200 
1201     // Draw r=7, one pixel at a time, in random order.
1202     std::vector<Box> boxesB_7;
1203     for (int i = 0; i < NUM_PIXELS; ++i)
1204     {
1205         int iy  = pixelIdx / W;
1206         float y = iy;
1207         int ix  = pixelIdx % W;
1208         float x = ix;
1209         pixelIdx =
1210             (pixelIdx + 97422697) % NUM_PIXELS;  // Prime numbers guarantee we hit every pixel once.
1211         boxesB_7.push_back(Box{{x, y, x + 1, y + 1}, {7, 0, 0, 0}});
1212     }
1213 
1214     PLSTestTexture tex(GL_R32F);
1215 
1216     GLFramebuffer fbo;
1217     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1218     glFramebufferTexturePixelLocalStorageANGLE(0, tex, 0, 0);
1219     glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(1, 0, 0, 0));
1220     glViewport(0, 0, W, H);
1221     glDrawBuffers(0, nullptr);
1222 
1223     // First make sure it works properly with a barrier.
1224     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE}));
1225     mProgram.drawBoxes(boxesA_100, UseBarriers::No);
1226     glPixelLocalStorageBarrierANGLE();
1227     mProgram.drawBoxes(boxesB_7, UseBarriers::No);
1228     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE}));
1229 
1230     attachTexture2DToScratchFBO(tex);
1231     EXPECT_PIXEL_RECT32F_EQ(0, 0, W, H, GLColor32F(211, 0, 0, 1));
1232 
1233     ASSERT_GL_NO_ERROR();
1234 
1235     // Vulkan generates rightful "SYNC-HAZARD-READ_AFTER_WRITE" validation errors when we omit the
1236     // barrier.
1237     ANGLE_SKIP_TEST_IF(IsVulkan() &&
1238                        !IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent"));
1239 
1240     // Now forget to insert the barrier and ensure our nondeterminism still falls within predictable
1241     // constraints.
1242     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1243     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE}));
1244     mProgram.drawBoxes(boxesA_100, UseBarriers::No);
1245     // OOPS! We forgot to insert a barrier!
1246     mProgram.drawBoxes(boxesB_7, UseBarriers::No);
1247     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE}));
1248 
1249     float pixels[H * W * 4];
1250     attachTexture2DToScratchFBO(tex);
1251     glReadPixels(0, 0, W, H, GL_RGBA, GL_FLOAT, pixels);
1252     for (int r = 0; r < NUM_PIXELS * 4; r += 4)
1253     {
1254         // When two fragments, A and B, touch a pixel, there are 6 possible orderings of operations:
1255         //
1256         //   * Read A, Write A, Read B, Write B
1257         //   * Read B, Write B, Read A, Write A
1258         //   * Read A, Read B, Write A, Write B
1259         //   * Read A, Read B, Write B, Write A
1260         //   * Read B, Read A, Write B, Write A
1261         //   * Read B, Read A, Write A, Write B
1262         //
1263         // Which (assumimg the read and/or write operations themselves are atomic), is equivalent to
1264         // 1 of 4 potential effects:
1265         bool isAcceptableValue = pixels[r] == 211 ||  // A, then B  (  7 + (100 + 1 * 2) * 2 == 211)
1266                                  pixels[r] == 118 ||  // B, then A  (100 + (  7 + 1 * 2) * 2 == 118)
1267                                  pixels[r] == 102 ||  // A only     (100 +             1 * 2 == 102)
1268                                  pixels[r] == 9;
1269         if (!isAcceptableValue)
1270         {
1271             printf(__FILE__ "(%i): UNACCEPTABLE value at pixel location [%i, %i]\n", __LINE__,
1272                    (r / 4) % W, (r / 4) / W);
1273             printf("              Got: %f\n", pixels[r]);
1274             printf("  Expected one of: { 211, 118, 102, 9 }\n");
1275         }
1276         ASSERT_TRUE(isAcceptableValue);
1277     }
1278 
1279     ASSERT_GL_NO_ERROR();
1280 }
1281 
1282 // Check loading and storing from memoryless local storage planes.
TEST_P(PixelLocalStorageTest,MemorylessStorage)1283 TEST_P(PixelLocalStorageTest, MemorylessStorage)
1284 {
1285     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
1286 
1287     // Bind the texture, but don't call glTexStorage until after creating the memoryless plane.
1288     GLTexture tex;
1289     glBindTexture(GL_TEXTURE_2D, tex);
1290 
1291     GLFramebuffer fbo;
1292     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1293     // Create a memoryless plane.
1294     glFramebufferMemorylessPixelLocalStorageANGLE(1, GL_RGBA8);
1295     // Define the persistent texture now, after attaching the memoryless pixel local storage. This
1296     // verifies that the GL_TEXTURE_2D binding doesn't get perturbed by local storage.
1297     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, W, H);
1298     glFramebufferTexturePixelLocalStorageANGLE(0, tex, 0, 0);
1299     glViewport(0, 0, W, H);
1300     glDrawBuffers(0, nullptr);
1301 
1302     PLSProgram drawMemorylessProgram;
1303     drawMemorylessProgram.compile(R"(
1304     layout(binding=0, rgba8) uniform highp pixelLocalANGLE framebuffer;
1305     layout(binding=1, rgba8) uniform highp pixelLocalANGLE memoryless;
1306     void main()
1307     {
1308         pixelLocalStoreANGLE(memoryless, color + pixelLocalLoadANGLE(memoryless));
1309     })");
1310 
1311     PLSProgram transferToTextureProgram;
1312     transferToTextureProgram.compile(R"(
1313     layout(binding=0, rgba8) uniform highp pixelLocalANGLE framebuffer;
1314     layout(binding=1, rgba8) uniform highp pixelLocalANGLE memoryless;
1315     void main()
1316     {
1317         pixelLocalStoreANGLE(framebuffer, vec4(1) - pixelLocalLoadANGLE(memoryless));
1318     })");
1319 
1320     glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE}));
1321 
1322     // Draw into memoryless storage.
1323     drawMemorylessProgram.bind();
1324     drawMemorylessProgram.drawBoxes({{{0, 20, W, H}, {1, 0, 0, 0}},
1325                                      {{0, 40, W, H}, {0, 1, 0, 0}},
1326                                      {{0, 60, W, H}, {0, 0, 1, 0}}});
1327 
1328     ASSERT_GL_NO_ERROR();
1329 
1330     // Transfer to a texture.
1331     transferToTextureProgram.bind();
1332     transferToTextureProgram.drawBoxes({{FULLSCREEN}});
1333 
1334     glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_DONT_CARE}));
1335 
1336     attachTexture2DToScratchFBO(tex);
1337     EXPECT_PIXEL_RECT_EQ(0, 60, W, H - 60, GLColor(0, 0, 0, 255));
1338     EXPECT_PIXEL_RECT_EQ(0, 40, W, 20, GLColor(0, 0, 255, 255));
1339     EXPECT_PIXEL_RECT_EQ(0, 20, W, 20, GLColor(0, 255, 255, 255));
1340     EXPECT_PIXEL_RECT_EQ(0, 0, W, 20, GLColor(255, 255, 255, 255));
1341 
1342     // Ensure the GL_TEXTURE_2D binding still hasn't been perturbed by local storage.
1343     GLint textureBinding2D;
1344     glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding2D);
1345     ASSERT_EQ((GLuint)textureBinding2D, tex);
1346 
1347     ASSERT_GL_NO_ERROR();
1348 }
1349 
1350 // Check that it works to render with the maximum supported data payload:
1351 //
1352 //   GL_MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE
1353 //
TEST_P(PixelLocalStorageTest,MaxCombinedDrawBuffersAndPLSPlanes)1354 TEST_P(PixelLocalStorageTest, MaxCombinedDrawBuffersAndPLSPlanes)
1355 {
1356     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
1357 
1358     for (int numDrawBuffers : {0, 1, MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - 1})
1359     {
1360         numDrawBuffers =
1361             std::min(numDrawBuffers, MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE);
1362         int numPLSPlanes =
1363             MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - numDrawBuffers;
1364         numPLSPlanes = std::min(numPLSPlanes, MAX_PIXEL_LOCAL_STORAGE_PLANES);
1365 
1366         std::stringstream fs;
1367         for (int i = 0; i < numPLSPlanes; ++i)
1368         {
1369             fs << "layout(binding=" << i << ", rgba8ui) uniform highp upixelLocalANGLE pls" << i
1370                << ";\n";
1371         }
1372         for (int i = 0; i < numDrawBuffers; ++i)
1373         {
1374             if (numDrawBuffers > 1)
1375             {
1376                 fs << "layout(location=" << i << ") ";
1377             }
1378             fs << "out uvec4 out" << i << ";\n";
1379         }
1380         fs << "void main() {\n";
1381         int c = 0;
1382         for (; c < std::min(numPLSPlanes, numDrawBuffers); ++c)
1383         {
1384             // Nest an expression involving a fragment output, which will have an unspecified
1385             // location when numDrawBuffers is 1, in pixelLocalStoreANGLE().
1386             fs << "pixelLocalStoreANGLE(pls" << c << ", uvec4(color) - (out" << c
1387                << " = uvec4(aux1) + uvec4(" << c << ")));\n";
1388         }
1389         for (int i = c; i < numPLSPlanes; ++i)
1390         {
1391             fs << "pixelLocalStoreANGLE(pls" << i << ", uvec4(color) - (uvec4(aux1) + uvec4(" << i
1392                << ")));\n";
1393         }
1394         for (int i = c; i < numDrawBuffers; ++i)
1395         {
1396             fs << "out" << i << " = uvec4(aux1) + uvec4(" << i << ");\n";
1397         }
1398         fs << "}";
1399         mProgram.compile(fs.str().c_str());
1400 
1401         glViewport(0, 0, W, H);
1402 
1403         GLFramebuffer fbo;
1404         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1405         std::vector<PLSTestTexture> localTexs;
1406         localTexs.reserve(numPLSPlanes);
1407         for (int i = 0; i < numPLSPlanes; ++i)
1408         {
1409             localTexs.emplace_back(GL_RGBA8UI);
1410             glFramebufferTexturePixelLocalStorageANGLE(i, localTexs[i], 0, 0);
1411         }
1412         std::vector<PLSTestTexture> renderTexs;
1413         renderTexs.reserve(numDrawBuffers);
1414         std::vector<GLenum> drawBuffers(numDrawBuffers);
1415         for (int i = 0; i < numDrawBuffers; ++i)
1416         {
1417             renderTexs.emplace_back(GL_RGBA32UI);
1418             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
1419                                    renderTexs[i], 0);
1420             drawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
1421         }
1422         glDrawBuffers(drawBuffers.size(), drawBuffers.data());
1423 
1424         glBeginPixelLocalStorageANGLE(
1425             numPLSPlanes, std::vector<GLenum>(numPLSPlanes, GL_LOAD_OP_ZERO_ANGLE).data());
1426         mProgram.drawBoxes({{FULLSCREEN, {255, 254, 253, 252}, {0, 1, 2, 3}}});
1427         glEndPixelLocalStorageANGLE(
1428             numPLSPlanes, std::vector<GLenum>(numPLSPlanes, GL_STORE_OP_STORE_ANGLE).data());
1429 
1430         for (int i = 0; i < numPLSPlanes; ++i)
1431         {
1432             attachTexture2DToScratchFBO(localTexs[i]);
1433             EXPECT_PIXEL_RECT32UI_EQ(
1434                 0, 0, W, H,
1435                 GLColor32UI(255u - i - 0u, 254u - i - 1u, 253u - i - 2u, 252u - i - 3u));
1436         }
1437         for (int i = 0; i < numDrawBuffers; ++i)
1438         {
1439             attachTexture2DToScratchFBO(renderTexs[i]);
1440             EXPECT_PIXEL_RECT32UI_EQ(0, 0, W, H, GLColor32UI(0u + i, 1u + i, 2u + i, 3u + i));
1441         }
1442 
1443         ASSERT_GL_NO_ERROR();
1444     }
1445 }
1446 
1447 // Verifies that program caching works for programs that use pixel local storage.
TEST_P(PixelLocalStorageTest,ProgramCache)1448 TEST_P(PixelLocalStorageTest, ProgramCache)
1449 {
1450     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
1451 
1452     GLFramebuffer fbo;
1453     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1454     PLSTestTexture pls0(GL_RGBA8UI, 1, 1);
1455     glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0);
1456     PLSTestTexture pls1(GL_RGBA8UI, 1, 1);
1457     glFramebufferTexturePixelLocalStorageANGLE(1, pls1, 0, 0);
1458     PLSTestTexture pls3(GL_RGBA8UI, 1, 1);
1459     glFramebufferTexturePixelLocalStorageANGLE(2, pls3, 0, 0);
1460     glDrawBuffers(0, nullptr);
1461     glViewport(0, 0, 1, 1);
1462 
1463     // Compile the same program multiple times and verify it works each time.
1464     for (int j = 0; j < 10; ++j)
1465     {
1466         mProgram.compile(R"(
1467         layout(binding=0, rgba8ui) uniform highp upixelLocalANGLE pls0;
1468         layout(binding=1, rgba8ui) uniform highp upixelLocalANGLE pls1;
1469         layout(binding=2, rgba8ui) uniform highp upixelLocalANGLE pls3;
1470         void main()
1471         {
1472             pixelLocalStoreANGLE(pls0, uvec4(color) - uvec4(aux1));
1473             pixelLocalStoreANGLE(pls1, uvec4(color) - uvec4(aux2));
1474             pixelLocalStoreANGLE(pls3, uvec4(color) - uvec4(aux1) - uvec4(aux2));
1475         })");
1476         glUniform1f(mProgram.widthUniform(), 1);
1477         glUniform1f(mProgram.heightUniform(), 1);
1478 
1479         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1480         glBeginPixelLocalStorageANGLE(
1481             3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE}));
1482         mProgram.drawBoxes({{FULLSCREEN, {255, 254, 253, 252}, {0, 1, 2, 3}, {4, 5, 6, 7}}});
1483         glEndPixelLocalStorageANGLE(
1484             3, GLenumArray(
1485                    {GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE}));
1486 
1487         attachTexture2DToScratchFBO(pls0);
1488         EXPECT_PIXEL_RECT32UI_EQ(0, 0, 1, 1,
1489                                  GLColor32UI(255u - 0u, 254u - 1u, 253u - 2u, 252u - 3u));
1490 
1491         attachTexture2DToScratchFBO(pls1);
1492         EXPECT_PIXEL_RECT32UI_EQ(0, 0, 1, 1,
1493                                  GLColor32UI(255u - 4u, 254u - 5u, 253u - 6u, 252u - 7u));
1494 
1495         attachTexture2DToScratchFBO(pls3);
1496         EXPECT_PIXEL_RECT32UI_EQ(
1497             0, 0, 1, 1,
1498             GLColor32UI(255u - 0u - 4u, 254u - 1u - 5u, 253u - 2u - 6u, 252u - 3u - 7u));
1499 
1500         ASSERT_GL_NO_ERROR();
1501     }
1502 }
1503 
1504 // Check that pls is preserved when a shader does not call pixelLocalStoreANGLE(). (Whether that's
1505 // because a conditional branch failed or because the shader didn't write to it at all.)
1506 //
1507 //   * The framebuffer fetch implementation needs to make sure every active plane's output variable
1508 //     gets written during every invocation, or else its value will become undefined.
1509 //
1510 //   * The native pixel local storage implementation needs to declare a variable for every active
1511 //     plane, even if it is unused in a particular shader invocation.
1512 //
1513 // Also check that a pixelLocalLoadANGLE() of an r32f texture returns (r, 0, 0, 1).
TEST_P(PixelLocalStorageTest,LoadOnly)1514 TEST_P(PixelLocalStorageTest, LoadOnly)
1515 {
1516     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
1517 
1518     PLSTestTexture tex(GL_RGBA8);
1519 
1520     GLFramebuffer fbo;
1521     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1522     glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_R32F);
1523     glFramebufferTexturePixelLocalStorageANGLE(1, tex, 0, 0);
1524     glViewport(0, 0, W, H);
1525     glDrawBuffers(0, nullptr);
1526 
1527     // Pass 1: draw to memoryless conditionally.
1528     PLSProgram pass1;
1529     pass1.compile(R"(
1530     layout(binding=0, r32f) uniform highp pixelLocalANGLE memoryless;
1531     layout(binding=1, rgba8) uniform highp pixelLocalANGLE tex;
1532     void main()
1533     {
1534         // Omit braces on the 'if' to ensure proper insertion of memoryBarriers in the translator.
1535         if (gl_FragCoord.x < 64.0)
1536             pixelLocalStoreANGLE(memoryless, vec4(1, -.1, .2, -.3));  // Only stores r.
1537     })");
1538 
1539     // Pass 2: draw to tex conditionally.
1540     // Don't touch memoryless -- make sure it gets preserved!
1541     PLSProgram pass2;
1542     pass2.compile(R"(
1543     layout(binding=0, r32f) uniform highp pixelLocalANGLE memoryless;
1544     layout(binding=1, rgba8) uniform highp pixelLocalANGLE tex;
1545     void main()
1546     {
1547         // Omit braces on the 'if' to ensure proper insertion of memoryBarriers in the translator.
1548         if (gl_FragCoord.y < 64.0)
1549             pixelLocalStoreANGLE(tex, vec4(0, 1, 1, 0));
1550     })");
1551 
1552     // Pass 3: combine memoryless and tex.
1553     PLSProgram pass3;
1554     pass3.compile(R"(
1555     layout(binding=0, r32f) uniform highp pixelLocalANGLE memoryless;
1556     layout(binding=1, rgba8) uniform highp pixelLocalANGLE tex;
1557     void main()
1558     {
1559         pixelLocalStoreANGLE(tex, pixelLocalLoadANGLE(tex) + pixelLocalLoadANGLE(memoryless));
1560     })");
1561 
1562     // Leave unit 0 with the default clear value of zero.
1563     glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(0, 0, 0, 0));
1564     glFramebufferPixelLocalClearValuefvANGLE(1, ClearF(0, 1, 0, 0));
1565     glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE, GL_LOAD_OP_CLEAR_ANGLE}));
1566 
1567     pass1.bind();
1568     pass1.drawBoxes({{FULLSCREEN}});
1569 
1570     pass2.bind();
1571     pass2.drawBoxes({{FULLSCREEN}});
1572 
1573     pass3.bind();
1574     pass3.drawBoxes({{FULLSCREEN}});
1575 
1576     glEndPixelLocalStorageANGLE(2, GLenumArray({GL_DONT_CARE, GL_STORE_OP_STORE_ANGLE}));
1577 
1578     attachTexture2DToScratchFBO(tex);
1579     EXPECT_PIXEL_RECT_EQ(0, 0, 64, 64, GLColor(255, 255, 255, 255));
1580     EXPECT_PIXEL_RECT_EQ(64, 0, W - 64, 64, GLColor(0, 255, 255, 255));
1581     EXPECT_PIXEL_RECT_EQ(0, 64, 64, H - 64, GLColor(255, 255, 0, 255));
1582     EXPECT_PIXEL_RECT_EQ(64, 64, W - 64, H - 64, GLColor(0, 255, 0, 255));
1583 
1584     ASSERT_GL_NO_ERROR();
1585 
1586     // Now treat "tex" as entirely readonly for an entire local storage render pass.
1587     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1588     PLSTestTexture tex2(GL_RGBA8);
1589 
1590     if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 0)
1591     {
1592         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2, 0);
1593         glDrawBuffers(1, GLenumArray({GL_COLOR_ATTACHMENT0}));
1594         glClear(GL_COLOR_BUFFER_BIT);
1595 
1596         mProgram.compile(R"(
1597         layout(binding=0, r32f) uniform highp pixelLocalANGLE memoryless;
1598         layout(binding=1, rgba8) uniform highp pixelLocalANGLE tex;
1599         out vec4 fragcolor;
1600         void main()
1601         {
1602             fragcolor = 1.0 - pixelLocalLoadANGLE(tex);
1603         })");
1604 
1605         glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_DONT_CARE, GL_LOAD_OP_LOAD_ANGLE}));
1606     }
1607     else
1608     {
1609         glFramebufferTexturePixelLocalStorageANGLE(2, tex2, 0, 0);
1610 
1611         mProgram.compile(R"(
1612         layout(binding=0, r32f) uniform highp pixelLocalANGLE memoryless;
1613         layout(binding=1, rgba8) uniform highp pixelLocalANGLE tex;
1614         layout(binding=2, rgba8) uniform highp pixelLocalANGLE fragcolor;
1615         void main()
1616         {
1617             pixelLocalStoreANGLE(fragcolor, 1.0 - pixelLocalLoadANGLE(tex));
1618         })");
1619 
1620         glBeginPixelLocalStorageANGLE(
1621             3, GLenumArray({GL_DONT_CARE, GL_LOAD_OP_LOAD_ANGLE, GL_LOAD_OP_ZERO_ANGLE}));
1622     }
1623 
1624     mProgram.drawBoxes({{FULLSCREEN}});
1625 
1626     int n;
1627     glGetIntegerv(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, &n);
1628     glEndPixelLocalStorageANGLE(
1629         n, GLenumArray({GL_DONT_CARE, GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE}));
1630 
1631     // Ensure "tex" was properly read in the shader.
1632     if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE == 0)
1633     {
1634         attachTexture2DToScratchFBO(tex2);
1635     }
1636     EXPECT_PIXEL_RECT_EQ(0, 0, 64, 64, GLColor(0, 0, 0, 0));
1637     EXPECT_PIXEL_RECT_EQ(64, 0, W - 64, 64, GLColor(255, 0, 0, 0));
1638     EXPECT_PIXEL_RECT_EQ(0, 64, 64, H - 64, GLColor(0, 0, 255, 0));
1639     EXPECT_PIXEL_RECT_EQ(64, 64, W - 64, H - 64, GLColor(255, 0, 255, 0));
1640 
1641     // Ensure "tex" was preserved after the shader.
1642     attachTexture2DToScratchFBO(tex);
1643     EXPECT_PIXEL_RECT_EQ(0, 0, 64, 64, GLColor(255, 255, 255, 255));
1644     EXPECT_PIXEL_RECT_EQ(64, 0, W - 64, 64, GLColor(0, 255, 255, 255));
1645     EXPECT_PIXEL_RECT_EQ(0, 64, 64, H - 64, GLColor(255, 255, 0, 255));
1646     EXPECT_PIXEL_RECT_EQ(64, 64, W - 64, H - 64, GLColor(0, 255, 0, 255));
1647 
1648     ASSERT_GL_NO_ERROR();
1649 }
1650 
1651 // Check that stores and loads in a single shader invocation are coherent.
TEST_P(PixelLocalStorageTest,LoadAfterStore)1652 TEST_P(PixelLocalStorageTest, LoadAfterStore)
1653 {
1654     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
1655 
1656     // Run a fibonacci loop that stores and loads the same PLS multiple times.
1657     mProgram.compile(R"(
1658     layout(binding=0, rgba8ui) uniform highp upixelLocalANGLE fibonacci;
1659     void main()
1660     {
1661         pixelLocalStoreANGLE(fibonacci, uvec4(1, 0, 0, 0));  // fib(1, 0, 0, 0)
1662         for (int i = 0; i < 3; ++i)
1663         {
1664             uvec4 fib0 = pixelLocalLoadANGLE(fibonacci);
1665             uvec4 fib1;
1666             fib1.w = fib0.x + fib0.y;
1667             fib1.z = fib1.w + fib0.x;
1668             fib1.y = fib1.z + fib1.w;
1669             fib1.x = fib1.y + fib1.z;  // fib(i*4 + (5, 4, 3, 2))
1670             pixelLocalStoreANGLE(fibonacci, fib1);
1671         }
1672         // fib is at indices (13, 12, 11, 10)
1673     })");
1674 
1675     PLSTestTexture tex(GL_RGBA8UI);
1676 
1677     GLFramebuffer fbo;
1678     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1679     glFramebufferTexturePixelLocalStorageANGLE(0, tex, 0, 0);
1680     glViewport(0, 0, W, H);
1681     glDrawBuffers(0, nullptr);
1682 
1683     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
1684     mProgram.drawBoxes({{FULLSCREEN}});
1685     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE}));
1686 
1687     attachTexture2DToScratchFBO(tex);
1688     EXPECT_PIXEL_RECT32UI_EQ(0, 0, W, H, GLColor32UI(233, 144, 89, 55));  // fib(13, 12, 11, 10)
1689 
1690     ASSERT_GL_NO_ERROR();
1691 
1692     // Now verify that r32f and r32ui still reload as (r, 0, 0, 1), even after an in-shader store.
1693     if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 0)
1694     {
1695         mProgram.compile(R"(
1696         layout(binding=0, r32f) uniform highp pixelLocalANGLE pls32f;
1697         layout(binding=1, r32ui) uniform highp upixelLocalANGLE pls32ui;
1698 
1699         out vec4 fragcolor;
1700         void main()
1701         {
1702             pixelLocalStoreANGLE(pls32f, vec4(1, .5, .5, .5));
1703             pixelLocalStoreANGLE(pls32ui, uvec4(1, 1, 1, 0));
1704             if ((int(floor(gl_FragCoord.x)) & 1) == 0)
1705                 fragcolor = pixelLocalLoadANGLE(pls32f);
1706             else
1707                 fragcolor = vec4(pixelLocalLoadANGLE(pls32ui));
1708         })");
1709 
1710         tex.reset(GL_RGBA8);
1711         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1712         glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_R32F);
1713         glFramebufferMemorylessPixelLocalStorageANGLE(1, GL_R32UI);
1714         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1715         glDrawBuffers(1, GLenumArray({GL_COLOR_ATTACHMENT0}));
1716 
1717         glBeginPixelLocalStorageANGLE(2,
1718                                       GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE}));
1719     }
1720     else
1721     {
1722         mProgram.compile(R"(
1723         layout(binding=0, r32f) uniform highp pixelLocalANGLE pls32f;
1724         layout(binding=1, r32ui) uniform highp upixelLocalANGLE pls32ui;
1725         layout(binding=2, rgba8) uniform highp pixelLocalANGLE fragcolor;
1726         void main()
1727         {
1728             pixelLocalStoreANGLE(pls32f, vec4(1, .5, .5, .5));
1729             pixelLocalStoreANGLE(pls32ui, uvec4(1, 1, 1, 0));
1730             if ((int(floor(gl_FragCoord.x)) & 1) == 0)
1731                 pixelLocalStoreANGLE(fragcolor, pixelLocalLoadANGLE(pls32f));
1732             else
1733                 pixelLocalStoreANGLE(fragcolor, vec4(pixelLocalLoadANGLE(pls32ui)));
1734         })");
1735 
1736         tex.reset(GL_RGBA8);
1737         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1738         glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_R32F);
1739         glFramebufferMemorylessPixelLocalStorageANGLE(1, GL_R32UI);
1740         glFramebufferTexturePixelLocalStorageANGLE(2, tex, 0, 0);
1741 
1742         glBeginPixelLocalStorageANGLE(
1743             3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_DONT_CARE}));
1744     }
1745 
1746     mProgram.drawBoxes({{FULLSCREEN}});
1747 
1748     int n;
1749     glGetIntegerv(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, &n);
1750     glEndPixelLocalStorageANGLE(n,
1751                                 GLenumArray({GL_DONT_CARE, GL_DONT_CARE, GL_STORE_OP_STORE_ANGLE}));
1752 
1753     if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE == 0)
1754     {
1755         attachTexture2DToScratchFBO(tex);
1756     }
1757     EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor(255, 0, 0, 255));
1758     ASSERT_GL_NO_ERROR();
1759 }
1760 
1761 // Check that PLS handles can be passed as function arguments.
TEST_P(PixelLocalStorageTest,FunctionArguments)1762 TEST_P(PixelLocalStorageTest, FunctionArguments)
1763 {
1764     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
1765 
1766     mProgram.compile(R"(
1767     layout(binding=0, rgba8) uniform lowp pixelLocalANGLE dst;
1768     layout(binding=1, rgba8) uniform mediump pixelLocalANGLE src1;
1769     void store2(lowp pixelLocalANGLE d);
1770     void store(highp pixelLocalANGLE d, lowp pixelLocalANGLE s)
1771     {
1772         pixelLocalStoreANGLE(d, pixelLocalLoadANGLE(s));
1773     }
1774     void main()
1775     {
1776         if (gl_FragCoord.x < 25.0)
1777             store(dst, src1);
1778         else
1779             store2(dst);
1780     }
1781     // Ensure inlining still works on a uniform declared after main().
1782     layout(binding=2, r32f) uniform highp pixelLocalANGLE src2;
1783     void store2(lowp pixelLocalANGLE d)
1784     {
1785         pixelLocalStoreANGLE(d, pixelLocalLoadANGLE(src2));
1786     })");
1787 
1788     PLSTestTexture dst(GL_RGBA8);
1789 
1790     GLFramebuffer fbo;
1791     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1792     glFramebufferTexturePixelLocalStorageANGLE(0, dst, 0, 0);
1793     glFramebufferMemorylessPixelLocalStorageANGLE(1, GL_RGBA8);
1794     glFramebufferMemorylessPixelLocalStorageANGLE(2, GL_R32F);
1795 
1796     glViewport(0, 0, W, H);
1797     glDrawBuffers(0, nullptr);
1798 
1799     glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(1, 1, 1, 1));  // ignored
1800     glFramebufferPixelLocalClearValuefvANGLE(1, ClearF(0, 1, 1, 0));
1801     glFramebufferPixelLocalClearValuefvANGLE(2, ClearF(1, 0, 0, 1));
1802     glBeginPixelLocalStorageANGLE(
1803         3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_CLEAR_ANGLE, GL_LOAD_OP_CLEAR_ANGLE}));
1804     mProgram.drawBoxes({{FULLSCREEN}});
1805     glEndPixelLocalStorageANGLE(3,
1806                                 GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_DONT_CARE, GL_DONT_CARE}));
1807 
1808     attachTexture2DToScratchFBO(dst);
1809     EXPECT_PIXEL_RECT_EQ(0, 0, 25, H, GLColor(0, 255, 255, 0));
1810     EXPECT_PIXEL_RECT_EQ(25, 0, W - 25, H, GLColor(255, 0, 0, 255));
1811 
1812     ASSERT_GL_NO_ERROR();
1813 }
1814 
1815 // Check that if the "_coherent" extension is advertised, PLS operations are ordered and coherent.
TEST_P(PixelLocalStorageTest,Coherency)1816 TEST_P(PixelLocalStorageTest, Coherency)
1817 {
1818     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
1819 
1820     mProgram.compile(R"(
1821     layout(binding=0, rgba8ui) uniform lowp upixelLocalANGLE framebuffer;
1822     layout(binding=1, rgba8) uniform lowp pixelLocalANGLE tmp;
1823     // The application shouldn't be able to override internal synchronization functions used by
1824     // the compiler.
1825     //
1826     // If the compiler accidentally calls any of these functions, stomp out the framebuffer to make
1827     // the test fail.
1828     void endInvocationInterlockNV() { pixelLocalStoreANGLE(framebuffer, uvec4(0)); }
1829     void beginFragmentShaderOrderingINTEL() { pixelLocalStoreANGLE(framebuffer, uvec4(0)); }
1830     void beginInvocationInterlockARB() { pixelLocalStoreANGLE(framebuffer, uvec4(0)); }
1831 
1832     // Give these functions a side effect so they don't get pruned, then call them from main().
1833     void beginInvocationInterlockNV() { pixelLocalStoreANGLE(tmp, vec4(0)); }
1834     void endInvocationInterlockARB() { pixelLocalStoreANGLE(tmp, vec4(0)); }
1835 
1836     void main()
1837     {
1838         highp uvec4 d = pixelLocalLoadANGLE(framebuffer) >> 1;
1839         pixelLocalStoreANGLE(framebuffer, uvec4(color) + d);
1840         beginInvocationInterlockNV();
1841         endInvocationInterlockARB();
1842     })");
1843 
1844     PLSTestTexture tex(GL_RGBA8UI);
1845 
1846     GLFramebuffer fbo;
1847     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1848     glFramebufferTexturePixelLocalStorageANGLE(0, tex, 0, 0);
1849     glFramebufferMemorylessPixelLocalStorageANGLE(1, GL_RGBA8);
1850     glViewport(0, 0, W, H);
1851     glDrawBuffers(0, nullptr);
1852 
1853     std::vector<uint8_t> expected(H * W * 4);
1854     memset(expected.data(), 0, H * W * 4);
1855 
1856     // This test times out on Swiftshader and noncoherent backends if we draw anywhere near the
1857     // same number of boxes as we do on coherent, hardware backends.
1858     int boxesPerList = !IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent") ||
1859                                strstr((const char *)glGetString(GL_RENDERER), "SwiftShader")
1860                            ? 200
1861                            : H * W * 3;
1862 
1863     // Prepare a ton of random sized boxes in various draws.
1864     std::vector<Box> boxesList[5];
1865     srand(17);
1866     uint32_t boxID = 1;
1867     for (auto &boxes : boxesList)
1868     {
1869         for (int i = 0; i < boxesPerList; ++i)
1870         {
1871             // Define a box.
1872             int w     = rand() % 10 + 1;
1873             int h     = rand() % 10 + 1;
1874             float x   = rand() % (W - w);
1875             float y   = rand() % (H - h);
1876             uint8_t r = boxID & 0x7f;
1877             uint8_t g = (boxID >> 7) & 0x7f;
1878             uint8_t b = (boxID >> 14) & 0x7f;
1879             uint8_t a = (boxID >> 21) & 0x7f;
1880             ++boxID;
1881             // Update expectations.
1882             for (int yy = y; yy < y + h; ++yy)
1883             {
1884                 for (int xx = x; xx < x + w; ++xx)
1885                 {
1886                     int p           = (yy * W + xx) * 4;
1887                     expected[p]     = r + (expected[p] >> 1);
1888                     expected[p + 1] = g + (expected[p + 1] >> 1);
1889                     expected[p + 2] = b + (expected[p + 2] >> 1);
1890                     expected[p + 3] = a + (expected[p + 3] >> 1);
1891                 }
1892             }
1893             // Set up the gpu draw.
1894             float x0 = x;
1895             float x1 = x + w;
1896             float y0 = y;
1897             float y1 = y + h;
1898             // Allow boxes to have negative widths and heights. This adds randomness by making the
1899             // diagonals go in different directions.
1900             if (rand() & 1)
1901                 std::swap(x0, x1);
1902             if (rand() & 1)
1903                 std::swap(y0, y1);
1904             boxes.push_back({{x0, y0, x1, y1}, {(float)r, (float)g, (float)b, (float)a}});
1905         }
1906     }
1907 
1908     glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE}));
1909     for (const std::vector<Box> &boxes : boxesList)
1910     {
1911         mProgram.drawBoxes(boxes);
1912     }
1913     glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_DONT_CARE}));
1914 
1915     attachTexture2DToScratchFBO(tex);
1916     std::vector<uint8_t> actual(H * W * 4);
1917     glReadPixels(0, 0, W, H, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, actual.data());
1918     EXPECT_EQ(expected, actual);
1919 
1920     ASSERT_GL_NO_ERROR();
1921 }
1922 
1923 // Check that binding mipmap levels to PLS is supported.
TEST_P(PixelLocalStorageTest,MipMapLevels)1924 TEST_P(PixelLocalStorageTest, MipMapLevels)
1925 {
1926     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
1927 
1928     mProgram.compile(R"(
1929         layout(binding=0, rgba8) uniform lowp pixelLocalANGLE pls;
1930         void main()
1931         {
1932             pixelLocalStoreANGLE(pls, color + pixelLocalLoadANGLE(pls));
1933         })");
1934 
1935     constexpr int LEVELS = 3;
1936     int levelWidth = 179, levelHeight = 313;
1937     std::vector<GLColor> redData(levelHeight * levelWidth, GLColor::black);
1938     GLuint tex;
1939     glGenTextures(1, &tex);
1940     glBindTexture(GL_TEXTURE_2D, tex);
1941     glTexStorage2D(GL_TEXTURE_2D, LEVELS, GL_RGBA8, levelWidth, levelHeight);
1942 
1943     GLFramebuffer fbo;
1944     for (int level = 0; level < LEVELS; ++level)
1945     {
1946         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1947 
1948         glUniform1f(mProgram.widthUniform(), levelWidth);
1949         glUniform1f(mProgram.heightUniform(), levelHeight);
1950         glViewport(0, 0, levelWidth, levelHeight);
1951         glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, levelWidth, levelHeight, GL_RGBA,
1952                         GL_UNSIGNED_BYTE, redData.data());
1953 
1954         glFramebufferTexturePixelLocalStorageANGLE(0, tex, level, 0);
1955         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_LOAD_ANGLE}));
1956         mProgram.drawBoxes({{{0, 0, (float)levelWidth - 3, (float)levelHeight}, {0, 0, 1, 0}},
1957                             {{0, 0, (float)levelWidth - 2, (float)levelHeight}, {0, 1, 0, 0}},
1958                             {{0, 0, (float)levelWidth - 1, (float)levelHeight}, {1, 0, 0, 0}}});
1959         glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE}));
1960         attachTexture2DToScratchFBO(tex, level);
1961         EXPECT_PIXEL_RECT_EQ(0, 0, levelWidth - 3, levelHeight, GLColor::white);
1962         EXPECT_PIXEL_RECT_EQ(levelWidth - 3, 0, 1, levelHeight, GLColor::yellow);
1963         EXPECT_PIXEL_RECT_EQ(levelWidth - 2, 0, 1, levelHeight, GLColor::red);
1964         EXPECT_PIXEL_RECT_EQ(levelWidth - 1, 0, 1, levelHeight, GLColor::black);
1965 
1966         levelWidth >>= 1;
1967         levelHeight >>= 1;
1968         ASSERT_GL_NO_ERROR();
1969     }
1970 
1971     // Delete fbo.
1972     // Don't delete tex -- exercise pixel local storage in a way that it has to clean itself up when
1973     // the context is torn down. (It has internal assertions that validate it is torn down
1974     // correctly.)
1975 }
1976 
1977 // Check that all supported texture types work at various levels and layers.
TEST_P(PixelLocalStorageTest,TextureLevelsAndLayers)1978 TEST_P(PixelLocalStorageTest, TextureLevelsAndLayers)
1979 {
1980     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
1981 
1982     mProgram.compile(R"(
1983         layout(binding=0, rgba8) uniform lowp pixelLocalANGLE pls;
1984         void main()
1985         {
1986             pixelLocalStoreANGLE(pls, vec4(0, 1, 0, 0) + pixelLocalLoadANGLE(pls));
1987         })");
1988 
1989     std::array<float, 4> HALFSCREEN = {0, 0, W / 2.f, H};
1990 
1991     int D = 5;
1992     std::vector<GLColor> redImg(H * W * D, GLColor::red);
1993 
1994     // GL_TEXTURE_2D
1995     {
1996         // Level 2.
1997         GLTexture tex;
1998         glBindTexture(GL_TEXTURE_2D, tex);
1999         glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, W * 4, H * 4);
2000         glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, redImg.data());
2001         GLFramebuffer fbo;
2002         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2003         glFramebufferTexturePixelLocalStorageANGLE(0, tex, 2, 0);
2004         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_LOAD_ANGLE}));
2005         mProgram.drawBoxes({{HALFSCREEN}});
2006         glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE}));
2007         attachTexture2DToScratchFBO(tex, 2);
2008         EXPECT_PIXEL_RECT_EQ(0, 0, W / 2.f, H, GLColor::yellow);
2009         EXPECT_PIXEL_RECT_EQ(W / 2.f, 0, W / 2.f, H, GLColor::red);
2010         ASSERT_GL_NO_ERROR();
2011     }
2012 
2013     // GL_TEXTURE_2D_ARRAY
2014     {
2015         // Level 1, layer 0.
2016         GLTexture tex;
2017         glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
2018         glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA8, W * 2, H * 2, D);
2019         glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, W, H, D, GL_RGBA, GL_UNSIGNED_BYTE,
2020                         redImg.data());
2021         GLFramebuffer fbo;
2022         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2023         glFramebufferTexturePixelLocalStorageANGLE(0, tex, 1, 0);
2024         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_LOAD_ANGLE}));
2025         mProgram.drawBoxes({{HALFSCREEN}});
2026         glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE}));
2027         attachTextureLayerToScratchFBO(tex, 1, 0);
2028         EXPECT_PIXEL_RECT_EQ(0, 0, W / 2.f, H, GLColor::yellow);
2029         EXPECT_PIXEL_RECT_EQ(W / 2.f, 0, W / 2.f, H, GLColor::red);
2030         ASSERT_GL_NO_ERROR();
2031 
2032         // Level 1, layer D - 1.
2033         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2034         glFramebufferTexturePixelLocalStorageANGLE(0, tex, 1, D - 1);
2035         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_LOAD_ANGLE}));
2036         mProgram.drawBoxes({{HALFSCREEN}});
2037         glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE}));
2038         attachTextureLayerToScratchFBO(tex, 1, D - 1);
2039         EXPECT_PIXEL_RECT_EQ(0, 0, W / 2.f, H, GLColor::yellow);
2040         EXPECT_PIXEL_RECT_EQ(W / 2.f, 0, W / 2.f, H, GLColor::red);
2041         ASSERT_GL_NO_ERROR();
2042     }
2043 }
2044 
doStateRestorationTest()2045 void PixelLocalStorageTest::doStateRestorationTest()
2046 {
2047     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
2048 
2049     // Setup state.
2050     PLSTestTexture plsTex(GL_RGBA8UI, 32, 33);
2051     GLFramebuffer fbo;
2052     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2053 
2054     glViewport(1, 1, 5, 5);
2055     glScissor(2, 2, 4, 4);
2056     glEnable(GL_SCISSOR_TEST);
2057 
2058     bool hasDrawBuffersIndexedOES = IsGLExtensionEnabled("GL_OES_draw_buffers_indexed");
2059     if (hasDrawBuffersIndexedOES)
2060     {
2061         for (int i = 0; i < MAX_DRAW_BUFFERS; ++i)
2062         {
2063             if (i % 2 == 1)
2064             {
2065                 glEnableiOES(GL_BLEND, i);
2066             }
2067             glColorMaskiOES(i, i % 3 == 0, i % 3 == 1, i % 3 == 2, i % 2 == 0);
2068         }
2069     }
2070     else
2071     {
2072         glEnable(GL_BLEND);
2073         glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
2074     }
2075 
2076     std::vector<GLenum> drawBuffers(MAX_DRAW_BUFFERS);
2077     for (int i = 0; i < MAX_DRAW_BUFFERS; ++i)
2078     {
2079         drawBuffers[i] = i % 3 == 0 ? GL_NONE : GL_COLOR_ATTACHMENT0 + i;
2080     }
2081     glDrawBuffers(MAX_DRAW_BUFFERS, drawBuffers.data());
2082 
2083     GLenum imageAccesses[] = {GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE};
2084     GLenum imageFormats[]  = {GL_RGBA8, GL_R32UI, GL_R32I, GL_R32F};
2085     std::vector<GLTexture> images;
2086     if (isContextVersionAtLeast(3, 1))
2087     {
2088         for (int i = 0; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i)
2089         {
2090             GLuint tex = images.emplace_back();
2091             glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
2092             glTexStorage3D(GL_TEXTURE_2D_ARRAY, 3, GL_RGBA8, 8, 8, 5);
2093             GLboolean layered = i % 2;
2094             glBindImageTexture(i, images.back(), i % 3, layered, layered == GL_FALSE ? i % 5 : 0,
2095                                imageAccesses[i % 3], imageFormats[i % 4]);
2096         }
2097 
2098         glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 17);
2099         glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
2100     }
2101 
2102     PLSTestTexture boundTex(GL_RGBA8, 1, 1);
2103     glBindTexture(GL_TEXTURE_2D, boundTex);
2104 
2105     // Run pixel local storage.
2106     glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_RGBA8);
2107     glFramebufferTexturePixelLocalStorageANGLE(1, plsTex, 0, 0);
2108     glFramebufferMemorylessPixelLocalStorageANGLE(2, GL_RGBA8);
2109     glFramebufferMemorylessPixelLocalStorageANGLE(3, GL_RGBA8);
2110     glFramebufferPixelLocalClearValuefvANGLE(2, ClearF(.1, .2, .3, .4));
2111     glBeginPixelLocalStorageANGLE(4, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_LOAD_ANGLE,
2112                                                   GL_LOAD_OP_CLEAR_ANGLE, GL_DONT_CARE}));
2113     glPixelLocalStorageBarrierANGLE();
2114     glEndPixelLocalStorageANGLE(
2115         4, GLenumArray({GL_DONT_CARE, GL_STORE_OP_STORE_ANGLE, GL_DONT_CARE, GL_DONT_CARE}));
2116 
2117     // Check state.
2118     GLint textureBinding2D;
2119     glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding2D);
2120     EXPECT_EQ(static_cast<GLuint>(textureBinding2D), boundTex);
2121 
2122     if (isContextVersionAtLeast(3, 1))
2123     {
2124         for (int i = 0; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i)
2125         {
2126             GLint name, level, layer, access, format;
2127             GLboolean layered;
2128             glGetIntegeri_v(GL_IMAGE_BINDING_NAME, i, &name);
2129             glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, i, &level);
2130             glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, i, &layered);
2131             glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, i, &layer);
2132             glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, i, &access);
2133             glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, i, &format);
2134             EXPECT_EQ(static_cast<GLuint>(name), images[i]);
2135             EXPECT_EQ(level, i % 3);
2136             EXPECT_EQ(layered, i % 2);
2137             EXPECT_EQ(layer, layered == GL_FALSE ? i % 5 : 0);
2138             EXPECT_EQ(static_cast<GLuint>(access), imageAccesses[i % 3]);
2139             EXPECT_EQ(static_cast<GLuint>(format), imageFormats[i % 4]);
2140         }
2141 
2142         GLint defaultWidth, defaultHeight;
2143         glGetFramebufferParameteriv(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
2144                                     &defaultWidth);
2145         glGetFramebufferParameteriv(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
2146                                     &defaultHeight);
2147         EXPECT_EQ(defaultWidth, 17);
2148         EXPECT_EQ(defaultHeight, 1);
2149     }
2150 
2151     for (int i = 0; i < MAX_COLOR_ATTACHMENTS; ++i)
2152     {
2153         GLint attachmentType;
2154         glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
2155                                               GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
2156                                               &attachmentType);
2157         EXPECT_EQ(attachmentType, GL_NONE);
2158     }
2159 
2160     for (int i = 0; i < MAX_DRAW_BUFFERS; ++i)
2161     {
2162         GLint drawBuffer;
2163         glGetIntegerv(GL_DRAW_BUFFER0 + i, &drawBuffer);
2164         if (i % 3 == 0)
2165         {
2166             EXPECT_EQ(drawBuffer, GL_NONE);
2167         }
2168         else
2169         {
2170             EXPECT_EQ(drawBuffer, GL_COLOR_ATTACHMENT0 + i);
2171         }
2172     }
2173 
2174     if (hasDrawBuffersIndexedOES)
2175     {
2176         for (int i = 0; i < MAX_DRAW_BUFFERS; ++i)
2177         {
2178             EXPECT_EQ(glIsEnablediOES(GL_BLEND, i), i % 2 == 1);
2179             // glGetBooleani_v is not in ES3.
2180             using ColorMaskInt = std::array<GLint, 4>;
2181             ColorMaskInt mask;
2182             glGetIntegeri_v(GL_COLOR_WRITEMASK, i, mask.data());
2183             EXPECT_EQ(mask, (ColorMaskInt{i % 3 == 0, i % 3 == 1, i % 3 == 2, i % 2 == 0}));
2184         }
2185     }
2186     else
2187     {
2188         EXPECT_TRUE(glIsEnabled(GL_BLEND));
2189         using ColorMask = std::array<GLboolean, 4>;
2190         ColorMask mask;
2191         glGetBooleanv(GL_COLOR_WRITEMASK, mask.data());
2192         EXPECT_EQ(mask, (ColorMask{GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE}));
2193     }
2194 
2195     EXPECT_TRUE(glIsEnabled(GL_SCISSOR_TEST));
2196 
2197     std::array<GLint, 4> scissorBox;
2198     glGetIntegerv(GL_SCISSOR_BOX, scissorBox.data());
2199     EXPECT_EQ(scissorBox, (std::array<GLint, 4>{2, 2, 4, 4}));
2200 
2201     std::array<GLint, 4> viewport;
2202     glGetIntegerv(GL_VIEWPORT, viewport.data());
2203     EXPECT_EQ(viewport, (std::array<GLint, 4>{1, 1, 5, 5}));
2204 
2205     GLint drawFramebuffer;
2206     glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFramebuffer);
2207     EXPECT_EQ(static_cast<GLuint>(drawFramebuffer), fbo);
2208 
2209     ASSERT_GL_NO_ERROR();
2210 }
2211 
2212 // Check that application-facing ES3 state is not perturbed by pixel local storage.
TEST_P(PixelLocalStorageTest,StateRestoration)2213 TEST_P(PixelLocalStorageTest, StateRestoration)
2214 {
2215     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
2216 
2217     doStateRestorationTest();
2218 }
2219 
doDrawStateTest()2220 void PixelLocalStorageTest::doDrawStateTest()
2221 {
2222     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
2223 
2224     glEnable(GL_BLEND);
2225     glBlendFunc(GL_ZERO, GL_ONE);
2226 
2227     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
2228 
2229     glEnable(GL_CULL_FACE);
2230     glCullFace(GL_FRONT_AND_BACK);
2231 
2232     glEnable(GL_DEPTH_TEST);
2233     glDepthFunc(GL_NEVER);
2234 
2235     glEnable(GL_POLYGON_OFFSET_FILL);
2236     glPolygonOffset(1e9f, 1e9f);
2237 
2238     glEnable(GL_SCISSOR_TEST);
2239     glScissor(0, 0, 1, 1);
2240 
2241     glEnable(GL_STENCIL_TEST);
2242     glStencilFunc(GL_NEVER, 0, 0);
2243 
2244     if (isContextVersionAtLeast(3, 1))
2245     {
2246         glEnable(GL_SAMPLE_MASK);
2247         glSampleMaski(0, 0);
2248     }
2249 
2250     glViewport(0, 0, 1, 1);
2251 
2252     glClearColor(.1f, .2f, .3f, .4f);
2253 
2254     // Issue a draw to ensure GL state gets synced.
2255     PLSTestTexture tex(GL_RGBA8);
2256     renderTextureToDefaultFramebuffer(tex);
2257 
2258     GLFramebuffer fbo;
2259     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2260 
2261     GLuint depthStencil;
2262     glGenRenderbuffers(1, &depthStencil);
2263     glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
2264     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, W, H);
2265     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2266                               depthStencil);
2267 
2268     glFramebufferTexturePixelLocalStorageANGLE(0, tex, 0, 0);
2269 
2270     mProgram.compile(R"(
2271         layout(binding=0, rgba8) uniform lowp pixelLocalANGLE pls;
2272         void main()
2273         {
2274             pixelLocalStoreANGLE(pls, vec4(1, 0, 0, 1));
2275         })");
2276 
2277     // Clear to green. This should work regardless of draw state.
2278     glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(0, 1, 0, 1));
2279     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE}));
2280 
2281     // Draw a red box. This should not go through because the blocking draw state should have been
2282     // restored after the clear.
2283     mProgram.drawBoxes({{FULLSCREEN}});
2284 
2285     // Store PLS to the texture. This should work again even though the blocking draw state was
2286     // synced for the previous draw.
2287     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE}));
2288 
2289     attachTexture2DToScratchFBO(tex);
2290     EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor(0, 255, 0, 255));
2291 
2292     ASSERT_GL_NO_ERROR();
2293 }
2294 
2295 // Check that draw state does not affect PLS loads and stores, particularly for
2296 // EXT_shader_pixel_local_storage, where they are implemented as fullscreen draws.
TEST_P(PixelLocalStorageTest,DrawStateReset)2297 TEST_P(PixelLocalStorageTest, DrawStateReset)
2298 {
2299     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
2300 
2301     doDrawStateTest();
2302 }
2303 
2304 // Check that blend and color mask state do not affect pixel local storage, and that PLS does not
2305 // affect blend or color mask on the application's draw buffers.
TEST_P(PixelLocalStorageTest,BlendAndColorMask)2306 TEST_P(PixelLocalStorageTest, BlendAndColorMask)
2307 {
2308     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
2309 
2310     PLSTestTexture tex1(GL_RGBA8);
2311     PLSTestTexture tex2(GL_RGBA8);
2312     PLSTestTexture tex3(GL_RGBA8);
2313     PLSTestTexture tex4(GL_RGBA8);
2314 
2315     GLFramebuffer fbo;
2316     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2317     glViewport(0, 0, W, H);
2318 
2319     if (!IsGLExtensionEnabled("GL_OES_draw_buffers_indexed") ||
2320         MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE < 2)
2321     {
2322         // Blend should not affect pixel local storage.
2323         glEnable(GL_BLEND);
2324         glBlendFunc(GL_ZERO, GL_ONE);
2325 
2326         // Color mask should not affect pixel local storage.
2327         glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
2328 
2329         mProgram.compile(R"(
2330         layout(binding=0, rgba8) uniform lowp pixelLocalANGLE pls1;
2331         layout(binding=1, rgba8) uniform lowp pixelLocalANGLE pls2;
2332         layout(binding=2, rgba8) uniform lowp pixelLocalANGLE pls3;
2333         layout(binding=3, rgba8) uniform lowp pixelLocalANGLE pls4;
2334         void main()
2335         {
2336             pixelLocalStoreANGLE(pls1, vec4(1, 0, 0, 1));
2337             pixelLocalStoreANGLE(pls2, vec4(0, 1, 0, 1));
2338             pixelLocalStoreANGLE(pls3, vec4(0, 0, 1, 1));
2339             pixelLocalStoreANGLE(pls4, vec4(0, 0, 0, 1));
2340         })");
2341 
2342         glFramebufferTexturePixelLocalStorageANGLE(0, tex1, 0, 0);
2343         glFramebufferTexturePixelLocalStorageANGLE(1, tex2, 0, 0);
2344         glFramebufferTexturePixelLocalStorageANGLE(2, tex3, 0, 0);
2345         glFramebufferTexturePixelLocalStorageANGLE(3, tex4, 0, 0);
2346 
2347         glBeginPixelLocalStorageANGLE(
2348             4, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE,
2349                             GL_LOAD_OP_ZERO_ANGLE}));
2350     }
2351     else
2352     {
2353         mProgram.compile(R"(
2354         layout(binding=0, rgba8) uniform lowp pixelLocalANGLE pls1;
2355         layout(binding=1, rgba8) uniform lowp pixelLocalANGLE pls2;
2356         layout(location=0) out lowp vec4 out1;
2357         layout(location=1) out lowp vec4 out2;
2358         void main()
2359         {
2360             out1 = vec4(0, 1, 1, 0);
2361             out2 = vec4(1, 1, 0, 0);
2362             pixelLocalStoreANGLE(pls1, vec4(0, 0, 1, 1));
2363             pixelLocalStoreANGLE(pls2, vec4(0, 0, 0, 1));
2364         })");
2365 
2366         std::vector<GLColor> whiteData(H * W, GLColor::white);
2367         glBindTexture(GL_TEXTURE_2D, tex1);
2368         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, whiteData.data());
2369 
2370         glEnablei(GL_BLEND, 0);
2371         glBlendEquationi(0, GL_FUNC_REVERSE_SUBTRACT);
2372         glBlendFunci(0, GL_ONE, GL_ONE);
2373 
2374         std::vector<GLColor> blackData(H * W, GLColor::black);
2375         glBindTexture(GL_TEXTURE_2D, tex2);
2376         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, blackData.data());
2377 
2378         glColorMaski(1, GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE);
2379 
2380         for (int i = 2; i < MAX_DRAW_BUFFERS; ++i)
2381         {
2382             // Blend should not affect pixel local storage.
2383             glEnablei(GL_BLEND, i);
2384             glBlendFunci(i, GL_ZERO, GL_ONE);
2385 
2386             // Color mask should not affect pixel local storage.
2387             glColorMaski(i, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
2388         }
2389 
2390         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex1, 0);
2391         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex2, 0);
2392         glFramebufferTexturePixelLocalStorageANGLE(0, tex3, 0, 0);
2393         glFramebufferTexturePixelLocalStorageANGLE(1, tex4, 0, 0);
2394         glDrawBuffers(2, GLenumArray({GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}));
2395 
2396         glBeginPixelLocalStorageANGLE(2,
2397                                       GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE}));
2398     }
2399 
2400     mProgram.drawBoxes({{FULLSCREEN}});
2401 
2402     int n;
2403     glGetIntegerv(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, &n);
2404     glEndPixelLocalStorageANGLE(n, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE,
2405                                                 GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE}));
2406 
2407     attachTexture2DToScratchFBO(tex1);
2408     EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::red);
2409 
2410     attachTexture2DToScratchFBO(tex2);
2411     EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::green);
2412 
2413     attachTexture2DToScratchFBO(tex3);
2414     EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::blue);
2415 
2416     attachTexture2DToScratchFBO(tex4);
2417     EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::black);
2418 
2419     ASSERT_GL_NO_ERROR();
2420 }
2421 
2422 // Check that PLS and EXT_shader_framebuffer_fetch can be used together.
TEST_P(PixelLocalStorageTest,ParallelFramebufferFetch)2423 TEST_P(PixelLocalStorageTest, ParallelFramebufferFetch)
2424 {
2425     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
2426     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch"));
2427     ANGLE_SKIP_TEST_IF(MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE == 0);
2428 
2429     mProgram.compile("#extension GL_EXT_shader_framebuffer_fetch : require", R"(
2430     layout(binding=0, rgba8) uniform mediump pixelLocalANGLE pls;
2431     inout highp vec4 fbfetch;
2432     void main()
2433     {
2434         // Swap pls and fbfetch.
2435         vec4 tmp = pixelLocalLoadANGLE(pls);
2436         pixelLocalStoreANGLE(pls, fbfetch);
2437         fbfetch = tmp;
2438     })");
2439 
2440     PLSTestTexture pls(GL_RGBA8), fbfetch(GL_RGBA8);
2441 
2442     GLFramebuffer fbo;
2443     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2444     glFramebufferTexturePixelLocalStorageANGLE(0, pls, 0, 0);
2445     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbfetch, 0);
2446 
2447     glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(0, 1, 0, 1));
2448     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE}));
2449 
2450     GLfloat red[] = {1, 0, 0, 1};
2451     glClearBufferfv(GL_COLOR, 0, red);
2452 
2453     // Swap pls and fbfetch.
2454     mProgram.drawBoxes({{FULLSCREEN}});
2455 
2456     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE}));
2457 
2458     EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::green);
2459 
2460     attachTexture2DToScratchFBO(pls);
2461     EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::red);
2462 }
2463 
2464 // Check that PLS gets properly cleaned up when its framebuffer and textures are never deleted.
TEST_P(PixelLocalStorageTest,LeakFramebufferAndTexture)2465 TEST_P(PixelLocalStorageTest, LeakFramebufferAndTexture)
2466 {
2467     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
2468 
2469     GLuint fbo;
2470     glGenFramebuffers(1, &fbo);
2471     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2472 
2473     GLuint tex0;
2474     glGenTextures(1, &tex0);
2475     glBindTexture(GL_TEXTURE_2D, tex0);
2476     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8UI, 10, 10);
2477     glFramebufferTexturePixelLocalStorageANGLE(0, tex0, 0, 0);
2478 
2479     PLSTestTexture tex1(GL_R32F);
2480     glFramebufferTexturePixelLocalStorageANGLE(1, tex1, 0, 0);
2481 
2482     glFramebufferMemorylessPixelLocalStorageANGLE(3, GL_RGBA8I);
2483 
2484     // Delete tex1.
2485     // Don't delete tex0.
2486     // Don't delete fbo.
2487 
2488     // The PixelLocalStorage frontend implementation has internal assertions that verify all its GL
2489     // context objects are properly disposed of.
2490 }
2491 
2492 // Check that sampler, texture, and PLS bindings all work when they are used in the same shader.
TEST_P(PixelLocalStorageTest,PLSWithSamplers)2493 TEST_P(PixelLocalStorageTest, PLSWithSamplers)
2494 {
2495     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
2496 
2497     GLFramebuffer fbo;
2498     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2499 
2500     PLSTestTexture tex0(GL_RGBA8);
2501     std::vector<GLColor> redData(H * H, GLColor::red);
2502     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, redData.data());
2503 
2504     PLSTestTexture tex1(GL_RGBA8);
2505     std::vector<GLColor> blueData(H * H, GLColor::blue);
2506     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, blueData.data());
2507 
2508     PLSTestTexture pls0(GL_RGBA8);
2509     std::vector<GLColor> greenData(H * H, GLColor::green);
2510     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, W, H, GL_RGBA, GL_UNSIGNED_BYTE, greenData.data());
2511 
2512     PLSTestTexture pls1(GL_RGBA8);
2513     PLSTestTexture pls2(GL_RGBA8);
2514 
2515     glViewport(0, 0, W, H);
2516 
2517     glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0);
2518     glFramebufferTexturePixelLocalStorageANGLE(1, pls1, 0, 0);
2519     glFramebufferTexturePixelLocalStorageANGLE(2, pls2, 0, 0);
2520 
2521     mProgram.compile(R"(
2522     layout(binding=0, rgba8) uniform mediump pixelLocalANGLE pls0;
2523     layout(binding=1, rgba8) uniform mediump pixelLocalANGLE pls1;
2524     layout(binding=2, rgba8) uniform mediump pixelLocalANGLE pls2;
2525     uniform mediump sampler2D tex0;
2526     uniform mediump sampler2D tex1;
2527     void main()
2528     {
2529         vec4 value;
2530         if (gl_FragCoord.y > 50.0)
2531         {
2532             if (gl_FragCoord.x > 50.0)
2533                 value = texture(tex1, color.xy);
2534             else
2535                 value = texture(tex0, color.xy);
2536         }
2537         else
2538         {
2539             if (gl_FragCoord.x > 50.0)
2540                 value = pixelLocalLoadANGLE(pls1);
2541             else
2542                 value = pixelLocalLoadANGLE(pls0);
2543         }
2544         pixelLocalStoreANGLE(pls2, value);
2545         pixelLocalStoreANGLE(pls1, vec4(0, 1, 1, 1));
2546     })");
2547     glUniform1i(glGetUniformLocation(mProgram, "tex0"), 0);
2548     glUniform1i(glGetUniformLocation(mProgram, "tex1"), 3);
2549 
2550     glFramebufferPixelLocalClearValuefvANGLE(1, ClearF(1, 1, 0, 1));
2551     glBeginPixelLocalStorageANGLE(
2552         3, GLenumArray({GL_LOAD_OP_LOAD_ANGLE, GL_LOAD_OP_CLEAR_ANGLE, GL_DONT_CARE}));
2553 
2554     glBindTexture(GL_TEXTURE_2D, tex0);
2555 
2556     glActiveTexture(GL_TEXTURE3);
2557     glBindTexture(GL_TEXTURE_2D, tex1);
2558 
2559     mProgram.drawBoxes({{FULLSCREEN, {0, 0, 1, 1}}});
2560     glEndPixelLocalStorageANGLE(3, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE,
2561                                                 GL_STORE_OP_STORE_ANGLE}));
2562 
2563     attachTexture2DToScratchFBO(pls2);
2564     EXPECT_PIXEL_RECT_EQ(0, 0, 50, 50, GLColor::green);
2565     EXPECT_PIXEL_RECT_EQ(50, 0, W - 50, 50, GLColor::yellow);
2566     EXPECT_PIXEL_RECT_EQ(0, 50, 50, H - 50, GLColor::red);
2567     EXPECT_PIXEL_RECT_EQ(50, 50, W - 50, H - 50, GLColor::blue);
2568 
2569     attachTexture2DToScratchFBO(pls1);
2570     EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::cyan);
2571 
2572     attachTexture2DToScratchFBO(pls0);
2573     EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::green);
2574 
2575     ASSERT_GL_NO_ERROR();
2576 }
2577 
2578 // Check the PLS interruption mechanism.
TEST_P(PixelLocalStorageTest,Interrupt)2579 TEST_P(PixelLocalStorageTest, Interrupt)
2580 {
2581     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
2582 
2583     PLSTestTexture t(GL_RGBA8);
2584     PLSTestTexture u0(GL_R32UI);
2585     PLSTestTexture u1(GL_R32UI);
2586     PLSTestTexture u2(GL_R32UI);
2587 
2588     GLFramebuffer f;
2589     glBindFramebuffer(GL_FRAMEBUFFER, f);
2590     glFramebufferTexturePixelLocalStorageANGLE(0, t, 0, 0);
2591 
2592     GLFramebuffer g;
2593     glBindFramebuffer(GL_FRAMEBUFFER, g);
2594     glFramebufferTexturePixelLocalStorageANGLE(0, u0, 0, 0);
2595     glFramebufferTexturePixelLocalStorageANGLE(1, u1, 0, 0);
2596     glFramebufferTexturePixelLocalStorageANGLE(2, u2, 0, 0);
2597 
2598     glViewport(0, 0, W, H);
2599     glDrawBuffers(0, nullptr);
2600 
2601     PLSProgram p;
2602     p.compile(R"(
2603     layout(binding=0, rgba8) uniform highp pixelLocalANGLE t;
2604     void main()
2605     {
2606         pixelLocalStoreANGLE(t, color + pixelLocalLoadANGLE(t));
2607     })");
2608 
2609     PLSProgram q;
2610     q.compile(R"(
2611     layout(binding=0, r32ui) uniform highp upixelLocalANGLE u0;
2612     layout(binding=1, r32ui) uniform highp upixelLocalANGLE u1;
2613     layout(binding=2, r32ui) uniform highp upixelLocalANGLE u2;
2614     void main()
2615     {
2616         pixelLocalStoreANGLE(u0, (pixelLocalLoadANGLE(u1) << 8) | 0xau);
2617         pixelLocalStoreANGLE(u1, (pixelLocalLoadANGLE(u2) << 8) | 0xbu);
2618         pixelLocalStoreANGLE(u2, (pixelLocalLoadANGLE(u0) << 8) | 0xcu);
2619     })");
2620 
2621     // Interleave 2 PLS rendering passes.
2622     glBindFramebuffer(GL_FRAMEBUFFER, f);
2623     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
2624     p.bind();
2625     p.drawBoxes({{{FULLSCREEN}, {1, 0, 0, 0}}});
2626     glFramebufferPixelLocalStorageInterruptANGLE();
2627 
2628     glBindFramebuffer(GL_FRAMEBUFFER, g);
2629     q.bind();
2630     glBeginPixelLocalStorageANGLE(
2631         3, GLenumArray({GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_ZERO_ANGLE}));
2632     q.drawBoxes({{{FULLSCREEN}}});
2633     glFramebufferPixelLocalStorageInterruptANGLE();
2634 
2635     p.bind();
2636     glBindFramebuffer(GL_FRAMEBUFFER, f);
2637     glFramebufferPixelLocalStorageRestoreANGLE();
2638     p.drawBoxes({{{FULLSCREEN}, {0, 0, 0, 1}}});
2639     glFramebufferPixelLocalStorageInterruptANGLE();
2640 
2641     glBindFramebuffer(GL_FRAMEBUFFER, g);
2642     glFramebufferPixelLocalStorageRestoreANGLE();
2643     q.bind();
2644     q.drawBoxes({{{FULLSCREEN}}});
2645     glFramebufferPixelLocalStorageInterruptANGLE();
2646 
2647     glBindFramebuffer(GL_FRAMEBUFFER, f);
2648     glFramebufferPixelLocalStorageRestoreANGLE();
2649     p.bind();
2650     p.drawBoxes({{{FULLSCREEN}, {0, 0, 1, 0}}});
2651     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE}));
2652 
2653     q.bind();
2654     glBindFramebuffer(GL_FRAMEBUFFER, g);
2655     glFramebufferPixelLocalStorageRestoreANGLE();
2656     q.drawBoxes({{{FULLSCREEN}}});
2657     glEndPixelLocalStorageANGLE(3, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE,
2658                                                 GL_STORE_OP_STORE_ANGLE}));
2659 
2660     attachTexture2DToScratchFBO(t);
2661     EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor(255, 0, 255, 255));
2662     ASSERT_GL_NO_ERROR();
2663 
2664     attachTexture2DToScratchFBO(u0);
2665     EXPECT_PIXEL_RECT32UI_EQ(0, 0, W, H, GLColor32UI(0x0a0c0b0a, 0, 0, 1));
2666 
2667     attachTexture2DToScratchFBO(u1);
2668     EXPECT_PIXEL_RECT32UI_EQ(0, 0, W, H, GLColor32UI(0x0b0a0c0b, 0, 0, 1));
2669 
2670     attachTexture2DToScratchFBO(u2);
2671     EXPECT_PIXEL_RECT32UI_EQ(0, 0, W, H, GLColor32UI(0x0c0b0a0c, 0, 0, 1));
2672 
2673     ASSERT_GL_NO_ERROR();
2674 }
2675 
2676 // Check that deleting attachments and PLS bindings on the current draw framebuffer implicitly
2677 // deactivates pixel local storage.
TEST_P(PixelLocalStorageTest,DeleteAttachments_draw_framebuffer)2678 TEST_P(PixelLocalStorageTest, DeleteAttachments_draw_framebuffer)
2679 {
2680     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
2681 
2682     GLFramebuffer fbo;
2683     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
2684 
2685     GLuint depthStencil;
2686     glGenRenderbuffers(1, &depthStencil);
2687     glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
2688     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, W, H);
2689     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2690                               depthStencil);
2691     EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthStencil);
2692     EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthStencil);
2693 
2694     PLSTestTexture colorTex(GL_RGBA8);
2695     if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 0)
2696     {
2697         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
2698         EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTex);
2699     }
2700 
2701     GLuint colorRenderbuffer;
2702     if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 1)
2703     {
2704         glGenRenderbuffers(1, &colorRenderbuffer);
2705         glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
2706         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, W, H);
2707         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
2708                                   colorRenderbuffer);
2709         EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, colorRenderbuffer);
2710     }
2711 
2712     PLSTestTexture pls0(GL_RGBA8);
2713     glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0);
2714     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, pls0);
2715 
2716     PLSTestTexture pls1(GL_RGBA8);
2717     glFramebufferTexturePixelLocalStorageANGLE(1, pls1, 0, 0);
2718     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, pls1);
2719 
2720     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
2721     EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 1);
2722     ASSERT_GL_NO_ERROR();
2723 
2724     // Deleting the depth/stencil will implicitly end pixel local storage.
2725     glDeleteRenderbuffers(1, &depthStencil);
2726     EXPECT_GL_NO_ERROR();
2727     EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
2728     EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 0);
2729     EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, 0);
2730 
2731     if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 0)
2732     {
2733         // Deleting the color texture will implicitly end pixel local storage.
2734         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
2735         colorTex.reset();
2736         EXPECT_GL_NO_ERROR();
2737         EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
2738         EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0);
2739     }
2740 
2741     if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 1)
2742     {
2743         // Deleting the color renderbuffer will implicitly end pixel local storage.
2744         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
2745         glDeleteRenderbuffers(1, &colorRenderbuffer);
2746         EXPECT_GL_NO_ERROR();
2747         EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
2748         EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0);
2749     }
2750 
2751     // Pixel local storage can't be ended because it's already deactivated.
2752     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
2753     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
2754 
2755     // Deleting an inactive PLS plane will implicitly end pixel local storage.
2756     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
2757     pls1.reset();
2758     EXPECT_GL_NO_ERROR();
2759     EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
2760     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 0);
2761 
2762     // Deleting an active PLS plane will implicitly end pixel local storage.
2763     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
2764     pls0.reset();
2765     EXPECT_GL_NO_ERROR();
2766     EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
2767     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 0);
2768 
2769     // Deleting the textures deinitialized the planes.
2770     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
2771     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
2772     EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
2773 }
2774 
2775 // Check that deleting attachments and PLS bindings on the current read framebuffer does *not*
2776 // deactivate pixel local storage.
TEST_P(PixelLocalStorageTest,DeleteAttachments_read_framebuffer)2777 TEST_P(PixelLocalStorageTest, DeleteAttachments_read_framebuffer)
2778 {
2779     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
2780 
2781     // Deleting attachments on the read framebuffer does not turn off PLS.
2782     GLFramebuffer readFBO;
2783     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2784 
2785     GLuint depthStencil;
2786     glGenRenderbuffers(1, &depthStencil);
2787     glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
2788     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, W, H);
2789     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2790                               depthStencil);
2791     EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthStencil);
2792     EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthStencil);
2793 
2794     PLSTestTexture colorTex(GL_RGBA8);
2795     if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 0)
2796     {
2797         colorTex.reset(GL_RGBA8);
2798         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex,
2799                                0);
2800         EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTex);
2801     }
2802 
2803     GLuint colorRenderbuffer;
2804     if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 1)
2805     {
2806         glGenRenderbuffers(1, &colorRenderbuffer);
2807         glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
2808         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, W, H);
2809         glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
2810                                   colorRenderbuffer);
2811         EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
2812                                            colorRenderbuffer);
2813     }
2814 
2815     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, readFBO);
2816 
2817     PLSTestTexture inactivePLS0(GL_RGBA8);
2818     glFramebufferTexturePixelLocalStorageANGLE(0, inactivePLS0, 0, 0);
2819     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, inactivePLS0);
2820 
2821     PLSTestTexture inactivePLS1(GL_RGBA8);
2822     glFramebufferTexturePixelLocalStorageANGLE(1, inactivePLS1, 0, 0);
2823     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, inactivePLS1);
2824 
2825     GLFramebuffer fbo;
2826     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
2827 
2828     PLSTestTexture activePLS(GL_RGBA8);
2829     glFramebufferTexturePixelLocalStorageANGLE(0, activePLS, 0, 0);
2830     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
2831     EXPECT_GL_NO_ERROR();
2832     EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 1);
2833 
2834     glDeleteRenderbuffers(1, &depthStencil);
2835     EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 0);
2836     EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, 0);
2837     if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 0)
2838     {
2839         colorTex.reset();
2840         EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0);
2841     }
2842 
2843     if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 1)
2844     {
2845         glDeleteRenderbuffers(1, &colorRenderbuffer);
2846         EXPECT_FRAMEBUFFER_ATTACHMENT_NAME(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 0);
2847     }
2848     inactivePLS0.reset();
2849     inactivePLS1.reset();
2850 
2851     EXPECT_GL_NO_ERROR();
2852     EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 1);
2853 
2854     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
2855     EXPECT_GL_NO_ERROR();
2856 
2857     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, readFBO);
2858     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 0);
2859     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 0);
2860 }
2861 
2862 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PixelLocalStorageTest);
2863 #define PLATFORM(API, BACKEND) API##_##BACKEND()
2864 #define PLS_INSTANTIATE_RENDERING_TEST_AND(TEST, API, ...)                                \
2865     ANGLE_INSTANTIATE_TEST(                                                               \
2866         TEST,                                                                             \
2867         PLATFORM(API, D3D11) /* D3D coherent. */                                          \
2868             .enable(Feature::EmulatePixelLocalStorage),                                   \
2869         PLATFORM(API, D3D11) /* D3D noncoherent. */                                       \
2870             .enable(Feature::DisableRasterizerOrderViews)                                 \
2871             .enable(Feature::EmulatePixelLocalStorage),                                   \
2872         PLATFORM(API, OPENGL) /* OpenGL coherent. */                                      \
2873             .enable(Feature::EmulatePixelLocalStorage),                                   \
2874         PLATFORM(API, OPENGL) /* OpenGL noncoherent. */                                   \
2875             .enable(Feature::EmulatePixelLocalStorage)                                    \
2876             .disable(Feature::SupportsFragmentShaderInterlockNV)                          \
2877             .disable(Feature::SupportsFragmentShaderOrderingINTEL)                        \
2878             .disable(Feature::SupportsFragmentShaderInterlockARB),                        \
2879         PLATFORM(API, OPENGLES) /* OpenGL ES coherent */                                  \
2880             .enable(Feature::EmulatePixelLocalStorage),                                   \
2881         PLATFORM(API, OPENGLES) /* OpenGL ES noncoherent                                  \
2882                                    (EXT_shader_framebuffer_fetch_non_coherent). */        \
2883             .enable(Feature::EmulatePixelLocalStorage)                                    \
2884             .disable(Feature::SupportsShaderFramebufferFetchEXT)                          \
2885             .disable(Feature::SupportsShaderPixelLocalStorageEXT),                        \
2886         PLATFORM(API, OPENGLES) /* OpenGL ES noncoherent (shader images). */              \
2887             .enable(Feature::EmulatePixelLocalStorage)                                    \
2888             .disable(Feature::SupportsShaderFramebufferFetchEXT)                          \
2889             .disable(Feature::SupportsShaderFramebufferFetchNonCoherentEXT)               \
2890             .disable(Feature::SupportsShaderPixelLocalStorageEXT),                        \
2891         PLATFORM(API, VULKAN) /* Vulkan coherent. */                                      \
2892             .enable(Feature::AsyncCommandQueue)                                           \
2893             .enable(Feature::EmulatePixelLocalStorage),                                   \
2894         PLATFORM(API, VULKAN) /* Vulkan noncoherent. */                                   \
2895             .disable(Feature::SupportsShaderFramebufferFetch)                             \
2896             .disable(Feature::SupportsFragmentShaderPixelInterlock)                       \
2897             .enable(Feature::EmulatePixelLocalStorage),                                   \
2898         PLATFORM(API, VULKAN_SWIFTSHADER) /* Swiftshader coherent (framebuffer fetch). */ \
2899             .enable(Feature::AsyncCommandQueue)                                           \
2900             .enable(Feature::EmulatePixelLocalStorage),                                   \
2901         PLATFORM(API, VULKAN_SWIFTSHADER) /* Swiftshader noncoherent. */                  \
2902             .disable(Feature::SupportsShaderFramebufferFetch)                             \
2903             .disable(Feature::SupportsFragmentShaderPixelInterlock)                       \
2904             .enable(Feature::AsyncCommandQueue)                                           \
2905             .enable(Feature::EmulatePixelLocalStorage),                                   \
2906         PLATFORM(API, VULKAN_SWIFTSHADER) /* Test PLS not having access to                \
2907                                              glEnablei/glDisablei/glColorMaski. */        \
2908             .enable(Feature::EmulatePixelLocalStorage)                                    \
2909             .enable(Feature::DisableDrawBuffersIndexed),                                  \
2910         __VA_ARGS__)
2911 
2912 #define PLS_INSTANTIATE_RENDERING_TEST_ES3(TEST)                                                   \
2913     PLS_INSTANTIATE_RENDERING_TEST_AND(                                                            \
2914         TEST, ES3, /* Metal, coherent (in tiled memory on Apple Silicon).*/                        \
2915         ES3_METAL().enable(Feature::EmulatePixelLocalStorage), /* Metal, coherent via raster order \
2916                                                                   groups + read_write textures.*/  \
2917         ES3_METAL()                                                                                \
2918             .enable(Feature::EmulatePixelLocalStorage)                                             \
2919             .enable(Feature::DisableProgrammableBlending), /* Metal, coherent, r32 packed          \
2920                                                               read_write texture formats.*/        \
2921         ES3_METAL()                                                                                \
2922             .enable(Feature::EmulatePixelLocalStorage)                                             \
2923             .enable(Feature::DisableProgrammableBlending)                                          \
2924             .enable(Feature::DisableRWTextureTier2Support), /* Metal, noncoherent if not on Apple  \
2925                                                                Silicon. (Apple GPUs don't support  \
2926                                                                fragment-to-fragment memory         \
2927                                                                barriers.)*/                        \
2928         ES3_METAL()                                                                                \
2929             .enable(Feature::EmulatePixelLocalStorage)                                             \
2930             .enable(Feature::DisableRasterOrderGroups))
2931 
2932 #define PLS_INSTANTIATE_RENDERING_TEST_ES31(TEST) PLS_INSTANTIATE_RENDERING_TEST_AND(TEST, ES31)
2933 
2934 PLS_INSTANTIATE_RENDERING_TEST_ES3(PixelLocalStorageTest);
2935 
2936 class PixelLocalStorageTestES31 : public PixelLocalStorageTest
2937 {};
2938 
2939 // Check that early_fragment_tests are not triggered when PLS uniforms are not declared.
TEST_P(PixelLocalStorageTestES31,EarlyFragmentTests)2940 TEST_P(PixelLocalStorageTestES31, EarlyFragmentTests)
2941 {
2942     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
2943 
2944     PLSTestTexture tex(GL_RGBA8);
2945     GLFramebuffer fbo;
2946     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2947     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
2948 
2949     GLuint stencil;
2950     glGenRenderbuffers(1, &stencil);
2951     glBindRenderbuffer(GL_RENDERBUFFER, stencil);
2952     glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, W, H);
2953     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencil);
2954     glClearStencil(0);
2955     glClear(GL_STENCIL_BUFFER_BIT);
2956 
2957     glEnable(GL_STENCIL_TEST);
2958     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
2959 
2960     // Emits a fullscreen quad.
2961     constexpr char kFullscreenVS[] = R"(#version 310 es
2962     precision highp float;
2963     void main()
2964     {
2965         gl_Position.x = (gl_VertexID & 1) == 0 ? -1.0 : 1.0;
2966         gl_Position.y = (gl_VertexID & 2) == 0 ? -1.0 : 1.0;
2967         gl_Position.zw = vec2(0, 1);
2968     })";
2969 
2970     // Renders green to the framebuffer.
2971     constexpr char kDrawRed[] = R"(#version 310 es
2972     out mediump vec4 fragColor;
2973     void main()
2974     {
2975         fragColor = vec4(1, 0, 0, 1);
2976     })";
2977 
2978     ANGLE_GL_PROGRAM(drawGreen, kFullscreenVS, kDrawRed);
2979 
2980     // Render to stencil without PLS uniforms and with a discard. Since we discard, and since the
2981     // shader shouldn't enable early_fragment_tests, stencil should not be affected.
2982     constexpr char kNonPLSDiscard[] = R"(#version 310 es
2983     #extension GL_ANGLE_shader_pixel_local_storage : enable
2984     void f(highp ipixelLocalANGLE pls)
2985     {
2986         // Function arguments don't trigger PLS restrictions.
2987         pixelLocalStoreANGLE(pls, ivec4(8));
2988     }
2989     void main()
2990     {
2991         discard;
2992     })";
2993     ANGLE_GL_PROGRAM(lateDiscard, kFullscreenVS, kNonPLSDiscard);
2994     glUseProgram(lateDiscard);
2995     glStencilFunc(GL_ALWAYS, 1, ~0u);
2996     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2997 
2998     // Clear the framebuffer to green.
2999     glClearColor(0, 1, 0, 1);
3000     glClear(GL_COLOR_BUFFER_BIT);
3001 
3002     // Render red to the framebuffer with a stencil test. This should have no effect because the
3003     // stencil buffer should be all zeros.
3004     glUseProgram(drawGreen);
3005     glStencilFunc(GL_NOTEQUAL, 0, ~0u);
3006     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3007     EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::green);
3008 
3009     // Now double check that this test would have failed if the shader had enabled
3010     // early_fragment_tests. Render to stencil *with* early_fragment_tests and a discard. Stencil
3011     // should be affected this time even though we discard.
3012     ANGLE_GL_PROGRAM(earlyDiscard, kFullscreenVS,
3013                      (std::string(kNonPLSDiscard) + "layout(early_fragment_tests) in;").c_str());
3014     glUseProgram(earlyDiscard);
3015     glStencilFunc(GL_ALWAYS, 1, ~0u);
3016     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3017 
3018     // Clear the framebuffer to green.
3019     glClearColor(0, 1, 0, 1);
3020     glClear(GL_COLOR_BUFFER_BIT);
3021 
3022     // Render red to the framebuffer again. This time the stencil test should pass because the
3023     // stencil buffer should be all ones.
3024     glUseProgram(drawGreen);
3025     glStencilFunc(GL_NOTEQUAL, 0, ~0u);
3026     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3027     EXPECT_PIXEL_RECT_EQ(0, 0, W, H, GLColor::red);
3028 
3029     ASSERT_GL_NO_ERROR();
3030 }
3031 
3032 // Check that application-facing ES31 state is not perturbed by pixel local storage.
TEST_P(PixelLocalStorageTestES31,StateRestoration)3033 TEST_P(PixelLocalStorageTestES31, StateRestoration)
3034 {
3035     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
3036 
3037     doStateRestorationTest();
3038 }
3039 
3040 // Check that draw state does not affect PLS loads and stores, particularly for
3041 // EXT_shader_pixel_local_storage, where they are implemented as fullscreen draws.
TEST_P(PixelLocalStorageTestES31,DrawStateReset)3042 TEST_P(PixelLocalStorageTestES31, DrawStateReset)
3043 {
3044     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
3045 
3046     doDrawStateTest();
3047 }
3048 
3049 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PixelLocalStorageTestES31);
3050 PLS_INSTANTIATE_RENDERING_TEST_ES31(PixelLocalStorageTestES31);
3051 
3052 class PixelLocalStorageRequestableExtensionTest : public ANGLETest<>
3053 {
3054   protected:
PixelLocalStorageRequestableExtensionTest()3055     PixelLocalStorageRequestableExtensionTest() { setExtensionsEnabled(false); }
3056 };
3057 
do_implicitly_enabled_extensions_test(const char * plsExtensionToRequest)3058 static void do_implicitly_enabled_extensions_test(const char *plsExtensionToRequest)
3059 {
3060     bool hasDrawBuffersIndexedOES = IsGLExtensionRequestable("GL_OES_draw_buffers_indexed");
3061     bool hasDrawBuffersIndexedEXT = IsGLExtensionRequestable("GL_EXT_draw_buffers_indexed");
3062     bool hasColorBufferFloat      = IsGLExtensionRequestable("GL_EXT_color_buffer_float");
3063     bool hasColorBufferHalfFloat  = IsGLExtensionRequestable("GL_EXT_color_buffer_half_float");
3064     bool hasCoherent = IsGLExtensionRequestable("GL_ANGLE_shader_pixel_local_storage_coherent");
3065 
3066     EXPECT_TRUE(!IsGLExtensionEnabled("GL_OES_draw_buffers_indexed"));
3067     EXPECT_TRUE(!IsGLExtensionEnabled("GL_EXT_draw_buffers_indexed"));
3068     EXPECT_TRUE(!IsGLExtensionEnabled("GL_EXT_color_buffer_float"));
3069     EXPECT_TRUE(!IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"));
3070     EXPECT_TRUE(!IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent"));
3071     EXPECT_TRUE(!IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
3072 
3073     glRequestExtensionANGLE(plsExtensionToRequest);
3074     EXPECT_GL_NO_ERROR();
3075 
3076     if (hasDrawBuffersIndexedOES)
3077     {
3078         EXPECT_TRUE(IsGLExtensionEnabled("GL_OES_draw_buffers_indexed"));
3079     }
3080     if (hasDrawBuffersIndexedEXT)
3081     {
3082         EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_draw_buffers_indexed"));
3083     }
3084     if (hasColorBufferFloat)
3085     {
3086         EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_color_buffer_float"));
3087     }
3088     if (hasColorBufferHalfFloat)
3089     {
3090         EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"));
3091     }
3092     if (hasCoherent)
3093     {
3094         EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent"));
3095     }
3096     EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
3097 
3098     if (hasDrawBuffersIndexedOES)
3099     {
3100         // If OES_draw_buffers_indexed ever becomes disablable, it will have to implicitly disable
3101         // ANGLE_shader_pixel_local_storage.
3102         glDisableExtensionANGLE("GL_OES_draw_buffers_indexed");
3103         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3104         EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
3105         EXPECT_TRUE(IsGLExtensionEnabled("GL_OES_draw_buffers_indexed"));
3106     }
3107 
3108     if (hasDrawBuffersIndexedEXT)
3109     {
3110         // If EXT_draw_buffers_indexed ever becomes disablable, it will have to implicitly disable
3111         // ANGLE_shader_pixel_local_storage.
3112         glDisableExtensionANGLE("GL_EXT_draw_buffers_indexed");
3113         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3114         EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
3115         EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_draw_buffers_indexed"));
3116     }
3117 
3118     if (hasColorBufferFloat)
3119     {
3120         // If EXT_color_buffer_float ever becomes disablable, it will have to implicitly disable
3121         // ANGLE_shader_pixel_local_storage.
3122         glDisableExtensionANGLE("GL_EXT_color_buffer_float");
3123         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3124         EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
3125         EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_color_buffer_float"));
3126     }
3127 
3128     if (hasColorBufferHalfFloat)
3129     {
3130         // If EXT_color_buffer_half_float ever becomes disablable, it will have to implicitly
3131         // disable ANGLE_shader_pixel_local_storage.
3132         glDisableExtensionANGLE("GL_EXT_color_buffer_half_float");
3133         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3134         EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
3135         EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"));
3136     }
3137 
3138     if (hasCoherent)
3139     {
3140         // ANGLE_shader_pixel_local_storage_coherent is not disablable.
3141         glDisableExtensionANGLE("GL_ANGLE_shader_pixel_local_storage_coherent");
3142         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3143         EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
3144         EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent"));
3145     }
3146 
3147     // ANGLE_shader_pixel_local_storage is not disablable.
3148     glDisableExtensionANGLE("GL_ANGLE_shader_pixel_local_storage");
3149     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3150 
3151     // All dependency extensions should have remained enabled.
3152     if (hasDrawBuffersIndexedOES)
3153     {
3154         EXPECT_TRUE(IsGLExtensionEnabled("GL_OES_draw_buffers_indexed"));
3155     }
3156     if (hasDrawBuffersIndexedEXT)
3157     {
3158         EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_draw_buffers_indexed"));
3159     }
3160     if (hasColorBufferFloat)
3161     {
3162         EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_color_buffer_float"));
3163     }
3164     if (hasColorBufferHalfFloat)
3165     {
3166         EXPECT_TRUE(IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"));
3167     }
3168     if (hasCoherent)
3169     {
3170         EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent"));
3171     }
3172     EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
3173 }
3174 
3175 // Check that ANGLE_shader_pixel_local_storage implicitly enables its dependency extensions.
TEST_P(PixelLocalStorageRequestableExtensionTest,ImplicitlyEnabledExtensions)3176 TEST_P(PixelLocalStorageRequestableExtensionTest, ImplicitlyEnabledExtensions)
3177 {
3178     EXPECT_TRUE(IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(),
3179                                              "EGL_ANGLE_create_context_extensions_enabled"));
3180     ANGLE_SKIP_TEST_IF(!IsGLExtensionRequestable("GL_ANGLE_shader_pixel_local_storage"));
3181     do_implicitly_enabled_extensions_test("GL_ANGLE_shader_pixel_local_storage");
3182 }
3183 
3184 // Check that ANGLE_shader_pixel_local_storage_coherent implicitly enables its
3185 // dependency extensions.
TEST_P(PixelLocalStorageRequestableExtensionTest,ImplicitlyEnabledExtensionsCoherent)3186 TEST_P(PixelLocalStorageRequestableExtensionTest, ImplicitlyEnabledExtensionsCoherent)
3187 {
3188     EXPECT_TRUE(IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(),
3189                                              "EGL_ANGLE_create_context_extensions_enabled"));
3190     ANGLE_SKIP_TEST_IF(!IsGLExtensionRequestable("GL_ANGLE_shader_pixel_local_storage"));
3191     if (!IsGLExtensionRequestable("GL_ANGLE_shader_pixel_local_storage_coherent"))
3192     {
3193         // Requesting GL_ANGLE_shader_pixel_local_storage_coherent should not implicitly enable any
3194         // other extensions if the extension itself is not supported.
3195         glRequestExtensionANGLE("GL_ANGLE_shader_pixel_local_storage_coherent");
3196         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3197         EXPECT_TRUE(!IsGLExtensionEnabled("GL_OES_draw_buffers_indexed"));
3198         EXPECT_TRUE(!IsGLExtensionEnabled("GL_EXT_draw_buffers_indexed"));
3199         EXPECT_TRUE(!IsGLExtensionEnabled("GL_EXT_color_buffer_float"));
3200         EXPECT_TRUE(!IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"));
3201         EXPECT_TRUE(!IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent"));
3202         EXPECT_TRUE(!IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
3203     }
3204     else
3205     {
3206         do_implicitly_enabled_extensions_test("GL_ANGLE_shader_pixel_local_storage_coherent");
3207     }
3208 }
3209 
3210 // Check that the dependency extensions of ANGLE_shader_pixel_local_storage do not enable it.
TEST_P(PixelLocalStorageRequestableExtensionTest,ANGLEShaderPixelLocalStorageNotImplicitlyEnabled)3211 TEST_P(PixelLocalStorageRequestableExtensionTest, ANGLEShaderPixelLocalStorageNotImplicitlyEnabled)
3212 {
3213     EXPECT_TRUE(IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(),
3214                                              "EGL_ANGLE_create_context_extensions_enabled"));
3215     ANGLE_SKIP_TEST_IF(!IsGLExtensionRequestable("GL_ANGLE_shader_pixel_local_storage"));
3216 
3217     EnsureGLExtensionEnabled("GL_OES_draw_buffers_indexed");
3218     EnsureGLExtensionEnabled("GL_EXT_draw_buffers_indexed");
3219     EnsureGLExtensionEnabled("GL_EXT_color_buffer_float");
3220     EnsureGLExtensionEnabled("GL_EXT_color_buffer_half_float");
3221     EXPECT_TRUE(!IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent"));
3222     EXPECT_TRUE(!IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
3223 
3224     if (IsGLExtensionRequestable("GL_ANGLE_shader_pixel_local_storage_coherent"))
3225     {
3226         glRequestExtensionANGLE("GL_ANGLE_shader_pixel_local_storage_coherent");
3227         EXPECT_GL_NO_ERROR();
3228         EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent"));
3229         EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
3230     }
3231     else
3232     {
3233         glRequestExtensionANGLE("GL_ANGLE_shader_pixel_local_storage");
3234         EXPECT_GL_NO_ERROR();
3235         EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
3236     }
3237 }
3238 
3239 PLS_INSTANTIATE_RENDERING_TEST_ES3(PixelLocalStorageRequestableExtensionTest);
3240 
3241 class PixelLocalStorageValidationTest : public ANGLETest<>
3242 {
3243   public:
PixelLocalStorageValidationTest()3244     PixelLocalStorageValidationTest() { setExtensionsEnabled(false); }
3245 
3246   protected:
testSetUp()3247     void testSetUp() override
3248     {
3249         ASSERT(EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
3250         glGetIntegerv(GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE, &MAX_PIXEL_LOCAL_STORAGE_PLANES);
3251         glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE,
3252                       &MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE);
3253         glGetIntegerv(GL_MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE,
3254                       &MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES);
3255         glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &MAX_COLOR_ATTACHMENTS);
3256         glGetIntegerv(GL_MAX_DRAW_BUFFERS, &MAX_DRAW_BUFFERS);
3257 
3258         mHasDebugKHR = EnsureGLExtensionEnabled("GL_KHR_debug");
3259         if (mHasDebugKHR)
3260         {
3261             glDebugMessageControlKHR(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR,
3262                                      GL_DEBUG_SEVERITY_HIGH, 0, NULL, GL_TRUE);
3263             glDebugMessageCallbackKHR(&ErrorMessageCallback, this);
3264             glEnable(GL_DEBUG_OUTPUT);
3265             glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
3266         }
3267 
3268         // INVALID_OPERATION is generated if DITHER is enabled.
3269         glDisable(GL_DITHER);
3270 
3271         ANGLETest::testSetUp();
3272     }
3273 
isContextVersionAtLeast(int major,int minor)3274     int isContextVersionAtLeast(int major, int minor)
3275     {
3276         return getClientMajorVersion() > major ||
3277                (getClientMajorVersion() == major && getClientMinorVersion() >= minor);
3278     }
3279 
ErrorMessageCallback(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * message,const void * userParam)3280     static void GL_APIENTRY ErrorMessageCallback(GLenum source,
3281                                                  GLenum type,
3282                                                  GLuint id,
3283                                                  GLenum severity,
3284                                                  GLsizei length,
3285                                                  const GLchar *message,
3286                                                  const void *userParam)
3287     {
3288         auto test = const_cast<PixelLocalStorageValidationTest *>(
3289             static_cast<const PixelLocalStorageValidationTest *>(userParam));
3290         test->mErrorMessages.emplace_back(message);
3291     }
3292 
3293     GLint MAX_PIXEL_LOCAL_STORAGE_PLANES                           = 0;
3294     GLint MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE    = 0;
3295     GLint MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES = 0;
3296     GLint MAX_COLOR_ATTACHMENTS                                    = 0;
3297     GLint MAX_DRAW_BUFFERS                                         = 0;
3298 
3299     bool mHasDebugKHR;
3300     std::vector<std::string> mErrorMessages;
3301 };
3302 
3303 class ScopedEnable
3304 {
3305   public:
ScopedEnable(GLenum feature)3306     ScopedEnable(GLenum feature) : mFeature(feature) { glEnable(mFeature); }
~ScopedEnable()3307     ~ScopedEnable() { glDisable(mFeature); }
3308 
3309   private:
3310     GLenum mFeature;
3311 };
3312 
3313 #define EXPECT_GL_SINGLE_ERROR_MSG(msg)                         \
3314     if (mHasDebugKHR)                                           \
3315     {                                                           \
3316         EXPECT_EQ(mErrorMessages.size(), size_t(1));            \
3317         if (mErrorMessages.size() == 1)                         \
3318         {                                                       \
3319             EXPECT_EQ(std::string(msg), mErrorMessages.back()); \
3320         }                                                       \
3321         mErrorMessages.clear();                                 \
3322     }
3323 
3324 // Check that PLS state has the correct initial values.
TEST_P(PixelLocalStorageValidationTest,InitialValues)3325 TEST_P(PixelLocalStorageValidationTest, InitialValues)
3326 {
3327     // It's valid to query GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE even when fbo 0 is bound.
3328     EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
3329     EXPECT_GL_NO_ERROR();
3330 
3331     // Table 6.Y: Pixel Local Storage State
3332     GLFramebuffer fbo;
3333     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3334     EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
3335     for (int i = 0; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i)
3336     {
3337         EXPECT_PLS_INTEGER(i, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_NONE);
3338         EXPECT_PLS_INTEGER(i, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 0);
3339         EXPECT_PLS_INTEGER(i, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 0);
3340         EXPECT_PLS_INTEGER(i, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, 0);
3341     }
3342     EXPECT_GL_NO_ERROR();
3343 }
3344 
3345 // Check that glFramebufferMemorylessPixelLocalStorageANGLE validates as specified.
TEST_P(PixelLocalStorageValidationTest,FramebufferMemorylessPixelLocalStorageANGLE)3346 TEST_P(PixelLocalStorageValidationTest, FramebufferMemorylessPixelLocalStorageANGLE)
3347 {
3348     GLFramebuffer fbo;
3349     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3350 
3351     glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_R32F);
3352     EXPECT_GL_NO_ERROR();
3353     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_R32F);
3354     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, GL_NONE);
3355     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, GL_NONE);
3356     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, GL_NONE);
3357 
3358     // If <internalformat> is NONE, the pixel local storage plane at index <plane> is deinitialized
3359     // and any internal storage is released.
3360     glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_NONE);
3361     EXPECT_GL_NO_ERROR();
3362     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_NONE);
3363     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, GL_NONE);
3364     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, GL_NONE);
3365     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, GL_NONE);
3366 
3367     // Set back to GL_RGBA8I.
3368     glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_RGBA8I);
3369     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_RGBA8I);
3370 
3371     // INVALID_FRAMEBUFFER_OPERATION is generated if the default framebuffer object name 0 is bound
3372     // to DRAW_FRAMEBUFFER.
3373     glBindFramebuffer(GL_FRAMEBUFFER, 0);
3374     glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_R32UI);
3375     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
3376     EXPECT_GL_SINGLE_ERROR_MSG(
3377         "Default framebuffer object name 0 does not support pixel local storage.");
3378     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3379     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_RGBA8I);
3380 
3381     // INVALID_FRAMEBUFFER_OPERATION is generated if pixel local storage on the draw framebuffer is
3382     // in an interrupted state.
3383     EXPECT_GL_NO_ERROR();
3384     glFramebufferPixelLocalStorageInterruptANGLE();
3385     glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_R32UI);
3386     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
3387     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is interrupted.");
3388     glFramebufferPixelLocalStorageRestoreANGLE();
3389     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_RGBA8I);
3390 
3391     // INVALID_OPERATION is generated if PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is nonzero.
3392     {
3393         PLSTestTexture tmp(GL_RGBA8);
3394         glFramebufferTexturePixelLocalStorageANGLE(1, tmp, 0, 0);
3395         glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_DONT_CARE, GL_DONT_CARE}));
3396         glFramebufferMemorylessPixelLocalStorageANGLE(3, GL_R32UI);
3397         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3398         EXPECT_GL_SINGLE_ERROR_MSG("Operation not permitted while pixel local storage is active.");
3399         // The store operation is ignored if its plane is memoryless or disabled.
3400         glEndPixelLocalStorageANGLE(
3401             2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE}));
3402         glFramebufferTexturePixelLocalStorageANGLE(1, 0, 0, 0);
3403     }
3404 
3405     // INVALID_VALUE is generated if <plane> < 0 or <plane> >= MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.
3406     glFramebufferMemorylessPixelLocalStorageANGLE(-1, GL_R32UI);
3407     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
3408     EXPECT_GL_SINGLE_ERROR_MSG("Plane cannot be less than 0.");
3409     glFramebufferMemorylessPixelLocalStorageANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_R32UI);
3410     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
3411     EXPECT_GL_SINGLE_ERROR_MSG("Plane must be less than GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.");
3412     glFramebufferMemorylessPixelLocalStorageANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES - 1, GL_R32UI);
3413     EXPECT_GL_NO_ERROR();
3414     EXPECT_PLS_INTEGER(MAX_PIXEL_LOCAL_STORAGE_PLANES - 1, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_R32UI);
3415 
3416     // INVALID_ENUM is generated if <internalformat> is not one of the acceptable values in Table
3417     // X.2, or NONE.
3418     glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_RGBA16F);
3419     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
3420     EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage internal format.");
3421     glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_RGBA32UI);
3422     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
3423     EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage internal format.");
3424     glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_RGBA8_SNORM);
3425     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
3426     EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage internal format.");
3427 
3428     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_RGBA8I);
3429     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, GL_NONE);
3430     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, GL_NONE);
3431     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, GL_NONE);
3432 
3433     ASSERT_GL_NO_ERROR();
3434 }
3435 
3436 // Check that glFramebufferTexturePixelLocalStorageANGLE validates as specified.
TEST_P(PixelLocalStorageValidationTest,FramebufferTexturePixelLocalStorageANGLE)3437 TEST_P(PixelLocalStorageValidationTest, FramebufferTexturePixelLocalStorageANGLE)
3438 {
3439     GLFramebuffer fbo;
3440     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3441 
3442     // Initially, pixel local storage planes are in a deinitialized state and are unusable.
3443     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_NONE);
3444     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 0);
3445     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 0);
3446     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, 0);
3447 
3448     GLTexture tex;
3449     glBindTexture(GL_TEXTURE_2D, tex);
3450     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8UI, 10, 10);
3451     glFramebufferTexturePixelLocalStorageANGLE(1, tex, 1, 0);
3452     EXPECT_GL_NO_ERROR();
3453     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_RGBA8UI);
3454     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, tex);
3455     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 1);
3456     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, 0);
3457 
3458     // If <backingtexture> is 0, <level> and <layer> are ignored and the pixel local storage plane
3459     // <plane> is deinitialized.
3460     glFramebufferTexturePixelLocalStorageANGLE(1, 0, 1, 2);
3461     EXPECT_GL_NO_ERROR();
3462     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_NONE);
3463     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 0);
3464     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 0);
3465     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, 0);
3466 
3467     // Set back to GL_RGBA8I.
3468     glFramebufferTexturePixelLocalStorageANGLE(1, tex, 1, 0);
3469     EXPECT_GL_NO_ERROR();
3470     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_RGBA8UI);
3471     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, tex);
3472     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 1);
3473     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, 0);
3474 
3475     {
3476         // When a texture object is deleted, any pixel local storage plane to which it was bound is
3477         // automatically deinitialized.
3478         GLFramebuffer keepalive;  // Keep the underlying texture alive after deleting its ID by
3479                                   // binding it to a framebuffer.
3480         glBindFramebuffer(GL_FRAMEBUFFER, keepalive);
3481         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
3482         ASSERT_GL_NO_ERROR();
3483         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3484         tex.reset();
3485         PLSTestTexture newTextureMaybeRecycledID(GL_RGBA8, 1, 1);
3486         EXPECT_GL_NO_ERROR();
3487         EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_NONE);
3488         EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 0);
3489         EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 0);
3490         EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, 0);
3491     }
3492     glBindTexture(GL_TEXTURE_2D, tex);
3493     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8UI, 10, 10);
3494 
3495     // Same as above, but with orphaning.
3496     glFramebufferTexturePixelLocalStorageANGLE(1, tex, 1, 0);
3497     EXPECT_GL_NO_ERROR();
3498     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_RGBA8UI);
3499     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, tex);
3500     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 1);
3501     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, 0);
3502     glBindFramebuffer(GL_FRAMEBUFFER, 0);
3503     {
3504         GLFramebuffer keepalive;  // Keep the underlying texture alive after deleting its ID by
3505                                   // binding it to a framebuffer.
3506         glBindFramebuffer(GL_FRAMEBUFFER, keepalive);
3507         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
3508         ASSERT_GL_NO_ERROR();
3509         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3510         tex.reset();
3511         PLSTestTexture newTextureMaybeRecycledID(GL_RGBA8, 1, 1);
3512         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3513         EXPECT_GL_NO_ERROR();
3514         EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_NONE);
3515         EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 0);
3516         EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 0);
3517         EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, 0);
3518     }
3519     glBindTexture(GL_TEXTURE_2D, tex);
3520     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8UI, 10, 10);
3521 
3522     // INVALID_FRAMEBUFFER_OPERATION is generated if the default framebuffer object name 0 is bound
3523     // to DRAW_FRAMEBUFFER.
3524     glBindFramebuffer(GL_FRAMEBUFFER, 0);
3525     glFramebufferTexturePixelLocalStorageANGLE(1, tex, 1, 0);
3526     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
3527     EXPECT_GL_SINGLE_ERROR_MSG(
3528         "Default framebuffer object name 0 does not support pixel local storage.");
3529     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3530 
3531     // INVALID_FRAMEBUFFER_OPERATION is generated if pixel local storage on the draw framebuffer is
3532     // in an interrupted state.
3533     EXPECT_GL_NO_ERROR();
3534     glFramebufferTexturePixelLocalStorageANGLE(1, tex, 1, 0);
3535     glFramebufferPixelLocalStorageInterruptANGLE();
3536     glFramebufferTexturePixelLocalStorageANGLE(1, 0, 0, 0);
3537     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
3538     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is interrupted.");
3539     glFramebufferPixelLocalStorageRestoreANGLE();
3540     EXPECT_PLS_INTEGER(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, tex);
3541 
3542     // INVALID_OPERATION is generated if PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is nonzero.
3543     {
3544         PLSTestTexture tmp(GL_RGBA8);
3545         glFramebufferTexturePixelLocalStorageANGLE(0, tex, 0, 0);
3546         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
3547         glFramebufferTexturePixelLocalStorageANGLE(1, tmp, 0, 0);
3548         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3549         EXPECT_GL_SINGLE_ERROR_MSG("Operation not permitted while pixel local storage is active.");
3550         // The store operation is ignored if its plane is memoryless or disabled.
3551         glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
3552         glFramebufferTexturePixelLocalStorageANGLE(0, 0, 0, 0);
3553     }
3554 
3555     // INVALID_VALUE is generated if <plane> < 0 or <plane> >= MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.
3556     glFramebufferTexturePixelLocalStorageANGLE(-1, tex, 1, 0);
3557     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
3558     EXPECT_GL_SINGLE_ERROR_MSG("Plane cannot be less than 0.");
3559     glFramebufferTexturePixelLocalStorageANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES, tex, 1, 0);
3560     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
3561     EXPECT_GL_SINGLE_ERROR_MSG("Plane must be less than GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.");
3562     glFramebufferTexturePixelLocalStorageANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES - 1, tex, 2, 0);
3563     EXPECT_GL_NO_ERROR();
3564     EXPECT_PLS_INTEGER(MAX_PIXEL_LOCAL_STORAGE_PLANES - 1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, tex);
3565     EXPECT_PLS_INTEGER(MAX_PIXEL_LOCAL_STORAGE_PLANES - 1, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 2);
3566 
3567     // INVALID_OPERATION is generated if <backingtexture> is not the name of an existing immutable
3568     // texture object, or zero.
3569     GLTexture badTex;
3570     glFramebufferTexturePixelLocalStorageANGLE(2, badTex, 0, 0);
3571     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3572     EXPECT_GL_SINGLE_ERROR_MSG("Not a valid texture object name.");
3573     glBindTexture(GL_TEXTURE_2D, badTex);
3574     glFramebufferTexturePixelLocalStorageANGLE(2, badTex, 0, 0);
3575     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3576     EXPECT_GL_SINGLE_ERROR_MSG("Texture is not immutable.");
3577     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3578     EXPECT_GL_NO_ERROR();
3579     glFramebufferTexturePixelLocalStorageANGLE(2, badTex, 0, 0);
3580     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3581     EXPECT_GL_SINGLE_ERROR_MSG("Texture is not immutable.");
3582 
3583     // INVALID_OPERATION is generated if <backingtexture> is nonzero
3584     // and not of type TEXTURE_2D or TEXTURE_2D_ARRAY.
3585     GLTexture texCube;
3586     glBindTexture(GL_TEXTURE_CUBE_MAP, texCube);
3587     glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGBA8, 10, 10);
3588     EXPECT_GL_NO_ERROR();
3589     glFramebufferTexturePixelLocalStorageANGLE(0, texCube, 0, 1);
3590     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3591     EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage texture type.");
3592     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_NONE);
3593     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 0);
3594     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 0);
3595     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, 0);
3596 
3597     GLTexture tex2DMultisample;
3598     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex2DMultisample);
3599     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 10, 10, 1);
3600     EXPECT_GL_NO_ERROR();
3601     glFramebufferTexturePixelLocalStorageANGLE(0, tex2DMultisample, 0, 0);
3602     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3603     EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage texture type.");
3604     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_NONE);
3605     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 0);
3606     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 0);
3607     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, 0);
3608 
3609     GLTexture tex3D;
3610     glBindTexture(GL_TEXTURE_3D, tex3D);
3611     glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 5, 5, 5);
3612     EXPECT_GL_NO_ERROR();
3613     glFramebufferTexturePixelLocalStorageANGLE(0, tex3D, 0, 0);
3614     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3615     EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage texture type.");
3616     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_NONE);
3617     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 0);
3618     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 0);
3619     EXPECT_PLS_INTEGER(0, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, 0);
3620 
3621     // INVALID_VALUE is generated if <level> < 0.
3622     tex.reset();
3623     glBindTexture(GL_TEXTURE_2D, tex);
3624     glTexStorage2D(GL_TEXTURE_2D, 3, GL_R32UI, 10, 10);
3625     glFramebufferTexturePixelLocalStorageANGLE(2, tex, -1, 0);
3626     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
3627     EXPECT_GL_SINGLE_ERROR_MSG("Level is negative.");
3628 
3629     // GL_INVALID_VALUE is generated if <backingtexture> is nonzero and <level> >= the immutable
3630     // number of mipmap levels in <backingtexture>.
3631     glFramebufferTexturePixelLocalStorageANGLE(2, tex, 3, 0);
3632     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
3633     EXPECT_GL_SINGLE_ERROR_MSG("Level is larger than texture level count.");
3634 
3635     // INVALID_VALUE is generated if <layer> < 0.
3636     glFramebufferTexturePixelLocalStorageANGLE(2, tex, 1, -1);
3637     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
3638     EXPECT_GL_SINGLE_ERROR_MSG("Negative layer.");
3639 
3640     // GL_INVALID_VALUE is generated if <backingtexture> is nonzero and <layer> >= the immutable
3641     // number of texture layers in <backingtexture>.
3642     glFramebufferTexturePixelLocalStorageANGLE(2, tex, 1, 1);
3643     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
3644     EXPECT_GL_SINGLE_ERROR_MSG("Layer is larger than texture depth.");
3645 
3646     GLTexture tex2DArray;
3647     glBindTexture(GL_TEXTURE_2D_ARRAY, tex2DArray);
3648     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_RGBA8I, 10, 10, 7);
3649     EXPECT_GL_NO_ERROR();
3650     glFramebufferTexturePixelLocalStorageANGLE(2, tex2DArray, 1, 7);
3651     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
3652     EXPECT_GL_SINGLE_ERROR_MSG("Layer is larger than texture depth.");
3653     glFramebufferTexturePixelLocalStorageANGLE(2, tex2DArray, 2, 6);
3654     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
3655     EXPECT_GL_SINGLE_ERROR_MSG("Level is larger than texture level count.");
3656     glFramebufferTexturePixelLocalStorageANGLE(2, tex2DArray, 1, 6);
3657     EXPECT_GL_NO_ERROR();
3658     EXPECT_PLS_INTEGER(2, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_RGBA8I);
3659     EXPECT_PLS_INTEGER(2, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, tex2DArray);
3660     EXPECT_PLS_INTEGER(2, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 1);
3661     EXPECT_PLS_INTEGER(2, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, 6);
3662     // When a texture object is deleted, any pixel local storage plane to which it was bound is
3663     // automatically deinitialized.
3664     {
3665         GLFramebuffer keepalive;  // Keep the underlying texture alive after deleting its ID by
3666                                   // binding it to a framebuffer.
3667         glBindFramebuffer(GL_FRAMEBUFFER, keepalive);
3668         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2DArray, 0, 0);
3669         ASSERT_GL_NO_ERROR();
3670         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3671         tex2DArray.reset();
3672         PLSTestTexture newTextureMaybeRecycledID(GL_RGBA8, 1, 1);
3673         EXPECT_PLS_INTEGER(2, GL_PIXEL_LOCAL_FORMAT_ANGLE, GL_NONE);
3674         EXPECT_PLS_INTEGER(2, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 0);
3675         EXPECT_PLS_INTEGER(2, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 0);
3676         EXPECT_PLS_INTEGER(2, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE, 0);
3677     }
3678 
3679     // INVALID_ENUM is generated if <backingtexture> is nonzero and its internalformat is not
3680     // one of the acceptable values in Table X.2.
3681     tex.reset();
3682     glBindTexture(GL_TEXTURE_2D, tex);
3683     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RG32F, 10, 10);
3684     EXPECT_GL_NO_ERROR();
3685     glFramebufferTexturePixelLocalStorageANGLE(2, tex, 1, 0);
3686     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
3687     EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage internal format.");
3688 
3689     ASSERT_GL_NO_ERROR();
3690 }
3691 
3692 // Check that FramebufferPixelLocalClearValue{f,i,ui}vANGLE validate as specified.
TEST_P(PixelLocalStorageValidationTest,glFramebufferPixelLocalClearValuesANGLE)3693 TEST_P(PixelLocalStorageValidationTest, glFramebufferPixelLocalClearValuesANGLE)
3694 {
3695     // INVALID_FRAMEBUFFER_OPERATION is generated if the default framebuffer object name 0 is bound
3696     // to DRAW_FRAMEBUFFER.
3697     glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(0, 0, 0, 0));
3698     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
3699     EXPECT_GL_SINGLE_ERROR_MSG(
3700         "Default framebuffer object name 0 does not support pixel local storage.");
3701 
3702     glFramebufferPixelLocalClearValueivANGLE(1, ClearI(0, 0, 0, 0));
3703     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
3704     EXPECT_GL_SINGLE_ERROR_MSG(
3705         "Default framebuffer object name 0 does not support pixel local storage.");
3706 
3707     glFramebufferPixelLocalClearValueuivANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES - 1,
3708                                               ClearUI(0, 0, 0, 0));
3709     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
3710     EXPECT_GL_SINGLE_ERROR_MSG(
3711         "Default framebuffer object name 0 does not support pixel local storage.");
3712 
3713     ASSERT_GL_NO_ERROR();
3714 
3715     GLFramebuffer fbo;
3716     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3717 
3718     // INVALID_FRAMEBUFFER_OPERATION is generated if pixel local storage on the draw framebuffer is
3719     // in an interrupted state.
3720     glFramebufferPixelLocalStorageInterruptANGLE();
3721 
3722     glFramebufferPixelLocalClearValuefvANGLE(0, ClearF(1, 1, 1, 1));
3723     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
3724     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is interrupted.");
3725 
3726     glFramebufferPixelLocalClearValueivANGLE(1, ClearI(1, 1, 1, 1));
3727     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
3728     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is interrupted.");
3729 
3730     glFramebufferPixelLocalClearValueuivANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES - 1,
3731                                               ClearUI(1, 1, 1, 1));
3732     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
3733     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is interrupted.");
3734 
3735     glFramebufferPixelLocalStorageRestoreANGLE();
3736     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_FLOAT(0, ({0, 0, 0, 0}));
3737     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_INT(1, ({0, 0, 0, 0}));
3738     EXPECT_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT(MAX_PIXEL_LOCAL_STORAGE_PLANES - 1, ({0, 0, 0, 0}));
3739     ASSERT_GL_NO_ERROR();
3740 
3741     // INVALID_VALUE is generated if <plane> < 0 or <plane> >= MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.
3742     glFramebufferPixelLocalClearValuefvANGLE(-1, ClearF(0, 0, 0, 0));
3743     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
3744     EXPECT_GL_SINGLE_ERROR_MSG("Plane cannot be less than 0.");
3745 
3746     glFramebufferPixelLocalClearValueivANGLE(-1, ClearI(0, 0, 0, 0));
3747     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
3748     EXPECT_GL_SINGLE_ERROR_MSG("Plane cannot be less than 0.");
3749 
3750     glFramebufferPixelLocalClearValueuivANGLE(-1, ClearUI(0, 0, 0, 0));
3751     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
3752     EXPECT_GL_SINGLE_ERROR_MSG("Plane cannot be less than 0.");
3753 
3754     glFramebufferPixelLocalClearValuefvANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES, ClearF(0, 0, 0, 0));
3755     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
3756     EXPECT_GL_SINGLE_ERROR_MSG("Plane must be less than GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.");
3757 
3758     glFramebufferPixelLocalClearValueivANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES, ClearI(0, 0, 0, 0));
3759     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
3760     EXPECT_GL_SINGLE_ERROR_MSG("Plane must be less than GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.");
3761 
3762     glFramebufferPixelLocalClearValueuivANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES, ClearUI(0, 0, 0, 0));
3763     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
3764     EXPECT_GL_SINGLE_ERROR_MSG("Plane must be less than GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.");
3765 
3766     ASSERT_GL_NO_ERROR();
3767 
3768     // INVALID_OPERATION is generated if PIXEL_LOCAL_STORAGE_ACTIVE_ANGLE is TRUE.
3769     PLSTestTexture tex(GL_R32UI);
3770     glFramebufferTexturePixelLocalStorageANGLE(0, tex, 0, 0);
3771     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
3772     ASSERT_GL_NO_ERROR();
3773 
3774     glFramebufferPixelLocalClearValuefvANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES - 1,
3775                                              ClearF(0, 0, 0, 0));
3776     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3777     EXPECT_GL_SINGLE_ERROR_MSG("Operation not permitted while pixel local storage is active.");
3778 
3779     glFramebufferPixelLocalClearValuefvANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES - 2,
3780                                              ClearF(0, 0, 0, 0));
3781     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3782     EXPECT_GL_SINGLE_ERROR_MSG("Operation not permitted while pixel local storage is active.");
3783 
3784     glFramebufferPixelLocalClearValueuivANGLE(0, ClearUI(0, 0, 0, 0));
3785     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3786     EXPECT_GL_SINGLE_ERROR_MSG("Operation not permitted while pixel local storage is active.");
3787 
3788     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 1);
3789     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_STORE_OP_STORE_ANGLE}));
3790     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
3791 
3792     ASSERT_GL_NO_ERROR();
3793 }
3794 
3795 #define EXPECT_BANNED(cmd, msg)                   \
3796     cmd;                                          \
3797     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION); \
3798     EXPECT_GL_SINGLE_ERROR_MSG(msg)
3799 
3800 #define EXPECT_BANNED_DEFAULT_MSG(cmd) \
3801     EXPECT_BANNED(cmd, "Operation not permitted while pixel local storage is active.")
3802 
FormatBannedCapMsg(GLenum cap)3803 static std::vector<char> FormatBannedCapMsg(GLenum cap)
3804 {
3805     constexpr char format[] =
3806         "Cap 0x%04X cannot be enabled or disabled while pixel local storage is active.";
3807     std::vector<char> msg(std::snprintf(nullptr, 0, format, cap) + 1);
3808     std::snprintf(msg.data(), msg.size(), format, cap);
3809     return msg;
3810 }
3811 
3812 #define EXPECT_ALLOWED_CAP(cap) \
3813     {                           \
3814         glEnable(cap);          \
3815         glDisable(cap);         \
3816         glIsEnabled(cap);       \
3817         EXPECT_GL_NO_ERROR();   \
3818     }
3819 
3820 #define EXPECT_BANNED_CAP(cap)                           \
3821     {                                                    \
3822         std::vector<char> msg = FormatBannedCapMsg(cap); \
3823         EXPECT_BANNED(glEnable(cap), msg.data());        \
3824         EXPECT_BANNED(glDisable(cap), msg.data());       \
3825         glIsEnabled(cap);                                \
3826         EXPECT_GL_NO_ERROR();                            \
3827     }
3828 
3829 #define EXPECT_BANNED_CAP_INDEXED(cap)                   \
3830     {                                                    \
3831         std::vector<char> msg = FormatBannedCapMsg(cap); \
3832         EXPECT_BANNED(glEnablei(cap, 0), msg.data());    \
3833         EXPECT_BANNED(glDisablei(cap, 0), msg.data());   \
3834         EXPECT_GL_NO_ERROR();                            \
3835     }
3836 
3837 // Check that glBeginPixelLocalStorageANGLE validates non-PLS context state as specified.
TEST_P(PixelLocalStorageValidationTest,BeginPixelLocalStorageANGLE_context_state)3838 TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_context_state)
3839 {
3840     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
3841 
3842     // INVALID_FRAMEBUFFER_OPERATION is generated if the default framebuffer object name 0 is bound
3843     // to DRAW_FRAMEBUFFER.
3844     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
3845     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
3846     EXPECT_GL_SINGLE_ERROR_MSG(
3847         "Default framebuffer object name 0 does not support pixel local storage.");
3848     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
3849 
3850     GLFramebuffer fbo;
3851     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3852 
3853     // INVALID_FRAMEBUFFER_OPERATION is generated if pixel local storage on the draw framebuffer is
3854     // in an interrupted state.
3855     glFramebufferPixelLocalStorageInterruptANGLE();
3856     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
3857     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
3858     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is interrupted.");
3859     glFramebufferPixelLocalStorageRestoreANGLE();
3860     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
3861     ASSERT_GL_NO_ERROR();
3862 
3863     PLSTestTexture pls0(GL_RGBA8, 100, 100);
3864     glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0);
3865     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
3866     EXPECT_GL_NO_ERROR();
3867     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 1);
3868 
3869     // INVALID_OPERATION is generated if PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is nonzero.
3870     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
3871     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3872     EXPECT_GL_SINGLE_ERROR_MSG("Operation not permitted while pixel local storage is active.");
3873     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 1);
3874     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
3875     EXPECT_GL_NO_ERROR();
3876     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
3877 
3878     // INVALID_OPERATION is generated if the value of SAMPLE_BUFFERS is 1 (i.e., if rendering to a
3879     // multisampled framebuffer).
3880     {
3881         GLRenderbuffer msaa;
3882         glBindRenderbuffer(GL_RENDERBUFFER, msaa);
3883         glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_RGBA8, 100, 100);
3884         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaa);
3885         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
3886         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3887         EXPECT_GL_SINGLE_ERROR_MSG(
3888             "Attempted to begin pixel local storage with a multisampled framebuffer.");
3889         ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
3890     }
3891 
3892     // INVALID_OPERATION is generated if DITHER is enabled.
3893     {
3894         ScopedEnable scopedEnable(GL_DITHER);
3895         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
3896         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3897         EXPECT_GL_SINGLE_ERROR_MSG(
3898             "Attempted to begin pixel local storage with GL_DITHER enabled.");
3899         ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
3900     }
3901 
3902     // INVALID_OPERATION is generated if RASTERIZER_DISCARD is enabled.
3903     {
3904         ScopedEnable scopedEnable(GL_RASTERIZER_DISCARD);
3905         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
3906         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3907         EXPECT_GL_SINGLE_ERROR_MSG(
3908             "Attempted to begin pixel local storage with GL_RASTERIZER_DISCARD enabled.");
3909         ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
3910     }
3911 }
3912 
3913 // Check that transform feedback is banned when PLS is active.
TEST_P(PixelLocalStorageValidationTest,PLSActive_bans_transform_feedback)3914 TEST_P(PixelLocalStorageValidationTest, PLSActive_bans_transform_feedback)
3915 {
3916     GLFramebuffer fbo;
3917     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3918 
3919     PLSTestTexture pls0(GL_RGBA8, 100, 100);
3920     glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0);
3921 
3922     // INVALID_OPERATION is generated if TRANSFORM_FEEDBACK_ACTIVE is true.
3923     constexpr char kFS[] = R"(#version 300 es
3924         out mediump vec4 color;
3925         void main()
3926         {
3927             color = vec4(0.6, 0.0, 0.0, 1.0);
3928         })";
3929     std::vector<std::string> xfVaryings;
3930     xfVaryings.push_back("gl_Position");
3931     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(xfProgram, essl3_shaders::vs::Simple(), kFS, xfVaryings,
3932                                         GL_INTERLEAVED_ATTRIBS);
3933     glUseProgram(xfProgram);
3934     GLuint xfBuffer;
3935     glGenBuffers(1, &xfBuffer);
3936     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfBuffer);
3937     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
3938     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfBuffer);
3939     glBeginTransformFeedback(GL_TRIANGLES);
3940     ASSERT_GL_NO_ERROR();
3941     ASSERT_GL_INTEGER(GL_TRANSFORM_FEEDBACK_ACTIVE, 1);
3942 
3943     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
3944     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3945     EXPECT_GL_SINGLE_ERROR_MSG(
3946         "Attempted to begin pixel local storage with transform feedback active.");
3947     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
3948 
3949     glEndTransformFeedback();
3950 
3951     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
3952     EXPECT_GL_NO_ERROR();
3953     EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 1);
3954 
3955     // glBeginTransformFeedback is not on the PLS allow list.
3956     EXPECT_BANNED_DEFAULT_MSG(glBeginTransformFeedback(GL_TRIANGLES))
3957     ASSERT_GL_INTEGER(GL_TRANSFORM_FEEDBACK_ACTIVE, 0);
3958 
3959     glUseProgram(0);
3960     EXPECT_GL_NO_ERROR();
3961 
3962     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
3963     EXPECT_GL_NO_ERROR();
3964 }
3965 
3966 // Check that EXT_blend_func_extended is banned when PLS is active.
TEST_P(PixelLocalStorageValidationTest,PLSActive_bans_blend_func_extended)3967 TEST_P(PixelLocalStorageValidationTest, PLSActive_bans_blend_func_extended)
3968 {
3969     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_blend_func_extended"));
3970 
3971     GLFramebuffer fbo;
3972     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3973 
3974     PLSTestTexture pls0(GL_RGBA8, 100, 100);
3975     glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0);
3976 
3977     // INVALID_OPERATION is generated if BLEND_DST_ALPHA, BLEND_DST_RGB, BLEND_SRC_ALPHA, or
3978     // BLEND_SRC_RGB, for any draw buffer, is a blend function requiring the secondary color input,
3979     // as specified in EXT_blend_func_extended (SRC1_COLOR_EXT, ONE_MINUS_SRC1_COLOR_EXT,
3980     // SRC1_ALPHA_EXT, ONE_MINUS_SRC1_ALPHA_EXT).
3981     GLint maxDrawBuffersWithPLS =
3982         std::min(MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE,
3983                  MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - 1);
3984     for (auto blendFunc : {GL_SRC1_COLOR_EXT, GL_ONE_MINUS_SRC1_COLOR_EXT, GL_SRC1_ALPHA_EXT,
3985                            GL_ONE_MINUS_SRC1_ALPHA_EXT})
3986     {
3987         glBlendFunc(blendFunc, GL_ONE);
3988         ASSERT_GL_NO_ERROR();
3989         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
3990         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
3991         EXPECT_GL_SINGLE_ERROR_MSG(
3992             "Attempted to begin pixel local storage with a blend function requiring the secondary "
3993             "color input.");
3994         EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
3995         glBlendFunc(GL_ONE, GL_ZERO);
3996 
3997         if (IsGLExtensionEnabled("GL_OES_draw_buffers_indexed"))
3998         {
3999             glBlendFunci(MAX_DRAW_BUFFERS - 1, GL_ZERO, blendFunc);
4000             ASSERT_GL_NO_ERROR();
4001             glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
4002             EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4003             EXPECT_GL_SINGLE_ERROR_MSG(
4004                 "Attempted to begin pixel local storage with a blend function requiring the "
4005                 "secondary color input.");
4006             EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4007             glBlendFunc(GL_ONE, GL_ZERO);
4008         }
4009 
4010         glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, blendFunc);
4011         ASSERT_GL_NO_ERROR();
4012         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
4013         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4014         EXPECT_GL_SINGLE_ERROR_MSG(
4015             "Attempted to begin pixel local storage with a blend function requiring the secondary "
4016             "color input.");
4017         EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4018         glBlendFunc(GL_ONE, GL_ZERO);
4019 
4020         if (IsGLExtensionEnabled("GL_OES_draw_buffers_indexed"))
4021         {
4022             glBlendFuncSeparatei(MAX_DRAW_BUFFERS - 1, blendFunc, GL_ONE, GL_ONE, GL_ONE);
4023             ASSERT_GL_NO_ERROR();
4024             glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
4025             EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4026             EXPECT_GL_SINGLE_ERROR_MSG(
4027                 "Attempted to begin pixel local storage with a blend function requiring the "
4028                 "secondary color input.");
4029             EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4030             glBlendFunc(GL_ONE, GL_ZERO);
4031         }
4032 
4033         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
4034         ASSERT_GL_NO_ERROR();
4035         EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 1);
4036 
4037         // glBlendFunc(Separate) is not on the PLS allow list.
4038         EXPECT_BANNED_DEFAULT_MSG(glBlendFunc(GL_ONE, blendFunc))
4039         EXPECT_BANNED_DEFAULT_MSG(glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, blendFunc))
4040 
4041         // INVALID_OPERATION is generated by BlendFunci*() and BlendFuncSeparatei*() if
4042         // <srcRGB>, <dstRGB>, <srcAlpha>, or <dstAlpha> is a blend function requiring the
4043         // secondary color input, as specified in EXT_blend_func_extended (SRC1_COLOR_EXT,
4044         // ONE_MINUS_SRC1_COLOR_EXT, SRC1_ALPHA_EXT, ONE_MINUS_SRC1_ALPHA_EXT).
4045         if (IsGLExtensionEnabled("GL_OES_draw_buffers_indexed"))
4046         {
4047             if (maxDrawBuffersWithPLS > 0)
4048             {
4049                 glBlendFunci(maxDrawBuffersWithPLS - 1, blendFunc, GL_ZERO);
4050                 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
4051                 EXPECT_GL_SINGLE_ERROR_MSG(
4052                     "Blend functions requiring the secondary color input are not supported when "
4053                     "pixel local storage is active.");
4054 
4055                 glBlendFuncSeparatei(maxDrawBuffersWithPLS - 1, GL_ONE, GL_ONE, GL_ONE, blendFunc);
4056                 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
4057                 EXPECT_GL_SINGLE_ERROR_MSG(
4058                     "Blend functions requiring the secondary color input are not supported when "
4059                     "pixel local storage is active.");
4060             }
4061         }
4062 
4063         glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
4064         EXPECT_GL_NO_ERROR();
4065     }
4066 
4067     // GL_SRC_ALPHA_SATURATE_EXT is ok.
4068     glBlendFuncSeparate(GL_SRC_ALPHA_SATURATE_EXT, GL_SRC_ALPHA_SATURATE_EXT,
4069                         GL_SRC_ALPHA_SATURATE_EXT, GL_SRC_ALPHA_SATURATE_EXT);
4070     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
4071     EXPECT_GL_NO_ERROR();
4072     EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 1);
4073     if (IsGLExtensionEnabled("GL_OES_draw_buffers_indexed"))
4074     {
4075         for (GLsizei i = 0; i < maxDrawBuffersWithPLS; ++i)
4076         {
4077             glBlendFuncSeparatei(i, GL_SRC_ALPHA_SATURATE_EXT, GL_SRC_ALPHA_SATURATE_EXT,
4078                                  GL_SRC_ALPHA_SATURATE_EXT, GL_SRC_ALPHA_SATURATE_EXT);
4079             EXPECT_GL_NO_ERROR();
4080         }
4081     }
4082     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
4083     EXPECT_GL_NO_ERROR();
4084 }
4085 
4086 // Check that KHR_blend_equation_advanced is banned when PLS is active.
TEST_P(PixelLocalStorageValidationTest,PLSActive_bans_blend_equation_advanced)4087 TEST_P(PixelLocalStorageValidationTest, PLSActive_bans_blend_equation_advanced)
4088 {
4089     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
4090 
4091     GLFramebuffer fbo;
4092     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4093 
4094     PLSTestTexture pls0(GL_RGBA8, 100, 100);
4095     glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0);
4096 
4097     // INVALID_OPERATION is generated if BLEND_EQUATION_RGB and/or BLEND_EQUATION_ALPHA are one of
4098     // the advanced blend equations defined in KHR_blend_equation_advanced.
4099     for (auto blendEquation : {
4100              GL_MULTIPLY_KHR,
4101              GL_SCREEN_KHR,
4102              GL_OVERLAY_KHR,
4103              GL_DARKEN_KHR,
4104              GL_LIGHTEN_KHR,
4105              GL_COLORDODGE_KHR,
4106              GL_COLORBURN_KHR,
4107              GL_HARDLIGHT_KHR,
4108              GL_SOFTLIGHT_KHR,
4109              GL_DIFFERENCE_KHR,
4110              GL_EXCLUSION_KHR,
4111              GL_HSL_HUE_KHR,
4112              GL_HSL_SATURATION_KHR,
4113              GL_HSL_COLOR_KHR,
4114              GL_HSL_LUMINOSITY_KHR,
4115          })
4116     {
4117         glBlendEquation(blendEquation);
4118         ASSERT_GL_NO_ERROR();
4119 
4120         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
4121         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4122         EXPECT_GL_SINGLE_ERROR_MSG(
4123             "Attempted to begin pixel local storage with an advanced blend equation enabled.");
4124         EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4125 
4126         glBlendEquation(GL_FUNC_ADD);
4127         glBlendEquationi(0, blendEquation);
4128         ASSERT_GL_NO_ERROR();
4129         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
4130         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4131         EXPECT_GL_SINGLE_ERROR_MSG(
4132             "Attempted to begin pixel local storage with an advanced blend equation enabled.");
4133 
4134         glBlendEquationi(0, GL_FUNC_ADD);
4135         ASSERT_GL_NO_ERROR();
4136 
4137         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
4138         EXPECT_GL_NO_ERROR();
4139         EXPECT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 1);
4140 
4141         // glBlendEquation is not on the PLS allow list.
4142         EXPECT_BANNED_DEFAULT_MSG(glBlendEquation(blendEquation))
4143 
4144         // INVALID_OPERATION is generated by BlendEquationi*() if <mode> is one of the advanced
4145         // blend equations defined in KHR_blend_equation_advanced.
4146         if (IsGLExtensionEnabled("GL_OES_draw_buffers_indexed"))
4147         {
4148             GLint maxDrawBuffersWithPLS =
4149                 std::min(MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE,
4150                          MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - 1);
4151             if (maxDrawBuffersWithPLS > 0)
4152             {
4153                 glBlendEquationi(0, blendEquation);
4154                 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
4155                 EXPECT_GL_SINGLE_ERROR_MSG(
4156                     "Advanced blend equations are not supported when pixel local storage is "
4157                     "active.");
4158             }
4159         }
4160 
4161         EXPECT_GL_INTEGER(GL_BLEND_EQUATION_RGB, GL_FUNC_ADD);
4162         EXPECT_GL_INTEGER(GL_BLEND_EQUATION_ALPHA, GL_FUNC_ADD);
4163         ASSERT_GL_NO_ERROR();
4164 
4165         glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
4166         EXPECT_GL_NO_ERROR();
4167     }
4168 }
4169 
4170 // Check that glBeginPixelLocalStorageANGLE validates the draw framebuffer's state as specified.
TEST_P(PixelLocalStorageValidationTest,BeginPixelLocalStorageANGLE_framebuffer_state)4171 TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_framebuffer_state)
4172 {
4173     GLFramebuffer fbo;
4174     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4175     PLSTestTexture pls0(GL_RGBA8, 100, 100);
4176     glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0);
4177 
4178     // INVALID_VALUE is generated if <n> < 1 or <n> > MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.
4179     glBeginPixelLocalStorageANGLE(0, nullptr);
4180     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4181     EXPECT_GL_SINGLE_ERROR_MSG("Planes must be greater than 0.");
4182     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4183 
4184     glBeginPixelLocalStorageANGLE(
4185         MAX_PIXEL_LOCAL_STORAGE_PLANES + 1,
4186         std::vector<GLenum>(MAX_PIXEL_LOCAL_STORAGE_PLANES + 1, GL_DONT_CARE).data());
4187     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4188     EXPECT_GL_SINGLE_ERROR_MSG(
4189         "Planes must be less than or equal to GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.");
4190     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4191 
4192     // INVALID_FRAMEBUFFER_OPERATION is generated if the draw framebuffer has an image attached to
4193     // any color attachment point on or after:
4194     //
4195     //   COLOR_ATTACHMENT0 +
4196     //   MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE
4197     //
4198     if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE < MAX_COLOR_ATTACHMENTS)
4199     {
4200         for (int reservedAttachment :
4201              {MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE, MAX_COLOR_ATTACHMENTS - 1})
4202         {
4203             PLSTestTexture tmp(GL_RGBA8, 100, 100);
4204             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + reservedAttachment,
4205                                    GL_TEXTURE_2D, tmp, 0);
4206             glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
4207             EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
4208             EXPECT_GL_SINGLE_ERROR_MSG(
4209                 "Framebuffer cannot have images attached to color attachment points on or after "
4210                 "COLOR_ATTACHMENT0 + MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE.");
4211             ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4212         }
4213     }
4214 
4215     // INVALID_FRAMEBUFFER_OPERATION is generated if the draw framebuffer has an image attached to
4216     // any color attachment point on or after:
4217     //
4218     //   COLOR_ATTACHMENT0 + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - <n>
4219     //
4220     int maxColorAttachmentsWithMaxPLSPlanes =
4221         MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - MAX_PIXEL_LOCAL_STORAGE_PLANES;
4222     if (maxColorAttachmentsWithMaxPLSPlanes < MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE)
4223     {
4224         for (int reservedAttachment : {maxColorAttachmentsWithMaxPLSPlanes,
4225                                        MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE - 1})
4226         {
4227             PLSTestTexture tmp(GL_RGBA8, 100, 100);
4228             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + reservedAttachment,
4229                                    GL_TEXTURE_2D, tmp, 0);
4230             glBeginPixelLocalStorageANGLE(
4231                 MAX_PIXEL_LOCAL_STORAGE_PLANES,
4232                 std::vector<GLenum>(MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_DONT_CARE).data());
4233             EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
4234             EXPECT_GL_SINGLE_ERROR_MSG(
4235                 "Framebuffer cannot have images attached to color attachment points on or after "
4236                 "COLOR_ATTACHMENT0 + "
4237                 "MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - <n>.");
4238             ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4239         }
4240     }
4241 }
4242 
4243 // Check that glBeginPixelLocalStorageANGLE validates its loadops as specified.
TEST_P(PixelLocalStorageValidationTest,BeginPixelLocalStorageANGLE_loadops)4244 TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_loadops)
4245 {
4246     GLFramebuffer fbo;
4247     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4248     PLSTestTexture pls0(GL_RGBA8, 100, 100);
4249     glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0);
4250 
4251     // INVALID_VALUE is generated if <loadops> is NULL.
4252     glBeginPixelLocalStorageANGLE(1, nullptr);
4253     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4254     EXPECT_GL_SINGLE_ERROR_MSG("<loadops> cannot be null.");
4255 
4256     // INVALID_ENUM is generated if <loadops>[0..<n>-1] is not one of the Load Operations enumerated
4257     // in Table X.1.
4258     {
4259         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_REPLACE}));
4260 
4261         EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4262         EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Load Operation: 0x1E01.");
4263         ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4264 
4265         for (int i = 1; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i)
4266         {
4267             glFramebufferMemorylessPixelLocalStorageANGLE(i, GL_RGBA8);
4268         }
4269         std::vector<GLenum> loadops(MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_DONT_CARE);
4270         loadops.back() = GL_SCISSOR_BOX;
4271         glBeginPixelLocalStorageANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES, loadops.data());
4272         EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4273         EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Load Operation: 0x0C10.");
4274         ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4275         for (int i = 1; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i)
4276         {
4277             glFramebufferMemorylessPixelLocalStorageANGLE(i, GL_NONE);
4278         }
4279     }
4280 
4281     // INVALID_OPERATION is generated if <loadops>[0..<n>-1] is not DISABLE_ANGLE, and the pixel
4282     // local storage plane at that same index is is in a deinitialized state.
4283     {
4284         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE}));
4285         EXPECT_GL_NO_ERROR();
4286         glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
4287         EXPECT_GL_NO_ERROR();
4288 
4289         glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE, GL_DONT_CARE}));
4290         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4291         EXPECT_GL_SINGLE_ERROR_MSG(
4292             "Attempted to enable a pixel local storage plane that is in a deinitialized state.");
4293         ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4294 
4295         // If <backingtexture> is 0, <level> and <layer> are ignored and the pixel local storage
4296         // plane <plane> is deinitialized.
4297         glFramebufferTexturePixelLocalStorageANGLE(0, 0, -1, 999);
4298         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE}));
4299         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4300         EXPECT_GL_SINGLE_ERROR_MSG(
4301             "Attempted to enable a pixel local storage plane that is in a deinitialized state.");
4302         ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4303 
4304         glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0);
4305         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_ZERO_ANGLE}));
4306         EXPECT_GL_NO_ERROR();
4307         glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
4308         EXPECT_GL_NO_ERROR();
4309 
4310         // If <internalformat> is NONE, the pixel local storage plane at index <plane> is
4311         // deinitialized and any internal storage is released.
4312         glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_NONE);
4313         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE}));
4314         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4315         EXPECT_GL_SINGLE_ERROR_MSG(
4316             "Attempted to enable a pixel local storage plane that is in a deinitialized state.");
4317         ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4318     }
4319 
4320     // INVALID_OPERATION is generated if <loadops>[0..<n>-1] is LOAD_OP_LOAD_ANGLE and
4321     // the pixel local storage plane at that same index is memoryless.
4322     glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_RGBA8);
4323     glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_LOAD_OP_LOAD_ANGLE}));
4324     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4325     EXPECT_GL_SINGLE_ERROR_MSG(
4326         "Load Operation GL_LOAD_OP_LOAD_ANGLE is invalid for memoryless planes.");
4327     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4328 }
4329 
4330 // Check that glBeginPixelLocalStorageANGLE validates the pixel local storage planes as specified.
TEST_P(PixelLocalStorageValidationTest,BeginPixelLocalStorageANGLE_pls_planes)4331 TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_pls_planes)
4332 {
4333     GLFramebuffer fbo;
4334     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4335     PLSTestTexture pls0(GL_RGBA8, 100, 100);
4336     glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0);
4337 
4338     // INVALID_OPERATION is generated if all enabled, texture-backed pixel local storage planes do
4339     // not have the same width and height.
4340     {
4341         PLSTestTexture pls1(GL_RGBA8, 100, 100);
4342         GLTexture pls2;
4343         glBindTexture(GL_TEXTURE_2D, pls2);
4344         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 101);
4345 
4346         glFramebufferTexturePixelLocalStorageANGLE(0, pls0, 0, 0);
4347         glFramebufferTexturePixelLocalStorageANGLE(1, pls1, 0, 0);
4348         glFramebufferTexturePixelLocalStorageANGLE(2, pls2, 0, 0);
4349 
4350         // Disabling the mismatched size plane is fine.
4351         glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_LOAD_ANGLE, GL_DONT_CARE}));
4352         EXPECT_GL_NO_ERROR();
4353         glEndPixelLocalStorageANGLE(2, GLenumArray({GL_DONT_CARE, GL_STORE_OP_STORE_ANGLE}));
4354         EXPECT_GL_NO_ERROR();
4355 
4356         // Enabling the mismatched size plane errors.
4357         glBeginPixelLocalStorageANGLE(
4358             3, GLenumArray({GL_LOAD_OP_LOAD_ANGLE, GL_LOAD_OP_LOAD_ANGLE, GL_LOAD_OP_LOAD_ANGLE}));
4359         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4360         EXPECT_GL_SINGLE_ERROR_MSG("Mismatched pixel local storage backing texture sizes.");
4361         ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4362 
4363         // Deleting a texture deinitializes the plane.
4364         pls2.reset();
4365         PLSTestTexture newTextureMaybeRecycledID(GL_RGBA8, 1, 1);
4366         glBeginPixelLocalStorageANGLE(
4367             3, GLenumArray({GL_LOAD_OP_LOAD_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_CLEAR_ANGLE}));
4368         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4369         EXPECT_GL_SINGLE_ERROR_MSG(
4370             "Attempted to enable a pixel local storage plane that is in a deinitialized state.");
4371 
4372         // Converting the mismatched size plane to memoryless also works.
4373         glFramebufferMemorylessPixelLocalStorageANGLE(2, GL_RGBA8);
4374         glBeginPixelLocalStorageANGLE(
4375             3, GLenumArray({GL_LOAD_OP_LOAD_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_CLEAR_ANGLE}));
4376         EXPECT_GL_NO_ERROR();
4377         glEndPixelLocalStorageANGLE(
4378             3, GLenumArray(
4379                    {GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE, GL_STORE_OP_STORE_ANGLE}));
4380         EXPECT_GL_NO_ERROR();
4381 
4382         ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4383     }
4384 
4385     {
4386         // pls1 going out of scope deinitialized the PLS plane.
4387         PLSTestTexture newTextureMaybeRecycledID(GL_RGBA8, 1, 1);
4388         glBeginPixelLocalStorageANGLE(
4389             2, GLenumArray({GL_LOAD_OP_LOAD_ANGLE, GL_LOAD_OP_ZERO_ANGLE, GL_LOAD_OP_CLEAR_ANGLE}));
4390         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4391         EXPECT_GL_SINGLE_ERROR_MSG(
4392             "Attempted to enable a pixel local storage plane that is in a deinitialized state.");
4393     }
4394 
4395     // Convert to memoryless.
4396     glFramebufferMemorylessPixelLocalStorageANGLE(1, GL_RGBA8);
4397 
4398     // INVALID_OPERATION is generated if the draw framebuffer has other attachments, and its
4399     // enabled, texture-backed pixel local storage planes do not have identical dimensions with the
4400     // rendering area.
4401     if (MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE > 0)
4402     {
4403         PLSTestTexture rt0(GL_RGBA8, 200, 100);
4404         PLSTestTexture rt1(GL_RGBA8, 100, 200);
4405 
4406         // rt0 is wider than the PLS extents.
4407         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt0, 0);
4408         glBeginPixelLocalStorageANGLE(2,
4409                                       GLenumArray({GL_LOAD_OP_LOAD_ANGLE, GL_LOAD_OP_CLEAR_ANGLE}));
4410         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4411         EXPECT_GL_SINGLE_ERROR_MSG(
4412             "Pixel local storage backing texture dimensions not equal to the rendering area.");
4413         ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4414 
4415         // rt1 is taller than the PLS extents.
4416         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt1, 0);
4417         glBeginPixelLocalStorageANGLE(2,
4418                                       GLenumArray({GL_LOAD_OP_LOAD_ANGLE, GL_LOAD_OP_CLEAR_ANGLE}));
4419         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4420         EXPECT_GL_SINGLE_ERROR_MSG(
4421             "Pixel local storage backing texture dimensions not equal to the rendering area.");
4422         ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4423 
4424         // The intersection of rt0 and rt1 is equal to the PLS extents.
4425         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, rt0, 0);
4426         glBeginPixelLocalStorageANGLE(2,
4427                                       GLenumArray({GL_LOAD_OP_LOAD_ANGLE, GL_LOAD_OP_CLEAR_ANGLE}));
4428         EXPECT_GL_NO_ERROR();
4429         glEndPixelLocalStorageANGLE(2, GLenumArray({GL_STORE_OP_STORE_ANGLE, GL_DONT_CARE}));
4430 
4431         ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4432     }
4433 
4434     // INVALID_OPERATION is generated if the draw framebuffer has no attachments and no enabled,
4435     // texture-backed pixel local storage planes.
4436     {
4437         for (int i = 0; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i)
4438         {
4439             glFramebufferMemorylessPixelLocalStorageANGLE(i, GL_RGBA8);
4440         }
4441         glBeginPixelLocalStorageANGLE(
4442             MAX_PIXEL_LOCAL_STORAGE_PLANES,
4443             std::vector<GLenum>(MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_LOAD_OP_ZERO_ANGLE).data());
4444         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4445         EXPECT_GL_SINGLE_ERROR_MSG(
4446             "Draw framebuffer has no attachments and no enabled, texture-backed pixel local "
4447             "storage planes.");
4448         ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4449 
4450         glFramebufferMemorylessPixelLocalStorageANGLE(0, GL_RGBA8);
4451         glBeginPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
4452         EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4453         EXPECT_GL_SINGLE_ERROR_MSG(
4454             "Draw framebuffer has no attachments and no enabled, texture-backed pixel local "
4455             "storage planes.");
4456         ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4457     }
4458 }
4459 
4460 // TODO(anglebug.com/7279): Block feedback loops
4461 // Check glBeginPixelLocalStorageANGLE validates feedback loops as specified.
4462 // TEST_P(PixelLocalStorageValidationTest, BeginPixelLocalStorageANGLE_feedback_loops)
4463 // {
4464 //     // INVALID_OPERATION is generated if a single texture image is bound to more than one pixel
4465 //     // local storage plane.
4466 //
4467 //     // INVALID_OPERATION is generated if a single texture image is simultaneously bound to a
4468 //     // pixel local storage plane and attached to the draw framebuffer.
4469 //
4470 //     ASSERT_GL_NO_ERROR();
4471 // }
4472 
4473 // Check that glEndPixelLocalStorageANGLE and glPixelLocalStorageBarrierANGLE validate as specified.
TEST_P(PixelLocalStorageValidationTest,EndAndBarrierANGLE)4474 TEST_P(PixelLocalStorageValidationTest, EndAndBarrierANGLE)
4475 {
4476     // INVALID_FRAMEBUFFER_OPERATION is generated if pixel local storage on the draw framebuffer is
4477     // in an interrupted state.
4478     GLFramebuffer fbo;
4479     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
4480     glFramebufferPixelLocalStorageInterruptANGLE();
4481     glEndPixelLocalStorageANGLE(0, nullptr);
4482     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
4483     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is interrupted.");
4484     glFramebufferPixelLocalStorageRestoreANGLE();
4485     ASSERT_GL_NO_ERROR();
4486 
4487     // INVALID_OPERATION is generated if PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE is zero.
4488     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4489     glEndPixelLocalStorageANGLE(0, nullptr);
4490     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4491     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage is not active.");
4492     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4493 
4494     glPixelLocalStorageBarrierANGLE();
4495     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4496     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage is not active.");
4497     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4498 
4499     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
4500     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4501 
4502     glEndPixelLocalStorageANGLE(1, nullptr);
4503     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4504     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage is not active.");
4505 
4506     glPixelLocalStorageBarrierANGLE();
4507     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4508     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage is not active.");
4509 
4510     glBeginPixelLocalStorageANGLE(0, nullptr);
4511     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4512     EXPECT_GL_SINGLE_ERROR_MSG("Planes must be greater than 0.");
4513     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4514 
4515     glPixelLocalStorageBarrierANGLE();
4516     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4517     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage is not active.");
4518 
4519     glEndPixelLocalStorageANGLE(2, nullptr);
4520     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4521     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage is not active.");
4522 
4523     PLSTestTexture tex(GL_RGBA8);
4524     glFramebufferTexturePixelLocalStorageANGLE(0, tex, 0, 0);
4525     for (int i = 1; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i)
4526     {
4527         glFramebufferMemorylessPixelLocalStorageANGLE(i, GL_RGBA8);
4528     }
4529     glBeginPixelLocalStorageANGLE(
4530         MAX_PIXEL_LOCAL_STORAGE_PLANES,
4531         std::vector<GLenum>(MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_LOAD_OP_ZERO_ANGLE).data());
4532     EXPECT_GL_NO_ERROR();
4533     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, MAX_PIXEL_LOCAL_STORAGE_PLANES);
4534 
4535     glPixelLocalStorageBarrierANGLE();
4536     EXPECT_GL_NO_ERROR();
4537 
4538     glEndPixelLocalStorageANGLE(
4539         MAX_PIXEL_LOCAL_STORAGE_PLANES,
4540         std::vector<GLenum>(MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_DONT_CARE).data());
4541     EXPECT_GL_NO_ERROR();
4542 
4543     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, 0);
4544     EXPECT_GL_NO_ERROR();
4545 
4546     glEndPixelLocalStorageANGLE(0, nullptr);
4547     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4548     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage is not active.");
4549 
4550     glPixelLocalStorageBarrierANGLE();
4551     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4552     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage is not active.");
4553 
4554     ASSERT_GL_NO_ERROR();
4555 
4556     // INVALID_VALUE is generated if <n> != PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE.
4557     glBeginPixelLocalStorageANGLE(2, GLenumArray({GL_LOAD_OP_LOAD_ANGLE, GL_LOAD_OP_CLEAR_ANGLE}));
4558     ASSERT_GL_NO_ERROR();
4559 
4560     glEndPixelLocalStorageANGLE(3, GLenumArray({GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE}));
4561     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4562     EXPECT_GL_SINGLE_ERROR_MSG("<n> != ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE");
4563 
4564     glEndPixelLocalStorageANGLE(1, GLenumArray({GL_DONT_CARE}));
4565     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4566     EXPECT_GL_SINGLE_ERROR_MSG("<n> != ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE");
4567 
4568     glEndPixelLocalStorageANGLE(2, GLenumArray({GL_DONT_CARE, GL_DONT_CARE}));
4569     ASSERT_GL_NO_ERROR();
4570 
4571     // INVALID_ENUM is generated if <storeops>[0..PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE-1] is not
4572     // one of the Store Operations enumerated in Table X.2.
4573     glBeginPixelLocalStorageANGLE(
4574         3, GLenumArray({GL_LOAD_OP_LOAD_ANGLE, GL_DONT_CARE, GL_LOAD_OP_CLEAR_ANGLE}));
4575     ASSERT_GL_NO_ERROR();
4576 
4577     glEndPixelLocalStorageANGLE(
4578         3, GLenumArray({GL_LOAD_OP_CLEAR_ANGLE, GL_DONT_CARE, GL_STORE_OP_STORE_ANGLE}));
4579     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4580     EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Store Operation: 0x96E5.");
4581 
4582     glEndPixelLocalStorageANGLE(
4583         3, GLenumArray({GL_DONT_CARE, GL_LOAD_OP_LOAD_ANGLE, GL_STORE_OP_STORE_ANGLE}));
4584     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4585     EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Store Operation: 0x96E6.");
4586 
4587     glEndPixelLocalStorageANGLE(
4588         3, GLenumArray({GL_DONT_CARE, GL_STORE_OP_STORE_ANGLE, GL_LOAD_OP_ZERO_ANGLE}));
4589     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4590     EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Store Operation: 0x96E4.");
4591 
4592     glEndPixelLocalStorageANGLE(
4593         3, GLenumArray({GL_DONT_CARE, GL_SCISSOR_BOX, GL_STORE_OP_STORE_ANGLE}));
4594     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4595     EXPECT_GL_SINGLE_ERROR_MSG("Invalid pixel local storage Store Operation: 0x0C10.");
4596 
4597     ASSERT_GL_NO_ERROR();
4598 }
4599 
4600 // Check that FramebufferPixelLocalStorageInterruptANGLE validates as specified.
TEST_P(PixelLocalStorageValidationTest,InterruptMechanism)4601 TEST_P(PixelLocalStorageValidationTest, InterruptMechanism)
4602 {
4603     // These commands are ignored when the default framebuffer object name 0 is bound.
4604     glFramebufferPixelLocalStorageRestoreANGLE();
4605     glFramebufferPixelLocalStorageInterruptANGLE();
4606     glFramebufferPixelLocalStorageInterruptANGLE();
4607     glFramebufferPixelLocalStorageInterruptANGLE();
4608     glFramebufferPixelLocalStorageRestoreANGLE();
4609     glFramebufferPixelLocalStorageRestoreANGLE();
4610     glFramebufferPixelLocalStorageRestoreANGLE();
4611     glFramebufferPixelLocalStorageRestoreANGLE();
4612     EXPECT_GL_NO_ERROR();
4613 
4614     for (size_t i = 0; i < 256; ++i)
4615     {
4616         glFramebufferPixelLocalStorageInterruptANGLE();
4617     }
4618     EXPECT_GL_NO_ERROR();
4619 
4620     GLFramebuffer fbo;
4621     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
4622 
4623     // INVALID_FRAMEBUFFER_OPERATION is generated if pixel local storage on the draw framebuffer is
4624     // not in an interrupted state.
4625     glFramebufferPixelLocalStorageRestoreANGLE();
4626     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
4627     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is not interrupted.");
4628 
4629     for (size_t i = 0; i < 255; ++i)
4630     {
4631         glFramebufferPixelLocalStorageInterruptANGLE();
4632     }
4633     EXPECT_GL_NO_ERROR();
4634 
4635     // INVALID_FRAMEBUFFER_OPERATION is generated if the current interrupt count on the draw
4636     // framebuffer is greater than or equal to 255.
4637     glFramebufferPixelLocalStorageInterruptANGLE();
4638     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
4639     EXPECT_GL_SINGLE_ERROR_MSG(
4640         "Pixel local storage does not support more than 255 nested interruptions.");
4641 
4642     for (size_t i = 0; i < 255; ++i)
4643     {
4644         glFramebufferPixelLocalStorageRestoreANGLE();
4645     }
4646     EXPECT_GL_NO_ERROR();
4647 
4648     glFramebufferPixelLocalStorageRestoreANGLE();
4649     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
4650     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is not interrupted.");
4651 
4652     glFramebufferPixelLocalStorageInterruptANGLE();
4653     glFramebufferPixelLocalStorageInterruptANGLE();
4654     ASSERT_GL_NO_ERROR();
4655 
4656     glFramebufferPixelLocalStorageRestoreANGLE();
4657     glFramebufferPixelLocalStorageRestoreANGLE();
4658     ASSERT_GL_NO_ERROR();
4659 
4660     glFramebufferPixelLocalStorageRestoreANGLE();
4661     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
4662     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is not interrupted.");
4663 }
4664 
4665 // Check that glGetFramebufferPixelLocalStorageParameter(f|i|ui)(Robust)?ANGLE validate as
4666 // specified.
TEST_P(PixelLocalStorageValidationTest,GetFramebufferPixelLocalStorageParametersANGLE)4667 TEST_P(PixelLocalStorageValidationTest, GetFramebufferPixelLocalStorageParametersANGLE)
4668 {
4669     // The "Get.*Robust" variants require ANGLE_robust_client_memory. ANGLE_robust_client_memory is
4670     // not disableable and is therefore supported in every ANGLE context.
4671     //
4672     // If ANGLE ever does find itself in a situation where ANGLE_robust_client_memory is not
4673     // supported, we will need to hide the "Get.*Robust" variants in order to be spec compliant.
4674     EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_robust_client_memory"));
4675 
4676     GLfloat floats[5];
4677     GLint ints[5];
4678     GLsizei length;
4679 
4680     // INVALID_FRAMEBUFFER_OPERATION is generated if the default framebuffer object name 0 is bound
4681     // to DRAW_FRAMEBUFFER.
4682     glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(
4683         0, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, 4, &length, floats);
4684     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
4685     EXPECT_GL_SINGLE_ERROR_MSG(
4686         "Default framebuffer object name 0 does not support pixel local storage.");
4687     glGetFramebufferPixelLocalStorageParameterfvANGLE(0, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE,
4688                                                       floats);
4689     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
4690     EXPECT_GL_SINGLE_ERROR_MSG(
4691         "Default framebuffer object name 0 does not support pixel local storage.");
4692     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, 4,
4693                                                             &length, ints);
4694     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
4695     EXPECT_GL_SINGLE_ERROR_MSG(
4696         "Default framebuffer object name 0 does not support pixel local storage.");
4697     glGetFramebufferPixelLocalStorageParameterivANGLE(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, ints);
4698     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
4699     EXPECT_GL_SINGLE_ERROR_MSG(
4700         "Default framebuffer object name 0 does not support pixel local storage.");
4701 
4702     GLFramebuffer fbo;
4703     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
4704 
4705     // INVALID_FRAMEBUFFER_OPERATION is generated if pixel local storage on the draw framebuffer is
4706     // in an interrupted state.
4707     glFramebufferPixelLocalStorageInterruptANGLE();
4708     glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(
4709         0, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, 4, &length, floats);
4710     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
4711     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is interrupted.");
4712     glGetFramebufferPixelLocalStorageParameterfvANGLE(0, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE,
4713                                                       floats);
4714     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
4715     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is interrupted.");
4716     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, 4,
4717                                                             &length, ints);
4718     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
4719     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is interrupted.");
4720     glGetFramebufferPixelLocalStorageParameterivANGLE(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, ints);
4721     EXPECT_GL_SINGLE_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
4722     EXPECT_GL_SINGLE_ERROR_MSG("Pixel local storage on the draw framebuffer is interrupted.");
4723     glFramebufferPixelLocalStorageRestoreANGLE();
4724     ASSERT_GL_NO_ERROR();
4725 
4726     // INVALID_VALUE is generated if <plane> < 0 or <plane> >= MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.
4727     glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(
4728         -1, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, 4, &length, floats);
4729     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4730     EXPECT_GL_SINGLE_ERROR_MSG("Plane cannot be less than 0.");
4731     glGetFramebufferPixelLocalStorageParameterfvANGLE(-1, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE,
4732                                                       floats);
4733     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4734     EXPECT_GL_SINGLE_ERROR_MSG("Plane cannot be less than 0.");
4735 
4736     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(-1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE,
4737                                                             4, &length, ints);
4738     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4739     EXPECT_GL_SINGLE_ERROR_MSG("Plane cannot be less than 0.");
4740     glGetFramebufferPixelLocalStorageParameterivANGLE(-1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, ints);
4741     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4742     EXPECT_GL_SINGLE_ERROR_MSG("Plane cannot be less than 0.");
4743 
4744     glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(
4745         MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, 4, &length, floats);
4746     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4747     EXPECT_GL_SINGLE_ERROR_MSG("Plane must be less than GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.");
4748     glGetFramebufferPixelLocalStorageParameterfvANGLE(
4749         MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, floats);
4750     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4751     EXPECT_GL_SINGLE_ERROR_MSG("Plane must be less than GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.");
4752 
4753     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(
4754         MAX_PIXEL_LOCAL_STORAGE_PLANES, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, 1, &length, ints);
4755     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4756     EXPECT_GL_SINGLE_ERROR_MSG("Plane must be less than GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.");
4757     glGetFramebufferPixelLocalStorageParameterivANGLE(MAX_PIXEL_LOCAL_STORAGE_PLANES,
4758                                                       GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, ints);
4759     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4760     EXPECT_GL_SINGLE_ERROR_MSG("Plane must be less than GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.");
4761 
4762     // INVALID_ENUM is generated if the command issued is not the associated "Get Command" for
4763     // <pname> in Table 6.Y.
4764     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(
4765         0, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, 4, &length, ints);
4766     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4767     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96EC is currently not supported.");
4768     glGetFramebufferPixelLocalStorageParameterivANGLE(0, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE,
4769                                                       ints);
4770     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4771     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96EC is currently not supported.");
4772     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(
4773         0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, 4, &length, ints);
4774     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4775     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x8CD0 is currently not supported.");
4776     glGetFramebufferPixelLocalStorageParameterivANGLE(0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
4777                                                       ints);
4778     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4779     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x8CD0 is currently not supported.");
4780     glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, 4,
4781                                                             &length, floats);
4782     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4783     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96E8 is currently not supported.");
4784     glGetFramebufferPixelLocalStorageParameterfvANGLE(1, GL_PIXEL_LOCAL_FORMAT_ANGLE, floats);
4785     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4786     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96E8 is currently not supported.");
4787     glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 1,
4788                                                             &length, floats);
4789     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4790     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96E9 is currently not supported.");
4791     glGetFramebufferPixelLocalStorageParameterfvANGLE(1, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, floats);
4792     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4793     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96E9 is currently not supported.");
4794     glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(1, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE,
4795                                                             1, &length, floats);
4796     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4797     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96EA is currently not supported.");
4798     glGetFramebufferPixelLocalStorageParameterfvANGLE(1, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE,
4799                                                       floats);
4800     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4801     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96EA is currently not supported.");
4802     glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(1, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE,
4803                                                             1, &length, floats);
4804     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4805     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96EB is currently not supported.");
4806     glGetFramebufferPixelLocalStorageParameterfvANGLE(1, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE,
4807                                                       floats);
4808     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4809     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96EB is currently not supported.");
4810     glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(1, GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE,
4811                                                             1, &length, floats);
4812     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4813     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96ED is currently not supported.");
4814     glGetFramebufferPixelLocalStorageParameterfvANGLE(1, GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE,
4815                                                       floats);
4816     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4817     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96ED is currently not supported.");
4818     glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(
4819         1, GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE, 1, &length, floats);
4820     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4821     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96EE is currently not supported.");
4822     glGetFramebufferPixelLocalStorageParameterfvANGLE(
4823         1, GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE, floats);
4824     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4825     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x96EE is currently not supported.");
4826     glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(
4827         1, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, 1, &length, floats);
4828     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4829     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x8CD3 is currently not supported.");
4830     glGetFramebufferPixelLocalStorageParameterfvANGLE(
4831         1, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, floats);
4832     EXPECT_GL_SINGLE_ERROR(GL_INVALID_ENUM);
4833     EXPECT_GL_SINGLE_ERROR_MSG("Enum 0x8CD3 is currently not supported.");
4834 
4835     // INVALID_OPERATION is generated if <bufSize> is not large enough to receive the requested
4836     // parameter.
4837     //
4838     // ... When an error is generated, nothing is written to <length>.
4839     constexpr GLsizei kLengthInitValue = 0xbaadc0de;
4840     length                             = kLengthInitValue;
4841     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, 0,
4842                                                             &length, ints);
4843     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4844     EXPECT_GL_SINGLE_ERROR_MSG("More parameters are required than were provided.");
4845     EXPECT_EQ(length, kLengthInitValue);
4846 
4847     length = kLengthInitValue;
4848     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(0, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 0,
4849                                                             &length, ints);
4850     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4851     EXPECT_GL_SINGLE_ERROR_MSG("More parameters are required than were provided.");
4852     EXPECT_EQ(length, kLengthInitValue);
4853 
4854     length = kLengthInitValue;
4855     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(0, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE,
4856                                                             0, &length, ints);
4857     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4858     EXPECT_GL_SINGLE_ERROR_MSG("More parameters are required than were provided.");
4859     EXPECT_EQ(length, kLengthInitValue);
4860 
4861     length = kLengthInitValue;
4862     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(0, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE,
4863                                                             0, &length, ints);
4864     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4865     EXPECT_GL_SINGLE_ERROR_MSG("More parameters are required than were provided.");
4866     EXPECT_EQ(length, kLengthInitValue);
4867 
4868     length = kLengthInitValue;
4869     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(0, GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE,
4870                                                             3, &length, ints);
4871     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4872     EXPECT_GL_SINGLE_ERROR_MSG("More parameters are required than were provided.");
4873     EXPECT_EQ(length, kLengthInitValue);
4874 
4875     length = kLengthInitValue;
4876     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(
4877         0, GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE, 3, &length, ints);
4878     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4879     EXPECT_GL_SINGLE_ERROR_MSG("More parameters are required than were provided.");
4880     EXPECT_EQ(length, kLengthInitValue);
4881 
4882     length = kLengthInitValue;
4883     glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(
4884         0, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, 3, &length, floats);
4885     EXPECT_GL_SINGLE_ERROR(GL_INVALID_OPERATION);
4886     EXPECT_GL_SINGLE_ERROR_MSG("More parameters are required than were provided.");
4887     EXPECT_EQ(length, kLengthInitValue);
4888 
4889     // Not quite pure validation, but also ensure that <length> gets written properly.
4890     length = kLengthInitValue;
4891     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, 5,
4892                                                             &length, ints);
4893     EXPECT_GL_NO_ERROR();
4894     EXPECT_EQ(length, 1);
4895 
4896     length = kLengthInitValue;
4897     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(0, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 5,
4898                                                             &length, ints);
4899     EXPECT_GL_NO_ERROR();
4900     EXPECT_EQ(length, 1);
4901 
4902     length = kLengthInitValue;
4903     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(0, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE,
4904                                                             5, &length, ints);
4905     EXPECT_GL_NO_ERROR();
4906     EXPECT_EQ(length, 1);
4907 
4908     length = kLengthInitValue;
4909     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(0, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE,
4910                                                             5, &length, ints);
4911     EXPECT_GL_NO_ERROR();
4912     EXPECT_EQ(length, 1);
4913 
4914     length = kLengthInitValue;
4915     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(0, GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE,
4916                                                             5, &length, ints);
4917     EXPECT_GL_NO_ERROR();
4918     EXPECT_EQ(length, 4);
4919 
4920     length = kLengthInitValue;
4921     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(
4922         0, GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE, 5, &length, ints);
4923     EXPECT_GL_NO_ERROR();
4924     EXPECT_EQ(length, 4);
4925 
4926     length = kLengthInitValue;
4927     glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(
4928         0, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, 5, &length, floats);
4929     EXPECT_GL_NO_ERROR();
4930     EXPECT_EQ(length, 4);
4931 
4932     // INVALID_VALUE is generated if <params> is NULL.
4933     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, 5,
4934                                                             &length, nullptr);
4935     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4936     EXPECT_GL_SINGLE_ERROR_MSG("<params> cannot be null.");
4937     glGetFramebufferPixelLocalStorageParameterivANGLE(0, GL_PIXEL_LOCAL_FORMAT_ANGLE, nullptr);
4938     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4939     EXPECT_GL_SINGLE_ERROR_MSG("<params> cannot be null.");
4940 
4941     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(0, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, 5,
4942                                                             &length, nullptr);
4943     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4944     EXPECT_GL_SINGLE_ERROR_MSG("<params> cannot be null.");
4945     glGetFramebufferPixelLocalStorageParameterivANGLE(0, GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE,
4946                                                       nullptr);
4947     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4948     EXPECT_GL_SINGLE_ERROR_MSG("<params> cannot be null.");
4949 
4950     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(0, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE,
4951                                                             5, &length, nullptr);
4952     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4953     EXPECT_GL_SINGLE_ERROR_MSG("<params> cannot be null.");
4954     glGetFramebufferPixelLocalStorageParameterivANGLE(0, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE,
4955                                                       nullptr);
4956     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4957     EXPECT_GL_SINGLE_ERROR_MSG("<params> cannot be null.");
4958 
4959     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(0, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE,
4960                                                             5, &length, nullptr);
4961     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4962     EXPECT_GL_SINGLE_ERROR_MSG("<params> cannot be null.");
4963     glGetFramebufferPixelLocalStorageParameterivANGLE(0, GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE,
4964                                                       nullptr);
4965     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4966     EXPECT_GL_SINGLE_ERROR_MSG("<params> cannot be null.");
4967 
4968     glGetFramebufferPixelLocalStorageParameterivRobustANGLE(0, GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE,
4969                                                             5, &length, nullptr);
4970     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4971     EXPECT_GL_SINGLE_ERROR_MSG("<params> cannot be null.");
4972     glGetFramebufferPixelLocalStorageParameterivANGLE(0, GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE,
4973                                                       nullptr);
4974     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4975     EXPECT_GL_SINGLE_ERROR_MSG("<params> cannot be null.");
4976 
4977     glGetFramebufferPixelLocalStorageParameterfvRobustANGLE(
4978         0, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE, 5, &length, nullptr);
4979     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4980     EXPECT_GL_SINGLE_ERROR_MSG("<params> cannot be null.");
4981     glGetFramebufferPixelLocalStorageParameterfvANGLE(0, GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE,
4982                                                       nullptr);
4983     EXPECT_GL_SINGLE_ERROR(GL_INVALID_VALUE);
4984     EXPECT_GL_SINGLE_ERROR_MSG("<params> cannot be null.");
4985 }
4986 
4987 // Check command-specific errors that go into effect when PLS is active, as well as commands
4988 // specifically called out by EXT_shader_pixel_local_storage for flushing tiled memory.
TEST_P(PixelLocalStorageValidationTest,BannedCommands)4989 TEST_P(PixelLocalStorageValidationTest, BannedCommands)
4990 {
4991     PLSTestTexture tex(GL_RGBA8);
4992     GLFramebuffer fbo;
4993     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
4994     glFramebufferTexturePixelLocalStorageANGLE(0, tex, 0, 0);
4995     int numActivePlanes = MAX_PIXEL_LOCAL_STORAGE_PLANES - 1;
4996     for (int i = 1; i < numActivePlanes; ++i)
4997     {
4998         glFramebufferMemorylessPixelLocalStorageANGLE(i, GL_RGBA8);
4999     }
5000     glBeginPixelLocalStorageANGLE(
5001         numActivePlanes, std::vector<GLenum>(numActivePlanes, GL_LOAD_OP_ZERO_ANGLE).data());
5002     ASSERT_GL_INTEGER(GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE, numActivePlanes);
5003     ASSERT_GL_NO_ERROR();
5004 
5005     // Check commands called out by EXT_shader_pixel_local_storage for flushing tiled memory.
5006     EXPECT_BANNED_DEFAULT_MSG(glFlush());
5007     EXPECT_BANNED_DEFAULT_MSG(glFinish());
5008     EXPECT_BANNED_DEFAULT_MSG(glClientWaitSync(nullptr, 0, 0));
5009     EXPECT_BANNED_DEFAULT_MSG(
5010         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
5011     EXPECT_BANNED_DEFAULT_MSG(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 0, 0));
5012     EXPECT_BANNED_DEFAULT_MSG(glBlitFramebuffer(0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
5013     EXPECT_BANNED_DEFAULT_MSG(glBindFramebuffer(GL_FRAMEBUFFER, 0));
5014     EXPECT_BANNED_DEFAULT_MSG(glDrawBuffers(0, nullptr));
5015 
5016     // INVALID_OPERATION is generated by Enable(), Disable() if <cap> is not one of: CULL_FACE,
5017     // DEPTH_CLAMP_EXT, DEPTH_TEST, POLYGON_OFFSET_POINT_NV, POLYGON_OFFSET_LINE_NV,
5018     // POLYGON_OFFSET_LINE_ANGLE, POLYGON_OFFSET_FILL, PRIMITIVE_RESTART_FIXED_INDEX,
5019     // SCISSOR_TEST, STENCIL_TEST, CLIP_DISTANCE[0..7]_EXT
5020     EXPECT_ALLOWED_CAP(GL_CULL_FACE);
5021     if (EnsureGLExtensionEnabled("GL_KHR_debug"))
5022     {
5023         EXPECT_ALLOWED_CAP(GL_DEBUG_OUTPUT);
5024         EXPECT_ALLOWED_CAP(GL_DEBUG_OUTPUT_SYNCHRONOUS);
5025         // Now turn them back on since the test actually uses these caps...
5026         glEnable(GL_DEBUG_OUTPUT);
5027         glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
5028     }
5029     EXPECT_ALLOWED_CAP(GL_DEPTH_TEST);
5030     if (EnsureGLExtensionEnabled("GL_EXT_depth_clamp"))
5031     {
5032         EXPECT_ALLOWED_CAP(GL_DEPTH_CLAMP_EXT);
5033     }
5034     if (EnsureGLExtensionEnabled("GL_ANGLE_polygon_mode"))
5035     {
5036         EXPECT_ALLOWED_CAP(GL_POLYGON_OFFSET_LINE_ANGLE);
5037         glPolygonModeANGLE(GL_FRONT_AND_BACK, GL_FILL_ANGLE);
5038         EXPECT_GL_NO_ERROR();
5039     }
5040     if (EnsureGLExtensionEnabled("GL_NV_polygon_mode"))
5041     {
5042         EXPECT_ALLOWED_CAP(GL_POLYGON_OFFSET_POINT_NV);
5043         EXPECT_ALLOWED_CAP(GL_POLYGON_OFFSET_LINE_NV);
5044         glPolygonModeNV(GL_FRONT_AND_BACK, GL_FILL_NV);
5045         EXPECT_GL_NO_ERROR();
5046     }
5047     if (EnsureGLExtensionEnabled("GL_EXT_polygon_offset_clamp"))
5048     {
5049         glPolygonOffsetClampEXT(0.0f, 0.0f, 0.0f);
5050         EXPECT_GL_NO_ERROR();
5051     }
5052     EXPECT_ALLOWED_CAP(GL_POLYGON_OFFSET_FILL);
5053     EXPECT_ALLOWED_CAP(GL_PRIMITIVE_RESTART_FIXED_INDEX);
5054     EXPECT_ALLOWED_CAP(GL_SCISSOR_TEST);
5055     EXPECT_ALLOWED_CAP(GL_STENCIL_TEST);
5056     if (EnsureGLExtensionEnabled("GL_EXT_clip_cull_distance"))
5057     {
5058         for (GLenum i = 0; i < 8; ++i)
5059         {
5060             EXPECT_ALLOWED_CAP(GL_CLIP_DISTANCE0_EXT + i);
5061         }
5062     }
5063     EXPECT_BANNED_CAP(GL_SAMPLE_ALPHA_TO_COVERAGE);
5064     EXPECT_BANNED_CAP(GL_SAMPLE_COVERAGE);
5065     EXPECT_BANNED_CAP(GL_BLEND);
5066     EXPECT_BANNED_CAP(GL_DITHER);
5067     EXPECT_BANNED_CAP(GL_RASTERIZER_DISCARD);
5068     if (isContextVersionAtLeast(3, 1))
5069     {
5070         EXPECT_BANNED_CAP(GL_SAMPLE_MASK);
5071     }
5072     if (EnsureGLExtensionEnabled("GL_EXT_multisample_compatibility"))
5073     {
5074         EXPECT_BANNED_CAP(GL_MULTISAMPLE_EXT);
5075         EXPECT_BANNED_CAP(GL_SAMPLE_ALPHA_TO_ONE_EXT);
5076     }
5077     if (EnsureGLExtensionEnabled("GL_OES_sample_shading"))
5078     {
5079         EXPECT_BANNED_CAP(GL_SAMPLE_SHADING);
5080     }
5081     if (EnsureGLExtensionEnabled("GL_QCOM_shading_rate"))
5082     {
5083         EXPECT_BANNED_CAP(GL_SHADING_RATE_PRESERVE_ASPECT_RATIO_QCOM);
5084     }
5085     if (EnsureGLExtensionEnabled("GL_ANGLE_logic_op"))
5086     {
5087         EXPECT_BANNED_CAP(GL_COLOR_LOGIC_OP);
5088     }
5089     // BLEND is the only indexed capability in ANGLE, but we can at least use SHADING_RATE_IMAGE_NV
5090     // to check the debug output and verify that PLS validation is banning it, which ensures it is
5091     // future proof against hypothetical future extensions that add indexed capabilities.
5092     EXPECT_BANNED_CAP_INDEXED(GL_SHADING_RATE_IMAGE_NV);
5093 
5094     // The validation tests are expected to run in a configuration where the draw buffers are
5095     // restricted by PLS (e.g., not shader images).
5096     int bannedColorAttachment = MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE;
5097     ASSERT(bannedColorAttachment < MAX_DRAW_BUFFERS);
5098 
5099     int bannedCombinedAttachment =
5100         MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES - numActivePlanes;
5101 
5102     // INVALID_OPERATION is generated by ClearBufferfv(), ClearBufferiv(), ClearBufferuiv() if
5103     // <buffer> is GL_COLOR and and any of the following are true:
5104     //
5105     //   <buffer> >= MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE
5106     //   <buffer> >= (MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE -
5107     //                ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE)
5108     //
5109     GLfloat clearf[4]{};
5110     GLint cleari[4]{};
5111     GLuint clearui[4]{};
5112     {
5113         const char *msg =
5114             "Argument <drawbuffer> must be less than "
5115             "MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE when pixel local "
5116             "storage is active.";
5117         EXPECT_BANNED(glClearBufferfv(GL_COLOR, bannedColorAttachment, clearf), msg);
5118         EXPECT_BANNED(glClearBufferiv(GL_COLOR, bannedColorAttachment, cleari), msg);
5119         EXPECT_BANNED(glClearBufferuiv(GL_COLOR, bannedColorAttachment, clearui), msg);
5120         EXPECT_BANNED(glClearBufferfv(GL_COLOR, MAX_DRAW_BUFFERS - 1, clearf), msg);
5121         EXPECT_BANNED(glClearBufferiv(GL_COLOR, MAX_DRAW_BUFFERS - 1, cleari), msg);
5122         EXPECT_BANNED(glClearBufferuiv(GL_COLOR, MAX_DRAW_BUFFERS - 1, clearui), msg);
5123     }
5124     if (bannedCombinedAttachment < bannedColorAttachment)
5125     {
5126         const char *msg =
5127             "Argument <drawbuffer> must be less than "
5128             "(MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - "
5129             "ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE) when pixel local storage is active.";
5130         EXPECT_BANNED(glClearBufferfv(GL_COLOR, bannedCombinedAttachment, clearf), msg);
5131         EXPECT_BANNED(glClearBufferiv(GL_COLOR, bannedCombinedAttachment, cleari), msg);
5132         EXPECT_BANNED(glClearBufferuiv(GL_COLOR, bannedCombinedAttachment, clearui), msg);
5133     }
5134     glClearBufferfv(GL_DEPTH, 0, clearf);
5135     EXPECT_GL_NO_ERROR();
5136     glClearBufferiv(GL_STENCIL, 0, cleari);
5137     EXPECT_GL_NO_ERROR();
5138 
5139     if (IsGLExtensionEnabled("GL_OES_draw_buffers_indexed"))
5140     {
5141         // INVALID_OPERATION is generated by Enablei*(), Disablei*() if and any
5142         // of the following are true:
5143         //
5144         //   <index> >= MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE
5145         //   <index> >= (MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE -
5146         //              ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE)
5147         //
5148         {
5149             const char *msg =
5150                 "Argument <index> must be less than "
5151                 "MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE when pixel local "
5152                 "storage is active.";
5153             EXPECT_BANNED(glEnableiOES(GL_BLEND, bannedColorAttachment), msg);
5154             EXPECT_BANNED(glDisableiOES(GL_BLEND, bannedColorAttachment), msg);
5155             EXPECT_BANNED(glEnableiOES(GL_BLEND, MAX_DRAW_BUFFERS - 1), msg);
5156             EXPECT_BANNED(glDisableiOES(GL_BLEND, MAX_DRAW_BUFFERS - 1), msg);
5157         }
5158         if (bannedCombinedAttachment < bannedColorAttachment)
5159         {
5160             const char *msg =
5161                 "Argument <index> must be less than "
5162                 "(MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - "
5163                 "ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE) when pixel local storage is active.";
5164             EXPECT_BANNED(glEnableiOES(GL_BLEND, bannedCombinedAttachment), msg);
5165             EXPECT_BANNED(glDisableiOES(GL_BLEND, bannedCombinedAttachment), msg);
5166         }
5167 
5168         // INVALID_OPERATION is generated by BlendEquationi*(), BlendEquationSeparatei*(),
5169         // BlendFunci*(), BlendFuncSeparatei*(), ColorMaski*() if and any of the following are true:
5170         //
5171         //   <buf> >= MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE
5172         //   <buf> >= (MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE -
5173         //             ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE)
5174         //
5175         {
5176             const char *msg =
5177                 "Argument <buf> must be less than "
5178                 "MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE when pixel local "
5179                 "storage is active.";
5180             EXPECT_BANNED(glBlendEquationiOES(bannedColorAttachment, GL_FUNC_ADD), msg);
5181             EXPECT_BANNED(glBlendEquationSeparateiOES(bannedColorAttachment, GL_FUNC_SUBTRACT,
5182                                                       GL_FUNC_REVERSE_SUBTRACT),
5183                           msg);
5184             EXPECT_BANNED(glBlendFunciOES(bannedColorAttachment, GL_ZERO, GL_ZERO), msg);
5185             EXPECT_BANNED(
5186                 glBlendFuncSeparateiOES(bannedColorAttachment, GL_ZERO, GL_ZERO, GL_ZERO, GL_ZERO),
5187                 msg);
5188             EXPECT_BANNED(
5189                 glColorMaskiOES(bannedColorAttachment, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE),
5190                 msg);
5191             EXPECT_BANNED(glBlendEquationiOES(MAX_DRAW_BUFFERS - 1, GL_FUNC_ADD), msg);
5192             EXPECT_BANNED(glBlendEquationSeparateiOES(MAX_DRAW_BUFFERS - 1, GL_FUNC_SUBTRACT,
5193                                                       GL_FUNC_REVERSE_SUBTRACT),
5194                           msg);
5195             EXPECT_BANNED(glBlendFunciOES(MAX_DRAW_BUFFERS - 1, GL_ZERO, GL_ZERO), msg);
5196             EXPECT_BANNED(
5197                 glBlendFuncSeparateiOES(MAX_DRAW_BUFFERS - 1, GL_ZERO, GL_ZERO, GL_ZERO, GL_ZERO),
5198                 msg);
5199             EXPECT_BANNED(
5200                 glColorMaskiOES(MAX_DRAW_BUFFERS - 1, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE), msg);
5201         }
5202         if (bannedCombinedAttachment < MAX_DRAW_BUFFERS - 1)
5203         {
5204             const char *msg =
5205                 "Argument <buf> must be less than "
5206                 "(MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - "
5207                 "ACTIVE_PIXEL_LOCAL_STORAGE_PLANES_ANGLE) when pixel local storage is active.";
5208             EXPECT_BANNED(glBlendEquationiOES(bannedCombinedAttachment, GL_FUNC_ADD), msg);
5209             EXPECT_BANNED(glBlendEquationSeparateiOES(bannedCombinedAttachment, GL_FUNC_SUBTRACT,
5210                                                       GL_FUNC_REVERSE_SUBTRACT),
5211                           msg);
5212             EXPECT_BANNED(glBlendFunciOES(bannedCombinedAttachment, GL_ZERO, GL_ZERO), msg);
5213             EXPECT_BANNED(glBlendFuncSeparateiOES(bannedCombinedAttachment, GL_ZERO, GL_ZERO,
5214                                                   GL_ZERO, GL_ZERO),
5215                           msg);
5216             EXPECT_BANNED(
5217                 glColorMaskiOES(bannedCombinedAttachment, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE),
5218                 msg);
5219         }
5220     }
5221 
5222     // INVALID_OPERATION is generated if a draw is issued with a fragment shader that accesses a
5223     // texture bound to pixel local storage.
5224     //
5225     // TODO(anglebug.com/7279).
5226 
5227     // INVALID_OPERATION is generated if a draw is issued with a fragment shader that has a
5228     // pixel local uniform bound to an inactive pixel local storage plane.
5229     //
5230     // TODO(anglebug.com/7279).
5231 
5232     // INVALID_OPERATION is generated if a draw is issued with a fragment shader that does _not_
5233     // have a pixel local uniform bound to an _active_ pixel local storage plane (i.e., the
5234     // fragment shader must declare uniforms bound to every single active pixel local storage
5235     // plane).
5236     //
5237     // This is because many backend implementations need to account for every active pixel local
5238     // storage plane, even if the application code does not access it during a particular shader
5239     // invocation.
5240     //
5241     // TODO(anglebug.com/7279).
5242 
5243     // INVALID_OPERATION is generated if a draw is issued with a fragment shader that has a
5244     // pixel local storage uniform whose format layout qualifier does not identically match the
5245     // internalformat of its associated pixel local storage plane on the current draw
5246     // framebuffer, as enumerated in Table X.3.
5247     //
5248     // TODO(anglebug.com/7279).
5249 
5250     ASSERT_GL_NO_ERROR();
5251 }
5252 
5253 // Check that PLS gets properly cleaned up when its framebuffer and textures are never deleted.
TEST_P(PixelLocalStorageValidationTest,LeakFramebufferAndTexture)5254 TEST_P(PixelLocalStorageValidationTest, LeakFramebufferAndTexture)
5255 {
5256     GLuint fbo;
5257     glGenFramebuffers(1, &fbo);
5258     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5259 
5260     GLuint tex0;
5261     glGenTextures(1, &tex0);
5262     glBindTexture(GL_TEXTURE_2D, tex0);
5263     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8UI, 10, 10);
5264     glFramebufferTexturePixelLocalStorageANGLE(0, tex0, 0, 0);
5265 
5266     PLSTestTexture tex1(GL_R32F);
5267     glFramebufferTexturePixelLocalStorageANGLE(1, tex1, 0, 0);
5268 
5269     glFramebufferMemorylessPixelLocalStorageANGLE(3, GL_RGBA8I);
5270 
5271     // Delete tex1.
5272     // Don't delete tex0.
5273     // Don't delete fbo.
5274 
5275     // The PixelLocalStorage frontend implementation has internal assertions that verify all its GL
5276     // context objects are properly disposed of.
5277 }
5278 
5279 // Check that PLS gets properly cleaned up when the context is lost.
TEST_P(PixelLocalStorageValidationTest,LoseContext)5280 TEST_P(PixelLocalStorageValidationTest, LoseContext)
5281 {
5282     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_CHROMIUM_lose_context"));
5283 
5284     GLuint fbo0;
5285     glGenFramebuffers(1, &fbo0);
5286 
5287     GLFramebuffer fbo1;
5288 
5289     GLuint tex0;
5290     glGenTextures(1, &tex0);
5291     glBindTexture(GL_TEXTURE_2D, tex0);
5292     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8UI, 10, 10);
5293 
5294     PLSTestTexture tex1(GL_R32F);
5295 
5296     glBindFramebuffer(GL_FRAMEBUFFER, fbo0);
5297     glFramebufferTexturePixelLocalStorageANGLE(0, tex0, 0, 0);
5298     glFramebufferTexturePixelLocalStorageANGLE(1, tex1, 0, 0);
5299     glFramebufferMemorylessPixelLocalStorageANGLE(3, GL_RGBA8I);
5300 
5301     glBindFramebuffer(GL_FRAMEBUFFER, fbo1);
5302     glFramebufferTexturePixelLocalStorageANGLE(0, tex0, 0, 0);
5303     glFramebufferTexturePixelLocalStorageANGLE(1, tex1, 0, 0);
5304     glFramebufferMemorylessPixelLocalStorageANGLE(3, GL_RGBA8I);
5305 
5306     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5307 
5308     glLoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET, GL_INNOCENT_CONTEXT_RESET);
5309 
5310     // Delete tex1.
5311     // Don't delete tex0.
5312     // Delete fbo1.
5313     // Don't delete fbo0.
5314 
5315     // The PixelLocalStorage frontend implementation has internal assertions that verify all its GL
5316     // context objects are properly disposed of.
5317 }
5318 
5319 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PixelLocalStorageValidationTest);
5320 ANGLE_INSTANTIATE_TEST(PixelLocalStorageValidationTest,
5321                        WithRobustness(ES31_NULL()).enable(Feature::EmulatePixelLocalStorage),
5322                        WithRobustness(ES31_NULL())
5323                            .enable(Feature::EmulatePixelLocalStorage)
5324                            .enable(Feature::DisableDrawBuffersIndexed));
5325 
5326 class PixelLocalStorageCompilerTest : public ANGLETest<>
5327 {
5328   public:
PixelLocalStorageCompilerTest()5329     PixelLocalStorageCompilerTest() { setExtensionsEnabled(false); }
5330 
5331   protected:
testSetUp()5332     void testSetUp() override
5333     {
5334         ASSERT(EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
5335 
5336         // INVALID_OPERATION is generated if DITHER is enabled.
5337         glDisable(GL_DITHER);
5338 
5339         ANGLETest::testSetUp();
5340     }
5341     ShaderInfoLog log;
5342 };
5343 
5344 // Check that PLS #extension support is properly implemented.
TEST_P(PixelLocalStorageCompilerTest,Extension)5345 TEST_P(PixelLocalStorageCompilerTest, Extension)
5346 {
5347     // GL_ANGLE_shader_pixel_local_storage_coherent isn't a shader extension. Shaders must always
5348     // use GL_ANGLE_shader_pixel_local_storage, regardless of coherency.
5349     constexpr char kNonexistentPLSCoherentExtension[] = R"(#version 310 es
5350     #extension GL_ANGLE_shader_pixel_local_storage_coherent : require
5351     void main()
5352     {
5353     })";
5354     EXPECT_FALSE(log.compileFragmentShader(kNonexistentPLSCoherentExtension));
5355     EXPECT_TRUE(log.has(
5356         "ERROR: 0:2: 'GL_ANGLE_shader_pixel_local_storage_coherent' : extension is not supported"));
5357 
5358     // PLS type names cannot be used as variable names when the extension is enabled.
5359     constexpr char kPLSEnabledTypesAsNames[] = R"(#version 310 es
5360     #extension all : warn
5361     void main()
5362     {
5363         int pixelLocalANGLE = 0;
5364         int ipixelLocalANGLE = 0;
5365         int upixelLocalANGLE = 0;
5366     })";
5367     EXPECT_FALSE(log.compileFragmentShader(kPLSEnabledTypesAsNames));
5368     EXPECT_TRUE(log.has("ERROR: 0:5: 'pixelLocalANGLE' : syntax error"));
5369 
5370     // PLS type names are fair game when the extension is disabled.
5371     constexpr char kPLSDisabledTypesAsNames[] = R"(#version 310 es
5372     #extension GL_ANGLE_shader_pixel_local_storage : disable
5373     void main()
5374     {
5375         int pixelLocalANGLE = 0;
5376         int ipixelLocalANGLE = 0;
5377         int upixelLocalANGLE = 0;
5378     })";
5379     EXPECT_TRUE(log.compileFragmentShader(kPLSDisabledTypesAsNames));
5380 
5381     // PLS is not allowed in a vertex shader.
5382     constexpr char kPLSInVertexShader[] = R"(#version 310 es
5383     #extension GL_ANGLE_shader_pixel_local_storage : enable
5384     layout(binding=0, rgba8) lowp uniform pixelLocalANGLE pls;
5385     void main()
5386     {
5387         pixelLocalStoreANGLE(pls, vec4(0));
5388     })";
5389     EXPECT_FALSE(log.compileShader(kPLSInVertexShader, GL_VERTEX_SHADER));
5390     EXPECT_TRUE(
5391         log.has("ERROR: 0:3: 'pixelLocalANGLE' : undefined use of pixel local storage outside a "
5392                 "fragment shader"));
5393 
5394     // Internal synchronization functions used by the compiler shouldn't be visible in ESSL.
5395     EXPECT_FALSE(log.compileFragmentShader(R"(#version 310 es
5396     #extension GL_ANGLE_shader_pixel_local_storage : require
5397     void main()
5398     {
5399         beginInvocationInterlockNV();
5400         endInvocationInterlockNV();
5401     })"));
5402     EXPECT_TRUE(log.has(
5403         "ERROR: 0:5: 'beginInvocationInterlockNV' : no matching overloaded function found"));
5404     EXPECT_TRUE(
5405         log.has("ERROR: 0:6: 'endInvocationInterlockNV' : no matching overloaded function found"));
5406 
5407     EXPECT_FALSE(log.compileFragmentShader(R"(#version 310 es
5408     #extension GL_ANGLE_shader_pixel_local_storage : require
5409     void main()
5410     {
5411         beginFragmentShaderOrderingINTEL();
5412     })"));
5413     EXPECT_TRUE(log.has(
5414         "ERROR: 0:5: 'beginFragmentShaderOrderingINTEL' : no matching overloaded function found"));
5415 
5416     EXPECT_FALSE(log.compileFragmentShader(R"(#version 310 es
5417     #extension GL_ANGLE_shader_pixel_local_storage : require
5418     void main()
5419     {
5420         beginInvocationInterlockARB();
5421         endInvocationInterlockARB();
5422     })"));
5423     EXPECT_TRUE(log.has(
5424         "ERROR: 0:5: 'beginInvocationInterlockARB' : no matching overloaded function found"));
5425     EXPECT_TRUE(
5426         log.has("ERROR: 0:6: 'endInvocationInterlockARB' : no matching overloaded function found"));
5427 
5428     ASSERT_GL_NO_ERROR();
5429 }
5430 
5431 // Check proper validation of PLS handle declarations.
TEST_P(PixelLocalStorageCompilerTest,Declarations)5432 TEST_P(PixelLocalStorageCompilerTest, Declarations)
5433 {
5434     // PLS handles must be uniform.
5435     constexpr char kPLSTypesMustBeUniform[] = R"(#version 310 es
5436     #extension GL_ANGLE_shader_pixel_local_storage : enable
5437     layout(binding=0, rgba8) highp pixelLocalANGLE pls1;
5438     void main()
5439     {
5440         highp ipixelLocalANGLE pls2;
5441         highp upixelLocalANGLE pls3;
5442     })";
5443     EXPECT_FALSE(log.compileFragmentShader(kPLSTypesMustBeUniform));
5444     EXPECT_TRUE(log.has("ERROR: 0:3: 'pixelLocalANGLE' : pixelLocalANGLEs must be uniform"));
5445     EXPECT_TRUE(log.has("ERROR: 0:6: 'ipixelLocalANGLE' : ipixelLocalANGLEs must be uniform"));
5446     EXPECT_TRUE(log.has("ERROR: 0:7: 'upixelLocalANGLE' : upixelLocalANGLEs must be uniform"));
5447 
5448     // Memory qualifiers are not allowed on PLS handles.
5449     constexpr char kPLSMemoryQualifiers[] = R"(#version 310 es
5450     #extension GL_ANGLE_shader_pixel_local_storage : require
5451     layout(binding=0, rgba8) uniform lowp volatile coherent restrict pixelLocalANGLE pls1;
5452     layout(binding=1, rgba8i) uniform mediump readonly ipixelLocalANGLE pls2;
5453     void f(uniform highp writeonly upixelLocalANGLE pls);
5454     void main()
5455     {
5456     })";
5457     EXPECT_FALSE(log.compileFragmentShader(kPLSMemoryQualifiers));
5458     EXPECT_TRUE(log.has("ERROR: 0:3: 'coherent' : "));
5459     EXPECT_TRUE(log.has("ERROR: 0:3: 'restrict' : "));
5460     EXPECT_TRUE(log.has("ERROR: 0:3: 'volatile' : "));
5461     EXPECT_TRUE(log.has("ERROR: 0:4: 'readonly' : "));
5462     EXPECT_TRUE(log.has("ERROR: 0:5: 'writeonly' : "));
5463 
5464     // PLS handles must specify precision.
5465     constexpr char kPLSNoPrecision[] = R"(#version 310 es
5466     #extension GL_ANGLE_shader_pixel_local_storage : enable
5467     layout(binding=0, rgba8) uniform pixelLocalANGLE pls1;
5468     layout(binding=1, rgba8i) uniform ipixelLocalANGLE pls2;
5469     void f(upixelLocalANGLE pls3)
5470     {
5471     }
5472     void main()
5473     {
5474     })";
5475     EXPECT_FALSE(log.compileFragmentShader(kPLSNoPrecision));
5476     EXPECT_TRUE(log.has("ERROR: 0:3: 'pixelLocalANGLE' : No precision specified"));
5477     EXPECT_TRUE(log.has("ERROR: 0:4: 'ipixelLocalANGLE' : No precision specified"));
5478     EXPECT_TRUE(log.has("ERROR: 0:5: 'upixelLocalANGLE' : No precision specified"));
5479 
5480     // PLS handles cannot cannot be aggregated in arrays.
5481     constexpr char kPLSArrays[] = R"(#version 310 es
5482     #extension GL_ANGLE_shader_pixel_local_storage : require
5483     layout(binding=0, rgba8) uniform lowp pixelLocalANGLE pls1[1];
5484     layout(binding=1, rgba8i) uniform mediump ipixelLocalANGLE pls2[2];
5485     layout(binding=2, rgba8ui) uniform highp upixelLocalANGLE pls3[3];
5486     void main()
5487     {
5488     })";
5489     EXPECT_FALSE(log.compileFragmentShader(kPLSArrays));
5490     EXPECT_TRUE(log.has(
5491         "ERROR: 0:3: 'array' : pixel local storage handles cannot be aggregated in arrays"));
5492     EXPECT_TRUE(log.has(
5493         "ERROR: 0:4: 'array' : pixel local storage handles cannot be aggregated in arrays"));
5494     EXPECT_TRUE(log.has(
5495         "ERROR: 0:5: 'array' : pixel local storage handles cannot be aggregated in arrays"));
5496 
5497     // If PLS handles could be used before their declaration, then we would need to update the PLS
5498     // rewriters to make two passes.
5499     constexpr char kPLSUseBeforeDeclaration[] = R"(#version 310 es
5500     #extension GL_ANGLE_shader_pixel_local_storage : require
5501     void f()
5502     {
5503         pixelLocalStoreANGLE(pls, vec4(0));
5504         pixelLocalStoreANGLE(pls2, ivec4(0));
5505     }
5506     layout(binding=0, rgba8) uniform lowp pixelLocalANGLE pls;
5507     void main()
5508     {
5509         pixelLocalStoreANGLE(pls, vec4(0));
5510         pixelLocalStoreANGLE(pls2, ivec4(0));
5511     }
5512     layout(binding=1, rgba8i) uniform lowp ipixelLocalANGLE pls2;)";
5513     EXPECT_FALSE(log.compileFragmentShader(kPLSUseBeforeDeclaration));
5514     EXPECT_TRUE(log.has("ERROR: 0:5: 'pls' : undeclared identifier"));
5515     EXPECT_TRUE(log.has("ERROR: 0:6: 'pls2' : undeclared identifier"));
5516     EXPECT_TRUE(log.has("ERROR: 0:12: 'pls2' : undeclared identifier"));
5517 
5518     // PLS unimorms must be declared at global scope; they cannot be declared in structs or
5519     // interface blocks.
5520     constexpr char kPLSInStruct[] = R"(#version 310 es
5521     #extension GL_ANGLE_shader_pixel_local_storage : require
5522     struct Foo
5523     {
5524         lowp pixelLocalANGLE pls;
5525     };
5526     uniform Foo foo;
5527     uniform PLSBlock
5528     {
5529         lowp pixelLocalANGLE blockpls;
5530     };
5531     void main()
5532     {
5533         pixelLocalStoreANGLE(foo.pls, pixelLocalLoadANGLE(blockpls));
5534     })";
5535     EXPECT_FALSE(log.compileFragmentShader(kPLSInStruct));
5536     EXPECT_TRUE(log.has("ERROR: 0:5: 'pixelLocalANGLE' : disallowed type in struct"));
5537     EXPECT_TRUE(
5538         log.has("ERROR: 0:10: 'PLSBlock' : Opaque types are not allowed in interface blocks"));
5539 
5540     ASSERT_GL_NO_ERROR();
5541 }
5542 
5543 // Check proper validation of PLS layout qualifiers.
TEST_P(PixelLocalStorageCompilerTest,LayoutQualifiers)5544 TEST_P(PixelLocalStorageCompilerTest, LayoutQualifiers)
5545 {
5546     // PLS handles must use a supported format and binding.
5547     constexpr char kPLSUnsupportedFormatsAndBindings[] = R"(#version 310 es
5548     #extension GL_ANGLE_shader_pixel_local_storage : require
5549     layout(binding=0, rgba32f) highp uniform pixelLocalANGLE pls0;
5550     layout(binding=1, rgba16f) highp uniform pixelLocalANGLE pls1;
5551     layout(binding=2, rgba8_snorm) highp uniform pixelLocalANGLE pls2;
5552     layout(binding=3, rgba32ui) highp uniform upixelLocalANGLE pls3;
5553     layout(binding=4, rgba16ui) highp uniform upixelLocalANGLE pls4;
5554     layout(binding=5, rgba32i) highp uniform ipixelLocalANGLE pls5;
5555     layout(binding=6, rgba16i) highp uniform ipixelLocalANGLE pls6;
5556     layout(binding=7, r32i) highp uniform ipixelLocalANGLE pls7;
5557     layout(binding=999999999, rgba) highp uniform ipixelLocalANGLE pls8;
5558     highp uniform pixelLocalANGLE pls9;
5559     void main()
5560     {
5561     })";
5562     EXPECT_FALSE(log.compileFragmentShader(kPLSUnsupportedFormatsAndBindings));
5563     EXPECT_TRUE(log.has("ERROR: 0:3: 'rgba32f' : illegal pixel local storage format"));
5564     EXPECT_TRUE(log.has("ERROR: 0:4: 'rgba16f' : illegal pixel local storage format"));
5565     EXPECT_TRUE(log.has("ERROR: 0:5: 'rgba8_snorm' : illegal pixel local storage format"));
5566     EXPECT_TRUE(log.has("ERROR: 0:6: 'rgba32ui' : illegal pixel local storage format"));
5567     EXPECT_TRUE(log.has("ERROR: 0:7: 'rgba16ui' : illegal pixel local storage format"));
5568     EXPECT_TRUE(log.has("ERROR: 0:8: 'rgba32i' : illegal pixel local storage format"));
5569     EXPECT_TRUE(log.has("ERROR: 0:9: 'rgba16i' : illegal pixel local storage format"));
5570     EXPECT_TRUE(log.has("ERROR: 0:10: 'r32i' : illegal pixel local storage format"));
5571     EXPECT_TRUE(log.has("ERROR: 0:11: 'rgba' : invalid layout qualifier"));
5572     EXPECT_TRUE(log.has(
5573         "ERROR: 0:11: 'layout qualifier' : pixel local storage requires a format specifier"));
5574     EXPECT_TRUE(log.has(
5575         "ERROR: 0:12: 'layout qualifier' : pixel local storage requires a format specifier"));
5576     // TODO(anglebug.com/7279): "PLS binding greater than gl_MaxPixelLocalStoragePlanesANGLE".
5577     EXPECT_TRUE(
5578         log.has("ERROR: 0:12: 'layout qualifier' : pixel local storage requires a binding index"));
5579 
5580     // PLS handles must use the correct type for the given format.
5581     constexpr char kPLSInvalidTypeForFormat[] = R"(#version 310 es
5582     #extension GL_ANGLE_shader_pixel_local_storage : require
5583     layout(binding=0) highp uniform pixelLocalANGLE pls0;
5584     layout(binding=1) highp uniform upixelLocalANGLE pls1;
5585     layout(binding=2) highp uniform ipixelLocalANGLE pls2;
5586     layout(binding=3, rgba8) highp uniform ipixelLocalANGLE pls3;
5587     layout(binding=4, rgba8) highp uniform upixelLocalANGLE pls4;
5588     layout(binding=5, rgba8ui) highp uniform pixelLocalANGLE pls5;
5589     layout(binding=6, rgba8ui) highp uniform ipixelLocalANGLE pls6;
5590     layout(binding=7, rgba8i) highp uniform upixelLocalANGLE pls7;
5591     layout(binding=8, rgba8i) highp uniform pixelLocalANGLE pls8;
5592     layout(binding=9, r32f) highp uniform ipixelLocalANGLE pls9;
5593     layout(binding=10, r32f) highp uniform upixelLocalANGLE pls10;
5594     layout(binding=11, r32ui) highp uniform pixelLocalANGLE pls11;
5595     layout(binding=12, r32ui) highp uniform ipixelLocalANGLE pls12;
5596     void main()
5597     {
5598     })";
5599     EXPECT_FALSE(log.compileFragmentShader(kPLSInvalidTypeForFormat));
5600     EXPECT_TRUE(log.has(
5601         "ERROR: 0:3: 'layout qualifier' : pixel local storage requires a format specifier"));
5602     EXPECT_TRUE(log.has(
5603         "ERROR: 0:4: 'layout qualifier' : pixel local storage requires a format specifier"));
5604     EXPECT_TRUE(log.has(
5605         "ERROR: 0:5: 'layout qualifier' : pixel local storage requires a format specifier"));
5606     EXPECT_TRUE(
5607         log.has("ERROR: 0:6: 'rgba8' : pixel local storage format requires pixelLocalANGLE"));
5608     EXPECT_TRUE(
5609         log.has("ERROR: 0:7: 'rgba8' : pixel local storage format requires pixelLocalANGLE"));
5610     EXPECT_TRUE(
5611         log.has("ERROR: 0:8: 'rgba8ui' : pixel local storage format requires upixelLocalANGLE"));
5612     EXPECT_TRUE(
5613         log.has("ERROR: 0:9: 'rgba8ui' : pixel local storage format requires upixelLocalANGLE"));
5614     EXPECT_TRUE(
5615         log.has("ERROR: 0:10: 'rgba8i' : pixel local storage format requires ipixelLocalANGLE"));
5616     EXPECT_TRUE(
5617         log.has("ERROR: 0:11: 'rgba8i' : pixel local storage format requires ipixelLocalANGLE"));
5618     EXPECT_TRUE(
5619         log.has("ERROR: 0:12: 'r32f' : pixel local storage format requires pixelLocalANGLE"));
5620     EXPECT_TRUE(
5621         log.has("ERROR: 0:13: 'r32f' : pixel local storage format requires pixelLocalANGLE"));
5622     EXPECT_TRUE(
5623         log.has("ERROR: 0:14: 'r32ui' : pixel local storage format requires upixelLocalANGLE"));
5624     EXPECT_TRUE(
5625         log.has("ERROR: 0:15: 'r32ui' : pixel local storage format requires upixelLocalANGLE"));
5626 
5627     // PLS handles cannot have duplicate binding indices.
5628     constexpr char kPLSDuplicateBindings[] = R"(#version 310 es
5629     #extension GL_ANGLE_shader_pixel_local_storage : require
5630     layout(binding=0, rgba) uniform highp pixelLocalANGLE pls0;
5631     layout(rgba8i, binding=1) uniform highp ipixelLocalANGLE pls1;
5632     layout(binding=2, rgba8ui) uniform highp upixelLocalANGLE pls2;
5633     layout(binding=1, rgba) uniform highp ipixelLocalANGLE pls3;
5634     layout(rgba8i, binding=0) uniform mediump ipixelLocalANGLE pls4;
5635     void main()
5636     {
5637     })";
5638     EXPECT_FALSE(log.compileFragmentShader(kPLSDuplicateBindings));
5639     EXPECT_TRUE(log.has("ERROR: 0:6: '1' : duplicate pixel local storage binding index"));
5640     EXPECT_TRUE(log.has("ERROR: 0:7: '0' : duplicate pixel local storage binding index"));
5641 
5642     // PLS handles cannot have duplicate binding indices.
5643     constexpr char kPLSIllegalLayoutQualifiers[] = R"(#version 310 es
5644     #extension GL_ANGLE_shader_pixel_local_storage : require
5645     layout(foo) highp uniform pixelLocalANGLE pls1;
5646     layout(binding=0, location=0, rgba8ui) highp uniform upixelLocalANGLE pls2;
5647     void main()
5648     {
5649     })";
5650     EXPECT_FALSE(log.compileFragmentShader(kPLSIllegalLayoutQualifiers));
5651     EXPECT_TRUE(log.has("ERROR: 0:3: 'foo' : invalid layout qualifier"));
5652     EXPECT_TRUE(
5653         log.has("ERROR: 0:4: 'location' : location must only be specified for a single input or "
5654                 "output variable"));
5655 
5656     // Check that binding is not allowed in ES3, other than pixel local storage. ES3 doesn't have
5657     // blocks, and only has one opaque type: samplers. So we just need to make sure binding isn't
5658     // allowed on samplers.
5659     constexpr char kBindingOnSampler[] = R"(#version 300 es
5660     #extension GL_ANGLE_shader_pixel_local_storage : require
5661     layout(binding=0) uniform mediump sampler2D sampler;
5662     void main()
5663     {
5664     })";
5665     EXPECT_FALSE(log.compileFragmentShader(kBindingOnSampler));
5666     EXPECT_TRUE(
5667         log.has("ERROR: 0:3: 'binding' : invalid layout qualifier: only valid when used with pixel "
5668                 "local storage"));
5669 
5670     // Binding qualifiers generate different error messages depending on ES3 and ES31.
5671     constexpr char kBindingOnOutput[] = R"(#version 310 es
5672     layout(binding=0) out mediump vec4 color;
5673     void main()
5674     {
5675     })";
5676     EXPECT_FALSE(log.compileFragmentShader(kBindingOnOutput));
5677     EXPECT_TRUE(
5678         log.has("ERROR: 0:2: 'binding' : invalid layout qualifier: only valid when used with "
5679                 "opaque types or blocks"));
5680 
5681     // Check that internalformats are not allowed in ES3 except for PLS.
5682     constexpr char kFormatOnSamplerES3[] = R"(#version 300 es
5683     layout(rgba8) uniform mediump sampler2D sampler1;
5684     layout(rgba8_snorm) uniform mediump sampler2D sampler2;
5685     void main()
5686     {
5687     })";
5688     EXPECT_FALSE(log.compileFragmentShader(kFormatOnSamplerES3));
5689     EXPECT_TRUE(
5690         log.has("ERROR: 0:2: 'rgba8' : invalid layout qualifier: not supported before GLSL ES "
5691                 "3.10, except pixel local storage"));
5692     EXPECT_TRUE(log.has(
5693         "ERROR: 0:3: 'rgba8_snorm' : invalid layout qualifier: not supported before GLSL ES 3.10"));
5694 
5695     // Format qualifiers generate different error messages depending on whether they can be used
5696     // with PLS.
5697     constexpr char kFormatOnSamplerES31[] = R"(#version 310 es
5698     layout(rgba8) uniform mediump sampler2D sampler1;
5699     layout(rgba8_snorm) uniform mediump sampler2D sampler2;
5700     void main()
5701     {
5702     })";
5703     EXPECT_FALSE(log.compileFragmentShader(kFormatOnSamplerES31));
5704     EXPECT_TRUE(
5705         log.has("ERROR: 0:2: 'rgba8' : invalid layout qualifier: only valid when used with images "
5706                 "or pixel local storage"));
5707     EXPECT_TRUE(log.has(
5708         "ERROR: 0:3: 'rgba8_snorm' : invalid layout qualifier: only valid when used with images"));
5709 
5710     ASSERT_GL_NO_ERROR();
5711 }
5712 
5713 // Check proper validation of the discard statement when pixel local storage is(n't) declared.
TEST_P(PixelLocalStorageCompilerTest,Discard)5714 TEST_P(PixelLocalStorageCompilerTest, Discard)
5715 {
5716     // Discard is not allowed when pixel local storage has been declared. When polyfilled with
5717     // shader images, pixel local storage requires early_fragment_tests, which causes discard to
5718     // interact differently with the depth and stencil tests.
5719     //
5720     // To ensure identical behavior across all backends (some of which may not have access to
5721     // early_fragment_tests), we disallow discard if pixel local storage has been declared.
5722     constexpr char kDiscardWithPLS[] = R"(#version 310 es
5723     #extension GL_ANGLE_shader_pixel_local_storage : require
5724     layout(binding=0, rgba8) highp uniform pixelLocalANGLE pls;
5725     void a()
5726     {
5727         discard;
5728     }
5729     void b();
5730     void main()
5731     {
5732         if (gl_FragDepth == 3.14)
5733             discard;
5734         discard;
5735     }
5736     void b()
5737     {
5738         discard;
5739     })";
5740     EXPECT_FALSE(log.compileFragmentShader(kDiscardWithPLS));
5741     EXPECT_TRUE(
5742         log.has("ERROR: 0:6: 'discard' : illegal discard when pixel local storage is declared"));
5743     EXPECT_TRUE(
5744         log.has("ERROR: 0:12: 'discard' : illegal discard when pixel local storage is declared"));
5745     EXPECT_TRUE(
5746         log.has("ERROR: 0:13: 'discard' : illegal discard when pixel local storage is declared"));
5747     EXPECT_TRUE(
5748         log.has("ERROR: 0:17: 'discard' : illegal discard when pixel local storage is declared"));
5749 
5750     // Discard is OK when pixel local storage has _not_ been declared.
5751     constexpr char kDiscardNoPLS[] = R"(#version 310 es
5752     #extension GL_ANGLE_shader_pixel_local_storage : require
5753     void f(lowp pixelLocalANGLE pls);  // Function arguments don't trigger PLS restrictions.
5754     void a()
5755     {
5756         discard;
5757     }
5758     void b();
5759     void main()
5760     {
5761         if (gl_FragDepth == 3.14)
5762             discard;
5763         discard;
5764     }
5765     void b()
5766     {
5767         discard;
5768     })";
5769     EXPECT_TRUE(log.compileFragmentShader(kDiscardNoPLS));
5770 
5771     // Ensure discard is caught even if it happens before PLS is declared.
5772     constexpr char kDiscardBeforePLS[] = R"(#version 310 es
5773     #extension GL_ANGLE_shader_pixel_local_storage : require
5774     void a()
5775     {
5776         discard;
5777     }
5778     void main()
5779     {
5780     }
5781     layout(binding=0, rgba8) highp uniform pixelLocalANGLE pls;)";
5782     EXPECT_FALSE(log.compileFragmentShader(kDiscardBeforePLS));
5783     EXPECT_TRUE(
5784         log.has("ERROR: 0:5: 'discard' : illegal discard when pixel local storage is declared"));
5785 
5786     ASSERT_GL_NO_ERROR();
5787 }
5788 
5789 // Check proper validation of the return statement when pixel local storage is(n't) declared.
TEST_P(PixelLocalStorageCompilerTest,Return)5790 TEST_P(PixelLocalStorageCompilerTest, Return)
5791 {
5792     // Returning from main isn't allowed when pixel local storage has been declared.
5793     // (ARB_fragment_shader_interlock isn't allowed after return from main.)
5794     constexpr char kReturnFromMainWithPLS[] = R"(#version 310 es
5795     #extension GL_ANGLE_shader_pixel_local_storage : require
5796     layout(binding=0, rgba8) highp uniform pixelLocalANGLE pls;
5797     void main()
5798     {
5799         if (gl_FragDepth == 3.14)
5800             return;
5801         return;
5802     })";
5803     EXPECT_FALSE(log.compileFragmentShader(kReturnFromMainWithPLS));
5804     EXPECT_TRUE(log.has(
5805         "ERROR: 0:7: 'return' : illegal return from main when pixel local storage is declared"));
5806     EXPECT_TRUE(log.has(
5807         "ERROR: 0:8: 'return' : illegal return from main when pixel local storage is declared"));
5808 
5809     // Returning from main is OK when pixel local storage has _not_ been declared.
5810     constexpr char kReturnFromMainNoPLS[] = R"(#version 310 es
5811     #extension GL_ANGLE_shader_pixel_local_storage : require
5812     void main()
5813     {
5814         if (gl_FragDepth == 3.14)
5815             return;
5816         return;
5817     })";
5818     EXPECT_TRUE(log.compileFragmentShader(kReturnFromMainNoPLS));
5819 
5820     // Returning from subroutines is OK when pixel local storage has been declared.
5821     constexpr char kReturnFromSubroutinesWithPLS[] = R"(#version 310 es
5822     #extension GL_ANGLE_shader_pixel_local_storage : require
5823     layout(rgba8ui, binding=0) highp uniform upixelLocalANGLE pls;
5824     void a()
5825     {
5826         return;
5827     }
5828     void b();
5829     void main()
5830     {
5831         a();
5832         b();
5833     }
5834     void b()
5835     {
5836         return;
5837     })";
5838     EXPECT_TRUE(log.compileFragmentShader(kReturnFromSubroutinesWithPLS));
5839 
5840     // Ensure return from main is caught even if it happens before PLS is declared.
5841     constexpr char kDiscardBeforePLS[] = R"(#version 310 es
5842     #extension GL_ANGLE_shader_pixel_local_storage : require
5843     void main()
5844     {
5845         return;
5846     }
5847     layout(binding=0, rgba8) highp uniform pixelLocalANGLE pls;)";
5848     EXPECT_FALSE(log.compileFragmentShader(kDiscardBeforePLS));
5849     EXPECT_TRUE(log.has(
5850         "ERROR: 0:5: 'return' : illegal return from main when pixel local storage is declared"));
5851 
5852     ASSERT_GL_NO_ERROR();
5853 }
5854 
5855 // Check that gl_FragDepth(EXT) and gl_SampleMask are not assignable when PLS is declared.
TEST_P(PixelLocalStorageCompilerTest,FragmentTestVariables)5856 TEST_P(PixelLocalStorageCompilerTest, FragmentTestVariables)
5857 {
5858     // gl_FragDepth is not assignable when pixel local storage has been declared. When polyfilled
5859     // with shader images, pixel local storage requires early_fragment_tests, which causes
5860     // assignments to gl_FragDepth(EXT) and gl_SampleMask to be ignored.
5861     //
5862     // To ensure identical behavior across all backends, we disallow assignment to these values if
5863     // pixel local storage has been declared.
5864     constexpr char kAssignFragDepthWithPLS[] = R"(#version 310 es
5865     #extension GL_ANGLE_shader_pixel_local_storage : require
5866     void set(out mediump float x, mediump float val)
5867     {
5868         x = val;
5869     }
5870     void set2(inout mediump float x, mediump float val)
5871     {
5872         x = val;
5873     }
5874     void main()
5875     {
5876         gl_FragDepth = 0.0;
5877         gl_FragDepth -= 1.0;
5878         set(gl_FragDepth, 0.0);
5879         set2(gl_FragDepth, 0.1);
5880     }
5881     layout(binding=0, rgba8i) lowp uniform ipixelLocalANGLE pls;)";
5882     EXPECT_FALSE(log.compileFragmentShader(kAssignFragDepthWithPLS));
5883     EXPECT_TRUE(log.has(
5884         "ERROR: 0:13: 'gl_FragDepth' : value not assignable when pixel local storage is declared"));
5885     EXPECT_TRUE(log.has(
5886         "ERROR: 0:14: 'gl_FragDepth' : value not assignable when pixel local storage is declared"));
5887     EXPECT_TRUE(log.has(
5888         "ERROR: 0:15: 'gl_FragDepth' : value not assignable when pixel local storage is declared"));
5889     EXPECT_TRUE(log.has(
5890         "ERROR: 0:16: 'gl_FragDepth' : value not assignable when pixel local storage is declared"));
5891 
5892     // Assigning gl_FragDepth is OK if we don't declare any PLS.
5893     constexpr char kAssignFragDepthNoPLS[] = R"(#version 310 es
5894     #extension GL_ANGLE_shader_pixel_local_storage : require
5895     void f(highp ipixelLocalANGLE pls)
5896     {
5897         // Function arguments don't trigger PLS restrictions.
5898         pixelLocalStoreANGLE(pls, ivec4(8));
5899     }
5900     void set(out mediump float x, mediump float val)
5901     {
5902         x = val;
5903     }
5904     void main()
5905     {
5906         gl_FragDepth = 0.0;
5907         gl_FragDepth /= 2.0;
5908         set(gl_FragDepth, 0.0);
5909     })";
5910     EXPECT_TRUE(log.compileFragmentShader(kAssignFragDepthNoPLS));
5911 
5912     // Reading gl_FragDepth is OK.
5913     constexpr char kReadFragDepth[] = R"(#version 310 es
5914     #extension GL_ANGLE_shader_pixel_local_storage : require
5915     layout(r32f, binding=0) highp uniform pixelLocalANGLE pls;
5916     highp vec4 get(in mediump float x)
5917     {
5918         return vec4(x);
5919     }
5920     void set(inout mediump float x, mediump float val)
5921     {
5922         x = val;
5923     }
5924     void main()
5925     {
5926         pixelLocalStoreANGLE(pls, get(gl_FragDepth));
5927         // Check when gl_FragDepth is involved in an l-value expression, but not assigned to.
5928         highp float x[2];
5929         x[int(gl_FragDepth)] = 1.0;
5930         set(x[1 - int(gl_FragDepth)], 2.0);
5931     })";
5932     EXPECT_TRUE(log.compileFragmentShader(kReadFragDepth));
5933 
5934     if (EnsureGLExtensionEnabled("GL_OES_sample_variables"))
5935     {
5936         // gl_SampleMask is not assignable when pixel local storage has been declared. The shader
5937         // image polyfill requires early_fragment_tests, which causes gl_SampleMask to be ignored.
5938         //
5939         // To ensure identical behavior across all implementations (some of which may not have
5940         // access to early_fragment_tests), we disallow assignment to these values if pixel local
5941         // storage has been declared.
5942         constexpr char kAssignSampleMaskWithPLS[] = R"(#version 310 es
5943         #extension GL_ANGLE_shader_pixel_local_storage : require
5944         #extension GL_OES_sample_variables : require
5945         void set(out highp int x, highp int val)
5946         {
5947             x = val;
5948         }
5949         void set2(inout highp int x, highp int val)
5950         {
5951             x = val;
5952         }
5953         void main()
5954         {
5955             gl_SampleMask[0] = 0;
5956             gl_SampleMask[0] ^= 1;
5957             set(gl_SampleMask[0], 9);
5958             set2(gl_SampleMask[0], 10);
5959         }
5960         layout(binding=0, rgba8i) highp uniform ipixelLocalANGLE pls;)";
5961         EXPECT_FALSE(log.compileFragmentShader(kAssignSampleMaskWithPLS));
5962         EXPECT_TRUE(
5963             log.has("ERROR: 0:14: 'gl_SampleMask' : value not assignable when pixel local storage "
5964                     "is declared"));
5965         EXPECT_TRUE(
5966             log.has("ERROR: 0:15: 'gl_SampleMask' : value not assignable when pixel local storage "
5967                     "is declared"));
5968         EXPECT_TRUE(
5969             log.has("ERROR: 0:16: 'gl_SampleMask' : value not assignable when pixel local storage "
5970                     "is declared"));
5971         EXPECT_TRUE(
5972             log.has("ERROR: 0:17: 'gl_SampleMask' : value not assignable when pixel local storage "
5973                     "is declared"));
5974 
5975         // Assigning gl_SampleMask is OK if we don't declare any PLS.
5976         constexpr char kAssignSampleMaskNoPLS[] = R"(#version 310 es
5977         #extension GL_ANGLE_shader_pixel_local_storage : require
5978         #extension GL_OES_sample_variables : require
5979         void set(out highp int x, highp int val)
5980         {
5981             x = val;
5982         }
5983         void main()
5984         {
5985             gl_SampleMask[0] = 0;
5986             gl_SampleMask[0] ^= 1;
5987             set(gl_SampleMask[0], 9);
5988         })";
5989         EXPECT_TRUE(log.compileFragmentShader(kAssignSampleMaskNoPLS));
5990 
5991         // Reading gl_SampleMask is OK enough (even though it's technically output only).
5992         constexpr char kReadSampleMask[] = R"(#version 310 es
5993         #extension GL_ANGLE_shader_pixel_local_storage : require
5994         #extension GL_OES_sample_variables : require
5995         layout(binding=0, rgba8i) highp uniform ipixelLocalANGLE pls;
5996         highp int get(in highp int x)
5997         {
5998             return x;
5999         }
6000         void set(out highp int x, highp int val)
6001         {
6002             x = val;
6003         }
6004         void main()
6005         {
6006             pixelLocalStoreANGLE(pls, ivec4(get(gl_SampleMask[0]), gl_SampleMaskIn[0], 0, 1));
6007             // Check when gl_SampleMask is involved in an l-value expression, but not assigned to.
6008             highp int x[2];
6009             x[gl_SampleMask[0]] = 1;
6010             set(x[gl_SampleMask[0]], 2);
6011         })";
6012         EXPECT_TRUE(log.compileFragmentShader(kReadSampleMask));
6013     }
6014 
6015     ASSERT_GL_NO_ERROR();
6016 }
6017 
6018 // Check that the "blend_support" layout qualifiers defined in KHR_blend_equation_advanced are
6019 // illegal when PLS is declared.
TEST_P(PixelLocalStorageCompilerTest,BlendFuncExtended_illegal_with_PLS)6020 TEST_P(PixelLocalStorageCompilerTest, BlendFuncExtended_illegal_with_PLS)
6021 {
6022     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_blend_func_extended"));
6023 
6024     // Just declaring the extension is ok.
6025     constexpr char kRequireBlendFuncExtended[] = R"(#version 300 es
6026     #extension GL_ANGLE_shader_pixel_local_storage : require
6027     #extension GL_EXT_blend_func_extended : require
6028     void main()
6029     {}
6030     layout(binding=0, rgba8) uniform lowp pixelLocalANGLE pls;)";
6031     EXPECT_TRUE(log.compileFragmentShader(kRequireBlendFuncExtended));
6032 
6033     // The <index> layout qualifier from EXT_blend_func_extended is illegal.
6034     constexpr char kBlendFuncExtendedIndex[] = R"(#version 300 es
6035     #extension GL_ANGLE_shader_pixel_local_storage : require
6036     #extension GL_EXT_blend_func_extended : require
6037     layout(location=0, index=1) out lowp vec4 out1;
6038     void main()
6039     {}
6040     layout(binding=0, rgba8) uniform lowp pixelLocalANGLE pls;)";
6041     EXPECT_FALSE(log.compileFragmentShader(kBlendFuncExtendedIndex));
6042     EXPECT_TRUE(
6043         log.has("ERROR: 0:4: 'layout' : illegal nonzero index qualifier when pixel local storage "
6044                 "is declared"));
6045 
6046     // Multiple unassigned fragment output locations are illegal, even if EXT_blend_func_extended is
6047     // enabled.
6048     constexpr char kBlendFuncExtendedNoLocation[] = R"(#version 300 es
6049     #extension GL_ANGLE_shader_pixel_local_storage : require
6050     #extension GL_EXT_blend_func_extended : require
6051     layout(binding=0, rgba8) uniform lowp pixelLocalANGLE pls;
6052     out lowp vec4 out1;
6053     out lowp vec4 out0;
6054     void main()
6055     {})";
6056     EXPECT_FALSE(log.compileFragmentShader(kBlendFuncExtendedNoLocation));
6057     EXPECT_TRUE(log.has(
6058         "ERROR: 0:5: 'out1' : must explicitly specify all locations when using multiple fragment "
6059         "outputs and pixel local storage, even if EXT_blend_func_extended is enabled"));
6060     EXPECT_TRUE(log.has(
6061         "ERROR: 0:6: 'out0' : must explicitly specify all locations when using multiple fragment "
6062         "outputs and pixel local storage, even if EXT_blend_func_extended is enabled"));
6063 
6064     // index=0 is ok.
6065     constexpr char kValidFragmentIndex0[] = R"(#version 300 es
6066     #extension all : warn
6067     layout(binding=0, rgba8) uniform lowp pixelLocalANGLE plane1;
6068     layout(location=0, index=0) out lowp vec4 outColor0;
6069     layout(location=1, index=0) out lowp vec4 outColor1;
6070     layout(location=2, index=0) out lowp vec4 outColor2;
6071     void main()
6072     {})";
6073     EXPECT_TRUE(log.compileFragmentShader(kValidFragmentIndex0));
6074 }
6075 
6076 // Check that the "blend_support" layout qualifiers defined in KHR_blend_equation_advanced are
6077 // illegal when PLS is declared.
TEST_P(PixelLocalStorageCompilerTest,BlendEquationAdvanced_illegal_with_PLS)6078 TEST_P(PixelLocalStorageCompilerTest, BlendEquationAdvanced_illegal_with_PLS)
6079 {
6080     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
6081 
6082     // Just declaring the extension is ok.
6083     constexpr char kRequireBlendAdvanced[] = R"(#version 300 es
6084     #extension GL_ANGLE_shader_pixel_local_storage : require
6085     #extension GL_KHR_blend_equation_advanced : require
6086     void main()
6087     {}
6088     layout(binding=0, rgba8i) uniform lowp ipixelLocalANGLE pls;)";
6089     EXPECT_TRUE(log.compileFragmentShader(kRequireBlendAdvanced));
6090 
6091     bool before = true;
6092     for (const char *layoutQualifier : {
6093              "blend_support_multiply",
6094              "blend_support_screen",
6095              "blend_support_overlay",
6096              "blend_support_darken",
6097              "blend_support_lighten",
6098              "blend_support_colordodge",
6099              "blend_support_colorburn",
6100              "blend_support_hardlight",
6101              "blend_support_softlight",
6102              "blend_support_difference",
6103              "blend_support_exclusion",
6104              "blend_support_hsl_hue",
6105              "blend_support_hsl_saturation",
6106              "blend_support_hsl_color",
6107              "blend_support_hsl_luminosity",
6108              "blend_support_all_equations",
6109          })
6110     {
6111         constexpr char kRequireBlendAdvancedBeforePLS[] = R"(#version 300 es
6112         #extension GL_ANGLE_shader_pixel_local_storage : require
6113         #extension GL_KHR_blend_equation_advanced : require
6114         layout(%s) out;
6115         void main()
6116         {}
6117         layout(binding=0, rgba8i) uniform lowp ipixelLocalANGLE pls;)";
6118 
6119         constexpr char kRequireBlendAdvancedAfterPLS[] = R"(#version 300 es
6120         #extension GL_ANGLE_shader_pixel_local_storage : require
6121         #extension GL_KHR_blend_equation_advanced : require
6122         layout(binding=0, rgba8i) uniform lowp ipixelLocalANGLE pls;
6123         layout(%s) out;
6124         void main()
6125         {})";
6126 
6127         const char *formatStr =
6128             before ? kRequireBlendAdvancedBeforePLS : kRequireBlendAdvancedAfterPLS;
6129         size_t buffSize =
6130             snprintf(nullptr, 0, formatStr, layoutQualifier) + 1;  // Extra space for '\0'
6131         std::unique_ptr<char[]> shader(new char[buffSize]);
6132         std::snprintf(shader.get(), buffSize, formatStr, layoutQualifier);
6133         EXPECT_FALSE(log.compileFragmentShader(shader.get()));
6134         if (before)
6135         {
6136             EXPECT_TRUE(
6137                 log.has("ERROR: 0:4: 'layout' : illegal advanced blend equation when pixel local "
6138                         "storage is declared"));
6139         }
6140         else
6141         {
6142             EXPECT_TRUE(
6143                 log.has("ERROR: 0:5: 'layout' : illegal advanced blend equation when pixel local "
6144                         "storage is declared"));
6145         }
6146 
6147         before = !before;
6148     }
6149 }
6150 
6151 // Check proper validation of PLS function arguments.
TEST_P(PixelLocalStorageCompilerTest,FunctionArguments)6152 TEST_P(PixelLocalStorageCompilerTest, FunctionArguments)
6153 {
6154     // Ensure PLS handles can't be the result of complex expressions.
6155     constexpr char kPLSHandleComplexExpression[] = R"(#version 310 es
6156     #extension GL_ANGLE_shader_pixel_local_storage : require
6157     layout(rgba8, binding=0) mediump uniform pixelLocalANGLE pls0;
6158     layout(rgba8, binding=1) mediump uniform pixelLocalANGLE pls1;
6159     void clear(mediump pixelLocalANGLE pls)
6160     {
6161         pixelLocalStoreANGLE(pls, vec4(0));
6162     }
6163     void main()
6164     {
6165         highp float x = gl_FragDepth;
6166         clear(((x += 50.0) < 100.0) ? pls0 : pls1);
6167     })";
6168     EXPECT_FALSE(log.compileFragmentShader(kPLSHandleComplexExpression));
6169     EXPECT_TRUE(log.has("ERROR: 0:12: '?:' : ternary operator is not allowed for opaque types"));
6170 
6171     // As function arguments, PLS handles cannot have layout qualifiers.
6172     constexpr char kPLSFnArgWithLayoutQualifiers[] = R"(#version 310 es
6173     #extension GL_ANGLE_shader_pixel_local_storage : require
6174     void f(layout(rgba8, binding=1) mediump pixelLocalANGLE pls)
6175     {
6176     }
6177     void g(layout(rgba8) lowp pixelLocalANGLE pls);
6178     void main()
6179     {
6180     })";
6181     EXPECT_FALSE(log.compileFragmentShader(kPLSFnArgWithLayoutQualifiers));
6182     EXPECT_TRUE(log.has("ERROR: 0:3: 'layout' : only allowed at global scope"));
6183     EXPECT_TRUE(log.has("ERROR: 0:6: 'layout' : only allowed at global scope"));
6184 
6185     ASSERT_GL_NO_ERROR();
6186 }
6187 
6188 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PixelLocalStorageCompilerTest);
6189 ANGLE_INSTANTIATE_TEST(PixelLocalStorageCompilerTest,
6190                        ES31_NULL().enable(Feature::EmulatePixelLocalStorage),
6191                        ES31_NULL()
6192                            .enable(Feature::EmulatePixelLocalStorage)
6193                            .enable(Feature::DisableDrawBuffersIndexed));
6194 
6195 class PixelLocalStorageTestPreES3 : public ANGLETest<>
6196 {
6197   public:
PixelLocalStorageTestPreES3()6198     PixelLocalStorageTestPreES3() { setExtensionsEnabled(false); }
6199 };
6200 
6201 // Check that GL_ANGLE_shader_pixel_local_storage is not advertised before ES 3.1.
6202 //
6203 // TODO(anglebug.com/7279): we can relax the min supported version once the implementation details
6204 // are inside ANGLE.
TEST_P(PixelLocalStorageTestPreES3,UnsupportedClientVersion)6205 TEST_P(PixelLocalStorageTestPreES3, UnsupportedClientVersion)
6206 {
6207     EXPECT_FALSE(EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage"));
6208     EXPECT_FALSE(EnsureGLExtensionEnabled("GL_ANGLE_shader_pixel_local_storage_coherent"));
6209 
6210     ShaderInfoLog log;
6211 
6212     constexpr char kRequireUnsupportedPLS[] = R"(#version 300 es
6213     #extension GL_ANGLE_shader_pixel_local_storage : require
6214     void main()
6215     {
6216     })";
6217     EXPECT_FALSE(log.compileFragmentShader(kRequireUnsupportedPLS));
6218     EXPECT_TRUE(
6219         log.has("ERROR: 0:2: 'GL_ANGLE_shader_pixel_local_storage' : extension is not supported"));
6220 
6221     ASSERT_GL_NO_ERROR();
6222 }
6223 
6224 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PixelLocalStorageTestPreES3);
6225 ANGLE_INSTANTIATE_TEST(PixelLocalStorageTestPreES3,
6226                        ES1_NULL().enable(Feature::EmulatePixelLocalStorage),
6227                        ES2_NULL().enable(Feature::EmulatePixelLocalStorage));
6228