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