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