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