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