• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2020 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 // VulkanPerformanceCounterTest:
7 //   Validates specific GL call patterns with ANGLE performance counters.
8 //   For example we can verify a certain call set doesn't break the render pass.
9 
10 #include "include/platform/Feature.h"
11 #include "test_utils/ANGLETest.h"
12 #include "test_utils/angle_test_instantiate.h"
13 #include "test_utils/gl_raii.h"
14 #include "util/random_utils.h"
15 #include "util/shader_utils.h"
16 #include "util/test_utils.h"
17 
18 using namespace angle;
19 
20 namespace
21 {
22 // Normally, if LOAD_OP_NONE is not supported, LOAD_OP_LOAD is used instead.  Similarly, if
23 // STORE_OP_NONE is not supported, STORE_OP_STORE is used instead.
24 //
25 // If an attachment has undefined contents and is unused, LOAD_OP_DONT_CARE and
26 // STORE_OP_DONT_CARE can be used.  However, these are write operations for synchronization
27 // purposes, and so ANGLE uses LOAD_OP_NONE and STORE_OP_NONE if available to avoid the
28 // synchronization.  When NONE is not available, ANGLE foregoes synchronization, producing
29 // syncval errors.
30 //
31 // For the sake of validation, it's unknown if NONE is turned into LOAD/STORE or DONT_CARE.  So
32 // validation allows variations there.
33 #define EXPECT_OP_LOAD_AND_NONE(expectedLoads, actualLoads, expectedNones, actualNones) \
34     {                                                                                   \
35         if (hasLoadOpNoneSupport())                                                     \
36         {                                                                               \
37             EXPECT_EQ(expectedLoads, actualLoads);                                      \
38             EXPECT_EQ(expectedNones, actualNones);                                      \
39         }                                                                               \
40         else                                                                            \
41         {                                                                               \
42             EXPECT_EQ(actualNones, 0u);                                                 \
43             EXPECT_LE(expectedLoads, actualLoads);                                      \
44             EXPECT_GE(expectedLoads + expectedNones, actualLoads);                      \
45         }                                                                               \
46     }
47 #define EXPECT_OP_STORE_AND_NONE(expectedStores, actualStores, expectedNones, actualNones) \
48     {                                                                                      \
49         if (hasStoreOpNoneSupport() && hasLoadOpNoneSupport())                             \
50         {                                                                                  \
51             EXPECT_EQ(expectedStores, actualStores);                                       \
52             EXPECT_EQ(expectedNones, actualNones);                                         \
53         }                                                                                  \
54         else                                                                               \
55         {                                                                                  \
56             if (!hasStoreOpNoneSupport())                                                  \
57             {                                                                              \
58                 EXPECT_EQ(actualNones, 0u);                                                \
59             }                                                                              \
60             EXPECT_LE(expectedStores, actualStores);                                       \
61             EXPECT_GE(expectedStores + expectedNones, actualStores + actualNones);         \
62         }                                                                                  \
63     }
64 
65 #define EXPECT_DEPTH_OP_COUNTERS(counters, expected)                                       \
66     {                                                                                      \
67         EXPECT_EQ(expected.depthLoadOpClears, counters.depthLoadOpClears);                 \
68         EXPECT_OP_LOAD_AND_NONE(expected.depthLoadOpLoads, counters.depthLoadOpLoads,      \
69                                 expected.depthLoadOpNones, counters.depthLoadOpNones);     \
70         EXPECT_OP_STORE_AND_NONE(expected.depthStoreOpStores, counters.depthStoreOpStores, \
71                                  expected.depthStoreOpNones, counters.depthStoreOpNones);  \
72     }
73 
74 #define EXPECT_STENCIL_OP_COUNTERS(counters, expected)                                         \
75     {                                                                                          \
76         EXPECT_EQ(expected.stencilLoadOpClears, counters.stencilLoadOpClears);                 \
77         EXPECT_OP_LOAD_AND_NONE(expected.stencilLoadOpLoads, counters.stencilLoadOpLoads,      \
78                                 expected.stencilLoadOpNones, counters.stencilLoadOpNones);     \
79         EXPECT_OP_STORE_AND_NONE(expected.stencilStoreOpStores, counters.stencilStoreOpStores, \
80                                  expected.stencilStoreOpNones, counters.stencilStoreOpNones);  \
81     }
82 
83 #define EXPECT_DEPTH_STENCIL_OP_COUNTERS(counters, expected) \
84     {                                                        \
85         EXPECT_DEPTH_OP_COUNTERS(counters, expected);        \
86         EXPECT_STENCIL_OP_COUNTERS(counters, expected);      \
87     }
88 
89 #define EXPECT_COLOR_OP_COUNTERS(counters, expected)                                       \
90     {                                                                                      \
91         EXPECT_EQ(expected.colorLoadOpClears, counters.colorLoadOpClears);                 \
92         EXPECT_OP_LOAD_AND_NONE(expected.colorLoadOpLoads, counters.colorLoadOpLoads,      \
93                                 expected.colorLoadOpNones, counters.colorLoadOpNones);     \
94         EXPECT_OP_STORE_AND_NONE(expected.colorStoreOpStores, counters.colorStoreOpStores, \
95                                  expected.colorStoreOpNones, counters.colorStoreOpNones);  \
96     }
97 
98 #define EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(counters, expected)            \
99     {                                                                        \
100         EXPECT_EQ(expected.depthLoadOpLoads, counters.depthLoadOpLoads);     \
101         EXPECT_EQ(expected.stencilLoadOpLoads, counters.stencilLoadOpLoads); \
102     }
103 
104 #define EXPECT_COUNTERS_FOR_UNRESOLVE_RESOLVE_TEST(counters, expected)                         \
105     {                                                                                          \
106         EXPECT_EQ(expected.colorAttachmentUnresolves, counters.colorAttachmentUnresolves);     \
107         EXPECT_EQ(expected.depthAttachmentUnresolves, counters.depthAttachmentUnresolves);     \
108         EXPECT_EQ(expected.stencilAttachmentUnresolves, counters.stencilAttachmentUnresolves); \
109         EXPECT_EQ(expected.colorAttachmentResolves, counters.colorAttachmentResolves);         \
110         EXPECT_EQ(expected.depthAttachmentResolves, counters.depthAttachmentResolves);         \
111         EXPECT_EQ(expected.stencilAttachmentResolves, counters.stencilAttachmentResolves);     \
112     }
113 
114 #define EXPECT_CLEAR_ATTACHMENTS_COUNTER(expected, actual) \
115     {                                                      \
116         if (hasPreferDrawOverClearAttachments())           \
117         {                                                  \
118             EXPECT_EQ(actual, 0u);                         \
119         }                                                  \
120         else                                               \
121         {                                                  \
122             EXPECT_EQ(actual, expected);                   \
123         }                                                  \
124     }
125 
126 enum class BufferUpdate
127 {
128     SubData,  // use glBufferSubData
129     Copy,     // use glCopyBufferSubData
130 };
131 
132 class VulkanPerformanceCounterTest : public ANGLETest<>
133 {
134   protected:
VulkanPerformanceCounterTest()135     VulkanPerformanceCounterTest()
136     {
137         // Depth/Stencil required for SwapShouldInvalidate*.
138         // Also RGBA8 is required to avoid the clear for emulated alpha.
139         setConfigRedBits(8);
140         setConfigGreenBits(8);
141         setConfigBlueBits(8);
142         setConfigAlphaBits(8);
143         setConfigDepthBits(24);
144         setConfigStencilBits(8);
145     }
146 
147     static constexpr GLsizei kOpsTestSize = 16;
148 
setupForColorOpsTest(GLFramebuffer * framebuffer,GLTexture * texture)149     void setupForColorOpsTest(GLFramebuffer *framebuffer, GLTexture *texture)
150     {
151         // Setup the framebuffer
152         glBindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
153         glBindTexture(GL_TEXTURE_2D, *texture);
154         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kOpsTestSize, kOpsTestSize, 0, GL_RGBA,
155                      GL_UNSIGNED_BYTE, nullptr);
156         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *texture, 0);
157         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
158     }
159 
setupForColorDepthOpsTest(GLFramebuffer * framebuffer,GLTexture * texture,GLRenderbuffer * renderbuffer)160     void setupForColorDepthOpsTest(GLFramebuffer *framebuffer,
161                                    GLTexture *texture,
162                                    GLRenderbuffer *renderbuffer)
163     {
164         // Setup color and depth
165         glBindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
166         glBindTexture(GL_TEXTURE_2D, *texture);
167         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kOpsTestSize, kOpsTestSize, 0, GL_RGBA,
168                      GL_UNSIGNED_BYTE, nullptr);
169         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *texture, 0);
170         glBindRenderbuffer(GL_RENDERBUFFER, *renderbuffer);
171         glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, kOpsTestSize, kOpsTestSize);
172         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
173                                   *renderbuffer);
174         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
175 
176         // Setup depth parameters
177         glEnable(GL_DEPTH_TEST);
178         glDepthMask(GL_TRUE);
179         glDepthFunc(GL_GEQUAL);
180         glClearDepthf(0.99f);
181         glViewport(0, 0, kOpsTestSize, kOpsTestSize);
182         ASSERT_GL_NO_ERROR();
183     }
184 
setupForDepthStencilOpsTest(GLFramebuffer * framebuffer,GLTexture * texture,GLRenderbuffer * renderbuffer)185     void setupForDepthStencilOpsTest(GLFramebuffer *framebuffer,
186                                      GLTexture *texture,
187                                      GLRenderbuffer *renderbuffer)
188     {
189         // Setup color, depth, and stencil
190         glBindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
191         glBindTexture(GL_TEXTURE_2D, *texture);
192         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kOpsTestSize, kOpsTestSize, 0, GL_RGBA,
193                      GL_UNSIGNED_BYTE, nullptr);
194         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *texture, 0);
195         glBindRenderbuffer(GL_RENDERBUFFER, *renderbuffer);
196         glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kOpsTestSize, kOpsTestSize);
197         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
198                                   *renderbuffer);
199         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
200 
201         // Setup depth parameters
202         glEnable(GL_DEPTH_TEST);
203         glDepthMask(GL_TRUE);
204         glDepthFunc(GL_GEQUAL);
205         glEnable(GL_STENCIL_TEST);
206         glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
207         glStencilMask(0xFF);
208         glClearDepthf(0.99f);
209         glClearStencil(0xAA);
210         glViewport(0, 0, kOpsTestSize, kOpsTestSize);
211         ASSERT_GL_NO_ERROR();
212     }
213 
setupClearAndDrawForDepthStencilOpsTest(GLProgram * program,GLFramebuffer * framebuffer,GLTexture * texture,GLRenderbuffer * renderbuffer,bool clearStencil)214     void setupClearAndDrawForDepthStencilOpsTest(GLProgram *program,
215                                                  GLFramebuffer *framebuffer,
216                                                  GLTexture *texture,
217                                                  GLRenderbuffer *renderbuffer,
218                                                  bool clearStencil)
219     {
220         setupForDepthStencilOpsTest(framebuffer, texture, renderbuffer);
221 
222         // Clear and draw with depth and stencil buffer enabled
223         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
224                 (clearStencil ? GL_STENCIL_BUFFER_BIT : 0));
225         drawQuad(*program, essl1_shaders::PositionAttrib(), 1.f);
226         ASSERT_GL_NO_ERROR();
227     }
228 
setExpectedCountersForDepthOps(const angle::VulkanPerfCounters & counters,uint64_t incrementalRenderPasses,uint64_t incrementalDepthLoadOpClears,uint64_t incrementalDepthLoadOpLoads,uint64_t incrementalDepthLoadOpNones,uint64_t incrementalDepthStoreOpStores,uint64_t incrementalDepthStoreOpNones,angle::VulkanPerfCounters * expected)229     void setExpectedCountersForDepthOps(const angle::VulkanPerfCounters &counters,
230                                         uint64_t incrementalRenderPasses,
231                                         uint64_t incrementalDepthLoadOpClears,
232                                         uint64_t incrementalDepthLoadOpLoads,
233                                         uint64_t incrementalDepthLoadOpNones,
234                                         uint64_t incrementalDepthStoreOpStores,
235                                         uint64_t incrementalDepthStoreOpNones,
236                                         angle::VulkanPerfCounters *expected)
237     {
238         expected->renderPasses       = counters.renderPasses + incrementalRenderPasses;
239         expected->depthLoadOpClears  = counters.depthLoadOpClears + incrementalDepthLoadOpClears;
240         expected->depthLoadOpLoads   = counters.depthLoadOpLoads + incrementalDepthLoadOpLoads;
241         expected->depthLoadOpNones   = counters.depthLoadOpNones + incrementalDepthLoadOpNones;
242         expected->depthStoreOpStores = counters.depthStoreOpStores + incrementalDepthStoreOpStores;
243         expected->depthStoreOpNones  = counters.depthStoreOpNones + incrementalDepthStoreOpNones;
244     }
245 
setExpectedCountersForStencilOps(const angle::VulkanPerfCounters & counters,uint64_t incrementalStencilLoadOpClears,uint64_t incrementalStencilLoadOpLoads,uint64_t incrementalStencilLoadOpNones,uint64_t incrementalStencilStoreOpStores,uint64_t incrementalStencilStoreOpNones,angle::VulkanPerfCounters * expected)246     void setExpectedCountersForStencilOps(const angle::VulkanPerfCounters &counters,
247                                           uint64_t incrementalStencilLoadOpClears,
248                                           uint64_t incrementalStencilLoadOpLoads,
249                                           uint64_t incrementalStencilLoadOpNones,
250                                           uint64_t incrementalStencilStoreOpStores,
251                                           uint64_t incrementalStencilStoreOpNones,
252                                           angle::VulkanPerfCounters *expected)
253     {
254         expected->stencilLoadOpClears =
255             counters.stencilLoadOpClears + incrementalStencilLoadOpClears;
256         expected->stencilLoadOpLoads = counters.stencilLoadOpLoads + incrementalStencilLoadOpLoads;
257         expected->stencilLoadOpNones = counters.stencilLoadOpNones + incrementalStencilLoadOpNones;
258         expected->stencilStoreOpStores =
259             counters.stencilStoreOpStores + incrementalStencilStoreOpStores;
260         expected->stencilStoreOpNones =
261             counters.stencilStoreOpNones + incrementalStencilStoreOpNones;
262     }
263 
setExpectedCountersForColorOps(const angle::VulkanPerfCounters & counters,uint64_t incrementalRenderPasses,uint64_t incrementalColorLoadOpClears,uint64_t incrementalColorLoadOpLoads,uint64_t incrementalColorLoadOpNones,uint64_t incrementalColorStoreOpStores,uint64_t incrementalColorStoreOpNones,angle::VulkanPerfCounters * expected)264     void setExpectedCountersForColorOps(const angle::VulkanPerfCounters &counters,
265                                         uint64_t incrementalRenderPasses,
266                                         uint64_t incrementalColorLoadOpClears,
267                                         uint64_t incrementalColorLoadOpLoads,
268                                         uint64_t incrementalColorLoadOpNones,
269                                         uint64_t incrementalColorStoreOpStores,
270                                         uint64_t incrementalColorStoreOpNones,
271                                         angle::VulkanPerfCounters *expected)
272     {
273         expected->renderPasses       = counters.renderPasses + incrementalRenderPasses;
274         expected->colorLoadOpClears  = counters.colorLoadOpClears + incrementalColorLoadOpClears;
275         expected->colorLoadOpLoads   = counters.colorLoadOpLoads + incrementalColorLoadOpLoads;
276         expected->colorLoadOpNones   = counters.colorLoadOpNones + incrementalColorLoadOpNones;
277         expected->colorStoreOpStores = counters.colorStoreOpStores + incrementalColorStoreOpStores;
278         expected->colorStoreOpNones  = counters.colorStoreOpNones + incrementalColorStoreOpNones;
279     }
280 
setAndIncrementDepthStencilLoadCountersForOpsTest(const angle::VulkanPerfCounters & counters,uint64_t incrementalDepthLoadOpLoads,uint64_t incrementalStencilLoadOpLoads,angle::VulkanPerfCounters * expected)281     void setAndIncrementDepthStencilLoadCountersForOpsTest(
282         const angle::VulkanPerfCounters &counters,
283         uint64_t incrementalDepthLoadOpLoads,
284         uint64_t incrementalStencilLoadOpLoads,
285         angle::VulkanPerfCounters *expected)
286     {
287         expected->depthLoadOpLoads   = counters.depthLoadOpLoads + incrementalDepthLoadOpLoads;
288         expected->stencilLoadOpLoads = counters.stencilLoadOpLoads + incrementalStencilLoadOpLoads;
289     }
290 
setExpectedCountersForUnresolveResolveTest(const angle::VulkanPerfCounters & counters,uint64_t incrementalColorAttachmentUnresolves,uint64_t incrementalDepthAttachmentUnresolves,uint64_t incrementalStencilAttachmentUnresolves,uint64_t incrementalColorAttachmentResolves,uint64_t incrementalDepthAttachmentResolves,uint64_t incrementalStencilAttachmentResolves,angle::VulkanPerfCounters * expected)291     void setExpectedCountersForUnresolveResolveTest(const angle::VulkanPerfCounters &counters,
292                                                     uint64_t incrementalColorAttachmentUnresolves,
293                                                     uint64_t incrementalDepthAttachmentUnresolves,
294                                                     uint64_t incrementalStencilAttachmentUnresolves,
295                                                     uint64_t incrementalColorAttachmentResolves,
296                                                     uint64_t incrementalDepthAttachmentResolves,
297                                                     uint64_t incrementalStencilAttachmentResolves,
298                                                     angle::VulkanPerfCounters *expected)
299     {
300         expected->colorAttachmentUnresolves =
301             counters.colorAttachmentUnresolves + incrementalColorAttachmentUnresolves;
302         expected->depthAttachmentUnresolves =
303             counters.depthAttachmentUnresolves + incrementalDepthAttachmentUnresolves;
304         expected->stencilAttachmentUnresolves =
305             counters.stencilAttachmentUnresolves + incrementalStencilAttachmentUnresolves;
306         expected->colorAttachmentResolves =
307             counters.colorAttachmentResolves + incrementalColorAttachmentResolves;
308         expected->depthAttachmentResolves =
309             counters.depthAttachmentResolves + incrementalDepthAttachmentResolves;
310         expected->stencilAttachmentResolves =
311             counters.stencilAttachmentResolves + incrementalStencilAttachmentResolves;
312     }
313 
314     void maskedFramebufferFetchDraw(const GLColor &clearColor, GLBuffer &buffer);
315     void maskedFramebufferFetchDrawVerify(const GLColor &expectedColor, GLBuffer &buffer);
316 
317     void saveAndReloadBinary(GLProgram *original, GLProgram *reloaded);
318     void testPipelineCacheIsWarm(GLProgram *program, GLColor color);
319 
updateBuffer(BufferUpdate update,GLenum target,GLintptr offset,GLsizeiptr size,const void * data)320     void updateBuffer(BufferUpdate update,
321                       GLenum target,
322                       GLintptr offset,
323                       GLsizeiptr size,
324                       const void *data)
325     {
326         if (update == BufferUpdate::SubData)
327         {
328             // If using glBufferSubData, directly upload data on the specified target (where the
329             // buffer is already bound)
330             glBufferSubData(target, offset, size, data);
331         }
332         else
333         {
334             // Otherwise copy through a temp buffer.  Use a non-zero offset for more coverage.
335             constexpr GLintptr kStagingOffset = 123;
336             GLBuffer staging;
337             glBindBuffer(GL_COPY_READ_BUFFER, staging);
338             glBufferData(GL_COPY_READ_BUFFER, offset + size + kStagingOffset * 2, nullptr,
339                          GL_STATIC_DRAW);
340             glBufferSubData(GL_COPY_READ_BUFFER, kStagingOffset, size, data);
341             glCopyBufferSubData(GL_COPY_READ_BUFFER, target, kStagingOffset, offset, size);
342         }
343     }
344 
345     void mappingGpuReadOnlyBufferGhostsBuffer(BufferUpdate update);
346     void partialBufferUpdateShouldNotBreakRenderPass(BufferUpdate update);
347     void bufferSubDataShouldNotTriggerSyncState(BufferUpdate update);
348 
getPerfCounters()349     angle::VulkanPerfCounters getPerfCounters()
350     {
351         if (mIndexMap.empty())
352         {
353             mIndexMap = BuildCounterNameToIndexMap();
354         }
355 
356         return GetPerfCounters(mIndexMap);
357     }
358 
359     // Support status for ANGLE features.
isFeatureEnabled(Feature feature) const360     bool isFeatureEnabled(Feature feature) const
361     {
362         return getEGLWindow()->isFeatureEnabled(feature);
363     }
hasLoadOpNoneSupport() const364     bool hasLoadOpNoneSupport() const
365     {
366         return isFeatureEnabled(Feature::SupportsRenderPassLoadStoreOpNone);
367     }
hasStoreOpNoneSupport() const368     bool hasStoreOpNoneSupport() const
369     {
370         return isFeatureEnabled(Feature::SupportsRenderPassLoadStoreOpNone) ||
371                isFeatureEnabled(Feature::SupportsRenderPassStoreOpNone);
372     }
hasMutableMipmapTextureUpload() const373     bool hasMutableMipmapTextureUpload() const
374     {
375         return isFeatureEnabled(Feature::MutableMipmapTextureUpload);
376     }
hasPreferDrawOverClearAttachments() const377     bool hasPreferDrawOverClearAttachments() const
378     {
379         return isFeatureEnabled(Feature::PreferDrawClearOverVkCmdClearAttachments);
380     }
hasSupportsPipelineCreationFeedback() const381     bool hasSupportsPipelineCreationFeedback() const
382     {
383         return isFeatureEnabled(Feature::SupportsPipelineCreationFeedback);
384     }
hasWarmUpPipelineCacheAtLink() const385     bool hasWarmUpPipelineCacheAtLink() const
386     {
387         return isFeatureEnabled(Feature::WarmUpPipelineCacheAtLink);
388     }
hasEffectivePipelineCacheSerialization() const389     bool hasEffectivePipelineCacheSerialization() const
390     {
391         return isFeatureEnabled(Feature::HasEffectivePipelineCacheSerialization);
392     }
hasPreferCPUForBufferSubData() const393     bool hasPreferCPUForBufferSubData() const
394     {
395         return isFeatureEnabled(Feature::PreferCPUForBufferSubData);
396     }
hasPreferSubmitAtFBOBoundary() const397     bool hasPreferSubmitAtFBOBoundary() const
398     {
399         return isFeatureEnabled(Feature::PreferSubmitAtFBOBoundary);
400     }
hasDisallowMixedDepthStencilLoadOpNoneAndLoad() const401     bool hasDisallowMixedDepthStencilLoadOpNoneAndLoad() const
402     {
403         return isFeatureEnabled(Feature::DisallowMixedDepthStencilLoadOpNoneAndLoad);
404     }
hasSupportsImagelessFramebuffer() const405     bool hasSupportsImagelessFramebuffer() const
406     {
407         return isFeatureEnabled(Feature::SupportsImagelessFramebuffer);
408     }
hasSupportsHostImageCopy() const409     bool hasSupportsHostImageCopy() const
410     {
411         return isFeatureEnabled(Feature::SupportsHostImageCopy);
412     }
hasDepthStencilResolveThroughAttachment() const413     bool hasDepthStencilResolveThroughAttachment() const
414     {
415         return isFeatureEnabled(Feature::SupportsDepthStencilResolve) &&
416                !isFeatureEnabled(Feature::DisableDepthStencilResolveThroughAttachment);
417     }
418 
419     CounterNameToIndexMap mIndexMap;
420 };
421 
422 class VulkanPerformanceCounterTest_ES31 : public VulkanPerformanceCounterTest
423 {};
424 
425 class VulkanPerformanceCounterTest_MSAA : public VulkanPerformanceCounterTest
426 {
427   protected:
VulkanPerformanceCounterTest_MSAA()428     VulkanPerformanceCounterTest_MSAA() : VulkanPerformanceCounterTest()
429     {
430         // Make sure the window is non-square to correctly test prerotation
431         setWindowWidth(32);
432         setWindowHeight(64);
433         setSamples(4);
434         setMultisampleEnabled(true);
435     }
436 };
437 
438 class VulkanPerformanceCounterTest_SingleBuffer : public VulkanPerformanceCounterTest
439 {
440   protected:
VulkanPerformanceCounterTest_SingleBuffer()441     VulkanPerformanceCounterTest_SingleBuffer() : VulkanPerformanceCounterTest()
442     {
443         setMutableRenderBuffer(true);
444     }
445 };
446 
maskedFramebufferFetchDraw(const GLColor & clearColor,GLBuffer & buffer)447 void VulkanPerformanceCounterTest::maskedFramebufferFetchDraw(const GLColor &clearColor,
448                                                               GLBuffer &buffer)
449 {
450     // Initialize the color buffer
451     angle::Vector4 clearAsVec4 = clearColor.toNormalizedVector();
452     glClearColor(clearAsVec4[0], clearAsVec4[1], clearAsVec4[2], clearAsVec4[3]);
453     glClear(GL_COLOR_BUFFER_BIT);
454     EXPECT_PIXEL_COLOR_NEAR(0, 0, clearColor, 1);
455 
456     // Create output buffer
457     constexpr GLsizei kBufferSize = kOpsTestSize * kOpsTestSize * sizeof(float[4]);
458     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
459     glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
460     glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, 0, kBufferSize);
461 
462     // Zero-initialize it
463     void *bufferData = glMapBufferRange(
464         GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
465         GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
466     memset(bufferData, 0, kBufferSize);
467     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
468 
469     // Mask color output
470     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
471 
472     static constexpr char kVS[] = R"(#version 310 es
473 in highp vec4 a_position;
474 
475 void main (void)
476 {
477     gl_Position = a_position;
478 })";
479 
480     static constexpr char kFS[] = R"(#version 310 es
481 #extension GL_EXT_shader_framebuffer_fetch_non_coherent : require
482 layout(noncoherent, location = 0) inout highp vec4 o_color;
483 
484 layout(std140, binding = 0) buffer outBlock {
485     highp vec4 data[256];
486 };
487 
488 uniform highp vec4 u_color;
489 void main (void)
490 {
491     uint index = uint(gl_FragCoord.y) * 16u + uint(gl_FragCoord.x);
492     data[index] = o_color;
493     o_color += u_color;
494 })";
495 
496     // Draw
497     ANGLE_GL_PROGRAM(program, kVS, kFS);
498     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
499     ASSERT_GL_NO_ERROR();
500 }
501 
maskedFramebufferFetchDrawVerify(const GLColor & expectedColor,GLBuffer & buffer)502 void VulkanPerformanceCounterTest::maskedFramebufferFetchDrawVerify(const GLColor &expectedColor,
503                                                                     GLBuffer &buffer)
504 {
505     angle::Vector4 expectedAsVec4 = expectedColor.toNormalizedVector();
506 
507     // Read back the storage buffer and make sure framebuffer fetch worked as intended despite
508     // masked color.
509     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
510 
511     constexpr GLsizei kBufferSize = kOpsTestSize * kOpsTestSize * sizeof(float[4]);
512     const float *colorData        = static_cast<const float *>(
513         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT));
514     for (uint32_t y = 0; y < kOpsTestSize; ++y)
515     {
516         for (uint32_t x = 0; x < kOpsTestSize; ++x)
517         {
518             uint32_t ssboIndex = (y * kOpsTestSize + x) * 4;
519             EXPECT_NEAR(colorData[ssboIndex + 0], expectedAsVec4[0], 0.05);
520             EXPECT_NEAR(colorData[ssboIndex + 1], expectedAsVec4[1], 0.05);
521             EXPECT_NEAR(colorData[ssboIndex + 2], expectedAsVec4[2], 0.05);
522             EXPECT_NEAR(colorData[ssboIndex + 3], expectedAsVec4[3], 0.05);
523         }
524     }
525     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
526 }
527 
528 // Tests that texture updates to unused textures don't break the RP.
TEST_P(VulkanPerformanceCounterTest,NewTextureDoesNotBreakRenderPass)529 TEST_P(VulkanPerformanceCounterTest, NewTextureDoesNotBreakRenderPass)
530 {
531     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
532 
533     GLColor kInitialData[4] = {GLColor::red, GLColor::blue, GLColor::green, GLColor::yellow};
534 
535     // Step 1: Set up a simple 2D Texture rendering loop.
536     GLTexture texture;
537     glBindTexture(GL_TEXTURE_2D, texture);
538     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, kInitialData);
539     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
540     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
541 
542     auto quadVerts = GetQuadVertices();
543 
544     GLBuffer vertexBuffer;
545     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
546     glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
547                  GL_STATIC_DRAW);
548 
549     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
550     glUseProgram(program);
551 
552     GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
553     ASSERT_NE(-1, posLoc);
554 
555     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
556     glEnableVertexAttribArray(posLoc);
557     ASSERT_GL_NO_ERROR();
558 
559     glDrawArrays(GL_TRIANGLES, 0, 6);
560     ASSERT_GL_NO_ERROR();
561 
562     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses;
563 
564     // Step 2: Introduce a new 2D Texture with the same Program and Framebuffer.
565     GLTexture newTexture;
566     glBindTexture(GL_TEXTURE_2D, newTexture);
567     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, kInitialData);
568     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
569     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
570 
571     glDrawArrays(GL_TRIANGLES, 0, 6);
572     ASSERT_GL_NO_ERROR();
573 
574     uint64_t actualRenderPassCount = getPerfCounters().renderPasses;
575     EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
576 }
577 
578 // Tests that submitting the outside command buffer due to texture upload size does not break the
579 // current render pass.
TEST_P(VulkanPerformanceCounterTest,SubmittingOutsideCommandBufferDoesNotBreakRenderPass)580 TEST_P(VulkanPerformanceCounterTest, SubmittingOutsideCommandBufferDoesNotBreakRenderPass)
581 {
582     constexpr size_t kMaxBufferToImageCopySize = 64 * 1024 * 1024;
583     constexpr uint64_t kNumSubmits             = 2;
584     uint64_t expectedRenderPassCount           = getPerfCounters().renderPasses + 1;
585     uint64_t expectedSubmitCommandsCount = getPerfCounters().vkQueueSubmitCallsTotal + kNumSubmits;
586 
587     // Step 1: Set up a simple 2D texture.
588     GLTexture texture;
589     constexpr GLsizei kTexDim         = 256;
590     constexpr uint32_t kPixelSizeRGBA = 4;
591     constexpr uint32_t kTextureSize   = kTexDim * kTexDim * kPixelSizeRGBA;
592     std::vector<GLColor> kInitialData(kTexDim * kTexDim, GLColor::green);
593 
594     glBindTexture(GL_TEXTURE_2D, texture);
595     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexDim, kTexDim, 0, GL_RGBA, GL_UNSIGNED_BYTE,
596                  kInitialData.data());
597     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
598     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
599 
600     auto quadVerts = GetQuadVertices();
601 
602     GLBuffer vertexBuffer;
603     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
604     glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
605                  GL_STATIC_DRAW);
606 
607     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
608     glUseProgram(program);
609 
610     GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
611     ASSERT_NE(-1, posLoc);
612 
613     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
614     glEnableVertexAttribArray(posLoc);
615     ASSERT_GL_NO_ERROR();
616 
617     glDrawArrays(GL_TRIANGLES, 0, 6);
618     ASSERT_GL_NO_ERROR();
619 
620     // Step 2: Load a new 2D Texture multiple times with the same Program and Framebuffer. The total
621     // size of the loaded textures must exceed the threshold to submit the outside command buffer.
622     constexpr size_t kMaxLoadCount = kMaxBufferToImageCopySize / kTextureSize * kNumSubmits + 1;
623     for (size_t loadCount = 0; loadCount < kMaxLoadCount; loadCount++)
624     {
625         GLTexture newTexture;
626         glBindTexture(GL_TEXTURE_2D, newTexture);
627         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexDim, kTexDim, 0, GL_RGBA, GL_UNSIGNED_BYTE,
628                      kInitialData.data());
629         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
630         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
631 
632         glDrawArrays(GL_TRIANGLES, 0, 6);
633         ASSERT_GL_NO_ERROR();
634     }
635 
636     // Verify render pass and submitted frame counts.
637     EXPECT_EQ(getPerfCounters().renderPasses, expectedRenderPassCount);
638     EXPECT_EQ(getPerfCounters().vkQueueSubmitCallsTotal, expectedSubmitCommandsCount);
639 }
640 
641 // Tests that submitting the outside command buffer due to texture upload size does not result in
642 // garbage collection of render pass resources..
TEST_P(VulkanPerformanceCounterTest,SubmittingOutsideCommandBufferDoesNotCollectRenderPassGarbage)643 TEST_P(VulkanPerformanceCounterTest, SubmittingOutsideCommandBufferDoesNotCollectRenderPassGarbage)
644 {
645     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_disjoint_timer_query"));
646 
647     // If VK_EXT_host_image_copy is used, uploads will all be done on the CPU and there would be no
648     // submissions.
649     ANGLE_SKIP_TEST_IF(hasSupportsHostImageCopy());
650 
651     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
652     uint64_t submitCommandsCount     = getPerfCounters().vkQueueSubmitCallsTotal;
653 
654     // Set up a simple 2D texture.
655     GLTexture texture;
656     constexpr GLsizei kTexDim = 256;
657     std::vector<GLColor> kInitialData(kTexDim * kTexDim, GLColor::green);
658 
659     glBindTexture(GL_TEXTURE_2D, texture);
660     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexDim, kTexDim, 0, GL_RGBA, GL_UNSIGNED_BYTE,
661                  kInitialData.data());
662     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
663     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
664 
665     auto quadVerts = GetQuadVertices();
666 
667     GLBuffer vertexBuffer;
668     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
669     glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
670                  GL_STATIC_DRAW);
671 
672     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
673     glUseProgram(program);
674 
675     GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
676     ASSERT_NE(-1, posLoc);
677 
678     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
679     glEnableVertexAttribArray(posLoc);
680     ASSERT_GL_NO_ERROR();
681 
682     // Issue a timestamp query, just for the sake of using it as a means of knowing when a
683     // submission is finished.  In the Vulkan backend, querying the status of the query results in a
684     // check of completed submissions, at which point associated garbage is also destroyed.
685     GLQuery query;
686     glQueryCounterEXT(query, GL_TIMESTAMP_EXT);
687 
688     // Issue a draw call, and delete the program
689     glDrawArrays(GL_TRIANGLES, 0, 6);
690     ASSERT_GL_NO_ERROR();
691     program.reset();
692 
693     ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
694     glUseProgram(program2);
695     ASSERT_EQ(posLoc, glGetAttribLocation(program2, essl1_shaders::PositionAttrib()));
696 
697     // Issue uploads until there's an implicit submission
698     size_t textureCount = 0;
699     while (getPerfCounters().vkQueueSubmitCallsTotal == submitCommandsCount)
700     {
701         GLTexture newTexture;
702         glBindTexture(GL_TEXTURE_2D, newTexture);
703         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexDim, kTexDim, 0, GL_RGBA, GL_UNSIGNED_BYTE,
704                      kInitialData.data());
705         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
706         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
707 
708         glDrawArrays(GL_TRIANGLES, 0, 6);
709         ASSERT_GL_NO_ERROR();
710         textureCount++;
711     }
712     // 256x256 texture upload should not trigger a submission
713     ASSERT(textureCount > 1);
714 
715     ++submitCommandsCount;
716     EXPECT_EQ(getPerfCounters().vkQueueSubmitCallsTotal, submitCommandsCount);
717 
718     // Busy wait until the query results are available.
719     GLuint ready = GL_FALSE;
720     while (ready == GL_FALSE)
721     {
722         angle::Sleep(0);
723         glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
724     }
725 
726     // At this point, the render pass should still not be submitted, and the pipeline that is
727     // deleted should still not be garbage collected.  Submit the commands and ensure there is no
728     // crash.
729     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
730     ++submitCommandsCount;
731 
732     // Verify counters.
733     EXPECT_EQ(getPerfCounters().renderPasses, expectedRenderPassCount);
734     EXPECT_EQ(getPerfCounters().vkQueueSubmitCallsTotal, submitCommandsCount);
735 }
736 
737 // Tests that submitting the outside command buffer due to texture upload size and triggers
738 // endRenderPass works correctly.
TEST_P(VulkanPerformanceCounterTest,SubmittingOutsideCommandBufferTriggersEndRenderPass)739 TEST_P(VulkanPerformanceCounterTest, SubmittingOutsideCommandBufferTriggersEndRenderPass)
740 {
741     // If VK_EXT_host_image_copy is used, uploads will all be done on the CPU and there would be no
742     // submissions.
743     ANGLE_SKIP_TEST_IF(hasSupportsHostImageCopy());
744 
745     const int width                  = getWindowWidth();
746     const int height                 = getWindowHeight();
747     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
748     uint64_t submitCommandsCount     = getPerfCounters().vkQueueSubmitCallsTotal;
749 
750     // Start a new renderpass with red quad on left.
751     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
752     glScissor(0, 0, width / 2, height);
753     glEnable(GL_SCISSOR_TEST);
754     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.5f);
755 
756     // Issue texture uploads and draw green quad on right until endRenderPass is triggered
757     glScissor(width / 2, 0, width / 2, height);
758     ANGLE_GL_PROGRAM(textureProgram, essl1_shaders::vs::Texture2D(),
759                      essl1_shaders::fs::Texture2D());
760     glUseProgram(textureProgram);
761     GLint textureLoc = glGetUniformLocation(textureProgram, essl1_shaders::Texture2DUniform());
762     ASSERT_NE(-1, textureLoc);
763     glUniform1i(textureLoc, 0);
764 
765     // This test is specifically try to test outsideRPCommands submission drain the reserved
766     // queueSerials. Right now we are reserving 15 queue Serials. This is to ensure if the
767     // implementation changes, we do not end up with infinite loop here.
768     constexpr GLsizei kMaxOutsideRPCommandsSubmitCount = 17;
769     constexpr GLsizei kTexDim                          = 1024;
770     std::vector<GLColor> kInitialData(kTexDim * kTexDim, GLColor::green);
771     // Put a limit on the loop to avoid infinite loop in bad case.
772     while (getPerfCounters().renderPasses == expectedRenderPassCount &&
773            getPerfCounters().vkQueueSubmitCallsTotal <
774                submitCommandsCount + kMaxOutsideRPCommandsSubmitCount)
775     {
776         GLTexture newTexture;
777         glBindTexture(GL_TEXTURE_2D, newTexture);
778         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTexDim, kTexDim);
779         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexDim, kTexDim, GL_RGBA, GL_UNSIGNED_BYTE,
780                         kInitialData.data());
781         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
782         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
783         drawQuad(textureProgram, essl1_shaders::PositionAttrib(), 0.5f);
784         ASSERT_GL_NO_ERROR();
785     }
786 
787     ++expectedRenderPassCount;
788     EXPECT_EQ(getPerfCounters().renderPasses, expectedRenderPassCount);
789 
790     // Verify renderpass draw quads correctly
791     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
792     EXPECT_PIXEL_COLOR_EQ(width / 2 + 1, 0, GLColor::green);
793 }
794 
795 // Tests that mutable texture is uploaded with appropriate mip level attributes.
TEST_P(VulkanPerformanceCounterTest,MutableTextureCompatibleMipLevelsInit)796 TEST_P(VulkanPerformanceCounterTest, MutableTextureCompatibleMipLevelsInit)
797 {
798     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
799 
800     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded + 1;
801 
802     std::vector<GLColor> mip0Color(4 * 4, GLColor::red);
803     std::vector<GLColor> mip1Color(2 * 2, GLColor::red);
804 
805     GLTexture texture1;
806     glBindTexture(GL_TEXTURE_2D, texture1);
807     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Color.data());
808     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Color.data());
809     EXPECT_GL_NO_ERROR();
810 
811     GLTexture texture2;
812     glBindTexture(GL_TEXTURE_2D, texture2);
813     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
814                  GLColor::green.data());
815     EXPECT_GL_NO_ERROR();
816     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
817 }
818 
819 // Tests that a single-level mutable texture is uploaded with appropriate attributes.
TEST_P(VulkanPerformanceCounterTest,MutableTextureCompatibleSingleMipLevelInit)820 TEST_P(VulkanPerformanceCounterTest, MutableTextureCompatibleSingleMipLevelInit)
821 {
822     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
823 
824     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded + 1;
825 
826     std::vector<GLColor> mip0Color(4 * 4, GLColor::red);
827 
828     GLTexture texture1;
829     glBindTexture(GL_TEXTURE_2D, texture1);
830     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Color.data());
831     EXPECT_GL_NO_ERROR();
832 
833     GLTexture texture2;
834     glBindTexture(GL_TEXTURE_2D, texture2);
835     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
836                  GLColor::green.data());
837     EXPECT_GL_NO_ERROR();
838     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
839 }
840 
841 // Tests that mutable texture is uploaded with appropriate mip level attributes, even with unequal
842 // dimensions.
TEST_P(VulkanPerformanceCounterTest,MutableTextureCompatibleMipLevelsNonSquareInit)843 TEST_P(VulkanPerformanceCounterTest, MutableTextureCompatibleMipLevelsNonSquareInit)
844 {
845     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
846 
847     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded + 1;
848 
849     std::vector<GLColor> mip0Color(4 * 2, GLColor::red);
850     std::vector<GLColor> mip1Color(2 * 1, GLColor::red);
851     std::vector<GLColor> mip2Color(1 * 1, GLColor::red);
852 
853     GLTexture texture1;
854     glBindTexture(GL_TEXTURE_2D, texture1);
855     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Color.data());
856     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Color.data());
857     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip2Color.data());
858     EXPECT_GL_NO_ERROR();
859 
860     GLTexture texture2;
861     glBindTexture(GL_TEXTURE_2D, texture2);
862     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
863                  GLColor::green.data());
864     EXPECT_GL_NO_ERROR();
865     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
866 }
867 
868 // Tests that a mutable texture is not uploaded if there are no data or updates for it.
TEST_P(VulkanPerformanceCounterTest,MutableTextureSingleLevelWithNoDataNoInit)869 TEST_P(VulkanPerformanceCounterTest, MutableTextureSingleLevelWithNoDataNoInit)
870 {
871     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
872 
873     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded;
874 
875     GLTexture texture1;
876     glBindTexture(GL_TEXTURE_2D, texture1);
877     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
878     EXPECT_GL_NO_ERROR();
879 
880     GLTexture texture2;
881     glBindTexture(GL_TEXTURE_2D, texture2);
882     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
883                  GLColor::green.data());
884     EXPECT_GL_NO_ERROR();
885     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
886 }
887 
888 // Tests that mutable texture is not uploaded with more than one updates in a single mip level.
TEST_P(VulkanPerformanceCounterTest,MutableTextureSingleLevelWithMultipleUpdatesNoInit)889 TEST_P(VulkanPerformanceCounterTest, MutableTextureSingleLevelWithMultipleUpdatesNoInit)
890 {
891     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
892 
893     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded;
894 
895     std::vector<GLColor> mip0Color(4 * 4, GLColor::red);
896 
897     GLTexture texture1;
898     glBindTexture(GL_TEXTURE_2D, texture1);
899     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
900     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, mip0Color.data());
901     glTexSubImage2D(GL_TEXTURE_2D, 0, 2, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, mip0Color.data());
902     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 2, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, mip0Color.data());
903     glTexSubImage2D(GL_TEXTURE_2D, 0, 2, 2, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, mip0Color.data());
904     EXPECT_GL_NO_ERROR();
905 
906     GLTexture texture2;
907     glBindTexture(GL_TEXTURE_2D, texture2);
908     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
909                  GLColor::green.data());
910     EXPECT_GL_NO_ERROR();
911     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
912 }
913 
914 // Tests that the optimization is not triggered when a mutable texture becomes immutable, e.g.,
915 // after glTexStorage2D.
TEST_P(VulkanPerformanceCounterTest,MutableTextureChangeToImmutableNoInit)916 TEST_P(VulkanPerformanceCounterTest, MutableTextureChangeToImmutableNoInit)
917 {
918     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
919 
920     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded;
921 
922     std::vector<GLColor> mip0Color(4 * 4, GLColor::red);
923     std::vector<GLColor> mip1Color(2 * 2, GLColor::red);
924 
925     GLTexture texture1;
926     glBindTexture(GL_TEXTURE_2D, texture1);
927     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Color.data());
928     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Color.data());
929     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 4, 4);
930     EXPECT_GL_NO_ERROR();
931 
932     GLTexture texture2;
933     glBindTexture(GL_TEXTURE_2D, texture2);
934     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
935                  GLColor::green.data());
936     EXPECT_GL_NO_ERROR();
937     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
938 }
939 
940 // Tests that mutable texture is not uploaded when there is no base mip level (0).
TEST_P(VulkanPerformanceCounterTest,MutableTextureNoBaseLevelNoInit)941 TEST_P(VulkanPerformanceCounterTest, MutableTextureNoBaseLevelNoInit)
942 {
943     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
944 
945     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded;
946 
947     std::vector<GLColor> mip1Color(4 * 4, GLColor::red);
948     std::vector<GLColor> mip2Color(2 * 2, GLColor::red);
949 
950     GLTexture texture1;
951     glBindTexture(GL_TEXTURE_2D, texture1);
952     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Color.data());
953     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip2Color.data());
954     EXPECT_GL_NO_ERROR();
955 
956     GLTexture texture2;
957     glBindTexture(GL_TEXTURE_2D, texture2);
958     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
959                  GLColor::green.data());
960     EXPECT_GL_NO_ERROR();
961     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
962 }
963 
964 // Tests that mutable texture is uploaded even when there is a missing mip level greater than 1
965 // despite the defined mip levels being compatible.
TEST_P(VulkanPerformanceCounterTest,MutableTextureMissingMipLevelGreaterThanOneInit)966 TEST_P(VulkanPerformanceCounterTest, MutableTextureMissingMipLevelGreaterThanOneInit)
967 {
968     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
969 
970     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded + 1;
971 
972     std::vector<GLColor> mip0Color(8 * 8, GLColor::red);
973     std::vector<GLColor> mip1Color(4 * 4, GLColor::red);
974     std::vector<GLColor> mip3Color(1 * 1, GLColor::red);
975 
976     GLTexture texture1;
977     glBindTexture(GL_TEXTURE_2D, texture1);
978     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Color.data());
979     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Color.data());
980     glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip3Color.data());
981     EXPECT_GL_NO_ERROR();
982 
983     GLTexture texture2;
984     glBindTexture(GL_TEXTURE_2D, texture2);
985     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
986                  GLColor::green.data());
987     EXPECT_GL_NO_ERROR();
988     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
989 }
990 
991 // Tests that mutable texture is not uploaded with incompatible mip level sizes.
TEST_P(VulkanPerformanceCounterTest,MutableTextureMipLevelsWithIncompatibleSizesNoInit)992 TEST_P(VulkanPerformanceCounterTest, MutableTextureMipLevelsWithIncompatibleSizesNoInit)
993 {
994     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
995 
996     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded;
997 
998     std::vector<GLColor> mip0Color(8 * 8, GLColor::red);
999     std::vector<GLColor> mip1Color(4 * 4, GLColor::red);
1000     std::vector<GLColor> mip2Color(3 * 3, GLColor::red);
1001 
1002     GLTexture texture1;
1003     glBindTexture(GL_TEXTURE_2D, texture1);
1004     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Color.data());
1005     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Color.data());
1006     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip2Color.data());
1007     EXPECT_GL_NO_ERROR();
1008 
1009     GLTexture texture2;
1010     glBindTexture(GL_TEXTURE_2D, texture2);
1011     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1012                  GLColor::green.data());
1013     EXPECT_GL_NO_ERROR();
1014     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
1015 }
1016 
1017 // Tests that mutable texture is not uploaded with incompatible mip level formats.
TEST_P(VulkanPerformanceCounterTest,MutableTextureMipLevelsWithIncompatibleFormatsNoInit)1018 TEST_P(VulkanPerformanceCounterTest, MutableTextureMipLevelsWithIncompatibleFormatsNoInit)
1019 {
1020     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
1021 
1022     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded;
1023 
1024     std::vector<GLColor> mip0Color(4 * 4, GLColor::red);
1025     std::vector<GLColor> mip1Color(2 * 2, GLColor::red);
1026 
1027     GLTexture texture1;
1028     glBindTexture(GL_TEXTURE_2D, texture1);
1029     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Color.data());
1030     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, mip1Color.data());
1031     EXPECT_GL_NO_ERROR();
1032 
1033     GLTexture texture2;
1034     glBindTexture(GL_TEXTURE_2D, texture2);
1035     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1036                  GLColor::green.data());
1037     EXPECT_GL_NO_ERROR();
1038     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
1039 }
1040 
1041 // Tests that mutable 3D texture is uploaded with appropriate mip level attributes.
TEST_P(VulkanPerformanceCounterTest,MutableTexture3DCompatibleMipLevelsInit)1042 TEST_P(VulkanPerformanceCounterTest, MutableTexture3DCompatibleMipLevelsInit)
1043 {
1044     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
1045 
1046     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded + 1;
1047 
1048     std::vector<GLColor> mip0Color(4 * 4 * 4, GLColor::red);
1049     std::vector<GLColor> mip1Color(2 * 2 * 2, GLColor::red);
1050 
1051     GLTexture texture1;
1052     glBindTexture(GL_TEXTURE_3D, texture1);
1053     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1054                  mip0Color.data());
1055     glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1056                  mip1Color.data());
1057     EXPECT_GL_NO_ERROR();
1058 
1059     GLTexture texture2;
1060     glBindTexture(GL_TEXTURE_3D, texture2);
1061     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1062                  GLColor::green.data());
1063     EXPECT_GL_NO_ERROR();
1064     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
1065 }
1066 
1067 // Tests that mutable 3D texture is uploaded with appropriate mip level attributes, even with
1068 // unequal dimensions.
TEST_P(VulkanPerformanceCounterTest,MutableTexture3DCompatibleMipLevelsNonCubeInit)1069 TEST_P(VulkanPerformanceCounterTest, MutableTexture3DCompatibleMipLevelsNonCubeInit)
1070 {
1071     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
1072 
1073     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded + 1;
1074 
1075     std::vector<GLColor> mip0Color(4 * 2 * 2, GLColor::red);
1076     std::vector<GLColor> mip1Color(2 * 1 * 1, GLColor::red);
1077     std::vector<GLColor> mip2Color(1 * 1 * 1, GLColor::red);
1078 
1079     GLTexture texture1;
1080     glBindTexture(GL_TEXTURE_3D, texture1);
1081     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 4, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1082                  mip0Color.data());
1083     glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA, 2, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1084                  mip1Color.data());
1085     glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1086                  mip1Color.data());
1087     EXPECT_GL_NO_ERROR();
1088 
1089     GLTexture texture2;
1090     glBindTexture(GL_TEXTURE_3D, texture2);
1091     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1092                  GLColor::green.data());
1093     EXPECT_GL_NO_ERROR();
1094     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
1095 }
1096 
1097 // Tests that mutable 3D texture is not uploaded with incompatible mip level sizes.
TEST_P(VulkanPerformanceCounterTest,MutableTexture3DMipLevelsWithIncompatibleSizesNoInit)1098 TEST_P(VulkanPerformanceCounterTest, MutableTexture3DMipLevelsWithIncompatibleSizesNoInit)
1099 {
1100     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
1101 
1102     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded;
1103 
1104     std::vector<GLColor> mip0Color(4 * 4 * 4, GLColor::red);
1105     std::vector<GLColor> mip1Color(2 * 2 * 3, GLColor::red);
1106 
1107     GLTexture texture1;
1108     glBindTexture(GL_TEXTURE_3D, texture1);
1109     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1110                  mip0Color.data());
1111     glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA, 2, 2, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1112                  mip1Color.data());
1113     EXPECT_GL_NO_ERROR();
1114 
1115     GLTexture texture2;
1116     glBindTexture(GL_TEXTURE_3D, texture2);
1117     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1118                  GLColor::green.data());
1119     EXPECT_GL_NO_ERROR();
1120     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
1121 }
1122 
1123 // Tests that mutable 2D array texture is not uploaded with incompatible mip level sizes.
TEST_P(VulkanPerformanceCounterTest,MutableTexture2DArrayMipLevelsWithIncompatibleSizesNoInit)1124 TEST_P(VulkanPerformanceCounterTest, MutableTexture2DArrayMipLevelsWithIncompatibleSizesNoInit)
1125 {
1126     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
1127 
1128     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded;
1129 
1130     std::vector<GLColor> mip0Color(4 * 4 * 4, GLColor::red);
1131     std::vector<GLColor> mip1Color(2 * 2 * 3, GLColor::red);
1132 
1133     GLTexture texture1;
1134     glBindTexture(GL_TEXTURE_2D_ARRAY, texture1);
1135     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1136                  mip0Color.data());
1137     glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA, 2, 2, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1138                  mip1Color.data());
1139     EXPECT_GL_NO_ERROR();
1140 
1141     GLTexture texture2;
1142     glBindTexture(GL_TEXTURE_3D, texture2);
1143     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1144                  GLColor::green.data());
1145     EXPECT_GL_NO_ERROR();
1146     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
1147 }
1148 
1149 // Tests that mutable cubemap texture is uploaded with appropriate mip level attributes.
TEST_P(VulkanPerformanceCounterTest,MutableTextureCubemapCompatibleMipLevelsInit)1150 TEST_P(VulkanPerformanceCounterTest, MutableTextureCubemapCompatibleMipLevelsInit)
1151 {
1152     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
1153 
1154     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded + 1;
1155 
1156     std::vector<GLColor> mip0Color(4 * 4, GLColor::red);
1157     std::vector<GLColor> mip1Color(2 * 2, GLColor::red);
1158 
1159     GLTexture texture1;
1160     glBindTexture(GL_TEXTURE_CUBE_MAP, texture1);
1161     for (size_t i = 0; i < 6; i++)
1162     {
1163         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA, 4, 4, 0, GL_RGBA,
1164                      GL_UNSIGNED_BYTE, mip0Color.data());
1165         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 1, GL_RGBA, 2, 2, 0, GL_RGBA,
1166                      GL_UNSIGNED_BYTE, mip1Color.data());
1167     }
1168     EXPECT_GL_NO_ERROR();
1169 
1170     GLTexture texture2;
1171     glBindTexture(GL_TEXTURE_2D, texture2);
1172     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1173                  GLColor::green.data());
1174     EXPECT_GL_NO_ERROR();
1175     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
1176 }
1177 
1178 // Tests that mutable cubemap texture is not uploaded with no data or updates.
TEST_P(VulkanPerformanceCounterTest,MutableTextureCubemapWithNoDataNoInit)1179 TEST_P(VulkanPerformanceCounterTest, MutableTextureCubemapWithNoDataNoInit)
1180 {
1181     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
1182 
1183     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded;
1184 
1185     GLTexture texture1;
1186     glBindTexture(GL_TEXTURE_CUBE_MAP, texture1);
1187     for (size_t i = 0; i < 6; i++)
1188     {
1189         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA, 4, 4, 0, GL_RGBA,
1190                      GL_UNSIGNED_BYTE, nullptr);
1191         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 1, GL_RGBA, 2, 2, 0, GL_RGBA,
1192                      GL_UNSIGNED_BYTE, nullptr);
1193     }
1194     EXPECT_GL_NO_ERROR();
1195 
1196     GLTexture texture2;
1197     glBindTexture(GL_TEXTURE_2D, texture2);
1198     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1199                  GLColor::green.data());
1200     EXPECT_GL_NO_ERROR();
1201     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
1202 }
1203 
1204 // Tests that mutable cubemap texture is not uploaded with more than one update in a cube face.
TEST_P(VulkanPerformanceCounterTest,MutableTextureCubemapMultipleUpdatesForOneFaceNoInit)1205 TEST_P(VulkanPerformanceCounterTest, MutableTextureCubemapMultipleUpdatesForOneFaceNoInit)
1206 {
1207     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
1208 
1209     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded;
1210 
1211     std::vector<GLColor> mip0Color(4 * 4, GLColor::red);
1212     std::vector<GLColor> mip1Color(2 * 2, GLColor::red);
1213 
1214     GLTexture texture1;
1215     glBindTexture(GL_TEXTURE_CUBE_MAP, texture1);
1216     for (size_t i = 0; i < 6; i++)
1217     {
1218         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA, 4, 4, 0, GL_RGBA,
1219                      GL_UNSIGNED_BYTE, nullptr);
1220         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 1, GL_RGBA, 2, 2, 0, GL_RGBA,
1221                      GL_UNSIGNED_BYTE, nullptr);
1222     }
1223     EXPECT_GL_NO_ERROR();
1224     for (size_t i = 0; i < 6; i++)
1225     {
1226         glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, 4, 4, GL_RGBA,
1227                         GL_UNSIGNED_BYTE, mip0Color.data());
1228         glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 1, 0, 0, 2, 2, GL_RGBA,
1229                         GL_UNSIGNED_BYTE, mip1Color.data());
1230     }
1231     glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 1, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
1232                     GLColor::red.data());
1233 
1234     GLTexture texture2;
1235     glBindTexture(GL_TEXTURE_2D, texture2);
1236     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1237                  GLColor::green.data());
1238     EXPECT_GL_NO_ERROR();
1239     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
1240 }
1241 
1242 // Tests that mutable cubemap texture is not uploaded if not complete.
TEST_P(VulkanPerformanceCounterTest,MutableTextureCubemapIncompleteInit)1243 TEST_P(VulkanPerformanceCounterTest, MutableTextureCubemapIncompleteInit)
1244 {
1245     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
1246 
1247     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded;
1248 
1249     std::vector<GLColor> mip0Color(4 * 4, GLColor::red);
1250     std::vector<GLColor> mip1Color(2 * 2, GLColor::red);
1251 
1252     GLTexture texture1;
1253     glBindTexture(GL_TEXTURE_CUBE_MAP, texture1);
1254     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1255                  mip0Color.data());
1256     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1257                  mip1Color.data());
1258     EXPECT_GL_NO_ERROR();
1259 
1260     GLTexture texture2;
1261     glBindTexture(GL_TEXTURE_2D, texture2);
1262     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1263                  GLColor::green.data());
1264     EXPECT_GL_NO_ERROR();
1265     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
1266 }
1267 
1268 // Tests that mutable cubemap array texture is uploaded with appropriate mip level attributes.
TEST_P(VulkanPerformanceCounterTest,MutableTextureCubemapArrayCompatibleMipLevelsInit)1269 TEST_P(VulkanPerformanceCounterTest, MutableTextureCubemapArrayCompatibleMipLevelsInit)
1270 {
1271     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
1272 
1273     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded + 1;
1274 
1275     std::vector<GLColor> mip0Color(4 * 4 * 6, GLColor::red);
1276     std::vector<GLColor> mip1Color(2 * 2 * 6, GLColor::red);
1277 
1278     GLTexture texture1;
1279     glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, texture1);
1280     glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 4, 4, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1281                  mip0Color.data());
1282     glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA, 2, 2, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1283                  mip1Color.data());
1284 
1285     EXPECT_GL_NO_ERROR();
1286 
1287     GLTexture texture2;
1288     glBindTexture(GL_TEXTURE_2D, texture2);
1289     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1290                  GLColor::green.data());
1291     EXPECT_GL_NO_ERROR();
1292     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
1293 }
1294 
1295 // Tests that mutable cubemap array texture is not uploaded with different layer-faces.
TEST_P(VulkanPerformanceCounterTest,MutableTextureCubemapArrayDifferentLayerFacesNoInit)1296 TEST_P(VulkanPerformanceCounterTest, MutableTextureCubemapArrayDifferentLayerFacesNoInit)
1297 {
1298     ANGLE_SKIP_TEST_IF(!hasMutableMipmapTextureUpload());
1299 
1300     uint32_t expectedMutableTexturesUploaded = getPerfCounters().mutableTexturesUploaded;
1301 
1302     std::vector<GLColor> mip0Color(4 * 4 * 6, GLColor::red);
1303     std::vector<GLColor> mip1Color(2 * 2 * 12, GLColor::red);
1304 
1305     GLTexture texture1;
1306     glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, texture1);
1307     glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 4, 4, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1308                  mip0Color.data());
1309     glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA, 2, 2, 12, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1310                  mip1Color.data());
1311 
1312     EXPECT_GL_NO_ERROR();
1313 
1314     GLTexture texture2;
1315     glBindTexture(GL_TEXTURE_2D, texture2);
1316     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1317                  GLColor::green.data());
1318     EXPECT_GL_NO_ERROR();
1319     EXPECT_EQ(getPerfCounters().mutableTexturesUploaded, expectedMutableTexturesUploaded);
1320 }
1321 
1322 // Tests that RGB texture should not break renderpass.
TEST_P(VulkanPerformanceCounterTest,SampleFromRGBTextureDoesNotBreakRenderPass)1323 TEST_P(VulkanPerformanceCounterTest, SampleFromRGBTextureDoesNotBreakRenderPass)
1324 {
1325     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
1326 
1327     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
1328     glUseProgram(program);
1329     GLint textureLoc = glGetUniformLocation(program, essl1_shaders::Texture2DUniform());
1330     ASSERT_NE(-1, textureLoc);
1331 
1332     GLTexture textureRGBA;
1333     glActiveTexture(GL_TEXTURE0);
1334     glBindTexture(GL_TEXTURE_2D, textureRGBA);
1335     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1336     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1337     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
1338     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1339 
1340     GLTexture textureRGB;
1341     glActiveTexture(GL_TEXTURE1);
1342     glBindTexture(GL_TEXTURE_2D, textureRGB);
1343     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
1344     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
1345     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
1346     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1347 
1348     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
1349 
1350     // First draw with textureRGBA which should start the renderpass
1351     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1352     glUniform1i(textureLoc, 0);
1353     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1354     ASSERT_GL_NO_ERROR();
1355 
1356     // Next draw with textureRGB which should not end the renderpass
1357     glUniform1i(textureLoc, 1);
1358     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1359     ASSERT_GL_NO_ERROR();
1360 
1361     uint64_t actualRenderPassCount = getPerfCounters().renderPasses;
1362     EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
1363 }
1364 
1365 // Tests that RGB texture should not break renderpass.
TEST_P(VulkanPerformanceCounterTest,RenderToRGBTextureDoesNotBreakRenderPass)1366 TEST_P(VulkanPerformanceCounterTest, RenderToRGBTextureDoesNotBreakRenderPass)
1367 {
1368     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
1369 
1370     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor());
1371     glUseProgram(program);
1372     GLint colorUniformLocation =
1373         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1374     ASSERT_NE(-1, colorUniformLocation);
1375     ASSERT_GL_NO_ERROR();
1376 
1377     GLTexture textureRGB;
1378     glActiveTexture(GL_TEXTURE1);
1379     glBindTexture(GL_TEXTURE_2D, textureRGB);
1380     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
1381     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1382     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1383 
1384     GLFramebuffer framebuffer;
1385     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1386     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureRGB, 0);
1387     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1388     ASSERT_GL_NO_ERROR();
1389 
1390     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
1391 
1392     // Draw into FBO
1393     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1394     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);  // clear to green
1395     glClear(GL_COLOR_BUFFER_BIT);
1396     glViewport(0, 0, 256, 256);
1397     glUniform4fv(colorUniformLocation, 1, GLColor::blue.toNormalizedVector().data());
1398     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1399 
1400     uint64_t actualRenderPassCount = getPerfCounters().renderPasses;
1401     EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
1402 }
1403 
1404 // Tests that changing a Texture's max level hits the descriptor set cache.
TEST_P(VulkanPerformanceCounterTest,ChangingMaxLevelHitsDescriptorCache)1405 TEST_P(VulkanPerformanceCounterTest, ChangingMaxLevelHitsDescriptorCache)
1406 {
1407     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
1408 
1409     GLColor kInitialData[4] = {GLColor::red, GLColor::blue, GLColor::green, GLColor::yellow};
1410 
1411     // Step 1: Set up a simple mipped 2D Texture rendering loop.
1412     GLTexture texture;
1413     glBindTexture(GL_TEXTURE_2D, texture);
1414     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, kInitialData);
1415     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, kInitialData);
1416     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1417     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1418     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
1419 
1420     auto quadVerts = GetQuadVertices();
1421 
1422     GLBuffer vertexBuffer;
1423     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1424     glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
1425                  GL_STATIC_DRAW);
1426 
1427     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
1428     glUseProgram(program);
1429 
1430     GLint posLoc = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1431     ASSERT_NE(-1, posLoc);
1432 
1433     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1434     glEnableVertexAttribArray(posLoc);
1435     ASSERT_GL_NO_ERROR();
1436 
1437     glDrawArrays(GL_TRIANGLES, 0, 6);
1438     ASSERT_GL_NO_ERROR();
1439 
1440     // Step 2: Change max level and draw.
1441     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
1442     glDrawArrays(GL_TRIANGLES, 0, 6);
1443     ASSERT_GL_NO_ERROR();
1444 
1445     uint64_t expectedWriteDescriptorSetCount = getPerfCounters().writeDescriptorSets;
1446 
1447     // Step 3: Change max level back to original value and verify we hit the cache.
1448     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
1449     glDrawArrays(GL_TRIANGLES, 0, 6);
1450     ASSERT_GL_NO_ERROR();
1451 
1452     uint64_t actualWriteDescriptorSetCount = getPerfCounters().writeDescriptorSets;
1453     EXPECT_EQ(expectedWriteDescriptorSetCount, actualWriteDescriptorSetCount);
1454 }
1455 
1456 // Tests that two glCopyBufferSubData commands can share a barrier.
TEST_P(VulkanPerformanceCounterTest,IndependentBufferCopiesShareSingleBarrier)1457 TEST_P(VulkanPerformanceCounterTest, IndependentBufferCopiesShareSingleBarrier)
1458 {
1459     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
1460 
1461     constexpr GLint srcDataA[] = {1, 2, 3, 4};
1462     constexpr GLint srcDataB[] = {5, 6, 7, 8};
1463 
1464     // Step 1: Set up four buffers for two copies.
1465     GLBuffer srcA;
1466     glBindBuffer(GL_COPY_READ_BUFFER, srcA);
1467     // Note: We can't use GL_STATIC_COPY. Using STATIC will cause driver to allocate a host
1468     // invisible memory and issue a copyToBuffer, which will trigger outsideRenderPassCommandBuffer
1469     // flush when glCopyBufferSubData is called due to read after write. That will break the
1470     // expectations and cause test to fail.
1471     glBufferData(GL_COPY_READ_BUFFER, sizeof(srcDataA), srcDataA, GL_DYNAMIC_COPY);
1472 
1473     GLBuffer dstA;
1474     glBindBuffer(GL_COPY_WRITE_BUFFER, dstA);
1475     // Note: We can't use GL_STATIC_COPY. Using STATIC will cause driver to allocate a host
1476     // invisible memory and issue a copyToBuffer, which will trigger outsideRenderPassCommandBuffer
1477     // flush when glCopyBufferSubData is called due to write after write. That will break the
1478     // expectations and cause test to fail.
1479     glBufferData(GL_COPY_WRITE_BUFFER, sizeof(srcDataA[0]) * 2, nullptr, GL_DYNAMIC_COPY);
1480 
1481     GLBuffer srcB;
1482     glBindBuffer(GL_COPY_READ_BUFFER, srcB);
1483     glBufferData(GL_COPY_READ_BUFFER, sizeof(srcDataB), srcDataB, GL_DYNAMIC_COPY);
1484 
1485     GLBuffer dstB;
1486     glBindBuffer(GL_COPY_WRITE_BUFFER, dstB);
1487     glBufferData(GL_COPY_WRITE_BUFFER, sizeof(srcDataB[0]) * 2, nullptr, GL_DYNAMIC_COPY);
1488 
1489     // We expect that ANGLE generate zero additional command buffers.
1490     uint64_t expectedFlushCount = getPerfCounters().flushedOutsideRenderPassCommandBuffers;
1491 
1492     // Step 2: Do the two copies.
1493     glBindBuffer(GL_COPY_READ_BUFFER, srcA);
1494     glBindBuffer(GL_COPY_WRITE_BUFFER, dstA);
1495     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, sizeof(srcDataB[0]), 0,
1496                         sizeof(srcDataA[0]) * 2);
1497 
1498     glBindBuffer(GL_COPY_READ_BUFFER, srcB);
1499     glBindBuffer(GL_COPY_WRITE_BUFFER, dstB);
1500     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, sizeof(srcDataB[0]), 0,
1501                         sizeof(srcDataB[0]) * 2);
1502 
1503     ASSERT_GL_NO_ERROR();
1504 
1505     uint64_t actualFlushCount = getPerfCounters().flushedOutsideRenderPassCommandBuffers;
1506     EXPECT_EQ(expectedFlushCount, actualFlushCount);
1507 }
1508 
1509 // Test resolving a multisampled texture with blit doesn't break the render pass so a subpass can be
1510 // used
TEST_P(VulkanPerformanceCounterTest_ES31,MultisampleResolveWithBlit)1511 TEST_P(VulkanPerformanceCounterTest_ES31, MultisampleResolveWithBlit)
1512 {
1513     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
1514 
1515     constexpr int kSize = 16;
1516     glViewport(0, 0, kSize, kSize);
1517 
1518     GLFramebuffer msaaFBO;
1519     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
1520 
1521     GLTexture texture;
1522     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
1523     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1524     ASSERT_GL_NO_ERROR();
1525     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
1526                            0);
1527     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1528 
1529     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
1530                      essl31_shaders::fs::RedGreenGradient());
1531     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1532     ASSERT_GL_NO_ERROR();
1533 
1534     // Create another FBO to resolve the multisample buffer into.
1535     GLTexture resolveTexture;
1536     GLFramebuffer resolveFBO;
1537     glBindTexture(GL_TEXTURE_2D, resolveTexture);
1538     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1539     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1540     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1541     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1542     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1543     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1544     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
1545     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1546 
1547     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1548     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1549     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1550     ASSERT_GL_NO_ERROR();
1551 
1552     EXPECT_EQ(getPerfCounters().resolveImageCommands, 0u);
1553 
1554     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1555     constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
1556     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
1557     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
1558     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
1559     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
1560                       255, 1.0);
1561 }
1562 
1563 // Test resolving a multisampled texture with blit and then invalidate the msaa buffer
TEST_P(VulkanPerformanceCounterTest_ES31,ResolveToFBOWithInvalidate)1564 TEST_P(VulkanPerformanceCounterTest_ES31, ResolveToFBOWithInvalidate)
1565 {
1566     angle::VulkanPerfCounters expected;
1567 
1568     // Expect rpCount+1, color(Clears+0, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
1569     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 0, 0, 1, 0, &expected);
1570     expected.colorAttachmentResolves = getPerfCounters().colorAttachmentResolves + 1;
1571 
1572     constexpr int kWindowWidth  = 4;
1573     constexpr int kWindowHeight = 4;
1574     GLTexture resolveTexture;
1575     glBindTexture(GL_TEXTURE_2D, resolveTexture);
1576     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWindowWidth, kWindowHeight, 0, GL_RGBA,
1577                  GL_UNSIGNED_BYTE, nullptr);
1578     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1579     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1580 
1581     GLFramebuffer resolveFBO;
1582     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1583     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
1584 
1585     GLTexture msaaTexture;
1586     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTexture);
1587     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWindowWidth, kWindowHeight,
1588                               GL_FALSE);
1589 
1590     GLFramebuffer msaaFBO;
1591     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
1592     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaaFBO,
1593                            0);
1594     ANGLE_GL_PROGRAM(redprogram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1595 
1596     drawQuad(redprogram, essl1_shaders::PositionAttrib(), 0.5f);
1597     // Resolve into FBO
1598     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1599     glBlitFramebuffer(0, 0, kWindowWidth, kWindowHeight, 0, 0, kWindowWidth, kWindowHeight,
1600                       GL_COLOR_BUFFER_BIT, GL_NEAREST);
1601 
1602     GLenum attachment = GL_COLOR_ATTACHMENT0;
1603     glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, &attachment);
1604     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1605 
1606     // Top-left pixels should be all red.
1607     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1608 
1609     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
1610     EXPECT_EQ(expected.colorAttachmentResolves, getPerfCounters().colorAttachmentResolves);
1611     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
1612 
1613     ASSERT_GL_NO_ERROR();
1614 }
1615 
1616 // Test resolving different attachments of an FBO to separate FBOs then invalidate
TEST_P(VulkanPerformanceCounterTest_ES31,MultisampleResolveBothAttachments)1617 TEST_P(VulkanPerformanceCounterTest_ES31, MultisampleResolveBothAttachments)
1618 {
1619     enum class Invalidate
1620     {
1621         AfterEachResolve,
1622         AllAtEnd,
1623     };
1624 
1625     constexpr char kFS[] = R"(#version 300 es
1626 precision highp float;
1627 
1628 uniform vec4 value0;
1629 uniform vec4 value2;
1630 
1631 layout(location = 0) out vec4 color0;
1632 layout(location = 2) out vec4 color2;
1633 
1634 void main()
1635 {
1636     color0 = value0;
1637     color2 = value2;
1638 })";
1639 
1640     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1641     glUseProgram(program);
1642     const GLint color0Loc = glGetUniformLocation(program, "value0");
1643     const GLint color1Loc = glGetUniformLocation(program, "value2");
1644 
1645     constexpr int kWidth  = 16;
1646     constexpr int kHeight = 20;
1647     glViewport(0, 0, kWidth, kHeight);
1648 
1649     GLTexture msaa0, msaa1;
1650     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa0);
1651     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
1652     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa1);
1653     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
1654 
1655     GLFramebuffer msaaFBO;
1656     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
1657     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa0,
1658                            0);
1659     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D_MULTISAMPLE, msaa1,
1660                            0);
1661     ASSERT_GL_NO_ERROR();
1662     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1663 
1664     GLenum bufs[3] = {GL_COLOR_ATTACHMENT0, GL_NONE, GL_COLOR_ATTACHMENT2};
1665     glDrawBuffers(3, bufs);
1666 
1667     // Create two resolve FBOs and textures. Use different texture levels and layers.
1668     GLTexture resolveTexture1;
1669     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
1670     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kWidth * 2, kHeight * 2);
1671 
1672     GLFramebuffer resolveFBO1;
1673     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
1674     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 1);
1675     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1676 
1677     GLTexture resolveTexture2;
1678     glBindTexture(GL_TEXTURE_2D_ARRAY, resolveTexture2);
1679     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RGBA8, kWidth * 4, kHeight * 4, 5);
1680 
1681     GLFramebuffer resolveFBO2;
1682     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
1683     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, resolveTexture2, 2, 3);
1684     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1685 
1686     auto test = [&](GLColor color0, GLColor color1, Invalidate invalidate) {
1687         const GLenum discards[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT2};
1688 
1689         // Resolve attachments should be used and the MSAA attachments should be invalidated.
1690         // Only the resolve attachments should have Store.
1691         //
1692         // Expect rpCount+1, color(Clears+0, Loads+0, LoadNones+0, Stores+2, StoreNones+0)
1693         angle::VulkanPerfCounters expected;
1694         setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 0, 0, 2, 0, &expected);
1695         expected.colorAttachmentResolves = getPerfCounters().colorAttachmentResolves + 2;
1696 
1697         glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
1698         glUniform4fv(color0Loc, 1, color0.toNormalizedVector().data());
1699         glUniform4fv(color1Loc, 1, color1.toNormalizedVector().data());
1700         drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1701         ASSERT_GL_NO_ERROR();
1702 
1703         // Resolve the first attachment
1704         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
1705         glReadBuffer(GL_COLOR_ATTACHMENT0);
1706         glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
1707                           GL_NEAREST);
1708         ASSERT_GL_NO_ERROR();
1709 
1710         if (invalidate == Invalidate::AfterEachResolve)
1711         {
1712             glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, discards);
1713         }
1714 
1715         // Resolve the second attachment
1716         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
1717         glReadBuffer(GL_COLOR_ATTACHMENT2);
1718         glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
1719                           GL_NEAREST);
1720         ASSERT_GL_NO_ERROR();
1721 
1722         if (invalidate == Invalidate::AfterEachResolve)
1723         {
1724             glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, discards + 1);
1725         }
1726         else if (invalidate == Invalidate::AllAtEnd)
1727         {
1728             glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 2, discards);
1729         }
1730 
1731         glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
1732         EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, color0);
1733         glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
1734         EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, color1);
1735         ASSERT_GL_NO_ERROR();
1736 
1737         EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
1738         EXPECT_EQ(expected.colorAttachmentResolves, getPerfCounters().colorAttachmentResolves);
1739         EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
1740     };
1741 
1742     test(GLColor::blue, GLColor::yellow, Invalidate::AfterEachResolve);
1743     test(GLColor::cyan, GLColor::magenta, Invalidate::AllAtEnd);
1744 }
1745 
1746 // Test resolving the depth/stencil attachment
TEST_P(VulkanPerformanceCounterTest_ES31,MultisampleDepthStencilResolve)1747 TEST_P(VulkanPerformanceCounterTest_ES31, MultisampleDepthStencilResolve)
1748 {
1749     ANGLE_SKIP_TEST_IF(!hasDepthStencilResolveThroughAttachment());
1750 
1751     constexpr int kWidth  = 24;
1752     constexpr int kHeight = 12;
1753     glViewport(0, 0, kWidth, kHeight);
1754 
1755     GLFramebuffer msaaFBO;
1756     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
1757 
1758     GLRenderbuffer depthStencil;
1759     glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
1760     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kWidth, kHeight);
1761     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
1762                               depthStencil);
1763     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1764     ASSERT_GL_NO_ERROR();
1765 
1766     // Create two resolve FBOs and textures. Use different texture levels and layers.
1767     GLTexture resolveTexture;
1768     glBindTexture(GL_TEXTURE_2D, resolveTexture);
1769     glTexStorage2D(GL_TEXTURE_2D, 4, GL_DEPTH24_STENCIL8, kWidth * 4, kHeight * 4);
1770 
1771     GLFramebuffer resolveFBO;
1772     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1773     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
1774                            resolveTexture, 2);
1775     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1776 
1777     ANGLE_GL_PROGRAM(red, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
1778 
1779     // Resolve attachment should be used and the MSAA attachment should be invalidated.
1780     // Only the resolve attachment should have Store.
1781     //
1782     // Expect rpCount+1, depth(Clears+0, Loads+0, LoadNones+0, Stores+1, StoreNones+0),
1783     // stencil(Clears+0, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
1784     angle::VulkanPerfCounters expected;
1785     setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 0, 0, 1, 0, &expected);
1786     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 1, 0, &expected);
1787     expected.depthAttachmentResolves   = getPerfCounters().depthAttachmentResolves + 1;
1788     expected.stencilAttachmentResolves = getPerfCounters().stencilAttachmentResolves + 1;
1789 
1790     glEnable(GL_DEPTH_TEST);
1791     glDepthFunc(GL_ALWAYS);
1792     glDepthMask(GL_TRUE);
1793     glEnable(GL_STENCIL_TEST);
1794     glStencilFunc(GL_ALWAYS, 0x55, 0xFF);
1795     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1796     glStencilMask(0xFF);
1797 
1798     // Initialize the depth/stencil image
1799     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
1800     drawQuad(red, essl1_shaders::PositionAttrib(), 0.3f);
1801     ASSERT_GL_NO_ERROR();
1802 
1803     // Resolve depth and stencil, then verify the results
1804     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1805     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
1806                       GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
1807 
1808     // Invalidate depth/stencil
1809     const GLenum discards[] = {GL_DEPTH_STENCIL_ATTACHMENT};
1810     glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, discards);
1811 
1812     // Break the render pass
1813     glFinish();
1814 
1815     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
1816     EXPECT_EQ(expected.depthAttachmentResolves, getPerfCounters().depthAttachmentResolves);
1817     EXPECT_EQ(expected.stencilAttachmentResolves, getPerfCounters().stencilAttachmentResolves);
1818     EXPECT_DEPTH_OP_COUNTERS(getPerfCounters(), expected);
1819     EXPECT_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
1820 
1821     ASSERT_GL_NO_ERROR();
1822 }
1823 // Ensures a read-only depth-stencil feedback loop works in a single RenderPass.
TEST_P(VulkanPerformanceCounterTest,ReadOnlyDepthStencilFeedbackLoopUsesSingleRenderPass)1824 TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthStencilFeedbackLoopUsesSingleRenderPass)
1825 {
1826     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
1827 
1828     constexpr GLsizei kSize = 4;
1829 
1830     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1831     ANGLE_GL_PROGRAM(texProgram, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
1832 
1833     GLTexture colorTexture;
1834     glBindTexture(GL_TEXTURE_2D, colorTexture);
1835     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1836 
1837     setupQuadVertexBuffer(0.5f, 1.0f);
1838     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
1839     glEnableVertexAttribArray(0);
1840 
1841     // Set up a depth texture and fill it with an arbitrary initial value.
1842     GLTexture depthTexture;
1843     glBindTexture(GL_TEXTURE_2D, depthTexture);
1844     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, kSize, kSize, 0, GL_DEPTH_COMPONENT,
1845                  GL_UNSIGNED_INT, nullptr);
1846     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1847     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1848     glBindTexture(GL_TEXTURE_2D, 0);
1849 
1850     GLFramebuffer depthAndColorFBO;
1851     glBindFramebuffer(GL_FRAMEBUFFER, depthAndColorFBO);
1852     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
1853     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
1854     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1855 
1856     GLFramebuffer depthOnlyFBO;
1857     glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFBO);
1858     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
1859     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1860 
1861     // Draw to a first FBO to initialize the depth buffer.
1862     glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFBO);
1863     glEnable(GL_DEPTH_TEST);
1864     glUseProgram(redProgram);
1865     glDrawArrays(GL_TRIANGLES, 0, 6);
1866     ASSERT_GL_NO_ERROR();
1867 
1868     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
1869 
1870     // Start new RenderPass with depth write disabled and no loop.
1871     glBindFramebuffer(GL_FRAMEBUFFER, depthAndColorFBO);
1872     glDepthMask(false);
1873     glDrawArrays(GL_TRIANGLES, 0, 6);
1874     ASSERT_GL_NO_ERROR();
1875 
1876     // Now set up the read-only feedback loop.
1877     glBindTexture(GL_TEXTURE_2D, depthTexture);
1878     glUseProgram(texProgram);
1879     glDrawArrays(GL_TRIANGLES, 0, 6);
1880     ASSERT_GL_NO_ERROR();
1881 
1882     // Tweak the bits to keep it read-only.
1883     glEnable(GL_DEPTH_TEST);
1884     glDrawArrays(GL_TRIANGLES, 0, 6);
1885     ASSERT_GL_NO_ERROR();
1886 
1887     // Render with just the depth attachment.
1888     glUseProgram(redProgram);
1889     glBindTexture(GL_TEXTURE_2D, 0);
1890     glDrawArrays(GL_TRIANGLES, 0, 6);
1891     ASSERT_GL_NO_ERROR();
1892 
1893     // Rebind the depth texture.
1894     glUseProgram(texProgram);
1895     glDepthMask(GL_FALSE);
1896     glEnable(GL_DEPTH_TEST);
1897     glBindTexture(GL_TEXTURE_2D, depthTexture);
1898     glDrawArrays(GL_TRIANGLES, 0, 6);
1899     ASSERT_GL_NO_ERROR();
1900 
1901     uint64_t actualRenderPassCount = getPerfCounters().renderPasses;
1902     EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
1903 
1904     // Do a final write to depth to make sure we can switch out of read-only mode.
1905     glBindTexture(GL_TEXTURE_2D, 0);
1906     glDepthMask(GL_TRUE);
1907     glDrawArrays(GL_TRIANGLES, 0, 6);
1908     ASSERT_GL_NO_ERROR();
1909 }
1910 
1911 // Ensures clear color buffer and read-only depth-stencil works in a single RenderPass (as seen in
1912 // gfxbench manhattan).
TEST_P(VulkanPerformanceCounterTest,ClearColorBufferAndReadOnlyDepthStencilUsesSingleRenderPass)1913 TEST_P(VulkanPerformanceCounterTest, ClearColorBufferAndReadOnlyDepthStencilUsesSingleRenderPass)
1914 {
1915     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
1916 
1917     constexpr GLsizei kSize = 4;
1918 
1919     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1920     ANGLE_GL_PROGRAM(texProgram, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
1921 
1922     setupQuadVertexBuffer(0.5f, 1.0f);
1923     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
1924     glEnableVertexAttribArray(0);
1925 
1926     // Set up a depth texture and draw a quad to initialize it with known value.
1927     GLTexture depthTexture;
1928     glBindTexture(GL_TEXTURE_2D, depthTexture);
1929     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, kSize, kSize, 0, GL_DEPTH_COMPONENT,
1930                  GL_UNSIGNED_INT, nullptr);
1931     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1932     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1933     glBindTexture(GL_TEXTURE_2D, 0);
1934     GLFramebuffer depthOnlyFBO;
1935     glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFBO);
1936     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
1937     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1938     glEnable(GL_DEPTH_TEST);
1939     glDepthMask(GL_TRUE);
1940     glUseProgram(redProgram);
1941     glDrawArrays(GL_TRIANGLES, 0, 6);
1942     ASSERT_GL_NO_ERROR();
1943 
1944     // Setup a color texture and FBO with color and read only depth attachment.
1945     GLTexture colorTexture;
1946     glBindTexture(GL_TEXTURE_2D, colorTexture);
1947     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1948     GLFramebuffer depthAndColorFBO;
1949     glBindFramebuffer(GL_FRAMEBUFFER, depthAndColorFBO);
1950     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
1951     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
1952     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1953     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
1954     // First clear color buffer. This should not cause this render pass to switch to read only depth
1955     // stencil mode
1956     glClearColor(0, 0, 0, 0);
1957     glClear(GL_COLOR_BUFFER_BIT);
1958     // Now set up the read-only feedback loop.
1959     glDepthMask(GL_FALSE);
1960     glEnable(GL_DEPTH_TEST);
1961     glBindTexture(GL_TEXTURE_2D, depthTexture);
1962     glUseProgram(texProgram);
1963     glDrawArrays(GL_TRIANGLES, 0, 6);
1964     ASSERT_GL_NO_ERROR();
1965 
1966     // Render with just the depth attachment.
1967     glUseProgram(redProgram);
1968     glBindTexture(GL_TEXTURE_2D, 0);
1969     glDrawArrays(GL_TRIANGLES, 0, 6);
1970     ASSERT_GL_NO_ERROR();
1971 
1972     // Rebind the depth texture.
1973     glUseProgram(texProgram);
1974     glDepthMask(GL_FALSE);
1975     glEnable(GL_DEPTH_TEST);
1976     glBindTexture(GL_TEXTURE_2D, depthTexture);
1977     glDrawArrays(GL_TRIANGLES, 0, 6);
1978     ASSERT_GL_NO_ERROR();
1979 
1980     uint64_t actualRenderPassCount = getPerfCounters().renderPasses;
1981     EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
1982 
1983     // Do a final write to depth to make sure we can switch out of read-only mode.
1984     glBindTexture(GL_TEXTURE_2D, 0);
1985     glDepthMask(GL_TRUE);
1986     glDrawArrays(GL_TRIANGLES, 0, 6);
1987     ASSERT_GL_NO_ERROR();
1988 }
1989 
1990 // Ensures an actual depth feedback loop (i.e, render and sample from same texture which is
1991 // undefined behavior according to spec) works in a single RenderPass. This is adoptted from usage
1992 // pattern from gangstar_vegas.
TEST_P(VulkanPerformanceCounterTest,DepthFeedbackLoopUsesSingleRenderPass)1993 TEST_P(VulkanPerformanceCounterTest, DepthFeedbackLoopUsesSingleRenderPass)
1994 {
1995     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
1996 
1997     constexpr GLsizei kSize = 4;
1998 
1999     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2000     ANGLE_GL_PROGRAM(texProgram, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
2001 
2002     GLTexture colorTexture;
2003     glBindTexture(GL_TEXTURE_2D, colorTexture);
2004     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2005 
2006     setupQuadVertexBuffer(0.5f, 1.0f);
2007     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
2008     glEnableVertexAttribArray(0);
2009 
2010     // Set up a depth texture and fill it with an arbitrary initial value.
2011     GLTexture depthTexture;
2012     glBindTexture(GL_TEXTURE_2D, depthTexture);
2013     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, kSize, kSize, 0, GL_DEPTH_COMPONENT,
2014                  GL_UNSIGNED_INT, nullptr);
2015     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2016     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2017     glBindTexture(GL_TEXTURE_2D, 0);
2018 
2019     GLFramebuffer depthAndColorFBO;
2020     glBindFramebuffer(GL_FRAMEBUFFER, depthAndColorFBO);
2021     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
2022     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
2023     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2024 
2025     GLFramebuffer depthOnlyFBO;
2026     glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFBO);
2027     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
2028     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2029 
2030     // Draw to a first FBO to initialize the depth buffer.
2031     glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFBO);
2032     glEnable(GL_DEPTH_TEST);
2033     glUseProgram(redProgram);
2034     glDrawArrays(GL_TRIANGLES, 0, 6);
2035     ASSERT_GL_NO_ERROR();
2036 
2037     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
2038 
2039     // Start new RenderPass with depth write enabled and form the actual feedback loop.
2040     glBindFramebuffer(GL_FRAMEBUFFER, depthAndColorFBO);
2041     glDepthMask(true);
2042     glUseProgram(texProgram);
2043     glBindTexture(GL_TEXTURE_2D, depthTexture);
2044     glDrawArrays(GL_TRIANGLES, 0, 6);
2045     ASSERT_GL_NO_ERROR();
2046 
2047     // Now set up the read-only feedback loop.
2048     glDepthMask(false);
2049     glDrawArrays(GL_TRIANGLES, 0, 6);
2050     ASSERT_GL_NO_ERROR();
2051 
2052     uint64_t actualRenderPassCount = getPerfCounters().renderPasses;
2053     EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
2054 
2055     // Do a final write to depth to make sure we can switch out of read-only mode.
2056     glBindTexture(GL_TEXTURE_2D, 0);
2057     glDepthMask(GL_TRUE);
2058     glDrawArrays(GL_TRIANGLES, 0, 6);
2059     ASSERT_GL_NO_ERROR();
2060 }
2061 
2062 // Tests that invalidate followed by masked draws results in no load and store.
2063 //
2064 // - Scenario: invalidate, mask color, draw
TEST_P(VulkanPerformanceCounterTest,ColorInvalidateMaskDraw)2065 TEST_P(VulkanPerformanceCounterTest, ColorInvalidateMaskDraw)
2066 {
2067     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2068 
2069     angle::VulkanPerfCounters expected;
2070 
2071     // Expect rpCount+1, color(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1)
2072     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 0, 1, 0, 1, &expected);
2073 
2074     GLFramebuffer framebuffer;
2075     GLTexture texture;
2076     setupForColorOpsTest(&framebuffer, &texture);
2077 
2078     // Invalidate
2079     const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
2080     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
2081     ASSERT_GL_NO_ERROR();
2082 
2083     // Mask color output
2084     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
2085 
2086     // Draw
2087     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2088     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2089     ASSERT_GL_NO_ERROR();
2090 
2091     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2092 
2093     // Use swapBuffers and then check how many loads and stores were actually done
2094     swapBuffers();
2095     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
2096 
2097     // Start and end another render pass without color mask
2098     ++expected.renderPasses;
2099     ++expected.colorStoreOpStores;
2100 
2101     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2102     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2103     ASSERT_GL_NO_ERROR();
2104     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2105 
2106     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
2107 }
2108 
2109 // Test glFenceSync followed by glInvalidateFramebuffer should still allow storeOp being optimized
2110 // out.
TEST_P(VulkanPerformanceCounterTest,FenceSyncAndColorInvalidate)2111 TEST_P(VulkanPerformanceCounterTest, FenceSyncAndColorInvalidate)
2112 {
2113     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2114 
2115     angle::VulkanPerfCounters expected;
2116 
2117     // Expect rpCount+1, color(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
2118     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 0, 0, 0, 0, &expected);
2119 
2120     GLFramebuffer framebuffer;
2121     GLTexture texture;
2122     setupForColorOpsTest(&framebuffer, &texture);
2123 
2124     // Draw
2125     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2126     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2127     ASSERT_GL_NO_ERROR();
2128 
2129     // Insert a fence which should trigger a deferred renderPass end
2130     GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
2131 
2132     // Invalidate FBO. This should still allow vulkan backend to optimize out the storeOp, even
2133     // though we just called glFenceSync .
2134     const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
2135     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
2136     ASSERT_GL_NO_ERROR();
2137 
2138     // Use swapBuffers and then check how many loads and stores were actually done
2139     swapBuffers();
2140     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
2141     glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
2142 }
2143 // Tests that invalidate followed by discarded draws results in no load and store.
2144 //
2145 // - Scenario: invalidate, rasterizer discard, draw
TEST_P(VulkanPerformanceCounterTest,ColorInvalidateDiscardDraw)2146 TEST_P(VulkanPerformanceCounterTest, ColorInvalidateDiscardDraw)
2147 {
2148     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2149 
2150     angle::VulkanPerfCounters expected;
2151 
2152     // Expect rpCount+1, color(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1)
2153     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 0, 1, 0, 1, &expected);
2154 
2155     GLFramebuffer framebuffer;
2156     GLTexture texture;
2157     setupForColorOpsTest(&framebuffer, &texture);
2158 
2159     // Invalidate
2160     const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
2161     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
2162     ASSERT_GL_NO_ERROR();
2163 
2164     // Mask color output
2165     glEnable(GL_RASTERIZER_DISCARD);
2166 
2167     // Draw
2168     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2169     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2170     ASSERT_GL_NO_ERROR();
2171 
2172     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2173 
2174     // Use swapBuffers and then check how many loads and stores were actually done
2175     swapBuffers();
2176     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
2177 
2178     // Start and end another render pass without color mask
2179     ++expected.renderPasses;
2180     ++expected.colorStoreOpStores;
2181 
2182     glDisable(GL_RASTERIZER_DISCARD);
2183     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2184     ASSERT_GL_NO_ERROR();
2185     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2186 
2187     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
2188 }
2189 
2190 // Tests that masked draws results in no load and store.
2191 //
2192 // - Scenario: mask color, draw
TEST_P(VulkanPerformanceCounterTest,ColorMaskedDraw)2193 TEST_P(VulkanPerformanceCounterTest, ColorMaskedDraw)
2194 {
2195     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2196 
2197     angle::VulkanPerfCounters expected;
2198 
2199     // Expect rpCount+1, color(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1)
2200     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 0, 1, 0, 1, &expected);
2201 
2202     GLFramebuffer framebuffer;
2203     GLTexture texture;
2204     setupForColorOpsTest(&framebuffer, &texture);
2205 
2206     // Initialize the color buffer
2207     glClearColor(1, 0, 0, 1);
2208     glClear(GL_COLOR_BUFFER_BIT);
2209     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2210 
2211     // Mask color output
2212     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
2213 
2214     // Draw
2215     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2216     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2217     ASSERT_GL_NO_ERROR();
2218 
2219     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2220 
2221     // Break the render pass and check how many loads and stores were actually done
2222     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2223     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
2224 
2225     // Start and end another render pass without color mask
2226     ++expected.renderPasses;
2227     ++expected.colorLoadOpLoads;
2228     ++expected.colorStoreOpStores;
2229 
2230     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2231     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2232     ASSERT_GL_NO_ERROR();
2233     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2234 
2235     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
2236 }
2237 
2238 // Tests that discarded draws results in no load and store.
2239 //
2240 // - Scenario: rasterizer discard, draw
TEST_P(VulkanPerformanceCounterTest,ColorDiscardDraw)2241 TEST_P(VulkanPerformanceCounterTest, ColorDiscardDraw)
2242 {
2243     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2244 
2245     angle::VulkanPerfCounters expected;
2246 
2247     // Expect rpCount+1, color(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1)
2248     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 0, 1, 0, 1, &expected);
2249 
2250     GLFramebuffer framebuffer;
2251     GLTexture texture;
2252     setupForColorOpsTest(&framebuffer, &texture);
2253 
2254     // Initialize the color buffer
2255     glClearColor(1, 0, 0, 1);
2256     glClear(GL_COLOR_BUFFER_BIT);
2257     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2258 
2259     // Mask color output
2260     glEnable(GL_RASTERIZER_DISCARD);
2261 
2262     // Draw
2263     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2264     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2265     ASSERT_GL_NO_ERROR();
2266 
2267     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2268 
2269     // Break the render pass and check how many loads and stores were actually done
2270     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2271     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
2272 
2273     // Start and end another render pass without color mask
2274     ++expected.renderPasses;
2275     ++expected.colorLoadOpLoads;
2276     ++expected.colorStoreOpStores;
2277 
2278     glDisable(GL_RASTERIZER_DISCARD);
2279     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2280     ASSERT_GL_NO_ERROR();
2281     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2282 
2283     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
2284 }
2285 
2286 // Test that read-only color usage results in load but no store.
2287 //
2288 // - Scenario: mask color, framebuffer fetch draw
TEST_P(VulkanPerformanceCounterTest_ES31,ColorMaskedFramebufferFetchDraw)2289 TEST_P(VulkanPerformanceCounterTest_ES31, ColorMaskedFramebufferFetchDraw)
2290 {
2291     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2292     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent"));
2293 
2294     angle::VulkanPerfCounters expected;
2295 
2296     // Expect rpCount+1, color(Clears+0, Loads+1, LoadNones+0, Stores+0, StoreNones+1)
2297     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 1, 0, 0, 1, &expected);
2298 
2299     GLFramebuffer framebuffer;
2300     GLTexture texture;
2301     setupForColorOpsTest(&framebuffer, &texture);
2302 
2303     GLBuffer buffer;
2304     const GLColor kClearColor(40, 70, 100, 150);
2305     maskedFramebufferFetchDraw(kClearColor, buffer);
2306 
2307     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2308 
2309     // Break the render pass and check how many loads and stores were actually done
2310     EXPECT_PIXEL_COLOR_NEAR(0, 0, kClearColor, 1);
2311 
2312     maskedFramebufferFetchDrawVerify(kClearColor, buffer);
2313     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
2314 }
2315 
2316 // Tests that clear after masked draws is optimized to use loadOp
2317 //
2318 // - Scenario: clear, mask color, draw, clear
TEST_P(VulkanPerformanceCounterTest,ColorClearMaskedDrawThenClear)2319 TEST_P(VulkanPerformanceCounterTest, ColorClearMaskedDrawThenClear)
2320 {
2321     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2322 
2323     angle::VulkanPerfCounters expected;
2324 
2325     // Expect rpCount+1, color(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
2326     // No vkCmdClearAttachments should be issued.
2327     setExpectedCountersForColorOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
2328     expected.colorClearAttachments = getPerfCounters().colorClearAttachments;
2329 
2330     GLFramebuffer framebuffer;
2331     GLTexture texture;
2332     setupForColorOpsTest(&framebuffer, &texture);
2333 
2334     // Clear color first
2335     glClearColor(1, 0, 0, 1);
2336     glClear(GL_COLOR_BUFFER_BIT);
2337 
2338     // Mask color output
2339     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
2340 
2341     // Draw
2342     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2343     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2344     ASSERT_GL_NO_ERROR();
2345 
2346     // Then clear color again.  This clear is moved up to loadOp, overriding the initial clear.
2347     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2348     glClearColor(0, 0, 1, 1);
2349     glClear(GL_COLOR_BUFFER_BIT);
2350 
2351     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2352 
2353     // Break the render pass and check how many loads and stores were actually done
2354     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2355     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
2356     EXPECT_CLEAR_ATTACHMENTS_COUNTER(expected.colorClearAttachments,
2357                                      getPerfCounters().colorClearAttachments);
2358 }
2359 
2360 // Test that clear of read-only color is not reordered with the draw.
2361 //
2362 // - Scenario: mask color, framebuffer fetch draw, clear
TEST_P(VulkanPerformanceCounterTest_ES31,ColorMaskedFramebufferFetchDrawThenClear)2363 TEST_P(VulkanPerformanceCounterTest_ES31, ColorMaskedFramebufferFetchDrawThenClear)
2364 {
2365     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2366     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent"));
2367 
2368     angle::VulkanPerfCounters expected;
2369 
2370     // Expect rpCount+1, color(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0)
2371     // vkCmdClearAttachments should be used for the second clear.
2372     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 1, 0, 1, 0, &expected);
2373     expected.colorClearAttachments = getPerfCounters().colorClearAttachments + 1;
2374 
2375     GLFramebuffer framebuffer;
2376     GLTexture texture;
2377     setupForColorOpsTest(&framebuffer, &texture);
2378 
2379     GLBuffer buffer;
2380     const GLColor kClearColor(40, 70, 100, 150);
2381     maskedFramebufferFetchDraw(kClearColor, buffer);
2382 
2383     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2384     glClearColor(1, 0, 0, 1);
2385     glClear(GL_COLOR_BUFFER_BIT);
2386 
2387     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2388 
2389     // Break the render pass and check how many loads and stores were actually done
2390     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2391 
2392     maskedFramebufferFetchDrawVerify(kClearColor, buffer);
2393     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
2394     EXPECT_CLEAR_ATTACHMENTS_COUNTER(expected.colorClearAttachments,
2395                                      getPerfCounters().colorClearAttachments);
2396 }
2397 
2398 // Test that masked draw after a framebuffer fetch render pass doesn't load color.
2399 //
2400 // - Scenario: framebuffer fetch render pass, mask color, normal draw
TEST_P(VulkanPerformanceCounterTest_ES31,FramebufferFetchRenderPassThenColorMaskedDraw)2401 TEST_P(VulkanPerformanceCounterTest_ES31, FramebufferFetchRenderPassThenColorMaskedDraw)
2402 {
2403     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2404     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_framebuffer_fetch_non_coherent"));
2405 
2406     angle::VulkanPerfCounters expected;
2407 
2408     // Expect rpCount+1, color(Clears+0, Loads+1, LoadNones+0, Stores+0, StoreNones+1)
2409     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 1, 0, 0, 1, &expected);
2410 
2411     GLFramebuffer framebuffer;
2412     GLTexture texture;
2413     setupForColorOpsTest(&framebuffer, &texture);
2414 
2415     GLBuffer buffer;
2416     const GLColor kClearColor(40, 70, 100, 150);
2417     maskedFramebufferFetchDraw(kClearColor, buffer);
2418 
2419     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2420 
2421     // Break the render pass and check how many loads and stores were actually done
2422     EXPECT_PIXEL_COLOR_NEAR(0, 0, kClearColor, 1);
2423 
2424     maskedFramebufferFetchDrawVerify(kClearColor, buffer);
2425     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
2426 
2427     // Start another render pass, and don't use framebuffer fetch.  Color is masked, so it should be
2428     // neither loaded nor stored.
2429 
2430     // Expect rpCount+1, color(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1)
2431     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 0, 1, 0, 1, &expected);
2432 
2433     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
2434 
2435     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2436     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2437     ASSERT_GL_NO_ERROR();
2438 
2439     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2440 
2441     // Break the render pass and check how many loads and stores were actually done
2442     EXPECT_PIXEL_COLOR_NEAR(0, 0, kClearColor, 1);
2443     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
2444 }
2445 
2446 // Tests that clear after unused depth/stencil is optimized to use loadOp
2447 //
2448 // - Scenario: disable depth/stencil, draw, clear
TEST_P(VulkanPerformanceCounterTest,DepthStencilMaskedDrawThenClear)2449 TEST_P(VulkanPerformanceCounterTest, DepthStencilMaskedDrawThenClear)
2450 {
2451     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2452 
2453     // This optimization is not implemented when this workaround is in effect.
2454     ANGLE_SKIP_TEST_IF(hasPreferDrawOverClearAttachments());
2455 
2456     angle::VulkanPerfCounters expected;
2457 
2458     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0),
2459     // stencil(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
2460     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
2461     setExpectedCountersForStencilOps(getPerfCounters(), 1, 0, 0, 1, 0, &expected);
2462 
2463     // No vkCmdClearAttachments should be issued.
2464     expected.depthClearAttachments   = getPerfCounters().depthClearAttachments;
2465     expected.stencilClearAttachments = getPerfCounters().stencilClearAttachments;
2466 
2467     GLFramebuffer framebuffer;
2468     GLTexture texture;
2469     GLRenderbuffer renderbuffer;
2470     setupForDepthStencilOpsTest(&framebuffer, &texture, &renderbuffer);
2471 
2472     // Disable depth/stencil
2473     glDisable(GL_DEPTH_TEST);
2474     glDisable(GL_STENCIL_TEST);
2475 
2476     // Issue a draw call
2477     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2478     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2479 
2480     // Clear depth/stencil
2481     glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2482 
2483     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2484 
2485     // Break the render pass and check how many loads and stores were actually done
2486     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2487     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
2488     EXPECT_CLEAR_ATTACHMENTS_COUNTER(expected.depthClearAttachments,
2489                                      getPerfCounters().depthClearAttachments);
2490     EXPECT_CLEAR_ATTACHMENTS_COUNTER(expected.stencilClearAttachments,
2491                                      getPerfCounters().depthClearAttachments);
2492 }
2493 
2494 // Tests that depth compare function change, get correct loadop for depth buffer
2495 //
2496 // - Scenario: depth test enabled, depth write mask = 0,
2497 //   clear depth, draw red quad with compare function always,
2498 //   and then  draw green quad with compare function less equal
TEST_P(VulkanPerformanceCounterTest,DepthFunctionDynamicChangeLoadOp)2499 TEST_P(VulkanPerformanceCounterTest, DepthFunctionDynamicChangeLoadOp)
2500 {
2501     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2502 
2503     // This optimization is not implemented when this workaround is in effect.
2504     ANGLE_SKIP_TEST_IF(hasPreferDrawOverClearAttachments());
2505 
2506     angle::VulkanPerfCounters expected;
2507 
2508     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0),
2509     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 0, 0, &expected);
2510 
2511     GLFramebuffer framebuffer;
2512     GLTexture texture;
2513     GLRenderbuffer renderbuffer;
2514     setupForColorDepthOpsTest(&framebuffer, &texture, &renderbuffer);
2515 
2516     // Clear color and depth.
2517     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2518 
2519     // No depth write
2520     glDepthMask(GL_FALSE);
2521     // Depth function always
2522     glDepthFunc(GL_ALWAYS);
2523 
2524     // Draw read quad.
2525     ANGLE_GL_PROGRAM(redprogram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2526     drawQuad(redprogram, essl1_shaders::PositionAttrib(), 0.5f);
2527 
2528     // Depth function switch to less equal
2529     glDepthFunc(GL_LEQUAL);
2530 
2531     // Draw green quad.
2532     ANGLE_GL_PROGRAM(greenprogram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2533     drawQuad(greenprogram, essl1_shaders::PositionAttrib(), 0.7f);
2534 
2535     GLenum attachments = GL_DEPTH_ATTACHMENT;
2536     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &attachments);
2537 
2538     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2539 
2540     // Break the render pass and check how many clears were actually done
2541     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2542     EXPECT_CLEAR_ATTACHMENTS_COUNTER(expected.depthLoadOpClears,
2543                                      getPerfCounters().depthLoadOpClears);
2544 }
2545 
2546 // Tests that common PUBG MOBILE case does not break render pass, and that counts are correct:
2547 //
2548 // - Scenario: invalidate, disable, draw
TEST_P(VulkanPerformanceCounterTest,DepthStencilInvalidateDisableDraw)2549 TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDisableDraw)
2550 {
2551     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2552 
2553     angle::VulkanPerfCounters expected;
2554 
2555     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0),
2556     // stencil(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
2557     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 0, 0, &expected);
2558     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected);
2559 
2560     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2561     GLFramebuffer framebuffer;
2562     GLTexture texture;
2563     GLRenderbuffer renderbuffer;
2564     setupClearAndDrawForDepthStencilOpsTest(&program, &framebuffer, &texture, &renderbuffer, false);
2565 
2566     // Execute the scenario that this test is for:
2567 
2568     // Invalidate (storeOp = DONT_CARE; mContentDefined = false)
2569     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2570     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
2571     ASSERT_GL_NO_ERROR();
2572 
2573     // Disable (shouldn't change result)
2574     glDisable(GL_DEPTH_TEST);
2575     glDisable(GL_STENCIL_TEST);
2576 
2577     // Draw (since disabled, shouldn't change result)
2578     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2579     ASSERT_GL_NO_ERROR();
2580 
2581     // Ensure that the render pass wasn't broken
2582     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2583 
2584     // Use swapBuffers and then check how many loads and stores were actually done
2585     swapBuffers();
2586     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
2587 
2588     // Start and end another render pass, to check that the load ops are as expected
2589     setAndIncrementDepthStencilLoadCountersForOpsTest(getPerfCounters(), 0, 0, &expected);
2590     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2591     ASSERT_GL_NO_ERROR();
2592     swapBuffers();
2593     EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(getPerfCounters(), expected);
2594 }
2595 
2596 // Tests that alternative PUBG MOBILE case does not break render pass, and that counts are correct:
2597 //
2598 // - Scenario: disable, invalidate, draw
TEST_P(VulkanPerformanceCounterTest,DisableInvalidateDraw)2599 TEST_P(VulkanPerformanceCounterTest, DisableInvalidateDraw)
2600 {
2601     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2602 
2603     angle::VulkanPerfCounters expected;
2604 
2605     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0),
2606     // stencil(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
2607     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 0, 0, &expected);
2608     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected);
2609 
2610     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2611     GLFramebuffer framebuffer;
2612     GLTexture texture;
2613     GLRenderbuffer renderbuffer;
2614     setupClearAndDrawForDepthStencilOpsTest(&program, &framebuffer, &texture, &renderbuffer, false);
2615 
2616     // Execute the scenario that this test is for:
2617 
2618     // Disable (shouldn't change result)
2619     glDisable(GL_DEPTH_TEST);
2620     glDisable(GL_STENCIL_TEST);
2621 
2622     // Invalidate (storeOp = DONT_CARE; mContentDefined = false)
2623     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2624     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
2625     ASSERT_GL_NO_ERROR();
2626 
2627     // Draw (since disabled, shouldn't change result)
2628     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2629     ASSERT_GL_NO_ERROR();
2630 
2631     // Ensure that the render pass wasn't broken
2632     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2633 
2634     // Use swapBuffers and then check how many loads and stores were actually done
2635     swapBuffers();
2636     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
2637 
2638     // Start and end another render pass, to check that the load ops are as expected
2639     setAndIncrementDepthStencilLoadCountersForOpsTest(getPerfCounters(), 0, 0, &expected);
2640     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2641     ASSERT_GL_NO_ERROR();
2642     swapBuffers();
2643     EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(getPerfCounters(), expected);
2644 }
2645 
2646 // Tests that another case does not break render pass, and that counts are correct:
2647 //
2648 // - Scenario: disable, draw, invalidate, enable
TEST_P(VulkanPerformanceCounterTest,DisableDrawInvalidateEnable)2649 TEST_P(VulkanPerformanceCounterTest, DisableDrawInvalidateEnable)
2650 {
2651     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2652 
2653     angle::VulkanPerfCounters expected;
2654 
2655     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0),
2656     // stencil(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
2657     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 0, 0, &expected);
2658     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected);
2659 
2660     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2661     GLFramebuffer framebuffer;
2662     GLTexture texture;
2663     GLRenderbuffer renderbuffer;
2664     setupClearAndDrawForDepthStencilOpsTest(&program, &framebuffer, &texture, &renderbuffer, false);
2665 
2666     // Execute the scenario that this test is for:
2667 
2668     // Note: setupClearAndDrawForDepthStencilOpsTest() did an enable and draw
2669 
2670     // Disable (since not invalidated, shouldn't change result)
2671     glDisable(GL_DEPTH_TEST);
2672     glDisable(GL_STENCIL_TEST);
2673 
2674     // Draw (since not invalidated, shouldn't change result)
2675     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2676     ASSERT_GL_NO_ERROR();
2677 
2678     // Invalidate (should result: in storeOp = DONT_CARE; mContentDefined = false)
2679     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2680     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
2681     ASSERT_GL_NO_ERROR();
2682 
2683     // Enable (shouldn't change result)
2684     glEnable(GL_DEPTH_TEST);
2685     glEnable(GL_STENCIL_TEST);
2686     // Note: The above enable calls will be ignored, since no drawing was done to force the enable
2687     // dirty bit to be processed
2688 
2689     // Ensure that the render pass wasn't broken
2690     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2691 
2692     // Break the render pass by reading back a pixel.
2693     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2694 
2695     // Use swapBuffers and then check how many loads and stores were actually done
2696     swapBuffers();
2697     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
2698 
2699     // Start and end another render pass, to check that the load ops are as expected
2700     setAndIncrementDepthStencilLoadCountersForOpsTest(getPerfCounters(), 0, 0, &expected);
2701     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2702     ASSERT_GL_NO_ERROR();
2703     swapBuffers();
2704     EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(getPerfCounters(), expected);
2705 }
2706 
2707 // Tests that common TRex case does not break render pass, and that counts are correct:
2708 //
2709 // - Scenario: invalidate
TEST_P(VulkanPerformanceCounterTest,DepthStencilInvalidate)2710 TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidate)
2711 {
2712     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2713 
2714     angle::VulkanPerfCounters expected;
2715 
2716     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0),
2717     // stencil(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
2718     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 0, 0, &expected);
2719     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected);
2720 
2721     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2722     GLFramebuffer framebuffer;
2723     GLTexture texture;
2724     GLRenderbuffer renderbuffer;
2725     setupClearAndDrawForDepthStencilOpsTest(&program, &framebuffer, &texture, &renderbuffer, false);
2726 
2727     // Execute the scenario that this test is for:
2728 
2729     // Invalidate (storeOp = DONT_CARE; mContentDefined = false)
2730     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2731     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
2732     ASSERT_GL_NO_ERROR();
2733 
2734     // Ensure that the render pass wasn't broken
2735     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2736 
2737     // Use swapBuffers and then check how many loads and stores were actually done
2738     swapBuffers();
2739     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
2740 
2741     // Start and end another render pass, to check that the load ops are as expected
2742     setAndIncrementDepthStencilLoadCountersForOpsTest(getPerfCounters(), 0, 0, &expected);
2743     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2744     ASSERT_GL_NO_ERROR();
2745     swapBuffers();
2746     EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(getPerfCounters(), expected);
2747 }
2748 
2749 // Similar to Invalidate, but uses glInvalidateSubFramebuffer such that the given area covers the
2750 // whole framebuffer.
TEST_P(VulkanPerformanceCounterTest,DepthStencilInvalidateSub)2751 TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateSub)
2752 {
2753     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2754 
2755     angle::VulkanPerfCounters expected;
2756 
2757     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0),
2758     // stencil(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
2759     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 0, 0, &expected);
2760     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected);
2761 
2762     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2763     GLFramebuffer framebuffer;
2764     GLTexture texture;
2765     GLRenderbuffer renderbuffer;
2766     setupClearAndDrawForDepthStencilOpsTest(&program, &framebuffer, &texture, &renderbuffer, false);
2767 
2768     // Execute the scenario that this test is for:
2769 
2770     // Invalidate (storeOp = DONT_CARE; mContentDefined = false)
2771     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2772     glInvalidateSubFramebuffer(GL_FRAMEBUFFER, 2, discards, -100, -100, kOpsTestSize + 200,
2773                                kOpsTestSize + 200);
2774     ASSERT_GL_NO_ERROR();
2775 
2776     // Ensure that the render pass wasn't broken
2777     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2778 
2779     // Use swapBuffers and then check how many loads and stores were actually done
2780     swapBuffers();
2781     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
2782 
2783     // Start and end another render pass, to check that the load ops are as expected
2784     setAndIncrementDepthStencilLoadCountersForOpsTest(getPerfCounters(), 0, 0, &expected);
2785     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2786     ASSERT_GL_NO_ERROR();
2787     swapBuffers();
2788     EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(getPerfCounters(), expected);
2789 }
2790 
2791 // Similar to InvalidateSub, but uses glInvalidateSubFramebuffer such that the given area does NOT
2792 // covers the whole framebuffer.
TEST_P(VulkanPerformanceCounterTest,DepthStencilPartialInvalidateSub)2793 TEST_P(VulkanPerformanceCounterTest, DepthStencilPartialInvalidateSub)
2794 {
2795     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2796 
2797     angle::VulkanPerfCounters expected;
2798 
2799     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0),
2800     // stencil(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
2801     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
2802     setExpectedCountersForStencilOps(getPerfCounters(), 1, 0, 0, 1, 0, &expected);
2803 
2804     // Create the framebuffer and make sure depth/stencil have valid contents.
2805     ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2806     GLFramebuffer framebuffer;
2807     GLTexture texture;
2808     GLRenderbuffer renderbuffer;
2809     setupClearAndDrawForDepthStencilOpsTest(&drawRed, &framebuffer, &texture, &renderbuffer, true);
2810 
2811     // Break the render pass so depth/stencil values are stored.
2812     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2813     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2814     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
2815 
2816     // Start a new render pass that is scissored.  Depth/stencil should be loaded.  The draw call is
2817     // followed by an invalidate, so store shouldn't happen.
2818 
2819     // Expect rpCount+1, depth(Clears+0, Loads+1, LoadNones+0, Stores+0, StoreNones+0),
2820     // stencil(Clears+0, Loads+1, LoadNones+0, Stores+0, StoreNones+0)
2821     setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 1, 0, 0, 0, &expected);
2822     setExpectedCountersForStencilOps(getPerfCounters(), 0, 1, 0, 0, 0, &expected);
2823 
2824     glEnable(GL_SCISSOR_TEST);
2825     glScissor(kOpsTestSize / 8, kOpsTestSize / 4, kOpsTestSize / 2, kOpsTestSize / 3);
2826 
2827     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
2828     glStencilFunc(GL_ALWAYS, 0x55, 0xFF);
2829     glDepthFunc(GL_ALWAYS);
2830 
2831     ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2832     drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.5f);
2833     ASSERT_GL_NO_ERROR();
2834 
2835     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2836     glInvalidateSubFramebuffer(GL_FRAMEBUFFER, 2, discards, kOpsTestSize / 8, kOpsTestSize / 8,
2837                                7 * kOpsTestSize / 8, 7 * kOpsTestSize / 8);
2838 
2839     // Break the render pass so depth/stencil values are discarded.
2840     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2841     EXPECT_PIXEL_COLOR_EQ(kOpsTestSize / 2, kOpsTestSize / 2, GLColor::green);
2842     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
2843 
2844     // Start another render pass without scissor.  Because parts of the framebuffer attachments were
2845     // not invalidated, depth/stencil should be loaded.
2846 
2847     // Expect rpCount+1, depth(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0),
2848     // stencil(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0)
2849     setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 1, 0, 1, 0, &expected);
2850     setExpectedCountersForStencilOps(getPerfCounters(), 0, 1, 0, 1, 0, &expected);
2851 
2852     glDisable(GL_SCISSOR_TEST);
2853 
2854     ANGLE_GL_PROGRAM(drawBlue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
2855     drawQuad(drawBlue, essl1_shaders::PositionAttrib(), 0.5f);
2856     ASSERT_GL_NO_ERROR();
2857 
2858     // Verify results
2859     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2860     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2861     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
2862 }
2863 
2864 // Tests that another case does not break render pass, and that counts are correct:
2865 //
2866 // - Scenario: invalidate, draw
TEST_P(VulkanPerformanceCounterTest,DepthStencilInvalidateDraw)2867 TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDraw)
2868 {
2869     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2870 
2871     angle::VulkanPerfCounters expected;
2872 
2873     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0),
2874     // stencil(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
2875     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
2876     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected);
2877 
2878     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2879     GLFramebuffer framebuffer;
2880     GLTexture texture;
2881     GLRenderbuffer renderbuffer;
2882     setupClearAndDrawForDepthStencilOpsTest(&program, &framebuffer, &texture, &renderbuffer, false);
2883 
2884     // Execute the scenario that this test is for:
2885 
2886     // Invalidate (should result: in storeOp = DONT_CARE; mContentDefined = false)
2887     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2888     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
2889     ASSERT_GL_NO_ERROR();
2890 
2891     // Draw (since enabled, should result: in storeOp = STORE; mContentDefined = true)
2892     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2893     ASSERT_GL_NO_ERROR();
2894 
2895     // Ensure that the render pass wasn't broken
2896     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2897 
2898     // Use swapBuffers and then check how many loads and stores were actually done
2899     swapBuffers();
2900     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
2901 
2902     // Start and end another render pass, to check that the load ops are as expected
2903     setAndIncrementDepthStencilLoadCountersForOpsTest(getPerfCounters(), 1, 0, &expected);
2904     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2905     ASSERT_GL_NO_ERROR();
2906     swapBuffers();
2907     EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(getPerfCounters(), expected);
2908 }
2909 
2910 // Tests that another case does not break render pass, and that counts are correct:
2911 //
2912 // - Scenario: invalidate, draw, disable
TEST_P(VulkanPerformanceCounterTest,DepthStencilInvalidateDrawDisable)2913 TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDrawDisable)
2914 {
2915     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2916 
2917     // http://anglebug.com/6857
2918     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsVulkan());
2919 
2920     angle::VulkanPerfCounters expected;
2921 
2922     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0),
2923     // stencil(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1)
2924     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
2925     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 1, 0, 1, &expected);
2926 
2927     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2928     GLFramebuffer framebuffer;
2929     GLTexture texture;
2930     GLRenderbuffer renderbuffer;
2931     setupClearAndDrawForDepthStencilOpsTest(&program, &framebuffer, &texture, &renderbuffer, false);
2932 
2933     // Execute the scenario that this test is for:
2934 
2935     // Invalidate (should result: in storeOp = DONT_CARE; mContentDefined = false)
2936     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2937     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
2938     ASSERT_GL_NO_ERROR();
2939 
2940     // Draw (since enabled, should result: in storeOp = STORE; mContentDefined = true)
2941     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2942     ASSERT_GL_NO_ERROR();
2943 
2944     // Disable (shouldn't change result)
2945     glDisable(GL_DEPTH_TEST);
2946     glDisable(GL_STENCIL_TEST);
2947     // Note: this draw is just so that the disable dirty bits will be processed
2948     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2949     ASSERT_GL_NO_ERROR();
2950 
2951     // Ensure that the render pass wasn't broken
2952     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
2953 
2954     // Break the render pass and then check how many loads and stores were actually done
2955     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2956     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
2957 
2958     // Start and end another render pass, to check that the load ops are as expected
2959     setAndIncrementDepthStencilLoadCountersForOpsTest(getPerfCounters(), 1, 1, &expected);
2960     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2961     ASSERT_GL_NO_ERROR();
2962     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2963     EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(getPerfCounters(), expected);
2964 }
2965 
2966 // Tests that another case does not break render pass, and that counts are correct:
2967 //
2968 // - Scenario: invalidate, disable, draw, enable
TEST_P(VulkanPerformanceCounterTest,DepthStencilInvalidateDisableDrawEnable)2969 TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDisableDrawEnable)
2970 {
2971     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
2972 
2973     angle::VulkanPerfCounters expected;
2974 
2975     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0),
2976     // stencil(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
2977     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 0, 0, &expected);
2978     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected);
2979 
2980     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2981     GLFramebuffer framebuffer;
2982     GLTexture texture;
2983     GLRenderbuffer renderbuffer;
2984     setupClearAndDrawForDepthStencilOpsTest(&program, &framebuffer, &texture, &renderbuffer, false);
2985 
2986     // Execute the scenario that this test is for:
2987 
2988     // Invalidate (should result: in storeOp = DONT_CARE; mContentDefined = false)
2989     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2990     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
2991     ASSERT_GL_NO_ERROR();
2992 
2993     // Disable (shouldn't change result)
2994     glDisable(GL_DEPTH_TEST);
2995     glDisable(GL_STENCIL_TEST);
2996 
2997     // Draw (since disabled, shouldn't change result)
2998     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2999     ASSERT_GL_NO_ERROR();
3000 
3001     // Enable (shouldn't change result)
3002     glEnable(GL_DEPTH_TEST);
3003     glEnable(GL_STENCIL_TEST);
3004     // Note: The above enable calls will be ignored, since no drawing was done to force the enable
3005     // dirty bit to be processed
3006 
3007     // Ensure that the render pass wasn't broken
3008     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
3009 
3010     // Use swapBuffers and then check how many loads and stores were actually done
3011     swapBuffers();
3012     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3013 
3014     // Start and end another render pass, to check that the load ops are as expected
3015     setAndIncrementDepthStencilLoadCountersForOpsTest(getPerfCounters(), 0, 0, &expected);
3016     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3017     ASSERT_GL_NO_ERROR();
3018     swapBuffers();
3019     EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(getPerfCounters(), expected);
3020 }
3021 
3022 // Tests that another case does not break render pass, and that counts are correct:
3023 //
3024 // - Scenario: invalidate, disable, draw, enable, draw
TEST_P(VulkanPerformanceCounterTest,DepthStencilInvalidateDisableDrawEnableDraw)3025 TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDisableDrawEnableDraw)
3026 {
3027     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3028 
3029     angle::VulkanPerfCounters expected;
3030 
3031     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0),
3032     // stencil(Clears+0, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
3033     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
3034     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 1, 0, &expected);
3035 
3036     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3037     GLFramebuffer framebuffer;
3038     GLTexture texture;
3039     GLRenderbuffer renderbuffer;
3040     setupClearAndDrawForDepthStencilOpsTest(&program, &framebuffer, &texture, &renderbuffer, false);
3041 
3042     // Execute the scenario that this test is for:
3043 
3044     // Invalidate (should result: in storeOp = DONT_CARE; mContentDefined = false)
3045     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
3046     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
3047     ASSERT_GL_NO_ERROR();
3048 
3049     // Disable (shouldn't change result)
3050     glDisable(GL_DEPTH_TEST);
3051     glDisable(GL_STENCIL_TEST);
3052 
3053     // Draw (since disabled, shouldn't change result)
3054     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3055     ASSERT_GL_NO_ERROR();
3056 
3057     // Enable (shouldn't change result)
3058     glEnable(GL_DEPTH_TEST);
3059     glEnable(GL_STENCIL_TEST);
3060     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
3061 
3062     // Draw (since enabled, should result: in storeOp = STORE; mContentDefined = true)
3063     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3064     ASSERT_GL_NO_ERROR();
3065 
3066     // Ensure that the render pass wasn't broken
3067     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
3068 
3069     // Break the render pass and then check how many loads and stores were actually done
3070     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3071     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3072 
3073     // Start and end another render pass, to check that the load ops are as expected
3074     setAndIncrementDepthStencilLoadCountersForOpsTest(getPerfCounters(), 1, 1, &expected);
3075     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3076     ASSERT_GL_NO_ERROR();
3077     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3078     EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(getPerfCounters(), expected);
3079 }
3080 
3081 // Tests that another case does not break render pass, and that counts are correct:
3082 //
3083 // - Scenario: invalidate, draw, disable, enable
TEST_P(VulkanPerformanceCounterTest,DepthStencilInvalidateDrawDisableEnable)3084 TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDrawDisableEnable)
3085 {
3086     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3087 
3088     angle::VulkanPerfCounters expected;
3089 
3090     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0),
3091     // stencil(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1)
3092     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
3093     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 1, 0, 1, &expected);
3094 
3095     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3096     GLFramebuffer framebuffer;
3097     GLTexture texture;
3098     GLRenderbuffer renderbuffer;
3099     setupClearAndDrawForDepthStencilOpsTest(&program, &framebuffer, &texture, &renderbuffer, false);
3100 
3101     // Execute the scenario that this test is for:
3102 
3103     // Invalidate (should result: in storeOp = DONT_CARE; mContentDefined = false)
3104     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
3105     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
3106     ASSERT_GL_NO_ERROR();
3107 
3108     // Draw (since enabled, should result: in storeOp = STORE; mContentDefined = true)
3109     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3110     ASSERT_GL_NO_ERROR();
3111 
3112     // Disable (shouldn't change result)
3113     glDisable(GL_DEPTH_TEST);
3114     glDisable(GL_STENCIL_TEST);
3115     // Note: this draw is just so that the disable dirty bits will be processed
3116     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3117     ASSERT_GL_NO_ERROR();
3118 
3119     // Enable (shouldn't change result)
3120     glEnable(GL_DEPTH_TEST);
3121     glEnable(GL_STENCIL_TEST);
3122     // Note: The above enable calls will be ignored, since no drawing was done to force the enable
3123     // dirty bit to be processed
3124 
3125     // Ensure that the render pass wasn't broken
3126     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
3127 
3128     // Break the render pass and then check how many loads and stores were actually done
3129     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3130     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3131 
3132     // Start and end another render pass, to check that the load ops are as expected
3133     setAndIncrementDepthStencilLoadCountersForOpsTest(getPerfCounters(), 1, 0, &expected);
3134     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3135     ASSERT_GL_NO_ERROR();
3136     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3137     EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(getPerfCounters(), expected);
3138 }
3139 
3140 // Tests that another case does not break render pass, and that counts are correct:
3141 //
3142 // - Scenario: invalidate, draw, disable, enable, invalidate
TEST_P(VulkanPerformanceCounterTest,DepthStencilInvalidateDrawDisableEnableInvalidate)3143 TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDrawDisableEnableInvalidate)
3144 {
3145     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3146 
3147     angle::VulkanPerfCounters expected;
3148 
3149     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0),
3150     // stencil(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
3151     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 0, 0, &expected);
3152     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected);
3153 
3154     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3155     GLFramebuffer framebuffer;
3156     GLTexture texture;
3157     GLRenderbuffer renderbuffer;
3158     setupClearAndDrawForDepthStencilOpsTest(&program, &framebuffer, &texture, &renderbuffer, false);
3159 
3160     // Execute the scenario that this test is for:
3161 
3162     // Invalidate (should result: in storeOp = DONT_CARE; mContentDefined = false)
3163     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
3164     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
3165     ASSERT_GL_NO_ERROR();
3166 
3167     // Draw (since enabled, should result: in storeOp = STORE; mContentDefined = true)
3168     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3169     ASSERT_GL_NO_ERROR();
3170 
3171     // Disable (shouldn't change result)
3172     glDisable(GL_DEPTH_TEST);
3173     glDisable(GL_STENCIL_TEST);
3174     // Note: this draw is just so that the disable dirty bits will be processed
3175     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3176     ASSERT_GL_NO_ERROR();
3177 
3178     // Enable (shouldn't change result)
3179     glEnable(GL_DEPTH_TEST);
3180     glEnable(GL_STENCIL_TEST);
3181 
3182     // Invalidate (should result: in storeOp = DONT_CARE; mContentDefined = false)
3183     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
3184     ASSERT_GL_NO_ERROR();
3185 
3186     // Ensure that the render pass wasn't broken
3187     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
3188 
3189     // Use swapBuffers and then check how many loads and stores were actually done
3190     swapBuffers();
3191     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3192 
3193     // Start and end another render pass, to check that the load ops are as expected
3194     setAndIncrementDepthStencilLoadCountersForOpsTest(getPerfCounters(), 0, 0, &expected);
3195     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3196     ASSERT_GL_NO_ERROR();
3197     swapBuffers();
3198     EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(getPerfCounters(), expected);
3199 }
3200 
3201 // Tests that another case does not break render pass, and that counts are correct:
3202 //
3203 // - Scenario: invalidate, draw, disable, enable, invalidate, draw
TEST_P(VulkanPerformanceCounterTest,DepthStencilInvalidateDrawDisableEnableInvalidateDraw)3204 TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDrawDisableEnableInvalidateDraw)
3205 {
3206     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3207 
3208     angle::VulkanPerfCounters expected;
3209 
3210     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0),
3211     // stencil(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
3212     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
3213     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected);
3214 
3215     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3216     GLFramebuffer framebuffer;
3217     GLTexture texture;
3218     GLRenderbuffer renderbuffer;
3219     setupClearAndDrawForDepthStencilOpsTest(&program, &framebuffer, &texture, &renderbuffer, false);
3220 
3221     // Execute the scenario that this test is for:
3222 
3223     // Invalidate (should result: in storeOp = DONT_CARE; mContentDefined = false)
3224     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
3225     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
3226     ASSERT_GL_NO_ERROR();
3227 
3228     // Draw (since enabled, should result: in storeOp = STORE; mContentDefined = true)
3229     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3230     ASSERT_GL_NO_ERROR();
3231 
3232     // Disable (shouldn't change result)
3233     glDisable(GL_DEPTH_TEST);
3234     glDisable(GL_STENCIL_TEST);
3235     // Note: this draw is just so that the disable dirty bits will be processed
3236     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3237     ASSERT_GL_NO_ERROR();
3238 
3239     // Enable (shouldn't change result)
3240     glEnable(GL_DEPTH_TEST);
3241     glEnable(GL_STENCIL_TEST);
3242 
3243     // Invalidate (should result: in storeOp = DONT_CARE; mContentDefined = false)
3244     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
3245     ASSERT_GL_NO_ERROR();
3246 
3247     // Draw (since enabled, should result: in storeOp = STORE; mContentDefined = true)
3248     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3249     ASSERT_GL_NO_ERROR();
3250 
3251     // Ensure that the render pass wasn't broken
3252     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
3253 
3254     // Use swapBuffers and then check how many loads and stores were actually done
3255     swapBuffers();
3256     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3257 
3258     // Start and end another render pass, to check that the load ops are as expected
3259     setAndIncrementDepthStencilLoadCountersForOpsTest(getPerfCounters(), 1, 0, &expected);
3260     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3261     ASSERT_GL_NO_ERROR();
3262     swapBuffers();
3263     EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(getPerfCounters(), expected);
3264 }
3265 
3266 // Tests that another common (dEQP) case does not break render pass, and that counts are correct:
3267 //
3268 // - Scenario: invalidate, disable, enable, draw
TEST_P(VulkanPerformanceCounterTest,DepthStencilInvalidateDisableEnableDraw)3269 TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDisableEnableDraw)
3270 {
3271     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3272 
3273     angle::VulkanPerfCounters expected;
3274 
3275     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0),
3276     // stencil(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1)
3277     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
3278     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 1, 0, 1, &expected);
3279 
3280     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3281     GLFramebuffer framebuffer;
3282     GLTexture texture;
3283     GLRenderbuffer renderbuffer;
3284     setupClearAndDrawForDepthStencilOpsTest(&program, &framebuffer, &texture, &renderbuffer, false);
3285 
3286     // Execute the scenario that this test is for:
3287 
3288     // Invalidate (should result: in storeOp = DONT_CARE; mContentDefined = false)
3289     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
3290     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
3291     ASSERT_GL_NO_ERROR();
3292 
3293     // Disable (shouldn't change result)
3294     glDisable(GL_DEPTH_TEST);
3295     glDisable(GL_STENCIL_TEST);
3296     // Note: this draw is just so that the disable dirty bits will be processed
3297     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3298     ASSERT_GL_NO_ERROR();
3299 
3300     // Enable (shouldn't change result)
3301     glEnable(GL_DEPTH_TEST);
3302     glEnable(GL_STENCIL_TEST);
3303 
3304     // Draw (since enabled, should result: in storeOp = STORE; mContentDefined = true)
3305     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3306     ASSERT_GL_NO_ERROR();
3307 
3308     // Ensure that the render pass wasn't broken
3309     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
3310 
3311     // Use swapBuffers and then check how many loads and stores were actually done
3312     swapBuffers();
3313     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3314 
3315     // Start and end another render pass, to check that the load ops are as expected
3316     setAndIncrementDepthStencilLoadCountersForOpsTest(getPerfCounters(), 1, 0, &expected);
3317     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3318     ASSERT_GL_NO_ERROR();
3319     swapBuffers();
3320     EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(getPerfCounters(), expected);
3321 }
3322 
3323 // Tests that an in renderpass clear after invalidate keeps content stored.
TEST_P(VulkanPerformanceCounterTest,DepthStencilInvalidateAndClear)3324 TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateAndClear)
3325 {
3326     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3327 
3328     angle::VulkanPerfCounters expected;
3329 
3330     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0),
3331     // stencil(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
3332     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
3333     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected);
3334 
3335     // Clear should vkCmdClearAttachments
3336     expected.depthClearAttachments = getPerfCounters().depthClearAttachments + 1;
3337 
3338     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3339     GLFramebuffer framebuffer;
3340     GLTexture texture;
3341     GLRenderbuffer renderbuffer;
3342     setupClearAndDrawForDepthStencilOpsTest(&program, &framebuffer, &texture, &renderbuffer, false);
3343 
3344     // Disable depth test but with depth mask enabled so that clear should still work.
3345     glDisable(GL_DEPTH_TEST);
3346     glDepthMask(GL_TRUE);
3347 
3348     // Invalidate (should result: in storeOp = DONT_CARE; mContentDefined = false)
3349     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
3350     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
3351     ASSERT_GL_NO_ERROR();
3352 
3353     // Do in-renderpass clear. This should result in StoreOp=STORE; mContentDefined = true.
3354     glClearDepthf(1.0f);
3355     glClear(GL_DEPTH_BUFFER_BIT);
3356     ASSERT_GL_NO_ERROR();
3357 
3358     // Use swapBuffers and then check how many loads and stores were actually done
3359     swapBuffers();
3360     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3361     EXPECT_CLEAR_ATTACHMENTS_COUNTER(expected.depthClearAttachments,
3362                                      getPerfCounters().depthClearAttachments);
3363 
3364     // Expect rpCount+1, depth(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0),
3365     // stencil(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1)
3366     setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 1, 0, 1, 0, &expected);
3367     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 1, 0, 1, &expected);
3368 
3369     // Bind FBO again and try to use the depth buffer without clear. This should result in
3370     // loadOp=LOAD and StoreOP=STORE
3371     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3372     glEnable(GL_DEPTH_TEST);
3373     glDepthFunc(GL_LESS);
3374     glDisable(GL_STENCIL_TEST);
3375     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3376     // Should pass depth test: (0.5+1.0)/2.0=0.75 < 1.0
3377     drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
3378     EXPECT_PIXEL_COLOR_EQ(kOpsTestSize / 2, kOpsTestSize / 2, GLColor::blue);
3379     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3380 }
3381 
3382 // Tests that the draw path for clear after invalidate and disabling depth/stencil test keeps
3383 // content stored.
TEST_P(VulkanPerformanceCounterTest,DepthStencilInvalidateAndMaskedClear)3384 TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateAndMaskedClear)
3385 {
3386     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3387 
3388     angle::VulkanPerfCounters expected;
3389 
3390     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0),
3391     // stencil(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
3392     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
3393     setExpectedCountersForStencilOps(getPerfCounters(), 1, 0, 0, 1, 0, &expected);
3394 
3395     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3396     GLFramebuffer framebuffer;
3397     GLTexture texture;
3398     GLRenderbuffer renderbuffer;
3399     setupClearAndDrawForDepthStencilOpsTest(&program, &framebuffer, &texture, &renderbuffer, true);
3400 
3401     // Invalidate (should result: in storeOp = DONT_CARE; mContentDefined = false)
3402     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
3403     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
3404     ASSERT_GL_NO_ERROR();
3405 
3406     // Disable depth/stencil test but make stencil masked
3407     glDisable(GL_DEPTH_TEST);
3408     glDisable(GL_STENCIL_TEST);
3409     glDepthMask(GL_TRUE);
3410     glStencilMask(0xF0);
3411 
3412     // Enable scissor for the draw path to be taken.
3413     glEnable(GL_SCISSOR_TEST);
3414     glScissor(kOpsTestSize / 4, kOpsTestSize / 4, kOpsTestSize / 2, kOpsTestSize / 2);
3415 
3416     // Do in-renderpass clear. This should result in StoreOp=STORE
3417     glClearDepthf(1.0f);
3418     glClearStencil(0x55);
3419     glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3420     ASSERT_GL_NO_ERROR();
3421 
3422     // Use swapBuffers and then check how many loads and stores were actually done
3423     swapBuffers();
3424     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3425 
3426     // Expect rpCount+1, depth(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0),
3427     // stencil(Clears+0, Loads+1, LoadNones+0, Stores+0, StoreNones+1)
3428     // Note that depth write is enabled, while stencil is disabled.
3429     setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 1, 0, 1, 0, &expected);
3430     setExpectedCountersForStencilOps(getPerfCounters(), 0, 1, 0, 0, 1, &expected);
3431 
3432     // Bind FBO again and try to use the depth buffer without clear. This should result in
3433     // loadOp=LOAD and StoreOP=STORE
3434     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3435     glEnable(GL_DEPTH_TEST);
3436     glDepthFunc(GL_LESS);
3437     glEnable(GL_STENCIL_TEST);
3438     glStencilFunc(GL_EQUAL, 0x50, 0xF0);
3439     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
3440     glStencilMask(0xFF);
3441     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3442     drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.95f);
3443     EXPECT_PIXEL_COLOR_EQ(kOpsTestSize / 2, kOpsTestSize / 2, GLColor::blue);
3444     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3445 }
3446 
3447 // Tests that the renderpass is using depthFunc(GL_ALWAYS) and depthMask(GL_FALSE), it should not
3448 // load or store depth value.
TEST_P(VulkanPerformanceCounterTest,DepthFuncALWAYSWithDepthMaskDisabledShouldNotLoadStore)3449 TEST_P(VulkanPerformanceCounterTest, DepthFuncALWAYSWithDepthMaskDisabledShouldNotLoadStore)
3450 {
3451     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3452 
3453     angle::VulkanPerfCounters expected;
3454 
3455     GLFramebuffer framebuffer;
3456     GLTexture texture;
3457     GLRenderbuffer renderbuffer;
3458     setupForDepthStencilOpsTest(&framebuffer, &texture, &renderbuffer);
3459 
3460     // Expect rpCount+1, depth(Clears+0, Loads+0, LoadNones+0, Stores+1, StoreNones+0),
3461     setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 0, 0, 1, 0, &expected);
3462     if (hasDisallowMixedDepthStencilLoadOpNoneAndLoad())
3463     {
3464         // stencil(Clears+0, Loads+1, LoadNones+0, Stores+0, StoreNones+1)
3465         setExpectedCountersForStencilOps(getPerfCounters(), 0, 1, 0, 0, 1, &expected);
3466     }
3467     else
3468     {
3469         // stencil(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1)
3470         setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 1, 0, 1, &expected);
3471     }
3472     // Initialize the buffers with known value
3473     glEnable(GL_DEPTH_TEST);
3474     glDepthMask(GL_TRUE);
3475     glDepthFunc(GL_ALWAYS);
3476     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3477     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.95f);
3478     EXPECT_PIXEL_COLOR_EQ(kOpsTestSize / 2, kOpsTestSize / 2, GLColor::red);
3479     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3480 
3481     // Expect rpCount+1, depth(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1),
3482     //                 stencil(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1)
3483     setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 0, 1, 0, 1, &expected);
3484     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 1, 0, 1, &expected);
3485 
3486     glEnable(GL_DEPTH_TEST);
3487     glDepthMask(GL_FALSE);
3488     glDepthFunc(GL_ALWAYS);
3489     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.95f);
3490     EXPECT_PIXEL_COLOR_EQ(kOpsTestSize / 2, kOpsTestSize / 2, GLColor::red);
3491     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3492 }
3493 
3494 // Tests that the renderpass is using depthFunc(GL_ALWAYS) and depthMask(GL_FALSE) and draw. Then it
3495 // followed by glClear, it should not load or store depth value.
TEST_P(VulkanPerformanceCounterTest,DepthFuncALWAYSWithDepthMaskDisabledThenClearShouldNotLoadStore)3496 TEST_P(VulkanPerformanceCounterTest,
3497        DepthFuncALWAYSWithDepthMaskDisabledThenClearShouldNotLoadStore)
3498 {
3499     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3500 
3501     angle::VulkanPerfCounters expected;
3502 
3503     GLFramebuffer framebuffer;
3504     GLTexture texture;
3505     GLRenderbuffer renderbuffer;
3506     setupForDepthStencilOpsTest(&framebuffer, &texture, &renderbuffer);
3507 
3508     // Initialize the buffers with known value
3509     glEnable(GL_DEPTH_TEST);
3510     glDepthMask(GL_TRUE);
3511     glDepthFunc(GL_ALWAYS);
3512     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3513     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.95f);
3514     EXPECT_PIXEL_COLOR_EQ(kOpsTestSize / 2, kOpsTestSize / 2, GLColor::red);
3515 
3516     if (hasPreferDrawOverClearAttachments())
3517     {
3518         // Expect rpCount+1, depth(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0),
3519         //                 stencil(Clears+0, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
3520         setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 1, 0, 1, 0, &expected);
3521     }
3522     else
3523     {
3524         // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0),
3525         //                 stencil(Clears+0, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
3526         setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
3527     }
3528     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 1, 0, &expected);
3529 
3530     glEnable(GL_DEPTH_TEST);
3531     glDepthMask(GL_FALSE);
3532     glDepthFunc(GL_ALWAYS);
3533     glEnable(GL_STENCIL_TEST);
3534     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.95f);
3535     glDepthMask(GL_TRUE);
3536     glClearDepthf(1);
3537     glClearStencil(0);
3538     glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3539     glDepthFunc(GL_LEQUAL);
3540     glDepthMask(GL_FALSE);
3541     glEnable(GL_STENCIL_TEST);
3542     glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0, 255);
3543     glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_KEEP);
3544     glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 255);
3545     glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
3546     glStencilMask(255);
3547     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.9f);
3548     EXPECT_PIXEL_COLOR_EQ(kOpsTestSize / 2, kOpsTestSize / 2, GLColor::red);
3549     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3550 }
3551 
3552 // Tests that the renderpass is using depthFunc(GL_NEVER) and depthMask(GL_FALSE), it should not
3553 // load or store depth value.
TEST_P(VulkanPerformanceCounterTest,DepthFuncNEVERWithDepthMaskDisabledShouldNotLoadStore)3554 TEST_P(VulkanPerformanceCounterTest, DepthFuncNEVERWithDepthMaskDisabledShouldNotLoadStore)
3555 {
3556     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3557 
3558     angle::VulkanPerfCounters expected;
3559 
3560     GLFramebuffer framebuffer;
3561     GLTexture texture;
3562     GLRenderbuffer renderbuffer;
3563     setupForDepthStencilOpsTest(&framebuffer, &texture, &renderbuffer);
3564 
3565     // Initialize the buffers with known value
3566     glEnable(GL_DEPTH_TEST);
3567     glDepthMask(GL_TRUE);
3568     glDepthFunc(GL_ALWAYS);
3569     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3570     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.95f);
3571     EXPECT_PIXEL_COLOR_EQ(kOpsTestSize / 2, kOpsTestSize / 2, GLColor::red);
3572 
3573     // Expect rpCount+1, depth(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1),
3574     //                 stencil(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1)
3575     setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 0, 1, 0, 1, &expected);
3576     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 1, 0, 1, &expected);
3577 
3578     glEnable(GL_DEPTH_TEST);
3579     glDepthMask(GL_FALSE);
3580     glDepthFunc(GL_NEVER);
3581     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.95f);
3582     EXPECT_PIXEL_COLOR_EQ(kOpsTestSize / 2, kOpsTestSize / 2, GLColor::red);
3583     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3584 }
3585 
3586 // Tests whether depth-stencil ContentDefined will be correct when:
3587 //
3588 // - Scenario: invalidate, detach D/S texture and modify it, attach D/S texture, draw with blend
TEST_P(VulkanPerformanceCounterTest,DepthStencilInvalidateDetachModifyTexAttachDrawWithBlend)3589 TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDetachModifyTexAttachDrawWithBlend)
3590 {
3591     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3592 
3593     angle::VulkanPerfCounters expected;
3594 
3595     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0),
3596     // stencil(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
3597     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 0, 0, &expected);
3598     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected);
3599 
3600     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3601     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
3602     GLFramebuffer framebuffer;
3603     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3604 
3605     GLTexture colorTexture;
3606     glBindTexture(GL_TEXTURE_2D, colorTexture);
3607     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3608     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3609 
3610     GLTexture depthStencilTexture;
3611     glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
3612     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 2, 2, 0, GL_DEPTH_STENCIL,
3613                  GL_UNSIGNED_INT_24_8, nullptr);
3614     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
3615                            depthStencilTexture, 0);
3616     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3617 
3618     // Clear and draw with depth-stencil enabled
3619     glEnable(GL_DEPTH_TEST);
3620     glDepthMask(GL_TRUE);
3621     glDepthFunc(GL_LEQUAL);
3622     glClearDepthf(0.99f);
3623     glEnable(GL_STENCIL_TEST);
3624     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3625     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.5f);
3626     ASSERT_GL_NO_ERROR();
3627 
3628     // Invalidate depth & stencil (should result: in storeOp = DONT_CARE; mContentDefined = false)
3629     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
3630     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
3631     ASSERT_GL_NO_ERROR();
3632 
3633     // Check for the expected number of render passes, expected color, and other expected counters
3634     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
3635     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3636     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3637 
3638     // Detach depth-stencil attachment
3639     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
3640     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3641 
3642     // Modify depth-stencil
3643     constexpr uint32_t kDepthStencilInitialValue = 0xafffff00;
3644     uint32_t depthStencilData[4] = {kDepthStencilInitialValue, kDepthStencilInitialValue,
3645                                     kDepthStencilInitialValue, kDepthStencilInitialValue};
3646     glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
3647     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 2, 2, 0, GL_DEPTH_STENCIL,
3648                  GL_UNSIGNED_INT_24_8, depthStencilData);
3649 
3650     // Re-attach depth-stencil
3651     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
3652                            depthStencilTexture, 0);
3653     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3654 
3655     // Draw again, showing that the modified depth-stencil value prevents a new color value
3656     //
3657     // Expect rpCount+1, depth(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0),
3658     // stencil(Clears+0, Loads+1, LoadNones+0, Stores+0, StoreNones+1)
3659     // Note that depth write is enabled, while stencil is disabled.
3660     setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 1, 0, 1, 0, &expected);
3661     setExpectedCountersForStencilOps(getPerfCounters(), 0, 1, 0, 0, 1, &expected);
3662     drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
3663     ASSERT_GL_NO_ERROR();
3664     // Check for the expected number of render passes, expected color, and other expected counters
3665     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
3666     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3667     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3668 
3669     // Draw again, using a different depth value, so that the drawing takes place
3670     //
3671     // Expect rpCount+1, depth(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0),
3672     // stencil(Clears+0, Loads+1, LoadNones+0, Stores+0, StoreNones+1)
3673     setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 1, 0, 1, 0, &expected);
3674     setExpectedCountersForStencilOps(getPerfCounters(), 0, 1, 0, 0, 1, &expected);
3675     drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.2f);
3676     ASSERT_GL_NO_ERROR();
3677     // Check for the expected number of render passes, expected color, and other expected counters
3678     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
3679     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3680     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3681 }
3682 
3683 // Tests that a GLRenderbuffer can be deleted before the render pass ends, and that everything
3684 // still works.
3685 //
3686 // - Scenario: invalidate
TEST_P(VulkanPerformanceCounterTest,DepthStencilInvalidateDrawAndDeleteRenderbuffer)3687 TEST_P(VulkanPerformanceCounterTest, DepthStencilInvalidateDrawAndDeleteRenderbuffer)
3688 {
3689     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3690 
3691     angle::VulkanPerfCounters expected;
3692 
3693     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0),
3694     // stencil(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
3695     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
3696     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected);
3697 
3698     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3699     GLFramebuffer framebuffer;
3700     GLTexture texture;
3701     {
3702         // Declare the RAII-based GLRenderbuffer object within this set of curly braces, so that it
3703         // will be deleted early (at the close-curly-brace)
3704         GLRenderbuffer renderbuffer;
3705         setupClearAndDrawForDepthStencilOpsTest(&program, &framebuffer, &texture, &renderbuffer,
3706                                                 false);
3707 
3708         // Invalidate (storeOp = DONT_CARE; mContentDefined = false)
3709         const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
3710         glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
3711         ASSERT_GL_NO_ERROR();
3712 
3713         // Draw (since enabled, should result: in storeOp = STORE; mContentDefined = true)
3714         drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3715         ASSERT_GL_NO_ERROR();
3716 
3717         // Ensure that the render pass wasn't broken
3718         EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
3719     }
3720 
3721     // The renderbuffer should now be deleted.
3722 
3723     // Use swapBuffers and then check how many loads and stores were actually done
3724     swapBuffers();
3725     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
3726 
3727     // Start and end another render pass, to check that the load ops are as expected
3728     setAndIncrementDepthStencilLoadCountersForOpsTest(getPerfCounters(), 0, 0, &expected);
3729     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3730     ASSERT_GL_NO_ERROR();
3731     swapBuffers();
3732     EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(getPerfCounters(), expected);
3733 }
3734 
3735 // Test that disabling color buffer after clear continues to use loadOp for it.
3736 //
3737 // - Scenario: clear color and depth, disable color, draw, enable color, draw
TEST_P(VulkanPerformanceCounterTest_ES31,ColorDisableThenDrawThenEnableThenDraw)3738 TEST_P(VulkanPerformanceCounterTest_ES31, ColorDisableThenDrawThenEnableThenDraw)
3739 {
3740     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3741 
3742     angle::VulkanPerfCounters expected;
3743 
3744     GLFramebuffer framebuffer;
3745     GLTexture texture;
3746     GLRenderbuffer renderbuffer;
3747     setupForColorDepthOpsTest(&framebuffer, &texture, &renderbuffer);
3748 
3749     // Expected:
3750     //   rpCount+1,
3751     //   depth(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
3752     //   color(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
3753     setExpectedCountersForDepthOps(getPerfCounters(), 0, 1, 0, 0, 1, 0, &expected);
3754     setExpectedCountersForColorOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
3755 
3756     // Clear color and depth first
3757     glClearColor(1, 0, 0, 1);
3758     glClearDepthf(0.123);
3759     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3760 
3761     // Disable color output
3762     GLenum drawBuffers[] = {GL_NONE};
3763     glDrawBuffers(1, drawBuffers);
3764 
3765     // Issue a draw call, only affecting depth
3766     glDepthFunc(GL_ALWAYS);
3767     ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
3768     drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.75f);
3769 
3770     // Enable color output
3771     drawBuffers[0] = GL_COLOR_ATTACHMENT0;
3772     glDrawBuffers(1, drawBuffers);
3773 
3774     // Issue another draw call, verifying depth simultaneously
3775     glDepthFunc(GL_LESS);
3776     ANGLE_GL_PROGRAM(drawBlue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3777     drawQuad(drawBlue, essl1_shaders::PositionAttrib(), 0.74f);
3778 
3779     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
3780 
3781     // Verify results and check how many loads and stores were actually done.
3782     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3783     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
3784     EXPECT_DEPTH_OP_COUNTERS(getPerfCounters(), expected);
3785     ASSERT_GL_NO_ERROR();
3786 }
3787 
3788 // Tests that even if the app clears depth, it should be invalidated if there is no read.
TEST_P(VulkanPerformanceCounterTest,SwapShouldInvalidateDepthAfterClear)3789 TEST_P(VulkanPerformanceCounterTest, SwapShouldInvalidateDepthAfterClear)
3790 {
3791     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3792 
3793     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3794 
3795     // Clear depth.
3796     glClear(GL_DEPTH_BUFFER_BIT);
3797 
3798     // Ensure we never read from depth.
3799     glDisable(GL_DEPTH_TEST);
3800 
3801     // Do one draw, then swap.
3802     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.5f);
3803     ASSERT_GL_NO_ERROR();
3804 
3805     uint64_t expectedDepthClears = getPerfCounters().depthLoadOpClears;
3806 
3807     swapBuffers();
3808 
3809     uint64_t actualDepthClears = getPerfCounters().depthLoadOpClears;
3810     EXPECT_EQ(expectedDepthClears, actualDepthClears);
3811 }
3812 
3813 // Tests that masked color clears don't break the RP.
TEST_P(VulkanPerformanceCounterTest,MaskedColorClearDoesNotBreakRenderPass)3814 TEST_P(VulkanPerformanceCounterTest, MaskedColorClearDoesNotBreakRenderPass)
3815 {
3816     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3817 
3818     GLTexture texture;
3819     glBindTexture(GL_TEXTURE_2D, texture);
3820     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3821 
3822     GLFramebuffer framebuffer;
3823     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3824     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3825     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3826     ASSERT_GL_NO_ERROR();
3827 
3828     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
3829 
3830     // Mask color channels and clear the framebuffer multiple times.
3831     glClearColor(0.25f, 0.25f, 0.25f, 0.25f);
3832     glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
3833     glClear(GL_COLOR_BUFFER_BIT);
3834 
3835     glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
3836     glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
3837     glClear(GL_COLOR_BUFFER_BIT);
3838 
3839     glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
3840     glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
3841     glClear(GL_COLOR_BUFFER_BIT);
3842 
3843     glClearColor(0.75f, 0.75f, 0.75f, 0.75f);
3844     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
3845     glClear(GL_COLOR_BUFFER_BIT);
3846 
3847     uint64_t actualRenderPassCount = getPerfCounters().renderPasses;
3848     EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
3849 
3850     EXPECT_PIXEL_NEAR(0, 0, 63, 127, 255, 191, 1);
3851 }
3852 
3853 // Tests that masked color/depth/stencil clears don't break the RP.
TEST_P(VulkanPerformanceCounterTest,MaskedClearDoesNotBreakRenderPass)3854 TEST_P(VulkanPerformanceCounterTest, MaskedClearDoesNotBreakRenderPass)
3855 {
3856     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3857 
3858     constexpr GLsizei kSize = 64;
3859 
3860     GLTexture texture;
3861     glBindTexture(GL_TEXTURE_2D, texture);
3862     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3863 
3864     GLRenderbuffer renderbuffer;
3865     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
3866     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSize, kSize);
3867 
3868     GLFramebuffer framebuffer;
3869     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3870     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3871     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3872                               renderbuffer);
3873     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3874     ASSERT_GL_NO_ERROR();
3875 
3876     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
3877 
3878     glEnable(GL_DEPTH_TEST);
3879     glEnable(GL_STENCIL_TEST);
3880 
3881     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor());
3882     glUseProgram(program);
3883     GLint colorUniformLocation =
3884         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
3885     ASSERT_NE(-1, colorUniformLocation);
3886     ASSERT_GL_NO_ERROR();
3887 
3888     // Clear the framebuffer with a draw call to start a render pass.
3889     glViewport(0, 0, kSize, kSize);
3890     glDepthFunc(GL_ALWAYS);
3891     glStencilFunc(GL_ALWAYS, 0x55, 0xFF);
3892     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
3893     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3894     drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f);
3895 
3896     // Issue a masked clear.
3897     glClearColor(0.25f, 1.0f, 0.25f, 1.25f);
3898     glClearDepthf(0.0f);
3899     glClearStencil(0x3F);
3900     glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
3901     glStencilMask(0xF0);
3902     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3903 
3904     // Make sure the render pass wasn't broken.
3905     EXPECT_EQ(expectedRenderPassCount, getPerfCounters().renderPasses);
3906 
3907     // Verify that clear was done correctly.
3908     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
3909     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::yellow);
3910     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::yellow);
3911     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::yellow);
3912     EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::yellow);
3913 
3914     glDisable(GL_SCISSOR_TEST);
3915     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3916     glStencilMask(0xFF);
3917 
3918     // Make sure depth = 0.0f, stencil = 0x35
3919     glDepthFunc(GL_GREATER);
3920     glStencilFunc(GL_EQUAL, 0x35, 0xFF);
3921     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
3922 
3923     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
3924     drawQuad(program, essl1_shaders::PositionAttrib(), 0.05f);
3925     ASSERT_GL_NO_ERROR();
3926 
3927     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3928     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
3929     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
3930     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
3931     EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::blue);
3932 }
3933 
3934 // Tests that clear followed by scissored draw uses loadOp to clear.
TEST_P(VulkanPerformanceCounterTest,ClearThenScissoredDraw)3935 TEST_P(VulkanPerformanceCounterTest, ClearThenScissoredDraw)
3936 {
3937     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
3938 
3939     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
3940     uint64_t expectedDepthClears     = getPerfCounters().depthLoadOpClears + 1;
3941     uint64_t expectedStencilClears   = getPerfCounters().stencilLoadOpClears + 1;
3942 
3943     constexpr GLsizei kSize = 64;
3944 
3945     GLTexture texture;
3946     glBindTexture(GL_TEXTURE_2D, texture);
3947     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3948 
3949     GLRenderbuffer renderbuffer;
3950     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
3951     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSize, kSize);
3952 
3953     GLFramebuffer framebuffer;
3954     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3955     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3956     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
3957                               renderbuffer);
3958     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3959     ASSERT_GL_NO_ERROR();
3960 
3961     // Clear depth/stencil
3962     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
3963     glClearDepthf(1.0f);
3964     glClearStencil(0x55);
3965     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3966 
3967     // Issue a scissored draw call, expecting depth/stencil to be 1.0 and 0x55.
3968     glViewport(0, 0, kSize, kSize);
3969     glScissor(0, 0, kSize / 2, kSize);
3970     glEnable(GL_SCISSOR_TEST);
3971 
3972     glEnable(GL_DEPTH_TEST);
3973     glDepthFunc(GL_LESS);
3974 
3975     glEnable(GL_STENCIL_TEST);
3976     glStencilFunc(GL_EQUAL, 0x55, 0xFF);
3977     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
3978     glStencilMask(0xFF);
3979 
3980     ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Green());
3981     drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.95f);
3982     ASSERT_GL_NO_ERROR();
3983 
3984     // Break the render pass.
3985     GLTexture copyTex;
3986     glBindTexture(GL_TEXTURE_2D, copyTex);
3987     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, kSize, kSize, 0);
3988     ASSERT_GL_NO_ERROR();
3989 
3990     // Make sure a single render pass was used and depth/stencil clear used loadOp=CLEAR.
3991     EXPECT_EQ(expectedRenderPassCount, getPerfCounters().renderPasses);
3992     EXPECT_EQ(expectedDepthClears, getPerfCounters().depthLoadOpClears);
3993     EXPECT_EQ(expectedStencilClears, getPerfCounters().stencilLoadOpClears);
3994 
3995     // Verify correctness.
3996     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3997     EXPECT_PIXEL_COLOR_EQ(kSize / 2 - 1, 0, GLColor::green);
3998     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
3999     EXPECT_PIXEL_COLOR_EQ(kSize / 2 - 1, kSize - 1, GLColor::green);
4000 
4001     EXPECT_PIXEL_COLOR_EQ(kSize / 2, 0, GLColor::red);
4002     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red);
4003     EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize - 1, GLColor::red);
4004     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red);
4005 }
4006 
4007 // Tests that scissored clears don't break the RP.
TEST_P(VulkanPerformanceCounterTest,ScissoredClearDoesNotBreakRenderPass)4008 TEST_P(VulkanPerformanceCounterTest, ScissoredClearDoesNotBreakRenderPass)
4009 {
4010     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
4011 
4012     constexpr GLsizei kSize = 64;
4013 
4014     GLTexture texture;
4015     glBindTexture(GL_TEXTURE_2D, texture);
4016     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4017 
4018     GLRenderbuffer renderbuffer;
4019     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
4020     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSize, kSize);
4021 
4022     GLFramebuffer framebuffer;
4023     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4024     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4025     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
4026                               renderbuffer);
4027     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4028     ASSERT_GL_NO_ERROR();
4029 
4030     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
4031 
4032     glEnable(GL_DEPTH_TEST);
4033     glEnable(GL_STENCIL_TEST);
4034 
4035     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor());
4036     glUseProgram(program);
4037     GLint colorUniformLocation =
4038         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
4039     ASSERT_NE(-1, colorUniformLocation);
4040     ASSERT_GL_NO_ERROR();
4041 
4042     // Clear the framebuffer with a draw call to start a render pass.
4043     glViewport(0, 0, kSize, kSize);
4044     glDepthFunc(GL_ALWAYS);
4045     glStencilFunc(GL_ALWAYS, 0x55, 0xFF);
4046     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
4047     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
4048     drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f);
4049 
4050     // Issue a scissored clear.
4051     glEnable(GL_SCISSOR_TEST);
4052     glScissor(kSize / 4, kSize / 4, kSize / 2, kSize / 2);
4053     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
4054     glClearDepthf(0.0f);
4055     glClearStencil(0x3F);
4056     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4057 
4058     // Make sure the render pass wasn't broken.
4059     EXPECT_EQ(expectedRenderPassCount, getPerfCounters().renderPasses);
4060 
4061     // Verify that clear was done correctly.
4062     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4063     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red);
4064     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red);
4065     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red);
4066 
4067     EXPECT_PIXEL_COLOR_EQ(kSize / 4, kSize / 4, GLColor::green);
4068     EXPECT_PIXEL_COLOR_EQ(3 * kSize / 4 - 1, kSize / 4, GLColor::green);
4069     EXPECT_PIXEL_COLOR_EQ(kSize / 4, 3 * kSize / 4 - 1, GLColor::green);
4070     EXPECT_PIXEL_COLOR_EQ(3 * kSize / 4 - 1, 3 * kSize / 4 - 1, GLColor::green);
4071     EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::green);
4072 
4073     glDisable(GL_SCISSOR_TEST);
4074 
4075     // Make sure the border has depth = 1.0f, stencil = 0x55
4076     glDepthFunc(GL_LESS);
4077     glStencilFunc(GL_EQUAL, 0x55, 0xFF);
4078     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
4079 
4080     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
4081     drawQuad(program, essl1_shaders::PositionAttrib(), 0.95f);
4082     ASSERT_GL_NO_ERROR();
4083 
4084     // Make sure the center has depth = 0.0f, stencil = 0x3F
4085     glDepthFunc(GL_GREATER);
4086     glStencilFunc(GL_EQUAL, 0x3F, 0xFF);
4087     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
4088 
4089     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 1.0f, 1.0f);
4090     drawQuad(program, essl1_shaders::PositionAttrib(), 0.05f);
4091     ASSERT_GL_NO_ERROR();
4092 
4093     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
4094     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
4095     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
4096     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
4097 
4098     EXPECT_PIXEL_COLOR_EQ(kSize / 4, kSize / 4, GLColor::magenta);
4099     EXPECT_PIXEL_COLOR_EQ(3 * kSize / 4 - 1, kSize / 4, GLColor::magenta);
4100     EXPECT_PIXEL_COLOR_EQ(kSize / 4, 3 * kSize / 4 - 1, GLColor::magenta);
4101     EXPECT_PIXEL_COLOR_EQ(3 * kSize / 4 - 1, 3 * kSize / 4 - 1, GLColor::magenta);
4102     EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::magenta);
4103 }
4104 
4105 // Tests that draw buffer change with all color channel mask off should not break renderpass
TEST_P(VulkanPerformanceCounterTest,DrawbufferChangeWithAllColorMaskDisabled)4106 TEST_P(VulkanPerformanceCounterTest, DrawbufferChangeWithAllColorMaskDisabled)
4107 {
4108     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
4109 
4110     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor());
4111     glUseProgram(program);
4112     GLint colorUniformLocation =
4113         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
4114     ASSERT_NE(-1, colorUniformLocation);
4115     ASSERT_GL_NO_ERROR();
4116 
4117     GLTexture textureRGBA;
4118     glBindTexture(GL_TEXTURE_2D, textureRGBA);
4119     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4120     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4121     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4122 
4123     GLTexture textureDepth;
4124     glBindTexture(GL_TEXTURE_2D, textureDepth);
4125     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 64, 64, 0, GL_DEPTH_COMPONENT,
4126                  GL_UNSIGNED_INT, nullptr);
4127     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4128     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4129 
4130     GLFramebuffer framebuffer;
4131     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4132     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureRGBA, 0);
4133     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, textureDepth, 0);
4134     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4135     ASSERT_GL_NO_ERROR();
4136 
4137     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
4138 
4139     // Draw into FBO
4140     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4141     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);  // clear to green
4142     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4143     glViewport(0, 0, 256, 256);
4144     glUniform4fv(colorUniformLocation, 1, GLColor::blue.toNormalizedVector().data());
4145     GLenum glDrawBuffers_bufs_1[] = {GL_COLOR_ATTACHMENT0};
4146     glDrawBuffers(1, glDrawBuffers_bufs_1);
4147     glEnable(GL_DEPTH_TEST);
4148     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4149     // Change draw buffer state and color mask
4150     GLenum glDrawBuffers_bufs_0[] = {GL_NONE};
4151     glDrawBuffers(1, glDrawBuffers_bufs_0);
4152     glColorMask(false, false, false, false);
4153     drawQuad(program, essl1_shaders::PositionAttrib(), 0.6f);
4154     // Change back draw buffer state and color mask
4155     glDrawBuffers(1, glDrawBuffers_bufs_1);
4156     glColorMask(true, true, true, true);
4157     glUniform4fv(colorUniformLocation, 1, GLColor::red.toNormalizedVector().data());
4158     drawQuad(program, essl1_shaders::PositionAttrib(), 0.7f);
4159 
4160     uint64_t actualRenderPassCount = getPerfCounters().renderPasses;
4161     EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
4162 }
4163 
4164 // Tests the optimization that a glFlush call issued inside a renderpass will be skipped.
TEST_P(VulkanPerformanceCounterTest,InRenderpassFlushShouldNotBreakRenderpass)4165 TEST_P(VulkanPerformanceCounterTest, InRenderpassFlushShouldNotBreakRenderpass)
4166 {
4167     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
4168 
4169     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
4170 
4171     GLTexture texture;
4172     glBindTexture(GL_TEXTURE_2D, texture);
4173     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4174 
4175     GLFramebuffer framebuffer;
4176     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4177     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4178     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4179     ASSERT_GL_NO_ERROR();
4180 
4181     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
4182     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.5f);
4183     glFlush();
4184     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
4185     drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
4186     ASSERT_GL_NO_ERROR();
4187 
4188     uint64_t actualRenderPassCount = getPerfCounters().renderPasses;
4189     EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
4190 }
4191 
4192 // Tests switch from query enabled draw to query disabled draw should break renderpass (so that wait
4193 // for query result will be available sooner).
TEST_P(VulkanPerformanceCounterTest,SwitchFromQueryEnabledDrawToQueryDisabledDrawShouldBreakRenderpass)4194 TEST_P(VulkanPerformanceCounterTest,
4195        SwitchFromQueryEnabledDrawToQueryDisabledDrawShouldBreakRenderpass)
4196 {
4197     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
4198 
4199     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
4200 
4201     uint64_t expectedRenderPassCount =
4202         getPerfCounters().renderPasses +
4203         (isFeatureEnabled(Feature::PreferSubmitOnAnySamplesPassedQueryEnd) ? 2 : 1);
4204 
4205     GLQueryEXT query1, query2;
4206     // Draw inside query
4207     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query1);
4208     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.8f, 0.5f);
4209     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
4210     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query2);
4211     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.8f, 0.5f);
4212     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
4213     // Draw outside his query
4214     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.8f, 0.5f);
4215 
4216     GLuint results[2];
4217     // will block waiting for result
4218     glGetQueryObjectuivEXT(query1, GL_QUERY_RESULT_EXT, &results[0]);
4219     glGetQueryObjectuivEXT(query2, GL_QUERY_RESULT_EXT, &results[1]);
4220     EXPECT_GL_NO_ERROR();
4221 
4222     uint64_t actualRenderPassCount = getPerfCounters().renderPasses;
4223     EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
4224 }
4225 
4226 // Tests that depth/stencil texture clear/load works correctly.
TEST_P(VulkanPerformanceCounterTest,DepthStencilTextureClearAndLoad)4227 TEST_P(VulkanPerformanceCounterTest, DepthStencilTextureClearAndLoad)
4228 {
4229     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
4230 
4231     // TODO: http://anglebug.com/5329 Flaky test
4232     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
4233 
4234     uint64_t expectedDepthClearCount   = getPerfCounters().depthLoadOpClears + 1;
4235     uint64_t expectedDepthLoadCount    = getPerfCounters().depthLoadOpLoads + 3;
4236     uint64_t expectedStencilClearCount = getPerfCounters().stencilLoadOpClears + 1;
4237     uint64_t expectedStencilLoadCount  = getPerfCounters().stencilLoadOpLoads + 3;
4238 
4239     constexpr GLsizei kSize = 6;
4240 
4241     // Create framebuffer to draw into, with both color and depth attachments.
4242     GLTexture color;
4243     glBindTexture(GL_TEXTURE_2D, color);
4244     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4245 
4246     GLTexture depth;
4247     glBindTexture(GL_TEXTURE_2D, depth);
4248     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, kSize, kSize, 0, GL_DEPTH_STENCIL,
4249                  GL_UNSIGNED_INT_24_8_OES, nullptr);
4250 
4251     GLFramebuffer fbo;
4252     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4253     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4254     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depth, 0);
4255     ASSERT_GL_NO_ERROR();
4256 
4257     // Set up texture for copy operation that breaks the render pass
4258     GLTexture copyTex;
4259     glBindTexture(GL_TEXTURE_2D, copyTex);
4260     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4261 
4262     // Set viewport and clear depth/stencil
4263     glViewport(0, 0, kSize, kSize);
4264     glClearDepthf(1);
4265     glClearStencil(0x55);
4266     glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4267 
4268     // If depth is not cleared to 1, rendering would fail.
4269     glEnable(GL_DEPTH_TEST);
4270     glDepthFunc(GL_LESS);
4271     glDepthMask(GL_FALSE);
4272 
4273     // If stencil is not clear to 0x55, rendering would fail.
4274     glEnable(GL_STENCIL_TEST);
4275     glStencilFunc(GL_EQUAL, 0x55, 0xFF);
4276     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
4277     glStencilMask(0xFF);
4278 
4279     // Set up program
4280     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
4281     glUseProgram(drawColor);
4282     GLint colorUniformLocation =
4283         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
4284     ASSERT_NE(colorUniformLocation, -1);
4285 
4286     // Draw red
4287     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
4288     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
4289     ASSERT_GL_NO_ERROR();
4290 
4291     // Break the render pass
4292     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kSize / 2, kSize / 2);
4293     ASSERT_GL_NO_ERROR();
4294 
4295     // Draw green
4296     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
4297     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
4298     ASSERT_GL_NO_ERROR();
4299 
4300     // Break the render pass
4301     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kSize / 2, 0, 0, 0, kSize / 2, kSize / 2);
4302     ASSERT_GL_NO_ERROR();
4303 
4304     // Draw blue
4305     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
4306     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
4307     ASSERT_GL_NO_ERROR();
4308 
4309     // Break the render pass
4310     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, kSize / 2, 0, 0, kSize / 2, kSize / 2);
4311     ASSERT_GL_NO_ERROR();
4312 
4313     // Draw yellow
4314     glUniform4f(colorUniformLocation, 1.0f, 1.0f, 0.0f, 1.0f);
4315     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
4316     ASSERT_GL_NO_ERROR();
4317 
4318     // Break the render pass
4319     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kSize / 2, kSize / 2, 0, 0, kSize / 2, kSize / 2);
4320     ASSERT_GL_NO_ERROR();
4321 
4322     // Verify the counters
4323     EXPECT_EQ(getPerfCounters().depthLoadOpClears, expectedDepthClearCount);
4324     EXPECT_EQ(getPerfCounters().depthLoadOpLoads, expectedDepthLoadCount);
4325     EXPECT_EQ(getPerfCounters().stencilLoadOpClears, expectedStencilClearCount);
4326     EXPECT_EQ(getPerfCounters().stencilLoadOpLoads, expectedStencilLoadCount);
4327 
4328     // Verify that copies were done correctly.
4329     GLFramebuffer verifyFBO;
4330     glBindFramebuffer(GL_FRAMEBUFFER, verifyFBO);
4331     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyTex, 0);
4332 
4333     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4334     EXPECT_PIXEL_COLOR_EQ(kSize / 2, 0, GLColor::green);
4335     EXPECT_PIXEL_COLOR_EQ(0, kSize / 2, GLColor::blue);
4336     EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::yellow);
4337 }
4338 
4339 // Tests that multisampled-render-to-texture depth/stencil textures don't ever load data.
TEST_P(VulkanPerformanceCounterTest,RenderToTextureDepthStencilTextureShouldNotLoad)4340 TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilTextureShouldNotLoad)
4341 {
4342     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
4343 
4344     // http://anglebug.com/5083
4345     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
4346 
4347     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2"));
4348 
4349     uint64_t expectedDepthClearCount   = getPerfCounters().depthLoadOpClears + 1;
4350     uint64_t expectedDepthLoadCount    = getPerfCounters().depthLoadOpLoads;
4351     uint64_t expectedStencilClearCount = getPerfCounters().stencilLoadOpClears + 1;
4352     uint64_t expectedStencilLoadCount  = getPerfCounters().stencilLoadOpLoads;
4353 
4354     constexpr GLsizei kSize = 6;
4355 
4356     // Create multisampled framebuffer to draw into, with both color and depth attachments.
4357     GLTexture colorMS;
4358     glBindTexture(GL_TEXTURE_2D, colorMS);
4359     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4360 
4361     GLTexture depthMS;
4362     glBindTexture(GL_TEXTURE_2D, depthMS);
4363     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, kSize, kSize, 0, GL_DEPTH_STENCIL,
4364                  GL_UNSIGNED_INT_24_8_OES, nullptr);
4365 
4366     GLFramebuffer fboMS;
4367     glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
4368     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
4369                                          colorMS, 0, 4);
4370     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
4371                                          depthMS, 0, 4);
4372     ASSERT_GL_NO_ERROR();
4373 
4374     // Set up texture for copy operation that breaks the render pass
4375     GLTexture copyTex;
4376     glBindTexture(GL_TEXTURE_2D, copyTex);
4377     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4378 
4379     // Set viewport and clear depth
4380     glViewport(0, 0, kSize, kSize);
4381     glClearDepthf(1);
4382     glClearStencil(0x55);
4383     glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4384 
4385     // If depth is not cleared to 1, rendering would fail.
4386     glEnable(GL_DEPTH_TEST);
4387     glDepthFunc(GL_LESS);
4388 
4389     // If stencil is not clear to 0x55, rendering would fail.
4390     glEnable(GL_STENCIL_TEST);
4391     glStencilFunc(GL_EQUAL, 0x55, 0xFF);
4392     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
4393     glStencilMask(0xFF);
4394 
4395     // Set up program
4396     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
4397     glUseProgram(drawColor);
4398     GLint colorUniformLocation =
4399         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
4400     ASSERT_NE(colorUniformLocation, -1);
4401 
4402     // Draw red
4403     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
4404     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
4405     ASSERT_GL_NO_ERROR();
4406 
4407     // Break the render pass
4408     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kSize / 2, kSize / 2);
4409     ASSERT_GL_NO_ERROR();
4410 
4411     // Draw green
4412     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
4413     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
4414     ASSERT_GL_NO_ERROR();
4415 
4416     // Break the render pass
4417     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kSize / 2, 0, 0, 0, kSize / 2, kSize / 2);
4418     ASSERT_GL_NO_ERROR();
4419 
4420     // Draw blue
4421     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
4422     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
4423     ASSERT_GL_NO_ERROR();
4424 
4425     // Break the render pass
4426     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, kSize / 2, 0, 0, kSize / 2, kSize / 2);
4427     ASSERT_GL_NO_ERROR();
4428 
4429     // Draw yellow
4430     glUniform4f(colorUniformLocation, 1.0f, 1.0f, 0.0f, 1.0f);
4431     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
4432     ASSERT_GL_NO_ERROR();
4433 
4434     // Break the render pass
4435     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kSize / 2, kSize / 2, 0, 0, kSize / 2, kSize / 2);
4436     ASSERT_GL_NO_ERROR();
4437 
4438     // Verify the counters
4439     EXPECT_EQ(getPerfCounters().depthLoadOpClears, expectedDepthClearCount);
4440     EXPECT_EQ(getPerfCounters().depthLoadOpLoads, expectedDepthLoadCount);
4441     EXPECT_EQ(getPerfCounters().stencilLoadOpClears, expectedStencilClearCount);
4442     EXPECT_EQ(getPerfCounters().stencilLoadOpLoads, expectedStencilLoadCount);
4443 
4444     // Verify that copies were done correctly.  Only the first copy can be verified because the
4445     // contents of the depth/stencil buffer is undefined after the first render pass break, meaning
4446     // it is unknown whether the three subsequent draw calls passed the depth or stencil tests.
4447     GLFramebuffer verifyFBO;
4448     glBindFramebuffer(GL_FRAMEBUFFER, verifyFBO);
4449     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyTex, 0);
4450 
4451     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4452     EXPECT_PIXEL_COLOR_EQ(kSize / 2 - 1, 0, GLColor::red);
4453     EXPECT_PIXEL_COLOR_EQ(0, kSize / 2 - 1, GLColor::red);
4454     EXPECT_PIXEL_COLOR_EQ(kSize / 2 - 1, kSize / 2 - 1, GLColor::red);
4455 }
4456 
4457 // Tests that multisampled-render-to-texture depth/stencil renderbuffers don't ever load
4458 // depth/stencil data.
TEST_P(VulkanPerformanceCounterTest,RenderToTextureDepthStencilRenderbufferShouldNotLoad)4459 TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilRenderbufferShouldNotLoad)
4460 {
4461     // http://anglebug.com/5083
4462     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
4463     // http://anglebug.com/5380
4464     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsVulkan());
4465 
4466     // http://crbug.com/1134286
4467     ANGLE_SKIP_TEST_IF(IsWindows7() && IsNVIDIA() && IsVulkan());
4468 
4469     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
4470     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
4471 
4472     angle::VulkanPerfCounters expected;
4473 
4474     // This test creates 4 render passes. In the first render pass, color, depth and stencil are
4475     // cleared.  In the following render passes, they must be loaded.  However, given that the
4476     // attachments are multisampled-render-to-texture, loads are done through an unresolve
4477     // operation.  All 4 render passes resolve the attachments.
4478 
4479     // Expect rpCount+4, depth(Clears+1, Loads+3, LoadNones+0, Stores+3, StoreNones+0),
4480     // stencil(Clears+1, Loads+3, LoadNones+0, Stores+3, StoreNones+0). Note that the Loads and
4481     // Stores are from the resolve attachments.
4482     setExpectedCountersForDepthOps(getPerfCounters(), 4, 1, 3, 0, 3, 0, &expected);
4483     setExpectedCountersForStencilOps(getPerfCounters(), 1, 3, 0, 3, 0, &expected);
4484 
4485     // Additionally, expect 4 resolves and 3 unresolves.
4486     setExpectedCountersForUnresolveResolveTest(getPerfCounters(), 3, 3, 3, 4, 4, 4, &expected);
4487 
4488     constexpr GLsizei kSize = 6;
4489 
4490     // Create multisampled framebuffer to draw into, with both color and depth attachments.
4491     GLTexture colorMS;
4492     glBindTexture(GL_TEXTURE_2D, colorMS);
4493     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4494 
4495     GLRenderbuffer depthStencilMS;
4496     glBindRenderbuffer(GL_RENDERBUFFER, depthStencilMS);
4497     glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kSize, kSize);
4498 
4499     GLFramebuffer fboMS;
4500     glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
4501     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
4502                                          colorMS, 0, 4);
4503     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
4504                               depthStencilMS);
4505     ASSERT_GL_NO_ERROR();
4506 
4507     // Set up texture for copy operation that breaks the render pass
4508     GLTexture copyTex;
4509     glBindTexture(GL_TEXTURE_2D, copyTex);
4510     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4511 
4512     // Set viewport and clear color, depth and stencil
4513     glViewport(0, 0, kSize, kSize);
4514     glClearDepthf(1);
4515     glClearStencil(0x55);
4516     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4517 
4518     // If depth is not cleared to 1, rendering would fail.
4519     glEnable(GL_DEPTH_TEST);
4520     glDepthFunc(GL_LESS);
4521 
4522     // If stencil is not clear to 0x55, rendering would fail.
4523     glEnable(GL_STENCIL_TEST);
4524     glStencilFunc(GL_EQUAL, 0x55, 0xFF);
4525     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
4526     glStencilMask(0xFF);
4527 
4528     // Set up program
4529     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
4530     glUseProgram(drawColor);
4531     GLint colorUniformLocation =
4532         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
4533     ASSERT_NE(colorUniformLocation, -1);
4534 
4535     // Draw red
4536     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
4537     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.75f);
4538     ASSERT_GL_NO_ERROR();
4539 
4540     // Break the render pass
4541     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kSize / 2, kSize / 2);
4542     ASSERT_GL_NO_ERROR();
4543 
4544     // Draw green
4545     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
4546     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
4547     ASSERT_GL_NO_ERROR();
4548 
4549     // Break the render pass
4550     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kSize / 2, 0, 0, 0, kSize / 2, kSize / 2);
4551     ASSERT_GL_NO_ERROR();
4552 
4553     // Draw blue
4554     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
4555     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.25f);
4556     ASSERT_GL_NO_ERROR();
4557 
4558     // Break the render pass
4559     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, kSize / 2, 0, 0, kSize / 2, kSize / 2);
4560     ASSERT_GL_NO_ERROR();
4561 
4562     // Draw yellow
4563     glUniform4f(colorUniformLocation, 1.0f, 1.0f, 0.0f, 1.0f);
4564     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
4565     ASSERT_GL_NO_ERROR();
4566 
4567     // Break the render pass
4568     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kSize / 2, kSize / 2, 0, 0, kSize / 2, kSize / 2);
4569     ASSERT_GL_NO_ERROR();
4570 
4571     // Verify the counters
4572     EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(getPerfCounters(), expected);
4573     EXPECT_COUNTERS_FOR_UNRESOLVE_RESOLVE_TEST(getPerfCounters(), expected);
4574 
4575     // Verify that copies were done correctly.
4576     GLFramebuffer verifyFBO;
4577     glBindFramebuffer(GL_FRAMEBUFFER, verifyFBO);
4578     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyTex, 0);
4579 
4580     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4581     EXPECT_PIXEL_COLOR_EQ(kSize / 2, 0, GLColor::green);
4582     EXPECT_PIXEL_COLOR_EQ(0, kSize / 2, GLColor::blue);
4583     EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::yellow);
4584 }
4585 
4586 // Tests counters when multisampled-render-to-texture color/depth/stencil renderbuffers are
4587 // invalidated.
TEST_P(VulkanPerformanceCounterTest,RenderToTextureInvalidate)4588 TEST_P(VulkanPerformanceCounterTest, RenderToTextureInvalidate)
4589 {
4590     // http://anglebug.com/5083
4591     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
4592 
4593     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
4594 
4595     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
4596 
4597     angle::VulkanPerfCounters expected;
4598 
4599     // This test creates 4 render passes. In the first render pass, color, depth and stencil are
4600     // cleared.  After every render pass, the attachments are invalidated.  In the following render
4601     // passes thus they are not loaded (rather unresolved, as the attachments are
4602     // multisampled-render-to-texture).  Due to the invalidate call, neither of the 4 render passes
4603     // should resolve the attachments.
4604 
4605     // Expect rpCount+4, color(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
4606     setExpectedCountersForColorOps(getPerfCounters(), 4, 1, 0, 0, 0, 0, &expected);
4607     // Expect rpCount+4, depth(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0),
4608     // stencil(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
4609     setExpectedCountersForDepthOps(getPerfCounters(), 4, 1, 0, 0, 0, 0, &expected);
4610     setExpectedCountersForStencilOps(getPerfCounters(), 1, 0, 0, 0, 0, &expected);
4611 
4612     // Additionally, expect no resolve and unresolve.
4613     setExpectedCountersForUnresolveResolveTest(getPerfCounters(), 0, 0, 0, 0, 0, 0, &expected);
4614 
4615     constexpr GLsizei kSize = 6;
4616 
4617     // Create multisampled framebuffer to draw into, with both color and depth attachments.
4618     GLTexture colorMS;
4619     glBindTexture(GL_TEXTURE_2D, colorMS);
4620     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4621 
4622     GLRenderbuffer depthStencilMS;
4623     glBindRenderbuffer(GL_RENDERBUFFER, depthStencilMS);
4624     glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kSize, kSize);
4625 
4626     GLFramebuffer fboMS;
4627     glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
4628     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
4629                                          colorMS, 0, 4);
4630     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
4631                               depthStencilMS);
4632     ASSERT_GL_NO_ERROR();
4633 
4634     // Set up texture for copy operation that breaks the render pass
4635     GLTexture copyTex;
4636     glBindTexture(GL_TEXTURE_2D, copyTex);
4637     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4638 
4639     // Set viewport and clear color, depth and stencil
4640     glViewport(0, 0, kSize, kSize);
4641     glClearColor(0, 0, 0, 1.0f);
4642     glClearDepthf(1);
4643     glClearStencil(0x55);
4644     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4645 
4646     // Output depth/stencil, but disable testing so all draw calls succeed
4647     glEnable(GL_DEPTH_TEST);
4648     glDepthFunc(GL_ALWAYS);
4649 
4650     glEnable(GL_STENCIL_TEST);
4651     glStencilFunc(GL_ALWAYS, 0x55, 0xFF);
4652     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
4653     glStencilMask(0xFF);
4654 
4655     // Set up program
4656     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
4657     glUseProgram(drawColor);
4658     GLint colorUniformLocation =
4659         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
4660     ASSERT_NE(colorUniformLocation, -1);
4661 
4662     // Draw red
4663     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
4664     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.75f);
4665     ASSERT_GL_NO_ERROR();
4666 
4667     // Invalidate everything
4668     const GLenum discards[] = {GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
4669     glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, discards);
4670 
4671     // Break the render pass
4672     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kSize / 2, kSize / 2);
4673     ASSERT_GL_NO_ERROR();
4674 
4675     // Draw green
4676     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
4677     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
4678     ASSERT_GL_NO_ERROR();
4679 
4680     // Invalidate everything
4681     glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, discards);
4682 
4683     // Break the render pass
4684     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kSize / 2, 0, 0, 0, kSize / 2, kSize / 2);
4685     ASSERT_GL_NO_ERROR();
4686 
4687     // Draw blue
4688     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
4689     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.25f);
4690     ASSERT_GL_NO_ERROR();
4691 
4692     // Invalidate everything
4693     glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, discards);
4694 
4695     // Break the render pass
4696     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, kSize / 2, 0, 0, kSize / 2, kSize / 2);
4697     ASSERT_GL_NO_ERROR();
4698 
4699     // Draw yellow
4700     glUniform4f(colorUniformLocation, 1.0f, 1.0f, 0.0f, 1.0f);
4701     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
4702     ASSERT_GL_NO_ERROR();
4703 
4704     // Invalidate everything
4705     glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, discards);
4706 
4707     // Break the render pass
4708     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kSize / 2, kSize / 2, 0, 0, kSize / 2, kSize / 2);
4709     ASSERT_GL_NO_ERROR();
4710 
4711     // Verify the counters
4712     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
4713     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
4714     EXPECT_COUNTERS_FOR_UNRESOLVE_RESOLVE_TEST(getPerfCounters(), expected);
4715 }
4716 
4717 // Tests counters when uninitialized multisampled-render-to-texture depth/stencil renderbuffers are
4718 // unused but not invalidated.
TEST_P(VulkanPerformanceCounterTest,RenderToTextureUninitializedAndUnusedDepthStencil)4719 TEST_P(VulkanPerformanceCounterTest, RenderToTextureUninitializedAndUnusedDepthStencil)
4720 {
4721     // http://anglebug.com/5083
4722     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
4723 
4724     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
4725 
4726     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
4727 
4728     angle::VulkanPerfCounters expected;
4729 
4730     // Expect rpCount+1, no depth/stencil clear, load or store.
4731     setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 0, 0, 0, 0, &expected);
4732     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 0, 0, 0, &expected);
4733 
4734     // Additionally, expect only color resolve.
4735     setExpectedCountersForUnresolveResolveTest(getPerfCounters(), 0, 0, 0, 1, 0, 0, &expected);
4736 
4737     constexpr GLsizei kSize = 6;
4738 
4739     // Create multisampled framebuffer to draw into, with both color and depth attachments.
4740     GLTexture colorMS;
4741     glBindTexture(GL_TEXTURE_2D, colorMS);
4742     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4743 
4744     GLRenderbuffer depthStencilMS;
4745     glBindRenderbuffer(GL_RENDERBUFFER, depthStencilMS);
4746     glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kSize, kSize);
4747 
4748     GLFramebuffer fboMS;
4749     glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
4750     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
4751                                          colorMS, 0, 4);
4752     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
4753                               depthStencilMS);
4754     ASSERT_GL_NO_ERROR();
4755 
4756     // Set up texture for copy operation that breaks the render pass
4757     GLTexture copyTex;
4758     glBindTexture(GL_TEXTURE_2D, copyTex);
4759     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4760 
4761     // Set viewport and clear color only
4762     glViewport(0, 0, kSize, kSize);
4763     glClearColor(0, 0, 0, 1.0f);
4764     glClear(GL_COLOR_BUFFER_BIT);
4765 
4766     // Disable depth/stencil testing.
4767     glDisable(GL_DEPTH_TEST);
4768     glDisable(GL_STENCIL_TEST);
4769 
4770     // Set up program
4771     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
4772     glUseProgram(drawColor);
4773     GLint colorUniformLocation =
4774         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
4775     ASSERT_NE(colorUniformLocation, -1);
4776 
4777     // Draw red
4778     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
4779     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.75f);
4780     ASSERT_GL_NO_ERROR();
4781 
4782     // Break the render pass
4783     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kSize / 2, kSize / 2);
4784     ASSERT_GL_NO_ERROR();
4785 
4786     // Verify the counters
4787     EXPECT_DEPTH_STENCIL_LOAD_OP_COUNTERS(getPerfCounters(), expected);
4788     EXPECT_COUNTERS_FOR_UNRESOLVE_RESOLVE_TEST(getPerfCounters(), expected);
4789 }
4790 
4791 // Ensures we use read-only depth layout when there is no write
TEST_P(VulkanPerformanceCounterTest,ReadOnlyDepthBufferLayout)4792 TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthBufferLayout)
4793 {
4794     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
4795 
4796     constexpr GLsizei kSize = 64;
4797 
4798     angle::VulkanPerfCounters expected;
4799 
4800     // Create depth only FBO and fill depth texture to leftHalf=0.0 and rightHalf=1.0. This should
4801     // use writeable layout
4802     expected.readOnlyDepthStencilRenderPasses = getPerfCounters().readOnlyDepthStencilRenderPasses;
4803 
4804     // Expect rpCount+1, depth(Clears+0, Loads+0, LoadNones+0, Stores+1, StoreNones+0),
4805     // stencil(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1)
4806     setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 0, 0, 1, 0, &expected);
4807     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 1, 0, 1, &expected);
4808 
4809     GLTexture depthTexture;
4810     glBindTexture(GL_TEXTURE_2D, depthTexture);
4811     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, kSize, kSize, 0, GL_DEPTH_COMPONENT,
4812                  GL_UNSIGNED_INT, nullptr);
4813     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4814     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4815 
4816     GLFramebuffer depthOnlyFBO;
4817     glBindFramebuffer(GL_FRAMEBUFFER, depthOnlyFBO);
4818     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
4819     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4820 
4821     glEnable(GL_DEPTH_TEST);
4822     glDepthFunc(GL_ALWAYS);
4823     glDepthMask(GL_TRUE);
4824     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
4825     glViewport(0, 0, kSize / 2, kSize);
4826     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.0f);
4827     glViewport(kSize / 2, 0, kSize / 2, kSize);
4828     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 1.0f);
4829     glViewport(0, 0, kSize, kSize);
4830     ASSERT_GL_NO_ERROR();
4831 
4832     // Because the layout counter is updated at end of renderpass, we need to issue a finish call
4833     // here to end the renderpass.
4834     glFinish();
4835 
4836     uint64_t actualReadOnlyDepthStencilCount = getPerfCounters().readOnlyDepthStencilRenderPasses;
4837     EXPECT_EQ(expected.readOnlyDepthStencilRenderPasses, actualReadOnlyDepthStencilCount);
4838     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
4839 
4840     // Create a color+depth FBO and use depth as read only. This should use read only layout
4841     ++expected.readOnlyDepthStencilRenderPasses;
4842     // Expect rpCount+1, depth(Clears+0, Loads+1, LoadNones+0, Stores+0, StoreNones+1),
4843     // stencil(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1)
4844     setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 1, 0, 0, 1, &expected);
4845     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 1, 0, 1, &expected);
4846 
4847     GLTexture colorTexture;
4848     glBindTexture(GL_TEXTURE_2D, colorTexture);
4849     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4850     GLFramebuffer depthAndColorFBO;
4851     glBindFramebuffer(GL_FRAMEBUFFER, depthAndColorFBO);
4852     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4853     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
4854     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4855 
4856     // Clear color to blue and draw a green quad with depth=0.5
4857     glEnable(GL_DEPTH_TEST);
4858     glDepthFunc(GL_LESS);
4859     glDepthMask(GL_FALSE);
4860 
4861     angle::Vector4 clearColor = GLColor::blue.toNormalizedVector();
4862     glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
4863     glClear(GL_COLOR_BUFFER_BIT);
4864     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.5f);
4865     ASSERT_GL_NO_ERROR();
4866     // The pixel check will end renderpass.
4867     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::blue);
4868     EXPECT_PIXEL_COLOR_EQ(1 + kSize / 2, 1, GLColor::red);
4869     actualReadOnlyDepthStencilCount = getPerfCounters().readOnlyDepthStencilRenderPasses;
4870     EXPECT_EQ(expected.readOnlyDepthStencilRenderPasses, actualReadOnlyDepthStencilCount);
4871     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
4872 }
4873 
4874 // Ensures depth/stencil is not loaded after storeOp=DONT_CARE due to optimization (as opposed to
4875 // invalidate)
TEST_P(VulkanPerformanceCounterTest,RenderPassAfterRenderPassWithoutDepthStencilWrite)4876 TEST_P(VulkanPerformanceCounterTest, RenderPassAfterRenderPassWithoutDepthStencilWrite)
4877 {
4878     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
4879 
4880     angle::VulkanPerfCounters expected;
4881 
4882     // Expect rpCount+1, depth(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1),
4883     // stencil(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1)
4884     setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 0, 1, 0, 1, &expected);
4885     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 1, 0, 1, &expected);
4886 
4887     constexpr GLsizei kSize = 64;
4888 
4889     // Create FBO with color, depth and stencil.  Leave depth/stencil uninitialized.
4890     GLTexture texture;
4891     glBindTexture(GL_TEXTURE_2D, texture);
4892     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4893 
4894     GLRenderbuffer renderbuffer;
4895     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
4896     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSize, kSize);
4897 
4898     GLFramebuffer framebuffer;
4899     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4900     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4901     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
4902                               renderbuffer);
4903     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4904     ASSERT_GL_NO_ERROR();
4905 
4906     // Draw to the FBO, without enabling depth/stencil.
4907     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor());
4908     glUseProgram(program);
4909     GLint colorUniformLocation =
4910         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
4911     ASSERT_NE(-1, colorUniformLocation);
4912     ASSERT_GL_NO_ERROR();
4913 
4914     glViewport(0, 0, kSize, kSize);
4915     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
4916     drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f);
4917 
4918     // Break the render pass and ensure no depth/stencil load/store was done.
4919     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4920     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
4921 
4922     // Expect rpCount+1, depth(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1),
4923     // stencil(Clears+0, Loads+0, LoadNones+1, Stores+0, StoreNones+1)
4924     setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 0, 1, 0, 1, &expected);
4925     setExpectedCountersForStencilOps(getPerfCounters(), 0, 0, 1, 0, 1, &expected);
4926 
4927     // Draw again with similar conditions, and again make sure no load/store is done.
4928     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
4929     drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f);
4930 
4931     // Break the render pass and ensure no depth/stencil load/store was done.
4932     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4933     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
4934 
4935     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4936 }
4937 
4938 // Ensures repeated clears of various kind (all attachments, some attachments, scissored, masked
4939 // etc) don't break the render pass.
TEST_P(VulkanPerformanceCounterTest,ClearAfterClearDoesNotBreakRenderPass)4940 TEST_P(VulkanPerformanceCounterTest, ClearAfterClearDoesNotBreakRenderPass)
4941 {
4942     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
4943 
4944     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
4945 
4946     constexpr GLsizei kSize = 6;
4947 
4948     // Create a framebuffer to clear with both color and depth/stencil attachments.
4949     GLTexture color;
4950     glBindTexture(GL_TEXTURE_2D, color);
4951     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4952 
4953     GLTexture depth;
4954     glBindTexture(GL_TEXTURE_2D, depth);
4955     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, kSize, kSize, 0, GL_DEPTH_STENCIL,
4956                  GL_UNSIGNED_INT_24_8_OES, nullptr);
4957 
4958     GLFramebuffer fbo;
4959     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4960     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4961     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depth, 0);
4962     ASSERT_GL_NO_ERROR();
4963 
4964     // Clear color and depth, but not stencil.
4965     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
4966     glClearDepthf(0.0f);
4967     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4968 
4969     // Clear color and stencil, but not depth.
4970     glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
4971     glClearStencil(0x11);
4972     glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4973 
4974     // Clear depth and stencil, but not color.
4975     glClearDepthf(0.1f);
4976     glClearStencil(0x22);
4977     glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4978 
4979     // Clear masked color, and unmasked depth.
4980     glClearDepthf(0.2f);
4981     glClearColor(0.1f, 1.0f, 0.0f, 1.0f);
4982     glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
4983     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4984 
4985     // Clear unmasked color, and masked stencil.
4986     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
4987     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4988     glClearStencil(0x33);
4989     glStencilMask(0xF0);
4990     glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4991 
4992     // Clear unmasked depth and stencil.
4993     glClearDepthf(0.3f);
4994     glClearStencil(0x44);
4995     glStencilMask(0xFF);
4996     glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4997 
4998     // Clear with scissor.
4999     glEnable(GL_SCISSOR_TEST);
5000     glScissor(kSize / 3, kSize / 3, kSize / 3, kSize / 3);
5001     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
5002     glClearDepthf(1.0f);
5003     glClearStencil(0x55);
5004     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
5005 
5006     // Verify render pass count.
5007     EXPECT_EQ(getPerfCounters().renderPasses, expectedRenderPassCount);
5008 
5009     // Make sure the result is correct.  The border of the image should be blue with depth 0.3f and
5010     // stencil 0x44.  The center is red with depth 1.0f and stencil 0x55.
5011 
5012     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5013     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
5014     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
5015     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
5016 
5017     EXPECT_PIXEL_COLOR_EQ(kSize / 3, kSize / 3, GLColor::red);
5018     EXPECT_PIXEL_COLOR_EQ(2 * kSize / 3 - 1, kSize / 3, GLColor::red);
5019     EXPECT_PIXEL_COLOR_EQ(kSize / 3, 2 * kSize / 3 - 1, GLColor::red);
5020     EXPECT_PIXEL_COLOR_EQ(2 * kSize / 3 - 1, 2 * kSize / 3 - 1, GLColor::red);
5021     EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::red);
5022 
5023     glViewport(0, 0, kSize, kSize);
5024     glDisable(GL_SCISSOR_TEST);
5025 
5026     // Center: If depth is not cleared to 1, rendering would fail.
5027     glEnable(GL_DEPTH_TEST);
5028     glDepthFunc(GL_LESS);
5029 
5030     // Center: If stencil is not clear to 0x55, rendering would fail.
5031     glEnable(GL_STENCIL_TEST);
5032     glStencilFunc(GL_EQUAL, 0x55, 0xFF);
5033     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
5034     glStencilMask(0xFF);
5035 
5036     // Set up program
5037     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5038     glUseProgram(drawColor);
5039     GLint colorUniformLocation =
5040         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
5041     ASSERT_NE(colorUniformLocation, -1);
5042 
5043     // Draw green
5044     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
5045     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95f);
5046     ASSERT_GL_NO_ERROR();
5047 
5048     // Verify that only the center has changed
5049     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5050     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
5051     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
5052     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
5053 
5054     EXPECT_PIXEL_COLOR_EQ(kSize / 3, kSize / 3, GLColor::green);
5055     EXPECT_PIXEL_COLOR_EQ(2 * kSize / 3 - 1, kSize / 3, GLColor::green);
5056     EXPECT_PIXEL_COLOR_EQ(kSize / 3, 2 * kSize / 3 - 1, GLColor::green);
5057     EXPECT_PIXEL_COLOR_EQ(2 * kSize / 3 - 1, 2 * kSize / 3 - 1, GLColor::green);
5058     EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::green);
5059 
5060     // Border: If depth is not cleared to 0.3f, rendering would fail.
5061     glDepthFunc(GL_LESS);
5062 
5063     // Center: If stencil is not clear to 0x44, rendering would fail.
5064     glStencilFunc(GL_EQUAL, 0x44, 0xFF);
5065 
5066     // Draw yellow
5067     glUniform4f(colorUniformLocation, 1.0f, 1.0f, 0.0f, 1.0f);
5068     drawQuad(drawColor, essl1_shaders::PositionAttrib(), -0.5f);
5069     ASSERT_GL_NO_ERROR();
5070 
5071     // Verify that only the border has changed
5072     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
5073     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::yellow);
5074     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::yellow);
5075     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::yellow);
5076 
5077     EXPECT_PIXEL_COLOR_EQ(kSize / 3, kSize / 3, GLColor::green);
5078     EXPECT_PIXEL_COLOR_EQ(2 * kSize / 3 - 1, kSize / 3, GLColor::green);
5079     EXPECT_PIXEL_COLOR_EQ(kSize / 3, 2 * kSize / 3 - 1, GLColor::green);
5080     EXPECT_PIXEL_COLOR_EQ(2 * kSize / 3 - 1, 2 * kSize / 3 - 1, GLColor::green);
5081     EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::green);
5082 }
5083 
5084 // Ensures that changing the scissor size doesn't break the render pass.
TEST_P(VulkanPerformanceCounterTest,ScissorDoesNotBreakRenderPass)5085 TEST_P(VulkanPerformanceCounterTest, ScissorDoesNotBreakRenderPass)
5086 {
5087     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
5088 
5089     constexpr GLsizei kSize = 16;
5090 
5091     // Create a framebuffer with a color attachment.
5092     GLTexture color;
5093     glBindTexture(GL_TEXTURE_2D, color);
5094     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5095 
5096     GLFramebuffer fbo;
5097     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5098     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
5099     ASSERT_GL_NO_ERROR();
5100 
5101     // First, issue a clear and make sure it's done.  Later we can verify that areas outside
5102     // scissors are not rendered to.
5103     glClearColor(0, 0, 0, 1);
5104     glClear(GL_COLOR_BUFFER_BIT);
5105     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
5106 
5107     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
5108 
5109     // This test starts with a small scissor and gradually grows it and issues draw calls and
5110     // various kinds of clears:
5111     //
5112     // - Clear the center to red
5113     //
5114     //     +----------------------+
5115     //     | K                    |
5116     //     |                      |
5117     //     |       +-----+        |
5118     //     |       |     |        |
5119     //     |       |  R  |        |
5120     //     |       |     |        |
5121     //     |       +-----+        |
5122     //     |                      |
5123     //     |                      |
5124     //     |                      |
5125     //     |                      |
5126     //     +----------------------+
5127     //
5128     // - Draw green to center right
5129     //
5130     //     +----------------------+
5131     //     |                      |
5132     //     |              +-------+
5133     //     |       +-----+|       |
5134     //     |       |     ||       |
5135     //     |       |  R  ||  G    |
5136     //     |       |     ||       |
5137     //     |       +-----+|       |
5138     //     |              |       |
5139     //     |              |       |
5140     //     |              |       |
5141     //     |              +-------+
5142     //     +----------------------+
5143     //
5144     // - Masked clear of center column, only outputting to the blue channel
5145     //
5146     //     +----------------------+
5147     //     |      +---+           |
5148     //     |      | B |   +-------+
5149     //     |      |+--+--+|       |
5150     //     |      ||  |  ||       |
5151     //     |      ||M |R ||  G    |
5152     //     |      ||  |  ||       |
5153     //     |      |+--+--+|       |
5154     //     |      |   |   |       |
5155     //     |      |   |   |       |
5156     //     |      |   |   |       |
5157     //     |      |   |   +-------+
5158     //     +------+---+-----------+
5159     //
5160     // - Masked draw of center row, only outputting to alpha.
5161     //
5162     //     +----------------------+
5163     //     | K    +---+ K         |
5164     //     |      | B |   +-------+
5165     //     |      |+--+--+|       |
5166     //     |      ||M |R ||   G   |
5167     //     | +----++--+--++-----+ |
5168     //     | |    ||TM|TR||     | |
5169     //     | | TK |+--+--+|  TG | |
5170     //     | |    |TB |TK |     | |
5171     //     | +----+---+---+-----+ |
5172     //     |      |   |   |   G   |
5173     //     | K    | B | K +-------+
5174     //     +------+---+-----------+
5175     //
5176     // Where: K=Black, R=Red, G=Green, B=Blue, M=Magenta, T=Transparent
5177 
5178     constexpr GLsizei kClearX      = kSize / 3;
5179     constexpr GLsizei kClearY      = kSize / 3;
5180     constexpr GLsizei kClearWidth  = kSize / 3;
5181     constexpr GLsizei kClearHeight = kSize / 3;
5182 
5183     constexpr GLsizei kDrawX      = kClearX + kClearWidth + 2;
5184     constexpr GLsizei kDrawY      = kSize / 5;
5185     constexpr GLsizei kDrawWidth  = kSize - kDrawX;
5186     constexpr GLsizei kDrawHeight = 7 * kSize / 10;
5187 
5188     constexpr GLsizei kMaskedClearX      = kSize / 4;
5189     constexpr GLsizei kMaskedClearY      = kSize / 8;
5190     constexpr GLsizei kMaskedClearWidth  = kSize / 4;
5191     constexpr GLsizei kMaskedClearHeight = 7 * kSize / 8;
5192 
5193     constexpr GLsizei kMaskedDrawX      = kSize / 8;
5194     constexpr GLsizei kMaskedDrawY      = kSize / 2;
5195     constexpr GLsizei kMaskedDrawWidth  = 6 * kSize / 8;
5196     constexpr GLsizei kMaskedDrawHeight = kSize / 4;
5197 
5198     glEnable(GL_SCISSOR_TEST);
5199 
5200     // Clear center to red
5201     glScissor(kClearX, kClearY, kClearWidth, kClearHeight);
5202     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
5203     glClear(GL_COLOR_BUFFER_BIT);
5204 
5205     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5206     glUseProgram(drawColor);
5207     GLint colorUniformLocation =
5208         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
5209     ASSERT_NE(colorUniformLocation, -1);
5210 
5211     // Draw green to center right
5212     glScissor(kDrawX, kDrawY, kDrawWidth, kDrawHeight);
5213     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
5214     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0);
5215     ASSERT_GL_NO_ERROR();
5216 
5217     // Masked blue-channel clear of center column
5218     glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
5219     glScissor(kMaskedClearX, kMaskedClearY, kMaskedClearWidth, kMaskedClearHeight);
5220     glClearColor(0.5f, 0.5f, 1.0f, 0.5f);
5221     glClear(GL_COLOR_BUFFER_BIT);
5222 
5223     // Masked alpha-channel draw of center row
5224     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
5225     glScissor(kMaskedDrawX, kMaskedDrawY, kMaskedDrawWidth, kMaskedDrawHeight);
5226     glUniform4f(colorUniformLocation, 0.5f, 0.5f, 0.5f, 0.0f);
5227     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0);
5228     ASSERT_GL_NO_ERROR();
5229 
5230     // Verify render pass count.
5231     EXPECT_EQ(getPerfCounters().renderPasses, expectedRenderPassCount);
5232 
5233     // Make sure the result is correct:
5234     //
5235     //     +----------------------+  <-- 0
5236     //     | K    +---+ K         |  <-- kMaskedClearY
5237     //     |      | B |   +-------+  <-- kDrawY
5238     //     |      |+--+--+|       |  <-- kClearY
5239     //     |      ||M |R ||   G   |
5240     //     | +----++--+--++-----+ |  <-- kMaskedDrawY
5241     //     | |    ||TM|TR||     | |
5242     //     | | TK |+--+--+|  TG | |  <-- kClearY + kClearHeight
5243     //     | |    |TB |TK |     | |
5244     //     | +----+---+---+-----+ |  <-- kMaskedDrawY + kMaskedDrawHeight
5245     //     |      |   |   |   G   |
5246     //     | K    | B | K +-------+  <-- kDrawY + kDrawHeight
5247     //     +------+---+-----------+  <-- kSize == kMaskedClearY + kMaskedClearHeight
5248     //     | |    ||  |  ||     | |
5249     //     | |    ||  |  ||     |  \---> kSize == kDrawX + kDrawWidth
5250     //     | |    ||  |  ||      \-----> kMaskedDrawX + kMaskedDrawWidth
5251     //     | |    ||  |  | \-----------> kDrawX
5252     //     | |    ||  |   \------------> kClearX + kClearWidth
5253     //     | |    ||   \---------------> kMaskedClearX + kMaskedClearWidth
5254     //     | |    | \------------------> kClearX
5255     //     | |     \-------------------> kMaskedClearX
5256     //     |  \------------------------> kMaskedDrawX
5257     //      \--------------------------> 0
5258 
5259     constexpr GLsizei kClearX2       = kClearX + kClearWidth;
5260     constexpr GLsizei kClearY2       = kClearY + kClearHeight;
5261     constexpr GLsizei kDrawX2        = kDrawX + kDrawWidth;
5262     constexpr GLsizei kDrawY2        = kDrawY + kDrawHeight;
5263     constexpr GLsizei kMaskedClearX2 = kMaskedClearX + kMaskedClearWidth;
5264     constexpr GLsizei kMaskedClearY2 = kMaskedClearY + kMaskedClearHeight;
5265     constexpr GLsizei kMaskedDrawX2  = kMaskedDrawX + kMaskedDrawWidth;
5266     constexpr GLsizei kMaskedDrawY2  = kMaskedDrawY + kMaskedDrawHeight;
5267 
5268     constexpr GLColor kTransparentRed(255, 0, 0, 0);
5269     constexpr GLColor kTransparentGreen(0, 255, 0, 0);
5270     constexpr GLColor kTransparentBlue(0, 0, 255, 0);
5271     constexpr GLColor kTransparentMagenta(255, 0, 255, 0);
5272 
5273     // Verify the black areas.
5274     EXPECT_PIXEL_RECT_EQ(0, 0, kMaskedClearX, kMaskedDrawY, GLColor::black);
5275     EXPECT_PIXEL_RECT_EQ(0, kMaskedDrawY2, kMaskedClearX, kSize - kMaskedDrawY2, GLColor::black);
5276     EXPECT_PIXEL_RECT_EQ(kMaskedClearX2, 0, kSize - kMaskedClearX2, kDrawY, GLColor::black);
5277     EXPECT_PIXEL_RECT_EQ(kMaskedClearX2, kDrawY2, kSize - kMaskedClearX2, kSize - kDrawY2,
5278                          GLColor::black);
5279     EXPECT_PIXEL_RECT_EQ(kMaskedClearX, 0, kMaskedClearWidth, kMaskedClearY, GLColor::black);
5280     EXPECT_PIXEL_RECT_EQ(kMaskedClearX2, kDrawY, kDrawX - kMaskedClearX2, kClearY - kDrawY,
5281                          GLColor::black);
5282     EXPECT_PIXEL_RECT_EQ(kClearX2, kClearY, kDrawX - kClearX2, kMaskedDrawY - kClearY,
5283                          GLColor::black);
5284     EXPECT_PIXEL_RECT_EQ(0, kMaskedDrawY, kMaskedDrawX, kMaskedDrawHeight, GLColor::black);
5285     EXPECT_PIXEL_RECT_EQ(kMaskedClearX2, kMaskedDrawY2, kDrawX - kMaskedClearX2,
5286                          kSize - kMaskedDrawY2, GLColor::black);
5287 
5288     // Verify the red area:
5289     EXPECT_PIXEL_RECT_EQ(kMaskedClearX2, kClearY, kClearX2 - kMaskedClearX2, kMaskedDrawY - kClearY,
5290                          GLColor::red);
5291     // Verify the transparent red area:
5292     EXPECT_PIXEL_RECT_EQ(kMaskedClearX2, kMaskedDrawY, kClearX2 - kMaskedClearX2,
5293                          kClearY2 - kMaskedDrawY, kTransparentRed);
5294     // Verify the magenta area:
5295     EXPECT_PIXEL_RECT_EQ(kClearX, kClearY, kMaskedClearX2 - kClearX, kMaskedDrawY - kClearY,
5296                          GLColor::magenta);
5297     // Verify the transparent magenta area:
5298     EXPECT_PIXEL_RECT_EQ(kClearX, kMaskedDrawY, kMaskedClearX2 - kClearX, kClearY2 - kMaskedDrawY,
5299                          kTransparentMagenta);
5300     // Verify the green area:
5301     EXPECT_PIXEL_RECT_EQ(kDrawX, kDrawY, kDrawWidth, kMaskedDrawY - kDrawY, GLColor::green);
5302     EXPECT_PIXEL_RECT_EQ(kDrawX, kMaskedDrawY2, kDrawWidth, kDrawY2 - kMaskedDrawY2,
5303                          GLColor::green);
5304     EXPECT_PIXEL_RECT_EQ(kMaskedDrawX2, kMaskedDrawY, kDrawX2 - kMaskedDrawX2, kMaskedDrawHeight,
5305                          GLColor::green);
5306     // Verify the transparent green area:
5307     EXPECT_PIXEL_RECT_EQ(kDrawX, kMaskedDrawY, kMaskedDrawX2 - kDrawX, kMaskedDrawHeight,
5308                          kTransparentGreen);
5309     // Verify the blue area:
5310     EXPECT_PIXEL_RECT_EQ(kMaskedClearX, kMaskedClearY, kMaskedClearWidth, kClearY - kMaskedClearY,
5311                          GLColor::blue);
5312     EXPECT_PIXEL_RECT_EQ(kMaskedClearX, kMaskedDrawY2, kMaskedClearWidth,
5313                          kMaskedClearY2 - kMaskedDrawY2, GLColor::blue);
5314     EXPECT_PIXEL_RECT_EQ(kMaskedClearX, kClearY, kClearX - kMaskedClearX, kMaskedDrawY - kClearY,
5315                          GLColor::blue);
5316     // Verify the transparent blue area:
5317     EXPECT_PIXEL_RECT_EQ(kMaskedClearX, kClearY2, kMaskedClearWidth, kMaskedDrawY2 - kClearY2,
5318                          kTransparentBlue);
5319     EXPECT_PIXEL_RECT_EQ(kMaskedClearX, kMaskedDrawY, kClearX - kMaskedClearX,
5320                          kClearY2 - kMaskedDrawY, kTransparentBlue);
5321     // Verify the transparent black area:
5322     EXPECT_PIXEL_RECT_EQ(kMaskedDrawX, kMaskedDrawY, kMaskedClearX - kMaskedDrawX,
5323                          kMaskedDrawHeight, GLColor::transparentBlack);
5324     EXPECT_PIXEL_RECT_EQ(kMaskedClearX2, kClearY2, kDrawX - kMaskedClearX2,
5325                          kMaskedDrawY2 - kClearY2, GLColor::transparentBlack);
5326     EXPECT_PIXEL_RECT_EQ(kClearX2, kMaskedDrawY, kDrawX - kClearX2, kMaskedDrawHeight,
5327                          GLColor::transparentBlack);
5328 }
5329 
5330 // Tests that changing UBO bindings does not allocate new descriptor sets.
TEST_P(VulkanPerformanceCounterTest,ChangingUBOsHitsDescriptorSetCache)5331 TEST_P(VulkanPerformanceCounterTest, ChangingUBOsHitsDescriptorSetCache)
5332 {
5333     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
5334 
5335     // Set up two UBOs, one filled with "1" and the second with "2".
5336     constexpr GLsizei kCount = 64;
5337     std::vector<GLint> data1(kCount, 1);
5338     std::vector<GLint> data2(kCount, 2);
5339 
5340     GLBuffer ubo1;
5341     glBindBuffer(GL_UNIFORM_BUFFER, ubo1);
5342     glBufferData(GL_UNIFORM_BUFFER, kCount * sizeof(data1[0]), data1.data(), GL_STATIC_DRAW);
5343 
5344     GLBuffer ubo2;
5345     glBindBuffer(GL_UNIFORM_BUFFER, ubo2);
5346     glBufferData(GL_UNIFORM_BUFFER, kCount * sizeof(data2[0]), data2.data(), GL_STATIC_DRAW);
5347 
5348     // Set up a program that verifies the contents of uniform blocks.
5349     constexpr char kVS[] = R"(#version 300 es
5350 precision mediump float;
5351 in vec4 position;
5352 void main()
5353 {
5354     gl_Position = position;
5355 })";
5356 
5357     constexpr char kFS[] = R"(#version 300 es
5358 precision mediump float;
5359 uniform buf {
5360     int data[64/4];
5361 };
5362 uniform int checkValue;
5363 out vec4 outColor;
5364 
5365 void main()
5366 {
5367     for (int i = 0; i < 64/4; ++i) {
5368         if (data[i] != checkValue) {
5369             outColor = vec4(1, 0, 0, 1);
5370             return;
5371         }
5372     }
5373     outColor = vec4(0, 1, 0, 1);
5374 })";
5375 
5376     ANGLE_GL_PROGRAM(program, kVS, kFS);
5377     glUseProgram(program);
5378     ASSERT_GL_NO_ERROR();
5379 
5380     GLint uniLoc = glGetUniformLocation(program, "checkValue");
5381     ASSERT_NE(-1, uniLoc);
5382 
5383     GLuint blockIndex = glGetUniformBlockIndex(program, "buf");
5384     ASSERT_NE(blockIndex, GL_INVALID_INDEX);
5385 
5386     glUniformBlockBinding(program, blockIndex, 0);
5387     ASSERT_GL_NO_ERROR();
5388 
5389     // Set up the rest of the GL state.
5390     auto quadVerts = GetQuadVertices();
5391     GLBuffer vertexBuffer;
5392     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
5393     glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
5394                  GL_STATIC_DRAW);
5395 
5396     GLint posLoc = glGetAttribLocation(program, "position");
5397     ASSERT_NE(-1, posLoc);
5398 
5399     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
5400     glEnableVertexAttribArray(posLoc);
5401 
5402     // Draw a few times with each UBO. Stream out one pixel for post-render verification.
5403     constexpr int kIterations         = 5;
5404     constexpr GLsizei kPackBufferSize = sizeof(GLColor) * kIterations * 2;
5405 
5406     GLBuffer packBuffer;
5407     glBindBuffer(GL_PIXEL_PACK_BUFFER, packBuffer);
5408     glBufferData(GL_PIXEL_PACK_BUFFER, kPackBufferSize, nullptr, GL_STREAM_READ);
5409 
5410     GLsizei offset = 0;
5411 
5412     uint64_t expectedShaderResourcesCacheMisses = 0;
5413 
5414     for (int iteration = 0; iteration < kIterations; ++iteration)
5415     {
5416         glUniform1i(uniLoc, 1);
5417         glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo1);
5418         glDrawArrays(GL_TRIANGLES, 0, 6);
5419         glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
5420                      reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(offset)));
5421         offset += sizeof(GLColor);
5422         glUniform1i(uniLoc, 2);
5423         glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo2);
5424         glDrawArrays(GL_TRIANGLES, 0, 6);
5425         glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
5426                      reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(offset)));
5427         offset += sizeof(GLColor);
5428 
5429         // Capture the allocations counter after the first run.
5430         if (iteration == 0)
5431         {
5432             expectedShaderResourcesCacheMisses =
5433                 getPerfCounters().shaderResourcesDescriptorSetCacheMisses;
5434         }
5435     }
5436 
5437     ASSERT_GL_NO_ERROR();
5438     EXPECT_GT(expectedShaderResourcesCacheMisses, 0u);
5439 
5440     // Verify correctness first.
5441     std::vector<GLColor> expectedData(kIterations * 2, GLColor::green);
5442     std::vector<GLColor> actualData(kIterations * 2, GLColor::black);
5443 
5444     void *mapPtr = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, kPackBufferSize, GL_MAP_READ_BIT);
5445     ASSERT_NE(nullptr, mapPtr);
5446     memcpy(actualData.data(), mapPtr, kPackBufferSize);
5447 
5448     glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
5449 
5450     EXPECT_EQ(expectedData, actualData);
5451 
5452     // Check for unnecessary descriptor set allocations.
5453     uint64_t actualShaderResourcesCacheMisses =
5454         getPerfCounters().shaderResourcesDescriptorSetCacheMisses;
5455     EXPECT_EQ(expectedShaderResourcesCacheMisses, actualShaderResourcesCacheMisses);
5456 }
5457 
5458 // Test that mapping a buffer that the GPU is using as read-only ghosts the buffer, rather than
5459 // waiting for the GPU access to complete before returning a pointer to the buffer.
mappingGpuReadOnlyBufferGhostsBuffer(BufferUpdate update)5460 void VulkanPerformanceCounterTest::mappingGpuReadOnlyBufferGhostsBuffer(BufferUpdate update)
5461 {
5462     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
5463 
5464     // 1. Create a buffer, map it, fill it with red
5465     // 2. Draw with buffer (GPU read-only)
5466     // 3. Map the same buffer and fill with white
5467     //    - This should ghost the buffer, rather than ending the render pass.
5468     // 4. Draw with buffer
5469     // 5. Update the buffer with glBufferSubData() or glCopyBufferSubData
5470     // 6. Draw with the buffer
5471     // The render pass should only be broken (counters.renderPasses == 0) due to the glReadPixels()
5472     // to verify the draw at the end.
5473 
5474     const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
5475                                                  GLColor::red};
5476     const std::array<GLColor, 4> kUpdateData1 = {GLColor::white, GLColor::white, GLColor::white,
5477                                                  GLColor::white};
5478     const std::array<GLColor, 4> kUpdateData2 = {GLColor::blue, GLColor::blue, GLColor::blue,
5479                                                  GLColor::blue};
5480 
5481     GLBuffer buffer;
5482     glBindBuffer(GL_UNIFORM_BUFFER, buffer);
5483     glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
5484     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
5485     ASSERT_GL_NO_ERROR();
5486 
5487     // Draw
5488     constexpr char kVerifyUBO[] = R"(#version 300 es
5489 precision mediump float;
5490 uniform block {
5491     uvec4 data;
5492 } ubo;
5493 uniform uint expect;
5494 uniform vec4 successOutput;
5495 out vec4 colorOut;
5496 void main()
5497 {
5498     if (all(equal(ubo.data, uvec4(expect))))
5499         colorOut = successOutput;
5500     else
5501         colorOut = vec4(1.0, 0, 0, 1.0);
5502 })";
5503 
5504     ANGLE_GL_PROGRAM(verifyUbo, essl3_shaders::vs::Simple(), kVerifyUBO);
5505     glUseProgram(verifyUbo);
5506 
5507     GLint expectLoc = glGetUniformLocation(verifyUbo, "expect");
5508     ASSERT_NE(-1, expectLoc);
5509     GLint successLoc = glGetUniformLocation(verifyUbo, "successOutput");
5510     ASSERT_NE(-1, successLoc);
5511 
5512     glUniform1ui(expectLoc, kInitialData[0].asUint());
5513     glUniform4f(successLoc, 0, 1, 0, 1);
5514 
5515     drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
5516     ASSERT_GL_NO_ERROR();
5517 
5518     // Map the buffer and update it.
5519     // This should ghost the buffer and avoid breaking the render pass, since the GPU is only
5520     // reading it.
5521     void *mappedBuffer =
5522         glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), GL_MAP_WRITE_BIT);
5523     // 'renderPasses == 0' here means the render pass was broken and a new one was started.
5524     ASSERT_EQ(getPerfCounters().renderPasses, 1u);
5525     ASSERT_EQ(getPerfCounters().buffersGhosted, 1u);
5526 
5527     memcpy(mappedBuffer, kUpdateData1.data(), sizeof(kInitialData));
5528 
5529     glUnmapBuffer(GL_UNIFORM_BUFFER);
5530     ASSERT_GL_NO_ERROR();
5531 
5532     // Verify that the buffer has the updated value.
5533     glUniform1ui(expectLoc, kUpdateData1[0].asUint());
5534     glUniform4f(successLoc, 0, 0, 1, 1);
5535 
5536     drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
5537     ASSERT_GL_NO_ERROR();
5538     ASSERT_EQ(getPerfCounters().renderPasses, 1u);
5539 
5540     // Update the buffer
5541     updateBuffer(update, GL_UNIFORM_BUFFER, 0, sizeof(kUpdateData2), kUpdateData2.data());
5542     ASSERT_GL_NO_ERROR();
5543     ASSERT_EQ(getPerfCounters().renderPasses, 1u);
5544 
5545     // Verify that the buffer has the updated value.
5546     glUniform1ui(expectLoc, kUpdateData2[0].asUint());
5547     glUniform4f(successLoc, 0, 1, 1, 1);
5548 
5549     drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
5550     ASSERT_GL_NO_ERROR();
5551     ASSERT_EQ(getPerfCounters().renderPasses, 1u);
5552 
5553     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
5554 }
5555 
5556 // Test that mapping a buffer that the GPU is using as read-only ghosts the buffer, rather than
5557 // waiting for the GPU access to complete before returning a pointer to the buffer.  This test uses
5558 // glBufferSubData to update the buffer.
TEST_P(VulkanPerformanceCounterTest,MappingGpuReadOnlyBufferGhostsBuffer_SubData)5559 TEST_P(VulkanPerformanceCounterTest, MappingGpuReadOnlyBufferGhostsBuffer_SubData)
5560 {
5561     mappingGpuReadOnlyBufferGhostsBuffer(BufferUpdate::SubData);
5562 }
5563 
5564 // Same as MappingGpuReadOnlyBufferGhostsBuffer_SubData, but using glCopyBufferSubData to update the
5565 // buffer.
TEST_P(VulkanPerformanceCounterTest,MappingGpuReadOnlyBufferGhostsBuffer_Copy)5566 TEST_P(VulkanPerformanceCounterTest, MappingGpuReadOnlyBufferGhostsBuffer_Copy)
5567 {
5568     mappingGpuReadOnlyBufferGhostsBuffer(BufferUpdate::Copy);
5569 }
5570 
partialBufferUpdateShouldNotBreakRenderPass(BufferUpdate update)5571 void VulkanPerformanceCounterTest::partialBufferUpdateShouldNotBreakRenderPass(BufferUpdate update)
5572 {
5573     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
5574 
5575     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
5576     if (!hasPreferCPUForBufferSubData())
5577     {
5578         ++expectedRenderPassCount;
5579     }
5580 
5581     const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::green, GLColor::blue,
5582                                                  GLColor::yellow};
5583     const std::array<GLColor, 1> kUpdateData1 = {GLColor::cyan};
5584     const std::array<GLColor, 3> kUpdateData2 = {GLColor::magenta, GLColor::black, GLColor::white};
5585 
5586     GLBuffer buffer;
5587     glBindBuffer(GL_UNIFORM_BUFFER, buffer);
5588     glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
5589     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
5590     ASSERT_GL_NO_ERROR();
5591 
5592     constexpr char kVS[] = R"(#version 300 es
5593 precision highp float;
5594 uniform float height;
5595 void main()
5596 {
5597     // gl_VertexID    x    y
5598     //      0        -1   -1
5599     //      1         1   -1
5600     //      2        -1    1
5601     //      3         1    1
5602     int bit0 = gl_VertexID & 1;
5603     int bit1 = gl_VertexID >> 1;
5604     gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, 0, 1);
5605 })";
5606 
5607     constexpr char kFS[] = R"(#version 300 es
5608 precision highp float;
5609 out vec4 colorOut;
5610 uniform block {
5611     uvec4 data;
5612 } ubo;
5613 uniform uvec4 expect;
5614 uniform vec4 successColor;
5615 void main()
5616 {
5617     if (all(equal(ubo.data, expect)))
5618         colorOut = successColor;
5619     else
5620         colorOut = vec4(0);
5621 })";
5622 
5623     ANGLE_GL_PROGRAM(program, kVS, kFS);
5624     glUseProgram(program);
5625 
5626     GLint expectLoc = glGetUniformLocation(program, "expect");
5627     ASSERT_NE(-1, expectLoc);
5628     GLint successLoc = glGetUniformLocation(program, "successColor");
5629     ASSERT_NE(-1, successLoc);
5630 
5631     glClearColor(0, 0, 0, 0);
5632     glClear(GL_COLOR_BUFFER_BIT);
5633 
5634     glEnable(GL_BLEND);
5635     glBlendFunc(GL_ONE, GL_ONE);
5636 
5637     // Draw once, using the buffer in the render pass.
5638     glUniform4ui(expectLoc, kInitialData[0].asUint(), kInitialData[1].asUint(),
5639                  kInitialData[2].asUint(), kInitialData[3].asUint());
5640     glUniform4f(successLoc, 1, 0, 0, 1);
5641     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5642 
5643     // Upload a small part of the buffer, and draw again.
5644     updateBuffer(update, GL_UNIFORM_BUFFER, 0, sizeof(kUpdateData1), kUpdateData1.data());
5645 
5646     glUniform4ui(expectLoc, kUpdateData1[0].asUint(), kInitialData[1].asUint(),
5647                  kInitialData[2].asUint(), kInitialData[3].asUint());
5648     glUniform4f(successLoc, 0, 1, 0, 1);
5649     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5650 
5651     // Upload a large part of the buffer, and draw again.
5652     updateBuffer(update, GL_UNIFORM_BUFFER, sizeof(kUpdateData1), sizeof(kUpdateData2),
5653                  kUpdateData2.data());
5654 
5655     glUniform4ui(expectLoc, kUpdateData1[0].asUint(), kUpdateData2[0].asUint(),
5656                  kUpdateData2[1].asUint(), kUpdateData2[2].asUint());
5657     glUniform4f(successLoc, 0, 0, 1, 1);
5658     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5659 
5660     // Verify results
5661     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
5662     ASSERT_GL_NO_ERROR();
5663 
5664     // Only one render pass should have been used.
5665     EXPECT_EQ(getPerfCounters().renderPasses, expectedRenderPassCount);
5666 }
5667 
5668 // Verifies that BufferSubData calls don't cause a render pass break when it only uses the buffer
5669 // read-only.  This test uses glBufferSubData to update the buffer.
TEST_P(VulkanPerformanceCounterTest,PartialBufferUpdateShouldNotBreakRenderPass_SubData)5670 TEST_P(VulkanPerformanceCounterTest, PartialBufferUpdateShouldNotBreakRenderPass_SubData)
5671 {
5672     partialBufferUpdateShouldNotBreakRenderPass(BufferUpdate::SubData);
5673 }
5674 
5675 // Same as PartialBufferUpdateShouldNotBreakRenderPass_SubData, but using glCopyBufferSubData to
5676 // update the buffer.
TEST_P(VulkanPerformanceCounterTest,PartialBufferUpdateShouldNotBreakRenderPass_Copy)5677 TEST_P(VulkanPerformanceCounterTest, PartialBufferUpdateShouldNotBreakRenderPass_Copy)
5678 {
5679     partialBufferUpdateShouldNotBreakRenderPass(BufferUpdate::Copy);
5680 }
5681 
bufferSubDataShouldNotTriggerSyncState(BufferUpdate update)5682 void VulkanPerformanceCounterTest::bufferSubDataShouldNotTriggerSyncState(BufferUpdate update)
5683 {
5684     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
5685 
5686     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
5687     glUseProgram(testProgram);
5688 
5689     GLint posLoc = glGetAttribLocation(testProgram, essl1_shaders::PositionAttrib());
5690     ASSERT_NE(-1, posLoc);
5691 
5692     setupQuadVertexBuffer(0.5f, 1.0f);
5693     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5694     glEnableVertexAttribArray(posLoc);
5695 
5696     glDrawArrays(GL_TRIANGLES, 0, 6);
5697     ASSERT_GL_NO_ERROR();
5698     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5699 
5700     EXPECT_EQ(getPerfCounters().vertexArraySyncStateCalls, 1u);
5701 
5702     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5703     size_t bufferSize                          = sizeof(quadVertices[0]) * quadVertices.size();
5704 
5705     updateBuffer(update, GL_ARRAY_BUFFER, 0, bufferSize, quadVertices.data());
5706 
5707     glDrawArrays(GL_TRIANGLES, 0, 6);
5708     ASSERT_GL_NO_ERROR();
5709     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5710 
5711     EXPECT_EQ(getPerfCounters().vertexArraySyncStateCalls, 1u);
5712 
5713     // Verify the BufferData with a whole buffer size is treated like the SubData call.
5714     glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices[0]) * quadVertices.size(),
5715                  quadVertices.data(), GL_STATIC_DRAW);
5716     glDrawArrays(GL_TRIANGLES, 0, 6);
5717     ASSERT_GL_NO_ERROR();
5718     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5719 
5720     EXPECT_EQ(getPerfCounters().vertexArraySyncStateCalls, 1u);
5721 }
5722 
5723 // Verifies that BufferSubData calls don't trigger state updates for non-translated formats.  This
5724 // test uses glBufferSubData to update the buffer.
TEST_P(VulkanPerformanceCounterTest,BufferSubDataShouldNotTriggerSyncState_SubData)5725 TEST_P(VulkanPerformanceCounterTest, BufferSubDataShouldNotTriggerSyncState_SubData)
5726 {
5727     bufferSubDataShouldNotTriggerSyncState(BufferUpdate::SubData);
5728 }
5729 
5730 // Same as BufferSubDataShouldNotTriggerSyncState_SubData, but using glCopyBufferSubData to update
5731 // the buffer.
TEST_P(VulkanPerformanceCounterTest,BufferSubDataShouldNotTriggerSyncState_Copy)5732 TEST_P(VulkanPerformanceCounterTest, BufferSubDataShouldNotTriggerSyncState_Copy)
5733 {
5734     bufferSubDataShouldNotTriggerSyncState(BufferUpdate::Copy);
5735 }
5736 
5737 // Verifies that rendering to backbuffer discards depth/stencil.
TEST_P(VulkanPerformanceCounterTest,SwapShouldInvalidateDepthStencil)5738 TEST_P(VulkanPerformanceCounterTest, SwapShouldInvalidateDepthStencil)
5739 {
5740     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
5741 
5742     angle::VulkanPerfCounters expected;
5743 
5744     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0),
5745     // stencil(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
5746     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 0, 0, &expected);
5747     setExpectedCountersForStencilOps(getPerfCounters(), 1, 0, 0, 0, 0, &expected);
5748 
5749     // Clear to verify that _some_ counters did change (as opposed to for example all being reset on
5750     // swap)
5751     glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
5752 
5753     glEnable(GL_DEPTH_TEST);
5754     glDepthMask(GL_TRUE);
5755     glDepthFunc(GL_ALWAYS);
5756     glEnable(GL_STENCIL_TEST);
5757     glStencilFunc(GL_ALWAYS, 0x00, 0xFF);
5758     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
5759 
5760     ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
5761     drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.5f);
5762     ASSERT_GL_NO_ERROR();
5763 
5764     // Swap buffers to implicitely resolve
5765     swapBuffers();
5766     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
5767 }
5768 
5769 // Verifies that rendering to MSAA backbuffer discards depth/stencil.
TEST_P(VulkanPerformanceCounterTest_MSAA,SwapShouldInvalidateDepthStencil)5770 TEST_P(VulkanPerformanceCounterTest_MSAA, SwapShouldInvalidateDepthStencil)
5771 {
5772     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
5773 
5774     angle::VulkanPerfCounters expected;
5775 
5776     // Expect rpCount+1, depth(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0),
5777     // stencil(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
5778     setExpectedCountersForDepthOps(getPerfCounters(), 1, 1, 0, 0, 0, 0, &expected);
5779     setExpectedCountersForStencilOps(getPerfCounters(), 1, 0, 0, 0, 0, &expected);
5780 
5781     // Clear to verify that _some_ counters did change (as opposed to for example all being reset on
5782     // swap)
5783     glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
5784 
5785     glEnable(GL_DEPTH_TEST);
5786     glDepthMask(GL_TRUE);
5787     glDepthFunc(GL_ALWAYS);
5788     glEnable(GL_STENCIL_TEST);
5789     glStencilFunc(GL_ALWAYS, 0x00, 0xFF);
5790     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
5791 
5792     ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
5793     drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.5f);
5794     ASSERT_GL_NO_ERROR();
5795 
5796     // Swap buffers to implicitely resolve
5797     swapBuffers();
5798     EXPECT_DEPTH_STENCIL_OP_COUNTERS(getPerfCounters(), expected);
5799 }
5800 
5801 // Verifies that multisample swapchain resolve occurs in subpass.
TEST_P(VulkanPerformanceCounterTest_MSAA,SwapShouldResolveWithSubpass)5802 TEST_P(VulkanPerformanceCounterTest_MSAA, SwapShouldResolveWithSubpass)
5803 {
5804     angle::VulkanPerfCounters expected;
5805     // Expect rpCount+1, color(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
5806     setExpectedCountersForColorOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
5807 
5808     uint64_t expectedResolvesSubpass = getPerfCounters().swapchainResolveInSubpass + 1;
5809     uint64_t expectedResolvesOutside = getPerfCounters().swapchainResolveOutsideSubpass;
5810 
5811     // Clear color.
5812     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
5813     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
5814 
5815     // Set up program
5816     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5817     glUseProgram(drawColor);
5818     GLint colorUniformLocation =
5819         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
5820     ASSERT_NE(colorUniformLocation, -1);
5821 
5822     // Draw green
5823     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
5824     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95f);
5825     ASSERT_GL_NO_ERROR();
5826 
5827     // Swap buffers to implicitly resolve
5828     swapBuffers();
5829     EXPECT_EQ(getPerfCounters().swapchainResolveInSubpass, expectedResolvesSubpass);
5830     EXPECT_EQ(getPerfCounters().swapchainResolveOutsideSubpass, expectedResolvesOutside);
5831 
5832     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
5833 }
5834 
5835 // Verifies that in a multisample swapchain, drawing to the default FBO followed by user FBO and
5836 // then swapping triggers the resolve outside the optimization subpass.
TEST_P(VulkanPerformanceCounterTest_MSAA,SwapAfterDrawToDifferentFBOsShouldResolveOutsideSubpass)5837 TEST_P(VulkanPerformanceCounterTest_MSAA, SwapAfterDrawToDifferentFBOsShouldResolveOutsideSubpass)
5838 {
5839     constexpr GLsizei kSize = 16;
5840     angle::VulkanPerfCounters expected;
5841     // Expect rpCount+1, color(Clears+1, Loads+0, LoadNones+0, Stores+2, StoreNones+0)
5842     setExpectedCountersForColorOps(getPerfCounters(), 1, 1, 0, 0, 2, 0, &expected);
5843 
5844     uint64_t expectedResolvesSubpass = getPerfCounters().swapchainResolveInSubpass;
5845     uint64_t expectedResolvesOutside = getPerfCounters().swapchainResolveOutsideSubpass + 1;
5846 
5847     // Create a framebuffer to clear.
5848     GLTexture color;
5849     glBindTexture(GL_TEXTURE_2D, color);
5850     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5851     GLFramebuffer fbo;
5852     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5853     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
5854     ASSERT_GL_NO_ERROR();
5855 
5856     // Clear color.
5857     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
5858     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
5859 
5860     // Set up program
5861     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5862     glUseProgram(drawColor);
5863     GLint colorUniformLocation =
5864         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
5865     ASSERT_NE(colorUniformLocation, -1);
5866 
5867     // Draw green to default framebuffer
5868     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5869     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
5870     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95f);
5871     ASSERT_GL_NO_ERROR();
5872 
5873     // Draw blue to the user framebuffer
5874     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5875     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
5876     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95f);
5877     ASSERT_GL_NO_ERROR();
5878 
5879     // Swap buffers to resolve outside the optimization subpass
5880     swapBuffers();
5881     EXPECT_EQ(getPerfCounters().swapchainResolveInSubpass, expectedResolvesSubpass);
5882     EXPECT_EQ(getPerfCounters().swapchainResolveOutsideSubpass, expectedResolvesOutside);
5883 
5884     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
5885 }
5886 
5887 // Verifies that in a multisample swapchain, subpass resolve only happens when the render pass
5888 // covers the entire area.
TEST_P(VulkanPerformanceCounterTest_MSAA,ResolveWhenRenderPassNotEntireArea)5889 TEST_P(VulkanPerformanceCounterTest_MSAA, ResolveWhenRenderPassNotEntireArea)
5890 {
5891     constexpr GLsizei kSize = 16;
5892     angle::VulkanPerfCounters expected;
5893     // Expect rpCount+1, color(Clears+0, Loads+1, LoadNones+0, Stores+2, StoreNones+0)
5894     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 1, 0, 2, 0, &expected);
5895 
5896     uint64_t expectedResolvesSubpass = getPerfCounters().swapchainResolveInSubpass;
5897     uint64_t expectedResolvesOutside = getPerfCounters().swapchainResolveOutsideSubpass + 1;
5898 
5899     // Create a framebuffer to clear.
5900     GLTexture color;
5901     glBindTexture(GL_TEXTURE_2D, color);
5902     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5903     GLFramebuffer fbo;
5904     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5905     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
5906     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5907     ASSERT_GL_NO_ERROR();
5908 
5909     // Clear color.
5910     glDisable(GL_SCISSOR_TEST);
5911     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
5912     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
5913     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
5914 
5915     // Set up program
5916     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5917     glUseProgram(drawColor);
5918     GLint colorUniformLocation =
5919         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
5920     ASSERT_NE(colorUniformLocation, -1);
5921 
5922     // Scissor the render area
5923     glEnable(GL_SCISSOR_TEST);
5924     glScissor(kSize / 4, kSize / 4, kSize / 2, kSize / 2);
5925 
5926     // Draw blue to the user framebuffer
5927     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5928     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
5929     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95f);
5930     ASSERT_GL_NO_ERROR();
5931 
5932     // Draw green to default framebuffer
5933     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5934     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
5935     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95f);
5936     ASSERT_GL_NO_ERROR();
5937 
5938     // Swap buffers, which should not resolve the image in subpass
5939     swapBuffers();
5940     EXPECT_EQ(getPerfCounters().swapchainResolveInSubpass, expectedResolvesSubpass);
5941     EXPECT_EQ(getPerfCounters().swapchainResolveOutsideSubpass, expectedResolvesOutside);
5942 
5943     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
5944 }
5945 
5946 // Tests that uniform updates eventually stop updating descriptor sets.
TEST_P(VulkanPerformanceCounterTest,UniformUpdatesHitDescriptorSetCache)5947 TEST_P(VulkanPerformanceCounterTest, UniformUpdatesHitDescriptorSetCache)
5948 {
5949     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
5950 
5951     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5952     glUseProgram(testProgram);
5953     GLint posLoc = glGetAttribLocation(testProgram, essl1_shaders::PositionAttrib());
5954     GLint uniLoc = glGetUniformLocation(testProgram, essl1_shaders::ColorUniform());
5955 
5956     std::array<Vector3, 6> quadVerts = GetQuadVertices();
5957 
5958     GLBuffer vbo;
5959     glBindBuffer(GL_ARRAY_BUFFER, vbo);
5960     glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
5961                  GL_STATIC_DRAW);
5962 
5963     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5964     glEnableVertexAttribArray(posLoc);
5965 
5966     ASSERT_GL_NO_ERROR();
5967 
5968     // Choose a number of iterations sufficiently large to ensure all uniforms are cached.
5969     constexpr int kIterations = 2000;
5970 
5971     // First pass: cache all the uniforms.
5972     RNG rng;
5973     for (int iteration = 0; iteration < kIterations; ++iteration)
5974     {
5975         Vector3 randomVec3 = RandomVec3(rng.randomInt(), 0.0f, 1.0f);
5976 
5977         glUniform4f(uniLoc, randomVec3.x(), randomVec3.y(), randomVec3.z(), 1.0f);
5978         glDrawArrays(GL_TRIANGLES, 0, 6);
5979 
5980         GLColor expectedColor = GLColor(randomVec3);
5981         EXPECT_PIXEL_COLOR_NEAR(0, 0, expectedColor, 5);
5982     }
5983 
5984     ASSERT_GL_NO_ERROR();
5985 
5986     uint64_t expectedCacheMisses = getPerfCounters().uniformsAndXfbDescriptorSetCacheMisses;
5987     EXPECT_GT(expectedCacheMisses, 0u);
5988 
5989     // Second pass: ensure all the uniforms are cached.
5990     for (int iteration = 0; iteration < kIterations; ++iteration)
5991     {
5992         Vector3 randomVec3 = RandomVec3(rng.randomInt(), 0.0f, 1.0f);
5993 
5994         glUniform4f(uniLoc, randomVec3.x(), randomVec3.y(), randomVec3.z(), 1.0f);
5995         glDrawArrays(GL_TRIANGLES, 0, 6);
5996 
5997         GLColor expectedColor = GLColor(randomVec3);
5998         EXPECT_PIXEL_COLOR_NEAR(0, 0, expectedColor, 5);
5999     }
6000 
6001     ASSERT_GL_NO_ERROR();
6002 
6003     uint64_t actualCacheMisses = getPerfCounters().uniformsAndXfbDescriptorSetCacheMisses;
6004     EXPECT_EQ(expectedCacheMisses, actualCacheMisses);
6005 }
6006 
6007 // Test one texture sampled by fragment shader, then image load it by compute
6008 // shader, at last fragment shader do something else.
TEST_P(VulkanPerformanceCounterTest_ES31,DrawDispatchImageReadDrawWithEndRP)6009 TEST_P(VulkanPerformanceCounterTest_ES31, DrawDispatchImageReadDrawWithEndRP)
6010 {
6011 
6012     constexpr char kVSSource[] = R"(#version 310 es
6013 in vec4 a_position;
6014 out vec2 v_texCoord;
6015 
6016 void main()
6017 {
6018     gl_Position = vec4(a_position.xy, 0.0, 1.0);
6019     v_texCoord = a_position.xy * 0.5 + vec2(0.5);
6020 })";
6021 
6022     constexpr char kFSSource[] = R"(#version 310 es
6023 precision mediump float;
6024 uniform sampler2D u_tex2D;
6025 in vec2 v_texCoord;
6026 out vec4 out_FragColor;
6027 void main()
6028 {
6029     out_FragColor = texture(u_tex2D, v_texCoord);
6030 })";
6031 
6032     constexpr char kFSSource1[] = R"(#version 310 es
6033 precision mediump float;
6034 out vec4 out_FragColor;
6035 void main()
6036 {
6037     out_FragColor = vec4(1.0);
6038 })";
6039 
6040     constexpr char kCSSource[] = R"(#version 310 es
6041 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
6042 layout(rgba32f, binding=0) readonly  uniform highp image2D uIn;
6043 layout(std140, binding=0) buffer buf {
6044     vec4 outData;
6045 };
6046 
6047 void main()
6048 {
6049     outData = imageLoad(uIn, ivec2(gl_LocalInvocationID.xy));
6050 })";
6051 
6052     GLfloat initValue[4] = {1.0, 1.0, 1.0, 1.0};
6053 
6054     // Step 1: Set up a simple 2D Texture rendering loop.
6055     GLTexture texture;
6056     glBindTexture(GL_TEXTURE_2D, texture);
6057     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
6058     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, initValue);
6059     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6060     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6061 
6062     GLBuffer vertexBuffer;
6063     GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
6064     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
6065     glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
6066 
6067     ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
6068     glUseProgram(program);
6069 
6070     GLint posLoc = glGetAttribLocation(program, "a_position");
6071     ASSERT_NE(-1, posLoc);
6072 
6073     glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
6074     glEnableVertexAttribArray(posLoc);
6075     ASSERT_GL_NO_ERROR();
6076     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
6077 
6078     GLBuffer ssbo;
6079     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
6080     glBufferData(GL_SHADER_STORAGE_BUFFER, 16, nullptr, GL_STREAM_DRAW);
6081     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
6082 
6083     // This is actually suboptimal, and ideally only one render pass should be necessary.
6084     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 2;
6085 
6086     glDrawArrays(GL_TRIANGLES, 0, 6);
6087     ASSERT_GL_NO_ERROR();
6088 
6089     // Step 2: load this image through compute
6090     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
6091     glUseProgram(csProgram);
6092 
6093     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
6094     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
6095 
6096     glDispatchCompute(1, 1, 1);
6097     EXPECT_GL_NO_ERROR();
6098 
6099     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
6100     const GLfloat *ptr = reinterpret_cast<const GLfloat *>(
6101         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT));
6102 
6103     EXPECT_GL_NO_ERROR();
6104     for (unsigned int idx = 0; idx < 4; idx++)
6105     {
6106         EXPECT_EQ(1.0, *(ptr + idx));
6107     }
6108 
6109     // Step3
6110     ANGLE_GL_PROGRAM(program2, kVSSource, kFSSource1);
6111     glUseProgram(program2);
6112     glDrawArrays(GL_TRIANGLES, 0, 6);
6113     ASSERT_GL_NO_ERROR();
6114 
6115     uint64_t actualRenderPassCount = getPerfCounters().renderPasses;
6116     EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
6117 }
6118 
6119 // Test one texture sampled by fragment shader, followed by glReadPixels, then image
6120 // load it by compute shader, and at last fragment shader do something else.
TEST_P(VulkanPerformanceCounterTest_ES31,DrawDispatchImageReadDrawWithoutEndRP)6121 TEST_P(VulkanPerformanceCounterTest_ES31, DrawDispatchImageReadDrawWithoutEndRP)
6122 {
6123 
6124     constexpr char kVSSource[] = R"(#version 310 es
6125 in vec4 a_position;
6126 out vec2 v_texCoord;
6127 
6128 void main()
6129 {
6130     gl_Position = vec4(a_position.xy, 0.0, 1.0);
6131     v_texCoord = a_position.xy * 0.5 + vec2(0.5);
6132 })";
6133 
6134     constexpr char kFSSource[] = R"(#version 310 es
6135 precision mediump float;
6136 uniform sampler2D u_tex2D;
6137 in vec2 v_texCoord;
6138 out vec4 out_FragColor;
6139 void main()
6140 {
6141     out_FragColor = texture(u_tex2D, v_texCoord);
6142 })";
6143 
6144     constexpr char kFSSource1[] = R"(#version 310 es
6145 precision mediump float;
6146 out vec4 out_FragColor;
6147 void main()
6148 {
6149     out_FragColor = vec4(1.0);
6150 })";
6151 
6152     constexpr char kCSSource[] = R"(#version 310 es
6153 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
6154 layout(rgba32f, binding=0) readonly  uniform highp image2D uIn;
6155 layout(std140, binding=0) buffer buf {
6156     vec4 outData;
6157 };
6158 
6159 void main()
6160 {
6161     outData = imageLoad(uIn, ivec2(gl_LocalInvocationID.xy));
6162 })";
6163 
6164     GLfloat initValue[4] = {1.0, 1.0, 1.0, 1.0};
6165 
6166     // Step 1: Set up a simple 2D Texture rendering loop.
6167     GLTexture texture;
6168     glBindTexture(GL_TEXTURE_2D, texture);
6169     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
6170     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, initValue);
6171     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6172     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6173 
6174     GLBuffer vertexBuffer;
6175     GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
6176     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
6177     glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
6178 
6179     GLBuffer ssbo;
6180     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
6181     glBufferData(GL_SHADER_STORAGE_BUFFER, 16, nullptr, GL_STREAM_DRAW);
6182     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
6183 
6184     ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
6185     glUseProgram(program);
6186 
6187     GLint posLoc = glGetAttribLocation(program, "a_position");
6188     ASSERT_NE(-1, posLoc);
6189 
6190     glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
6191     glEnableVertexAttribArray(posLoc);
6192     ASSERT_GL_NO_ERROR();
6193 
6194     glDrawArrays(GL_TRIANGLES, 0, 6);
6195     ASSERT_GL_NO_ERROR();
6196 
6197     // Call glReadPixels to reset the getPerfCounters().renderPasses
6198     std::vector<GLColor> actualColors(1);
6199     glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, actualColors.data());
6200 
6201     // Ideally, the following "FS sample + CS image load + FS something", should
6202     // handle in one render pass.
6203     // Currently, we can ensure the first of "FS sample + CS image load" in one
6204     // render pass, but will start new render pass if following the last FS operations,
6205     // which need to be optimized further.
6206     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 2;
6207 
6208     // Now this texture owns none layout transition
6209     glDrawArrays(GL_TRIANGLES, 0, 6);
6210     ASSERT_GL_NO_ERROR();
6211 
6212     // Step 2: load this image through compute
6213     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
6214     glUseProgram(csProgram);
6215 
6216     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
6217     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
6218     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
6219 
6220     glDispatchCompute(1, 1, 1);
6221     EXPECT_GL_NO_ERROR();
6222 
6223     // Step3
6224     ANGLE_GL_PROGRAM(program2, kVSSource, kFSSource1);
6225     glUseProgram(program2);
6226     glDrawArrays(GL_TRIANGLES, 0, 6);
6227     ASSERT_GL_NO_ERROR();
6228 
6229     uint64_t actualRenderPassCount = getPerfCounters().renderPasses;
6230     EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
6231 }
6232 
6233 // Test that one texture sampled by fragment shader, compute shader and fragment
6234 // shader sequentlly.
TEST_P(VulkanPerformanceCounterTest_ES31,TextureSampleByDrawDispatchDraw)6235 TEST_P(VulkanPerformanceCounterTest_ES31, TextureSampleByDrawDispatchDraw)
6236 {
6237     constexpr char kVSSource[] = R"(#version 310 es
6238 in vec4 a_position;
6239 out vec2 v_texCoord;
6240 
6241 void main()
6242 {
6243 gl_Position = vec4(a_position.xy, 0.0, 1.0);
6244 v_texCoord = a_position.xy * 0.5 + vec2(0.5);
6245 })";
6246 
6247     constexpr char kFSSource[] = R"(#version 310 es
6248 uniform sampler2D u_tex2D;
6249 precision highp float;
6250 in vec2 v_texCoord;
6251 out vec4 out_FragColor;
6252 void main()
6253 {
6254 out_FragColor = texture(u_tex2D, v_texCoord);
6255 })";
6256 
6257     constexpr char kCSSource[] = R"(#version 310 es
6258 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
6259 precision highp sampler2D;
6260 uniform sampler2D tex;
6261 layout(std140, binding=0) buffer buf {
6262 vec4 outData;
6263 };
6264 void main()
6265 {
6266 uint x = gl_LocalInvocationID.x;
6267 uint y = gl_LocalInvocationID.y;
6268 outData = texture(tex, vec2(x, y));
6269 })";
6270 
6271     GLfloat initValue[4] = {1.0, 1.0, 1.0, 1.0};
6272 
6273     // Step 1: Set up a simple 2D Texture rendering loop.
6274     GLTexture texture;
6275     glBindTexture(GL_TEXTURE_2D, texture);
6276     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
6277     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, initValue);
6278     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6279     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6280 
6281     GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
6282 
6283     GLBuffer vertexBuffer;
6284     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
6285     glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
6286 
6287     ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
6288     glUseProgram(program);
6289 
6290     GLint posLoc = glGetAttribLocation(program, "a_position");
6291     ASSERT_NE(-1, posLoc);
6292 
6293     glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
6294     glEnableVertexAttribArray(posLoc);
6295     ASSERT_GL_NO_ERROR();
6296 
6297     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6298     ASSERT_GL_NO_ERROR();
6299     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
6300 
6301     // Step 2: sample this texture through compute
6302     GLBuffer ssbo;
6303     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
6304     glBufferData(GL_SHADER_STORAGE_BUFFER, 16, nullptr, GL_STREAM_DRAW);
6305     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
6306 
6307     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
6308     glUseProgram(csProgram);
6309 
6310     glBindTexture(GL_TEXTURE_2D, texture);
6311     glUniform1i(glGetUniformLocation(csProgram, "tex"), 0);
6312     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
6313     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
6314 
6315     glDispatchCompute(1, 1, 1);
6316     EXPECT_GL_NO_ERROR();
6317 
6318     // Step3: use the first program sample texture again
6319     glUseProgram(program);
6320     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6321     ASSERT_GL_NO_ERROR();
6322 
6323     uint64_t actualRenderPassCount = getPerfCounters().renderPasses;
6324     EXPECT_EQ(expectedRenderPassCount, actualRenderPassCount);
6325 }
6326 
6327 // Verify a mid-render pass clear of a newly enabled attachment uses LOAD_OP_CLEAR.
TEST_P(VulkanPerformanceCounterTest,DisableThenMidRenderPassClear)6328 TEST_P(VulkanPerformanceCounterTest, DisableThenMidRenderPassClear)
6329 {
6330     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
6331 
6332     // This optimization is not implemented when this workaround is in effect.
6333     ANGLE_SKIP_TEST_IF(hasPreferDrawOverClearAttachments());
6334 
6335     angle::VulkanPerfCounters expected;
6336 
6337     // Expect rpCount+1, color(Clears+1, Loads+0, LoadNones+0, Stores+2, StoreNones+0)
6338     // vkCmdClearAttachments should be used for color attachment 0.
6339     setExpectedCountersForColorOps(getPerfCounters(), 1, 1, 0, 0, 2, 0, &expected);
6340     expected.colorClearAttachments = getPerfCounters().colorClearAttachments + 1;
6341 
6342     GLFramebuffer fbo;
6343     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6344 
6345     GLTexture textures[2];
6346 
6347     glBindTexture(GL_TEXTURE_2D, textures[0]);
6348     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
6349     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
6350 
6351     glBindTexture(GL_TEXTURE_2D, textures[1]);
6352     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
6353     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textures[1], 0);
6354 
6355     // Only enable attachment 0.
6356     GLenum drawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_NONE};
6357     glDrawBuffers(2, drawBuffers);
6358 
6359     // Draw red.
6360     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
6361     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.5f);
6362     ASSERT_GL_NO_ERROR();
6363 
6364     // Enable attachment 1.
6365     drawBuffers[1] = GL_COLOR_ATTACHMENT1;
6366     glDrawBuffers(2, drawBuffers);
6367 
6368     // Clear both attachments to green.
6369     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
6370     glClear(GL_COLOR_BUFFER_BIT);
6371 
6372     constexpr char kFS[] = R"(#version 300 es
6373 precision highp float;
6374 layout(location = 0) out vec4 my_FragColor0;
6375 layout(location = 1) out vec4 my_FragColor1;
6376 void main()
6377 {
6378     my_FragColor0 = vec4(0.0, 0.0, 1.0, 1.0);
6379     my_FragColor1 = vec4(0.0, 0.0, 1.0, 1.0);
6380 })";
6381 
6382     // Draw blue to both attachments.
6383     ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Simple(), kFS);
6384     drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f);
6385     ASSERT_GL_NO_ERROR();
6386 
6387     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
6388 
6389     // Verify attachment 0.
6390     glReadBuffer(GL_COLOR_ATTACHMENT0);
6391     ASSERT_GL_NO_ERROR();
6392     EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
6393     // Verify attachment 1.
6394     glReadBuffer(GL_COLOR_ATTACHMENT1);
6395     ASSERT_GL_NO_ERROR();
6396     EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
6397 
6398     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
6399     EXPECT_CLEAR_ATTACHMENTS_COUNTER(expected.colorClearAttachments,
6400                                      getPerfCounters().colorClearAttachments);
6401 
6402     // Expect rpCount+1, color(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0)
6403     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 1, 0, 1, 0, &expected);
6404 
6405     GLFramebuffer fbo2;
6406     glBindFramebuffer(GL_FRAMEBUFFER, fbo2);
6407     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[1], 0);
6408 
6409     glEnable(GL_BLEND);
6410     glBlendFunc(GL_ONE, GL_ONE);
6411 
6412     // Blend red
6413     drawQuad(redProgram, essl3_shaders::PositionAttrib(), 0.5f);
6414     ASSERT_GL_NO_ERROR();
6415 
6416     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
6417 
6418     // Verify purple
6419     glReadBuffer(GL_COLOR_ATTACHMENT0);
6420     EXPECT_PIXEL_EQ(0, 0, 255, 0, 255, 255);
6421     ASSERT_GL_NO_ERROR();
6422 
6423     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
6424 }
6425 
6426 // Copy of ClearTest.InceptionScissorClears.
6427 // Clears many small concentric rectangles using scissor regions. Verifies vkCmdClearAttachments()
6428 // is used for the scissored clears, rather than vkCmdDraw().
TEST_P(VulkanPerformanceCounterTest,InceptionScissorClears)6429 TEST_P(VulkanPerformanceCounterTest, InceptionScissorClears)
6430 {
6431     // https://issuetracker.google.com/166809097
6432     ANGLE_SKIP_TEST_IF(IsQualcomm() && IsVulkan());
6433 
6434     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
6435 
6436     angle::VulkanPerfCounters expected;
6437 
6438     // Expect rpCount+1, color(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
6439     setExpectedCountersForColorOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
6440 
6441     angle::RNG rng;
6442 
6443     constexpr GLuint kSize = 16;
6444 
6445     // Create a square user FBO so we have more control over the dimensions.
6446     GLFramebuffer fbo;
6447     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6448 
6449     GLRenderbuffer rbo;
6450     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
6451     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
6452 
6453     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
6454     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6455 
6456     glViewport(0, 0, kSize, kSize);
6457 
6458     // Clear small concentric squares using scissor.
6459     std::vector<GLColor> expectedColors;
6460     // TODO(syoussefi): verify this
6461     [[maybe_unused]] uint64_t numScissoredClears = 0;
6462     for (GLuint index = 0; index < (kSize - 1) / 2; index++)
6463     {
6464         // Do the first clear without the scissor.
6465         if (index > 0)
6466         {
6467             glEnable(GL_SCISSOR_TEST);
6468             glScissor(index, index, kSize - (index * 2), kSize - (index * 2));
6469             ++numScissoredClears;
6470         }
6471 
6472         GLColor color = RandomColor(&rng);
6473         expectedColors.push_back(color);
6474         Vector4 floatColor = color.toNormalizedVector();
6475         glClearColor(floatColor[0], floatColor[1], floatColor[2], floatColor[3]);
6476         glClear(GL_COLOR_BUFFER_BIT);
6477     }
6478 
6479     ASSERT_GL_NO_ERROR();
6480 
6481     // Make sure everything was done in a single renderpass.
6482     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
6483 
6484     std::vector<GLColor> actualColors(expectedColors.size());
6485     glReadPixels(0, kSize / 2, actualColors.size(), 1, GL_RGBA, GL_UNSIGNED_BYTE,
6486                  actualColors.data());
6487 
6488     EXPECT_EQ(expectedColors, actualColors);
6489 
6490     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
6491 }
6492 
6493 // Copy of ClearTest.Depth16Scissored.
6494 // Clears many small concentric rectangles using scissor regions. Verifies vkCmdClearAttachments()
6495 // is used for the scissored clears, rather than vkCmdDraw().
TEST_P(VulkanPerformanceCounterTest,Depth16Scissored)6496 TEST_P(VulkanPerformanceCounterTest, Depth16Scissored)
6497 {
6498     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
6499 
6500     GLRenderbuffer renderbuffer;
6501     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
6502     constexpr int kRenderbufferSize = 64;
6503     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kRenderbufferSize,
6504                           kRenderbufferSize);
6505 
6506     GLFramebuffer fbo;
6507     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6508     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
6509 
6510     glClearDepthf(0.0f);
6511     glClear(GL_DEPTH_BUFFER_BIT);
6512 
6513     glEnable(GL_SCISSOR_TEST);
6514     constexpr int kNumSteps = 13;
6515     // TODO(syoussefi): verify this
6516     [[maybe_unused]] uint64_t numScissoredClears = 0;
6517     for (int ndx = 1; ndx < kNumSteps; ndx++)
6518     {
6519         float perc = static_cast<float>(ndx) / static_cast<float>(kNumSteps);
6520         glScissor(0, 0, static_cast<int>(kRenderbufferSize * perc),
6521                   static_cast<int>(kRenderbufferSize * perc));
6522         glClearDepthf(perc);
6523         glClear(GL_DEPTH_BUFFER_BIT);
6524         ++numScissoredClears;
6525     }
6526 
6527     // Make sure everything was done in a single renderpass.
6528     EXPECT_EQ(getPerfCounters().renderPasses, 1u);
6529 }
6530 
6531 // Copy of ClearTest.InceptionScissorClears.
6532 // Clears many small concentric rectangles using scissor regions.
TEST_P(VulkanPerformanceCounterTest,DrawThenInceptionScissorClears)6533 TEST_P(VulkanPerformanceCounterTest, DrawThenInceptionScissorClears)
6534 {
6535     // https://issuetracker.google.com/166809097
6536     ANGLE_SKIP_TEST_IF(IsQualcomm() && IsVulkan());
6537 
6538     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
6539 
6540     angle::VulkanPerfCounters expected;
6541 
6542     // Expect rpCount+1, color(Clears+0, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
6543     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 0, 0, 1, 0, &expected);
6544 
6545     angle::RNG rng;
6546     std::vector<GLColor> expectedColors;
6547     constexpr GLuint kSize = 16;
6548 
6549     // Create a square user FBO so we have more control over the dimensions.
6550     GLFramebuffer fbo;
6551     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6552 
6553     GLRenderbuffer rbo;
6554     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
6555     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
6556 
6557     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
6558     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6559 
6560     glViewport(0, 0, kSize, kSize);
6561 
6562     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
6563     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.5f);
6564     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6565     expectedColors.push_back(GLColor::red);
6566 
6567     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
6568 
6569     // Expect rpCount+1, color(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0)
6570     // TODO: Optimize scissored clears to use loadOp = CLEAR. anglebug.com/5194
6571     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 1, 0, 1, 0, &expected);
6572 
6573     // Draw small concentric squares using scissor.
6574     // TODO(syoussefi): verify this
6575     [[maybe_unused]] uint64_t numScissoredClears = 0;
6576     // All clears are to a scissored render area.
6577     for (GLuint index = 1; index < (kSize - 1) / 2; index++)
6578     {
6579         glEnable(GL_SCISSOR_TEST);
6580         glScissor(index, index, kSize - (index * 2), kSize - (index * 2));
6581         ++numScissoredClears;
6582 
6583         GLColor color = RandomColor(&rng);
6584         expectedColors.push_back(color);
6585         Vector4 floatColor = color.toNormalizedVector();
6586         glClearColor(floatColor[0], floatColor[1], floatColor[2], floatColor[3]);
6587         glClear(GL_COLOR_BUFFER_BIT);
6588     }
6589 
6590     ASSERT_GL_NO_ERROR();
6591 
6592     // Make sure everything was done in a single renderpass.
6593     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
6594 
6595     // Close the render pass to update the performance counters.
6596     std::vector<GLColor> actualColors(expectedColors.size());
6597     glReadPixels(0, kSize / 2, actualColors.size(), 1, GL_RGBA, GL_UNSIGNED_BYTE,
6598                  actualColors.data());
6599     EXPECT_EQ(expectedColors, actualColors);
6600 
6601     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
6602 }
6603 
6604 // Test that color clears are respected after invalidate
TEST_P(VulkanPerformanceCounterTest,ColorClearAfterInvalidate)6605 TEST_P(VulkanPerformanceCounterTest, ColorClearAfterInvalidate)
6606 {
6607     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
6608 
6609     angle::VulkanPerfCounters expected;
6610 
6611     GLFramebuffer framebuffer;
6612     GLTexture texture;
6613     GLRenderbuffer renderbuffer;
6614     setupForColorDepthOpsTest(&framebuffer, &texture, &renderbuffer);
6615 
6616     // Execute the scenario that this test is for:
6617 
6618     // color+depth invalidate, color+depth clear
6619     //
6620     // Expected:
6621     //   rpCount+1,
6622     //   depth(Clears+1, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
6623     //   color(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
6624     setExpectedCountersForDepthOps(getPerfCounters(), 0, 1, 0, 0, 0, 0, &expected);
6625     setExpectedCountersForColorOps(getPerfCounters(), 1, 1, 0, 0, 1, 0, &expected);
6626 
6627     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
6628 
6629     // Invalidate (loadOp C=DONTCARE, D=DONTCARE)
6630     const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_COLOR_ATTACHMENT0};
6631     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, discards);
6632     ASSERT_GL_NO_ERROR();
6633 
6634     // Clear (loadOp C=CLEAR, D=CLEAR)
6635     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
6636 
6637     // Save existing draw buffers
6638     GLint maxDrawBuffers = 0;
6639     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
6640     std::vector<GLenum> savedDrawBuffers(maxDrawBuffers);
6641     for (int i = 0; i < maxDrawBuffers; i++)
6642         glGetIntegerv(GL_DRAW_BUFFER0 + i, (GLint *)&savedDrawBuffers[i]);
6643 
6644     // Draw depth-only
6645     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
6646     glDrawBuffers(0, nullptr);
6647     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
6648     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6649     glDrawBuffers(maxDrawBuffers, savedDrawBuffers.data());
6650     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6651     ASSERT_GL_NO_ERROR();
6652 
6653     // Invalidate depth only (storeOp should be C=STORE/D=CLEAR)
6654     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
6655 
6656     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6657 
6658     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
6659 
6660     // Use swapBuffers and then check how many loads and stores were actually done
6661     swapBuffers();
6662     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
6663     EXPECT_DEPTH_OP_COUNTERS(getPerfCounters(), expected);
6664     ASSERT_GL_NO_ERROR();
6665 }
6666 
6667 // Test that depth clears are picked up as loadOp even if a color blit is done in between.
TEST_P(VulkanPerformanceCounterTest,DepthClearThenColorBlitThenDraw)6668 TEST_P(VulkanPerformanceCounterTest, DepthClearThenColorBlitThenDraw)
6669 {
6670     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
6671 
6672     angle::VulkanPerfCounters expected;
6673 
6674     GLFramebuffer framebuffer;
6675     GLTexture texture;
6676     GLRenderbuffer renderbuffer;
6677     setupForColorDepthOpsTest(&framebuffer, &texture, &renderbuffer);
6678 
6679     // Execute the scenario that this test is for:
6680 
6681     // color+depth clear, blit color as source, draw
6682     //
6683     // Expected:
6684     //   rpCount+1,
6685     //   depth(Clears+1, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
6686     //   color(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0)
6687     setExpectedCountersForDepthOps(getPerfCounters(), 0, 1, 0, 0, 1, 0, &expected);
6688     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 1, 0, 1, 0, &expected);
6689 
6690     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
6691     glClearColor(0, 1, 0, 1);
6692     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
6693 
6694     // Blit color into another FBO
6695     GLTexture destColor;
6696     glBindTexture(GL_TEXTURE_2D, destColor);
6697     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kOpsTestSize, kOpsTestSize);
6698 
6699     GLFramebuffer destFbo;
6700     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destFbo);
6701     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, destColor, 0);
6702     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
6703 
6704     glBlitFramebuffer(0, 0, kOpsTestSize, kOpsTestSize, 0, 0, kOpsTestSize, kOpsTestSize,
6705                       GL_COLOR_BUFFER_BIT, GL_NEAREST);
6706 
6707     // Draw back to the original framebuffer
6708     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
6709     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
6710     drawQuad(program, essl1_shaders::PositionAttrib(), 1.f);
6711     ASSERT_GL_NO_ERROR();
6712 
6713     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
6714 
6715     // Use swapBuffers and then check how many loads and stores were actually done.  The clear
6716     // applied to depth should be done as loadOp, not flushed during the blit.
6717     swapBuffers();
6718     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
6719     EXPECT_DEPTH_OP_COUNTERS(getPerfCounters(), expected);
6720     ASSERT_GL_NO_ERROR();
6721 
6722     // Verify results
6723     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6724 
6725     // Result of blit should be green
6726     glBindFramebuffer(GL_READ_FRAMEBUFFER, destFbo);
6727     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6728 }
6729 
6730 // Ensure that image gets marked as defined after clear + invalidate + clear, and that we use
6731 // LoadOp=Load for a renderpass which draws to it after the clear has been flushed with a blit.
TEST_P(VulkanPerformanceCounterTest,InvalidateThenRepeatedClearThenBlitThenDraw)6732 TEST_P(VulkanPerformanceCounterTest, InvalidateThenRepeatedClearThenBlitThenDraw)
6733 {
6734     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
6735 
6736     angle::VulkanPerfCounters expected;
6737 
6738     constexpr GLsizei kSize = 2;
6739 
6740     // tex[0] is what's being tested.  The others are helpers.
6741     GLTexture tex[3];
6742     for (int i = 0; i < 3; ++i)
6743     {
6744         glBindTexture(GL_TEXTURE_2D, tex[i]);
6745         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6746                      nullptr);
6747     }
6748 
6749     GLFramebuffer fbo[3];
6750     for (int i = 0; i < 3; ++i)
6751     {
6752         glBindFramebuffer(GL_FRAMEBUFFER, fbo[i]);
6753         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex[i], 0);
6754     }
6755 
6756     // Expect rpCount+1, color(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0)
6757     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 1, 0, 1, 0, &expected);
6758 
6759     // Clear the image through fbo[0], and make sure the clear is flushed outside the render pass.
6760     glBindFramebuffer(GL_FRAMEBUFFER, fbo[0]);
6761     glClearColor(1, 0, 0, 1);
6762     glClear(GL_COLOR_BUFFER_BIT);
6763     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6764 
6765     // Invalidate it such that the contents are marked as undefined. Note that regardless of the
6766     // marking, the image is cleared nevertheless.
6767     const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
6768     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
6769 
6770     // Clear it again to the same color.
6771     glClear(GL_COLOR_BUFFER_BIT);
6772 
6773     // Bind tex[0] to fbo[1] as the read fbo, and blit to fbo[2]
6774     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo[1]);
6775     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex[0], 0);
6776     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[2]);
6777 
6778     // Blit.  This causes the second clear of tex[0] to be flushed outside the render pass, which
6779     // may be optimized out.
6780     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
6781 
6782     // Switch back to fbo[0] and draw with blend.  If the second clear is dropped and the image
6783     // continues to be marked as invalidated, loadOp=DONT_CARE would be used instead of loadOp=LOAD.
6784     glBindFramebuffer(GL_FRAMEBUFFER, fbo[0]);
6785 
6786     glEnable(GL_BLEND);
6787     glBlendFunc(GL_ONE, GL_ONE);
6788 
6789     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
6790     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
6791 
6792     EXPECT_EQ(expected.renderPasses, getPerfCounters().renderPasses);
6793 
6794     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
6795     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
6796 }
6797 
6798 // Ensure that image gets marked as defined after clear + invalidate + clear, and that we use
6799 // LoadOp=Load for a renderpass which draws to it after the clear has been flushed with read pixels.
TEST_P(VulkanPerformanceCounterTest,InvalidateThenRepeatedClearThenReadbackThenDraw)6800 TEST_P(VulkanPerformanceCounterTest, InvalidateThenRepeatedClearThenReadbackThenDraw)
6801 {
6802     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
6803 
6804     angle::VulkanPerfCounters expected;
6805 
6806     constexpr GLsizei kSize = 2;
6807 
6808     GLTexture tex;
6809     glBindTexture(GL_TEXTURE_2D, tex);
6810     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
6811 
6812     GLFramebuffer fbo;
6813     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6814     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
6815 
6816     // Expect rpCount+1, color(Clears+0, Loads+1, LoadNones+0, Stores+1, StoreNones+0)
6817     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 1, 0, 1, 0, &expected);
6818 
6819     // Clear the image, and make sure the clear is flushed outside the render pass.
6820     glClearColor(1, 0, 0, 1);
6821     glClear(GL_COLOR_BUFFER_BIT);
6822     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6823 
6824     // Invalidate it such that the contents are marked as undefined.  Note that regarldess of the
6825     // marking, the image is cleared nevertheless.
6826     const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
6827     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
6828 
6829     // Clear it again to the same color, and make sure the clear is flushed outside the render pass,
6830     // which may be optimized out.
6831     glClear(GL_COLOR_BUFFER_BIT);
6832     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6833 
6834     // Draw with blend.  If the second clear is dropped and the image continues to be marked as
6835     // invalidated, loadOp=DONT_CARE would be used instead of loadOp=LOAD.
6836     glEnable(GL_BLEND);
6837     glBlendFunc(GL_ONE, GL_ONE);
6838 
6839     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
6840     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
6841 
6842     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
6843     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
6844 }
6845 
6846 // Test that draw after invalidate restores the contents of the color image.
TEST_P(VulkanPerformanceCounterTest,InvalidateThenDraw)6847 TEST_P(VulkanPerformanceCounterTest, InvalidateThenDraw)
6848 {
6849     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
6850 
6851     angle::VulkanPerfCounters expected;
6852 
6853     constexpr GLsizei kSize = 2;
6854 
6855     GLTexture tex;
6856     glBindTexture(GL_TEXTURE_2D, tex);
6857     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
6858 
6859     GLFramebuffer fbo;
6860     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6861     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
6862 
6863     // Expect rpCount+1, color(Clears+0, Loads+0, LoadNones+0, Stores+1, StoreNones+0)
6864     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 0, 0, 1, 0, &expected);
6865 
6866     ANGLE_GL_PROGRAM(blue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
6867     drawQuad(blue, essl1_shaders::PositionAttrib(), 0);
6868 
6869     // Invalidate it such that the contents are marked as undefined
6870     const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
6871     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
6872 
6873     // Draw again.
6874     ANGLE_GL_PROGRAM(green, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6875     drawQuad(green, essl1_shaders::PositionAttrib(), 0);
6876 
6877     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6878     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
6879 }
6880 
6881 // Test that masked draw after invalidate does NOT restore the contents of the color image.
TEST_P(VulkanPerformanceCounterTest,InvalidateThenMaskedDraw)6882 TEST_P(VulkanPerformanceCounterTest, InvalidateThenMaskedDraw)
6883 {
6884     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
6885 
6886     angle::VulkanPerfCounters expected;
6887 
6888     constexpr GLsizei kSize = 2;
6889 
6890     GLTexture tex;
6891     glBindTexture(GL_TEXTURE_2D, tex);
6892     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
6893 
6894     GLFramebuffer fbo;
6895     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6896     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
6897 
6898     // Expect rpCount+1, color(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0)
6899     setExpectedCountersForColorOps(getPerfCounters(), 1, 0, 0, 0, 0, 0, &expected);
6900 
6901     ANGLE_GL_PROGRAM(blue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
6902     drawQuad(blue, essl1_shaders::PositionAttrib(), 0);
6903 
6904     // Invalidate it such that the contents are marked as undefined
6905     const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
6906     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
6907 
6908     // Draw again.
6909     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
6910     ANGLE_GL_PROGRAM(green, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6911     drawQuad(green, essl1_shaders::PositionAttrib(), 0);
6912 
6913     // Break the render pass
6914     glFinish();
6915 
6916     EXPECT_COLOR_OP_COUNTERS(getPerfCounters(), expected);
6917 }
6918 
6919 // Tests that the submission counters count the implicit submission in eglSwapBuffers().
TEST_P(VulkanPerformanceCounterTest,VerifySubmitCountersForSwapBuffer)6920 TEST_P(VulkanPerformanceCounterTest, VerifySubmitCountersForSwapBuffer)
6921 {
6922     uint64_t expectedVkQueueSubmitCount      = getPerfCounters().vkQueueSubmitCallsTotal;
6923     uint64_t expectedCommandQueueSubmitCount = getPerfCounters().commandQueueSubmitCallsTotal;
6924 
6925     // One submission coming from clear and read back
6926     ++expectedVkQueueSubmitCount;
6927     ++expectedCommandQueueSubmitCount;
6928 
6929     glClearColor(1, 0, 0, 1);
6930     glClear(GL_COLOR_BUFFER_BIT);
6931     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6932 
6933     EXPECT_EQ(getPerfCounters().vkQueueSubmitCallsTotal, expectedVkQueueSubmitCount);
6934     EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedCommandQueueSubmitCount);
6935 
6936     // One submission coming from draw and implicit submission from eglSwapBuffers
6937     ++expectedVkQueueSubmitCount;
6938     ++expectedCommandQueueSubmitCount;
6939 
6940     ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6941     drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 1.f);
6942     swapBuffers();
6943 
6944     EXPECT_EQ(getPerfCounters().vkQueueSubmitCallsTotal, expectedVkQueueSubmitCount);
6945     EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedCommandQueueSubmitCount);
6946 }
6947 
6948 // Tests that PreferSubmitAtFBOBoundary feature works properly. Bind to different FBO and should
6949 // trigger submit of previous FBO. In this specific test, we switch to system default framebuffer
6950 // which is always considered as "dirty".
TEST_P(VulkanPerformanceCounterTest,VerifySubmitCounterForSwitchUserFBOToSystemFramebuffer)6951 TEST_P(VulkanPerformanceCounterTest, VerifySubmitCounterForSwitchUserFBOToSystemFramebuffer)
6952 {
6953     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
6954 
6955     uint64_t expectedCommandQueueSubmitCount = getPerfCounters().commandQueueSubmitCallsTotal;
6956     uint64_t expectedCommandQueueWaitSemaphoreCount =
6957         getPerfCounters().commandQueueWaitSemaphoresTotal;
6958 
6959     GLFramebuffer framebuffer;
6960     GLTexture texture;
6961     setupForColorOpsTest(&framebuffer, &texture);
6962 
6963     // Draw
6964     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
6965     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6966     ASSERT_GL_NO_ERROR();
6967 
6968     // One submission coming from glBindFramebuffer and draw
6969     ++expectedCommandQueueSubmitCount;
6970     // This submission should not wait for any semaphore.
6971 
6972     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6973     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
6974     ASSERT_GL_NO_ERROR();
6975 
6976     EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedCommandQueueSubmitCount);
6977     EXPECT_EQ(getPerfCounters().commandQueueWaitSemaphoresTotal,
6978               expectedCommandQueueWaitSemaphoreCount);
6979 
6980     // This submission must wait for ANI's semaphore
6981     ++expectedCommandQueueWaitSemaphoreCount;
6982     ++expectedCommandQueueSubmitCount;
6983     swapBuffers();
6984     EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedCommandQueueSubmitCount);
6985     EXPECT_EQ(getPerfCounters().commandQueueWaitSemaphoresTotal,
6986               expectedCommandQueueWaitSemaphoreCount);
6987 }
6988 
6989 // Tests that PreferSubmitAtFBOBoundary feature works properly. Bind to different FBO and should
6990 // trigger submit of previous FBO. In this specific test, we test bind to a new user FBO which we
6991 // used to had a bug.
TEST_P(VulkanPerformanceCounterTest,VerifySubmitCounterForSwitchUserFBOToDirtyUserFBO)6992 TEST_P(VulkanPerformanceCounterTest, VerifySubmitCounterForSwitchUserFBOToDirtyUserFBO)
6993 {
6994     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
6995 
6996     uint64_t expectedCommandQueueSubmitCount = getPerfCounters().commandQueueSubmitCallsTotal;
6997     uint64_t expectedCommandQueueWaitSemaphoreCount =
6998         getPerfCounters().commandQueueWaitSemaphoresTotal;
6999 
7000     GLFramebuffer framebuffer;
7001     GLTexture texture;
7002     setupForColorOpsTest(&framebuffer, &texture);
7003 
7004     // Draw
7005     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
7006     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7007     ASSERT_GL_NO_ERROR();
7008 
7009     if (hasPreferSubmitAtFBOBoundary())
7010     {
7011         // One submission coming from glBindFramebuffer and draw
7012         ++expectedCommandQueueSubmitCount;
7013         // This submission should not wait for any semaphore.
7014     }
7015 
7016     // Create and bind to a new FBO
7017     GLFramebuffer framebuffer2;
7018     GLTexture texture2;
7019     setupForColorOpsTest(&framebuffer2, &texture2);
7020     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7021     ASSERT_GL_NO_ERROR();
7022     ++expectedCommandQueueSubmitCount;
7023     // This submission should not wait for ANI's semaphore
7024     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7025 
7026     EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedCommandQueueSubmitCount);
7027     EXPECT_EQ(getPerfCounters().commandQueueWaitSemaphoresTotal,
7028               expectedCommandQueueWaitSemaphoreCount);
7029 }
7030 
7031 // Ensure that glFlush doesn't lead to vkQueueSubmit if there's nothing to submit.
TEST_P(VulkanPerformanceCounterTest,UnnecessaryFlushDoesntCauseSubmission)7032 TEST_P(VulkanPerformanceCounterTest, UnnecessaryFlushDoesntCauseSubmission)
7033 {
7034     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
7035 
7036     swapBuffers();
7037     uint64_t expectedVkQueueSubmitCalls = getPerfCounters().vkQueueSubmitCallsTotal;
7038 
7039     glFlush();
7040     glFlush();
7041     glFlush();
7042 
7043     // Nothing was recorded, so there shouldn't be anything to flush.
7044     glFinish();
7045     EXPECT_EQ(getPerfCounters().vkQueueSubmitCallsTotal, expectedVkQueueSubmitCalls);
7046 
7047     glClearColor(1, 0, 0, 1);
7048     glClear(GL_COLOR_BUFFER_BIT);
7049     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7050 
7051     // One submission for the above readback
7052     ++expectedVkQueueSubmitCalls;
7053 
7054     glFinish();
7055     EXPECT_EQ(getPerfCounters().vkQueueSubmitCallsTotal, expectedVkQueueSubmitCalls);
7056 
7057     glFlush();
7058     glFlush();
7059     glFlush();
7060 
7061     // No additional submissions since last one
7062     glFinish();
7063     EXPECT_EQ(getPerfCounters().vkQueueSubmitCallsTotal, expectedVkQueueSubmitCalls);
7064 }
7065 
7066 // Ensure that glFenceSync doesn't lead to vkQueueSubmit if there's nothing to submit.
TEST_P(VulkanPerformanceCounterTest,SyncWihtoutCommandsDoesntCauseSubmission)7067 TEST_P(VulkanPerformanceCounterTest, SyncWihtoutCommandsDoesntCauseSubmission)
7068 {
7069     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
7070 
7071     swapBuffers();
7072     uint64_t expectedVkQueueSubmitCalls = getPerfCounters().vkQueueSubmitCallsTotal;
7073 
7074     glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
7075 
7076     // Nothing was recorded, so there shouldn't be anything to flush.
7077     glFinish();
7078     EXPECT_EQ(getPerfCounters().vkQueueSubmitCallsTotal, expectedVkQueueSubmitCalls);
7079 }
7080 
7081 // In single-buffer mode, ensure that unnecessary eglSwapBuffers is completely ignored (i.e. doesn't
7082 // lead to a command queue submission, consuming a submission serial).  Used to verify an
7083 // optimization that ensures CPU throttling doesn't incur GPU bubbles with unnecessary
7084 // eglSwapBuffers calls.
TEST_P(VulkanPerformanceCounterTest_SingleBuffer,SwapBuffersAfterFlushIgnored)7085 TEST_P(VulkanPerformanceCounterTest_SingleBuffer, SwapBuffersAfterFlushIgnored)
7086 {
7087     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
7088 
7089     // Set mode to single buffer
7090     EXPECT_EGL_TRUE(eglSurfaceAttrib(getEGLWindow()->getDisplay(), getEGLWindow()->getSurface(),
7091                                      EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER));
7092 
7093     // Swap buffers so mode switch takes effect.
7094     swapBuffers();
7095     uint64_t expectedCommandQueueSubmitCalls = getPerfCounters().commandQueueSubmitCallsTotal;
7096 
7097     // Further swap buffers should be ineffective.
7098     swapBuffers();
7099     swapBuffers();
7100     swapBuffers();
7101     swapBuffers();
7102 
7103     EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedCommandQueueSubmitCalls);
7104 
7105     // Issue commands and flush them.
7106     glClearColor(1, 0, 0, 1);
7107     glClear(GL_COLOR_BUFFER_BIT);
7108     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7109 
7110     // One submission for the above readback
7111     ++expectedCommandQueueSubmitCalls;
7112     EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedCommandQueueSubmitCalls);
7113 
7114     // Further swap buffers should again be ineffective.
7115     swapBuffers();
7116     swapBuffers();
7117     swapBuffers();
7118     swapBuffers();
7119     swapBuffers();
7120 
7121     EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedCommandQueueSubmitCalls);
7122 }
7123 
7124 // Verifies that we share Texture descriptor sets between programs.
TEST_P(VulkanPerformanceCounterTest,TextureDescriptorsAreShared)7125 TEST_P(VulkanPerformanceCounterTest, TextureDescriptorsAreShared)
7126 {
7127     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
7128 
7129     ANGLE_GL_PROGRAM(testProgram1, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
7130     ANGLE_GL_PROGRAM(testProgram2, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
7131 
7132     GLTexture texture1;
7133     glBindTexture(GL_TEXTURE_2D, texture1);
7134     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
7135     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7136     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7137 
7138     GLTexture texture2;
7139     glBindTexture(GL_TEXTURE_2D, texture2);
7140     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
7141     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7142     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7143 
7144     setupQuadVertexBuffer(0.5f, 1.0f);
7145 
7146     glUseProgram(testProgram1);
7147 
7148     ASSERT_GL_NO_ERROR();
7149 
7150     glBindTexture(GL_TEXTURE_2D, texture1);
7151     glDrawArrays(GL_TRIANGLES, 0, 6);
7152     glBindTexture(GL_TEXTURE_2D, texture2);
7153     glDrawArrays(GL_TRIANGLES, 0, 6);
7154 
7155     ASSERT_GL_NO_ERROR();
7156 
7157     GLuint expectedCacheMisses = getPerfCounters().textureDescriptorSetCacheMisses;
7158     EXPECT_GT(expectedCacheMisses, 0u);
7159 
7160     glUseProgram(testProgram2);
7161 
7162     glBindTexture(GL_TEXTURE_2D, texture1);
7163     glDrawArrays(GL_TRIANGLES, 0, 6);
7164     glBindTexture(GL_TEXTURE_2D, texture2);
7165     glDrawArrays(GL_TRIANGLES, 0, 6);
7166 
7167     ASSERT_GL_NO_ERROR();
7168 
7169     GLuint actualCacheMisses = getPerfCounters().textureDescriptorSetCacheMisses;
7170     EXPECT_EQ(expectedCacheMisses, actualCacheMisses);
7171 }
7172 
7173 // Verifies that we share Uniform Buffer descriptor sets between programs.
TEST_P(VulkanPerformanceCounterTest,UniformBufferDescriptorsAreShared)7174 TEST_P(VulkanPerformanceCounterTest, UniformBufferDescriptorsAreShared)
7175 {
7176     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
7177 
7178     constexpr char kFS[] = R"(#version 300 es
7179 precision mediump float;
7180 out vec4 color;
7181 uniform block {
7182    vec4 uniColor;
7183 };
7184 
7185 void main() {
7186     color = uniColor;
7187 })";
7188 
7189     ANGLE_GL_PROGRAM(testProgram1, essl3_shaders::vs::Simple(), kFS);
7190     ANGLE_GL_PROGRAM(testProgram2, essl3_shaders::vs::Simple(), kFS);
7191 
7192     Vector4 red(1, 0, 0, 1);
7193     Vector4 green(0, 1, 0, 1);
7194 
7195     GLBuffer ubo1;
7196     glBindBuffer(GL_UNIFORM_BUFFER, ubo1);
7197     glBufferData(GL_UNIFORM_BUFFER, sizeof(Vector4), red.data(), GL_STATIC_DRAW);
7198 
7199     GLBuffer ubo2;
7200     glBindBuffer(GL_UNIFORM_BUFFER, ubo2);
7201     glBufferData(GL_UNIFORM_BUFFER, sizeof(Vector4), green.data(), GL_STATIC_DRAW);
7202 
7203     setupQuadVertexBuffer(0.5f, 1.0f);
7204 
7205     glUseProgram(testProgram1);
7206 
7207     ASSERT_GL_NO_ERROR();
7208 
7209     glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo1);
7210     glDrawArrays(GL_TRIANGLES, 0, 6);
7211     glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo2);
7212     glDrawArrays(GL_TRIANGLES, 0, 6);
7213 
7214     ASSERT_GL_NO_ERROR();
7215 
7216     GLuint expectedCacheMisses = getPerfCounters().shaderResourcesDescriptorSetCacheMisses;
7217     EXPECT_GT(expectedCacheMisses, 0u);
7218 
7219     glUseProgram(testProgram2);
7220 
7221     glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo1);
7222     glDrawArrays(GL_TRIANGLES, 0, 6);
7223     glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo2);
7224     glDrawArrays(GL_TRIANGLES, 0, 6);
7225 
7226     ASSERT_GL_NO_ERROR();
7227 
7228     GLuint actualCacheMisses = getPerfCounters().shaderResourcesDescriptorSetCacheMisses;
7229     EXPECT_EQ(expectedCacheMisses, actualCacheMisses);
7230 }
7231 
7232 // Test modifying texture size and render to it does not cause VkFramebuffer cache explode
TEST_P(VulkanPerformanceCounterTest,ResizeFBOAttachedTexture)7233 TEST_P(VulkanPerformanceCounterTest, ResizeFBOAttachedTexture)
7234 {
7235     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
7236 
7237     int32_t framebufferCacheSizeBefore = getPerfCounters().framebufferCacheSize;
7238     GLTexture texture;
7239     GLFramebuffer fbo;
7240     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7241     for (GLint texWidth = 1; texWidth <= 10; texWidth++)
7242     {
7243         for (GLint texHeight = 1; texHeight <= 10; texHeight++)
7244         {
7245             // Allocate texture
7246             glBindTexture(GL_TEXTURE_2D, texture);
7247             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA,
7248                          GL_UNSIGNED_BYTE, nullptr);
7249             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7250             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7251             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
7252             ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7253 
7254             // Draw to FBO backed by the texture
7255             glUseProgram(blueProgram);
7256             drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7257             ASSERT_GL_NO_ERROR();
7258             EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
7259         }
7260     }
7261     int32_t framebufferCacheSizeAfter    = getPerfCounters().framebufferCacheSize;
7262     int32_t framebufferCacheSizeIncrease = framebufferCacheSizeAfter - framebufferCacheSizeBefore;
7263     int32_t expectedFramebufferCacheSizeIncrease = (hasSupportsImagelessFramebuffer()) ? 0 : 1;
7264     printf("\tframebufferCacheCountIncrease:%u\n", framebufferCacheSizeIncrease);
7265     // We should not cache obsolete VkImages. Only current VkImage should be cached.
7266     EXPECT_EQ(framebufferCacheSizeIncrease, expectedFramebufferCacheSizeIncrease);
7267 }
7268 
7269 // Test calling glTexParameteri(GL_TEXTURE_SWIZZLE_*) on a texture that attached to FBO with the
7270 // same value did not cause VkFramebuffer cache explode
TEST_P(VulkanPerformanceCounterTest,SetTextureSwizzleWithSameValueOnFBOAttachedTexture)7271 TEST_P(VulkanPerformanceCounterTest, SetTextureSwizzleWithSameValueOnFBOAttachedTexture)
7272 {
7273     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
7274     ANGLE_GL_PROGRAM(textureProgram, essl1_shaders::vs::Texture2D(),
7275                      essl1_shaders::fs::Texture2D());
7276 
7277     // Allocate texture
7278     GLTexture texture;
7279     glBindTexture(GL_TEXTURE_2D, texture);
7280     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
7281     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7282     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7283     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
7284     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
7285     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
7286     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
7287 
7288     GLFramebuffer fbo;
7289     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7290     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
7291     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7292 
7293     int32_t framebufferCacheSizeBefore = getPerfCounters().framebufferCacheSize;
7294     for (GLint loop = 0; loop < 10; loop++)
7295     {
7296         // Draw to FBO
7297         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7298         glUseProgram(blueProgram);
7299         drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7300 
7301         // Sample from texture
7302         glBindFramebuffer(GL_FRAMEBUFFER, 0);
7303         glClearColor(1, 0, 0, 1);
7304         glClear(GL_COLOR_BUFFER_BIT);
7305         glBindTexture(GL_TEXTURE_2D, texture);
7306         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
7307         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
7308         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
7309         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
7310         drawQuad(textureProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7311         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
7312     }
7313     // Now make fbo current and read out cache size and verify it does not grow just because of
7314     // swizzle update even though there is no actual change.
7315     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7316     glUseProgram(blueProgram);
7317     drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7318     ASSERT_GL_NO_ERROR();
7319     int32_t framebufferCacheSizeAfter    = getPerfCounters().framebufferCacheSize;
7320     int32_t framebufferCacheSizeIncrease = framebufferCacheSizeAfter - framebufferCacheSizeBefore;
7321     int32_t expectedFramebufferCacheSizeIncrease = (hasSupportsImagelessFramebuffer()) ? 0 : 1;
7322     // This should not cause frame buffer cache increase.
7323     EXPECT_EQ(framebufferCacheSizeIncrease, expectedFramebufferCacheSizeIncrease);
7324 }
7325 
7326 // Test calling glTexParameteri(GL_TEXTURE_SWIZZLE_*) on a texture that attached to FBO with
7327 // different value did not cause VkFramebuffer cache explode
TEST_P(VulkanPerformanceCounterTest,SetTextureSwizzleWithDifferentValueOnFBOAttachedTexture)7328 TEST_P(VulkanPerformanceCounterTest, SetTextureSwizzleWithDifferentValueOnFBOAttachedTexture)
7329 {
7330     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
7331     ANGLE_GL_PROGRAM(textureProgram, essl1_shaders::vs::Texture2D(),
7332                      essl1_shaders::fs::Texture2D());
7333 
7334     // Allocate texture
7335     GLTexture texture;
7336     glBindTexture(GL_TEXTURE_2D, texture);
7337     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
7338     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7339     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7340     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
7341     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
7342     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
7343     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
7344 
7345     GLFramebuffer fbo;
7346     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7347     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
7348     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7349 
7350     GLColor expectedColors[] = {GLColor::black,   GLColor::black,  GLColor::blue,  GLColor::black,
7351                                 GLColor::black,   GLColor::blue,   GLColor::green, GLColor::green,
7352                                 GLColor::cyan,    GLColor::black,  GLColor::black, GLColor::blue,
7353                                 GLColor::black,   GLColor::black,  GLColor::blue,  GLColor::green,
7354                                 GLColor::green,   GLColor::cyan,   GLColor::red,   GLColor::red,
7355                                 GLColor::magenta, GLColor::red,    GLColor::red,   GLColor::magenta,
7356                                 GLColor::yellow,  GLColor::yellow, GLColor::white};
7357     int32_t framebufferCacheSizeBefore = getPerfCounters().framebufferCacheSize;
7358     int loop                           = 0;
7359     for (GLenum swizzle_R = GL_RED; swizzle_R <= GL_BLUE; swizzle_R++)
7360     {
7361         for (GLenum swizzle_G = GL_RED; swizzle_G <= GL_BLUE; swizzle_G++)
7362         {
7363             for (GLenum swizzle_B = GL_RED; swizzle_B <= GL_BLUE; swizzle_B++)
7364             {
7365                 // Draw to FBO
7366                 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7367                 glUseProgram(blueProgram);
7368                 drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7369 
7370                 // Sample from texture
7371                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7372                 glClearColor(1, 0, 0, 1);
7373                 glClear(GL_COLOR_BUFFER_BIT);
7374                 glBindTexture(GL_TEXTURE_2D, texture);
7375                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, swizzle_R);
7376                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, swizzle_G);
7377                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, swizzle_B);
7378                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
7379                 drawQuad(textureProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7380                 EXPECT_PIXEL_COLOR_EQ(0, 0, expectedColors[loop]);
7381                 loop++;
7382             }
7383         }
7384     }
7385     // Now make fbo current and read out cache size and verify it does not grow just because of
7386     // swizzle update even though there is no actual change.
7387     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7388     glUseProgram(blueProgram);
7389     drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7390     ASSERT_GL_NO_ERROR();
7391     int32_t framebufferCacheSizeAfter    = getPerfCounters().framebufferCacheSize;
7392     int32_t framebufferCacheSizeIncrease = framebufferCacheSizeAfter - framebufferCacheSizeBefore;
7393     int32_t expectedFramebufferCacheSizeIncrease = (hasSupportsImagelessFramebuffer()) ? 0 : 1;
7394     // This should not cause frame buffer cache increase.
7395     EXPECT_EQ(framebufferCacheSizeIncrease, expectedFramebufferCacheSizeIncrease);
7396 }
7397 
saveAndReloadBinary(GLProgram * original,GLProgram * reloaded)7398 void VulkanPerformanceCounterTest::saveAndReloadBinary(GLProgram *original, GLProgram *reloaded)
7399 {
7400     GLint programLength = 0;
7401     GLint writtenLength = 0;
7402     GLenum binaryFormat = 0;
7403 
7404     // Get the binary out of the program and delete it.
7405     glGetProgramiv(*original, GL_PROGRAM_BINARY_LENGTH_OES, &programLength);
7406     EXPECT_GL_NO_ERROR();
7407 
7408     std::vector<uint8_t> binary(programLength);
7409     glGetProgramBinaryOES(*original, programLength, &writtenLength, &binaryFormat, binary.data());
7410     EXPECT_GL_NO_ERROR();
7411 
7412     original->reset();
7413 
7414     // Reload the binary into another program
7415     reloaded->makeEmpty();
7416     glProgramBinaryOES(*reloaded, binaryFormat, binary.data(), writtenLength);
7417     EXPECT_GL_NO_ERROR();
7418 
7419     GLint linkStatus;
7420     glGetProgramiv(*reloaded, GL_LINK_STATUS, &linkStatus);
7421     EXPECT_NE(linkStatus, 0);
7422 }
7423 
testPipelineCacheIsWarm(GLProgram * program,GLColor color)7424 void VulkanPerformanceCounterTest::testPipelineCacheIsWarm(GLProgram *program, GLColor color)
7425 {
7426     glUseProgram(*program);
7427     GLint colorUniformLocation =
7428         glGetUniformLocation(*program, angle::essl1_shaders::ColorUniform());
7429     ASSERT_NE(-1, colorUniformLocation);
7430     ASSERT_GL_NO_ERROR();
7431 
7432     GLuint expectedCacheHits   = getPerfCounters().pipelineCreationCacheHits + 1;
7433     GLuint expectedCacheMisses = getPerfCounters().pipelineCreationCacheMisses;
7434 
7435     glUniform4fv(colorUniformLocation, 1, color.toNormalizedVector().data());
7436     drawQuad(*program, essl1_shaders::PositionAttrib(), 0.5f);
7437 
7438     EXPECT_EQ(getPerfCounters().pipelineCreationCacheHits, expectedCacheHits);
7439     EXPECT_EQ(getPerfCounters().pipelineCreationCacheMisses, expectedCacheMisses);
7440 
7441     EXPECT_PIXEL_COLOR_EQ(0, 0, color);
7442 }
7443 
7444 // Verifies that the pipeline cache is warmed up at link time with reasonable defaults.
TEST_P(VulkanPerformanceCounterTest,PipelineCacheIsWarmedUpAtLinkTime)7445 TEST_P(VulkanPerformanceCounterTest, PipelineCacheIsWarmedUpAtLinkTime)
7446 {
7447     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
7448 
7449     // Test is only valid when pipeline creation feedback is available
7450     ANGLE_SKIP_TEST_IF(!hasSupportsPipelineCreationFeedback() || !hasWarmUpPipelineCacheAtLink() ||
7451                        !hasEffectivePipelineCacheSerialization());
7452 
7453     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor());
7454 
7455     testPipelineCacheIsWarm(&program, GLColor::red);
7456 }
7457 
7458 // Verifies that the pipeline cache is reloaded correctly through glProgramBinary.
TEST_P(VulkanPerformanceCounterTest,PipelineCacheIsRestoredWithProgramBinary)7459 TEST_P(VulkanPerformanceCounterTest, PipelineCacheIsRestoredWithProgramBinary)
7460 {
7461     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
7462 
7463     // Test is only valid when pipeline creation feedback is available
7464     ANGLE_SKIP_TEST_IF(!hasSupportsPipelineCreationFeedback() || !hasWarmUpPipelineCacheAtLink() ||
7465                        !hasEffectivePipelineCacheSerialization());
7466 
7467     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor());
7468     GLProgram reloadedProgram;
7469     saveAndReloadBinary(&program, &reloadedProgram);
7470 
7471     testPipelineCacheIsWarm(&reloadedProgram, GLColor::green);
7472 }
7473 
7474 // Verifies that the pipeline cache is reloaded correctly through glProgramBinary twice.
TEST_P(VulkanPerformanceCounterTest,PipelineCacheIsRestoredWithProgramBinaryTwice)7475 TEST_P(VulkanPerformanceCounterTest, PipelineCacheIsRestoredWithProgramBinaryTwice)
7476 {
7477     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
7478 
7479     // Test is only valid when pipeline creation feedback is available
7480     ANGLE_SKIP_TEST_IF(!hasSupportsPipelineCreationFeedback() || !hasWarmUpPipelineCacheAtLink() ||
7481                        !hasEffectivePipelineCacheSerialization());
7482 
7483     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor());
7484     GLProgram reloadedProgram;
7485     GLProgram twiceReloadedProgram;
7486     saveAndReloadBinary(&program, &reloadedProgram);
7487     saveAndReloadBinary(&reloadedProgram, &twiceReloadedProgram);
7488 
7489     testPipelineCacheIsWarm(&twiceReloadedProgram, GLColor::blue);
7490 }
7491 
7492 // Test calling glEGLImageTargetTexture2DOES repeatedly with same arguments will not leak
7493 // DescriptorSets. This is the same usage pattern surafceflinger is doing with notification shades
7494 // except with AHB.
TEST_P(VulkanPerformanceCounterTest,Source2DAndRepeatedlyRespecifyTarget2DWithSameParameter)7495 TEST_P(VulkanPerformanceCounterTest, Source2DAndRepeatedlyRespecifyTarget2DWithSameParameter)
7496 {
7497     EGLWindow *window = getEGLWindow();
7498     EGLDisplay dpy    = window->getDisplay();
7499     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_EGL_image") ||
7500                        !IsEGLDisplayExtensionEnabled(dpy, "EGL_KHR_image_base") ||
7501                        !IsEGLDisplayExtensionEnabled(dpy, "EGL_KHR_gl_texture_2D_image"));
7502 
7503     ANGLE_GL_PROGRAM(textureProgram, essl1_shaders::vs::Texture2D(),
7504                      essl1_shaders::fs::Texture2D());
7505 
7506     // Create a source 2D texture
7507     GLTexture sourceTexture;
7508     glBindTexture(GL_TEXTURE_2D, sourceTexture);
7509     GLubyte kLinearColor[] = {132, 55, 219, 255};
7510     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7511                  static_cast<void *>(&kLinearColor));
7512     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7513     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7514     ASSERT_GL_NO_ERROR();
7515     // Create an eglImage from the source texture
7516     constexpr EGLint kDefaultAttribs[] = {EGL_IMAGE_PRESERVED, EGL_TRUE, EGL_NONE};
7517     EGLClientBuffer clientBuffer =
7518         reinterpret_cast<EGLClientBuffer>(static_cast<size_t>(sourceTexture));
7519     EGLImageKHR image = eglCreateImageKHR(window->getDisplay(), window->getContext(),
7520                                           EGL_GL_TEXTURE_2D_KHR, clientBuffer, kDefaultAttribs);
7521     ASSERT_EGL_SUCCESS();
7522 
7523     // Create the target in a loop
7524     GLTexture targetTexture;
7525     constexpr size_t kMaxLoop = 2;
7526     GLint textureDescriptorSetCacheTotalSizeBefore =
7527         getPerfCounters().textureDescriptorSetCacheTotalSize;
7528     for (size_t loop = 0; loop < kMaxLoop; loop++)
7529     {
7530         //  Create a target texture from the image
7531         glBindTexture(GL_TEXTURE_2D, targetTexture);
7532         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
7533 
7534         // Disable mipmapping
7535         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7536         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7537 
7538         // Draw a quad with the target texture
7539         glBindTexture(GL_TEXTURE_2D, targetTexture);
7540         drawQuad(textureProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7541         // Expect that the rendered quad's color is the same as the reference color with a tolerance
7542         // of 1
7543         EXPECT_PIXEL_NEAR(0, 0, kLinearColor[0], kLinearColor[1], kLinearColor[2], kLinearColor[3],
7544                           1);
7545     }
7546     GLint textureDescriptorSetCacheTotalSizeIncrease =
7547         getPerfCounters().textureDescriptorSetCacheTotalSize -
7548         textureDescriptorSetCacheTotalSizeBefore;
7549 
7550     // We don't expect descriptorSet cache to keep growing
7551     EXPECT_EQ(1, textureDescriptorSetCacheTotalSizeIncrease);
7552 
7553     // Clean up
7554     eglDestroyImageKHR(window->getDisplay(), image);
7555 }
7556 
7557 // Test create, use and then destroy a texture does not increase number of DescriptoprSets.
7558 // DesriptorSet should be destroyed promptly. We are seeing this type of usage pattern in
7559 // surfaceflinger, except that the texture is created from AHB (and AHB keeps changing as well).
TEST_P(VulkanPerformanceCounterTest,CreateDestroyTextureDoesNotIncreaseDescriptporSetCache)7560 TEST_P(VulkanPerformanceCounterTest, CreateDestroyTextureDoesNotIncreaseDescriptporSetCache)
7561 {
7562     ANGLE_GL_PROGRAM(textureProgram, essl1_shaders::vs::Texture2D(),
7563                      essl1_shaders::fs::Texture2D());
7564 
7565     // Respecify texture in a loop
7566     GLubyte kLinearColor[]    = {132, 55, 219, 255};
7567     constexpr size_t kMaxLoop = 2;
7568     GLint textureDescriptorSetCacheTotalSizeBefore =
7569         getPerfCounters().textureDescriptorSetCacheTotalSize;
7570     for (size_t loop = 0; loop < kMaxLoop; loop++)
7571     {
7572         // Create a 2D texture
7573         GLTexture sourceTexture;
7574         glBindTexture(GL_TEXTURE_2D, sourceTexture);
7575         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
7576                      static_cast<void *>(&kLinearColor));
7577         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7578         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7579         ASSERT_GL_NO_ERROR();
7580 
7581         drawQuad(textureProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7582         // Expect that the rendered quad's color is the same as the reference color with a tolerance
7583         // of 1
7584         EXPECT_PIXEL_NEAR(0, 0, kLinearColor[0], kLinearColor[1], kLinearColor[2], kLinearColor[3],
7585                           1);
7586     }
7587     GLint textureDescriptorSetCacheTotalSizeIncrease =
7588         getPerfCounters().textureDescriptorSetCacheTotalSize -
7589         textureDescriptorSetCacheTotalSizeBefore;
7590 
7591     // We don't expect descriptorSet cache to keep growing
7592     EXPECT_EQ(0, textureDescriptorSetCacheTotalSizeIncrease);
7593 }
7594 
7595 // Similar to CreateDestroyTextureDoesNotIncreaseDescriptporSetCache, but for shader image.
TEST_P(VulkanPerformanceCounterTest_ES31,CreateDestroyTextureDoesNotIncreaseComputeShaderDescriptporSetCache)7596 TEST_P(VulkanPerformanceCounterTest_ES31,
7597        CreateDestroyTextureDoesNotIncreaseComputeShaderDescriptporSetCache)
7598 {
7599     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
7600 
7601     constexpr char kCS[] = R"(#version 310 es
7602 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
7603 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
7604 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
7605 void main()
7606 {
7607     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
7608     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
7609 })";
7610     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
7611     glUseProgram(program);
7612 
7613     constexpr int kWidth = 1, kHeight = 1;
7614     constexpr GLuint kInputValues[2][1] = {{200}, {100}};
7615     constexpr size_t kMaxLoop           = 20;
7616     GLint shaderResourceDescriptorSetCacheTotalSizeBefore =
7617         getPerfCounters().shaderResourcesDescriptorSetCacheTotalSize;
7618     for (size_t loop = 0; loop < kMaxLoop; loop++)
7619     {
7620         // Respecify texture in a loop
7621         GLTexture texture0;
7622         glBindTexture(GL_TEXTURE_2D, texture0);
7623         glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
7624         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
7625                         kInputValues[0]);
7626 
7627         GLTexture texture1;
7628         glBindTexture(GL_TEXTURE_2D, texture1);
7629         glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
7630         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
7631                         kInputValues[1]);
7632 
7633         glBindImageTexture(0, texture0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
7634         glBindImageTexture(1, texture1, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
7635         glDispatchCompute(1, 1, 1);
7636     }
7637     glFinish();
7638     GLint shaderResourceDescriptorSetCacheTotalSizeIncrease =
7639         getPerfCounters().shaderResourcesDescriptorSetCacheTotalSize -
7640         shaderResourceDescriptorSetCacheTotalSizeBefore;
7641 
7642     // We don't expect descriptorSet cache to keep growing
7643     EXPECT_EQ(0, shaderResourceDescriptorSetCacheTotalSizeIncrease);
7644 }
7645 
7646 // Similar to CreateDestroyTextureDoesNotIncreaseDescriptporSetCache, but for uniform buffers.
TEST_P(VulkanPerformanceCounterTest,DestroyUniformBufferAlsoDestroyDescriptporSetCache)7647 TEST_P(VulkanPerformanceCounterTest, DestroyUniformBufferAlsoDestroyDescriptporSetCache)
7648 {
7649     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
7650 
7651     const char *mkFS = R"(#version 300 es
7652 precision highp float;
7653 uniform uni { vec4 color; };
7654 out vec4 fragColor;
7655 void main()
7656 {
7657     fragColor = color;
7658 })";
7659     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), mkFS);
7660     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "uni");
7661     ASSERT_NE(uniformBufferIndex, -1);
7662 
7663     // Warm up. Make a draw to ensure other descriptorSets are created if needed.
7664     GLBuffer intialBuffer;
7665     glBindBuffer(GL_UNIFORM_BUFFER, intialBuffer);
7666     std::vector<float> initialData = {0.1, 0.2, 0.3, 0.4};
7667     glBufferData(GL_UNIFORM_BUFFER, sizeof(float) * initialData.size(), initialData.data(),
7668                  GL_DYNAMIC_DRAW);
7669     glBindBufferBase(GL_UNIFORM_BUFFER, 0, intialBuffer);
7670     glUniformBlockBinding(program, uniformBufferIndex, 0);
7671     glClear(GL_COLOR_BUFFER_BIT);
7672     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
7673     EXPECT_PIXEL_NEAR(0, 0, initialData[0] * 255, initialData[1] * 255, initialData[2] * 255,
7674                       initialData[3] * 255, 1);
7675 
7676     // Use big buffer size to force it into individual bufferBlocks
7677     constexpr GLsizei kBufferSize           = 4 * 1024 * 1024;
7678     GLint DescriptorSetCacheTotalSizeBefore = getPerfCounters().descriptorSetCacheTotalSize;
7679 
7680     // Create buffer and use it and then destroy it. Because buffers are big enough they should be
7681     // in a different bufferBlock. DescriptorSet created due to these temporary buffer should be
7682     // destroyed promptly.
7683     constexpr int kBufferCount = 16;
7684     for (int i = 0; i < kBufferCount; i++)
7685     {
7686         GLBuffer uniformBuffer;
7687         glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
7688         glBufferData(GL_UNIFORM_BUFFER, kBufferSize, nullptr, GL_DYNAMIC_DRAW);
7689         float *ptr = reinterpret_cast<float *>(
7690             glMapBufferRange(GL_UNIFORM_BUFFER, 0, kBufferSize, GL_MAP_WRITE_BIT));
7691         for (int j = 0; j < 4; j++)
7692         {
7693             ptr[j] = (float)(i * 4 + j) / 255.0f;
7694         }
7695         glUnmapBuffer(GL_UNIFORM_BUFFER);
7696         glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
7697         glUniformBlockBinding(program, uniformBufferIndex, 0);
7698         glClear(GL_COLOR_BUFFER_BIT);
7699         drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
7700         EXPECT_PIXEL_NEAR(0, 0, (i * 4), (i * 4 + 1), (i * 4 + 2), (i * 4 + 3), 1);
7701     }
7702     // Should trigger prune buffer call
7703     swapBuffers();
7704 
7705     GLint DescriptorSetCacheTotalSizeIncrease =
7706         getPerfCounters().descriptorSetCacheTotalSize - DescriptorSetCacheTotalSizeBefore;
7707     // We expect most of descriptorSet caches for temporary uniformBuffers gets destroyed. Give
7708     // extra room in case a new descriptorSet is allocated due to a new driver uniform buffer gets
7709     // allocated.
7710     EXPECT_LT(DescriptorSetCacheTotalSizeIncrease, 2);
7711 }
7712 
7713 // Similar to CreateDestroyTextureDoesNotIncreaseDescriptporSetCache, but for atomic acounter
7714 // buffer.
TEST_P(VulkanPerformanceCounterTest_ES31,DestroyAtomicCounterBufferAlsoDestroyDescriptporSetCache)7715 TEST_P(VulkanPerformanceCounterTest_ES31, DestroyAtomicCounterBufferAlsoDestroyDescriptporSetCache)
7716 {
7717     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
7718 
7719     constexpr char kFS[] =
7720         "#version 310 es\n"
7721         "precision highp float;\n"
7722         "layout(binding = 0, offset = 4) uniform atomic_uint ac;\n"
7723         "out highp vec4 my_color;\n"
7724         "void main()\n"
7725         "{\n"
7726         "    uint a1 = atomicCounter(ac);\n"
7727         "    my_color = vec4(float(a1)/255.0, 0.0, 0.0, 1.0);\n"
7728         "}\n";
7729     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
7730 
7731     // Warm up. Make a draw to ensure other descriptorSets are created if needed.
7732     GLBuffer intialBuffer;
7733     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, intialBuffer);
7734     uint32_t bufferData[3] = {0, 0u, 0u};
7735     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
7736     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, intialBuffer);
7737     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
7738     GLColor expectedColor = GLColor::black;
7739     EXPECT_PIXEL_COLOR_EQ(0, 0, expectedColor);
7740 
7741     GLint DescriptorSetCacheTotalSizeBefore = getPerfCounters().descriptorSetCacheTotalSize;
7742 
7743     // Create atomic counter buffer and use it and then destroy it.
7744     constexpr int kBufferCount = 16;
7745     GLBuffer paddingBuffers[kBufferCount];
7746     for (uint32_t i = 0; i < kBufferCount; i++)
7747     {
7748         // Allocate a padding buffer so that atomicCounterBuffer will be allocated in different
7749         // offset
7750         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, paddingBuffers[i]);
7751         glBufferData(GL_ATOMIC_COUNTER_BUFFER, 256, nullptr, GL_STATIC_DRAW);
7752         // Allocate, use, destroy atomic counter buffer
7753         GLBuffer atomicCounterBuffer;
7754         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
7755         bufferData[1] = i;
7756         glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
7757         glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
7758         drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
7759         expectedColor.R = bufferData[1];
7760         EXPECT_PIXEL_COLOR_EQ(0, 0, expectedColor);
7761     }
7762     ASSERT_GL_NO_ERROR();
7763 
7764     GLint DescriptorSetCacheTotalSizeIncrease =
7765         getPerfCounters().descriptorSetCacheTotalSize - DescriptorSetCacheTotalSizeBefore;
7766     // We expect most of descriptorSet caches for temporary atomic counter buffers gets destroyed.
7767     // Give extra room in case a new descriptorSet is allocated due to a new driver uniform buffer
7768     // gets allocated.
7769     EXPECT_LT(DescriptorSetCacheTotalSizeIncrease, 2);
7770 }
7771 
7772 // Test that post-render-pass-to-swapchain glFenceSync followed by eglSwapBuffers incurs only a
7773 // single submission.
TEST_P(VulkanPerformanceCounterTest,FenceThenSwapBuffers)7774 TEST_P(VulkanPerformanceCounterTest, FenceThenSwapBuffers)
7775 {
7776     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
7777 
7778     angle::VulkanPerfCounters expected;
7779 
7780     // Expect rpCount+1, depth(Clears+0, Loads+0, LoadNones+0, Stores+0, StoreNones+0),
7781     setExpectedCountersForDepthOps(getPerfCounters(), 1, 0, 0, 0, 0, 0, &expected);
7782     expected.vkQueueSubmitCallsTotal = getPerfCounters().vkQueueSubmitCallsTotal + 1;
7783 
7784     // Start a render pass and render to the surface.  Enable depth write so the depth/stencil image
7785     // is written to.
7786     glEnable(GL_DEPTH_TEST);
7787     glDepthFunc(GL_ALWAYS);
7788 
7789     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
7790     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
7791     ASSERT_GL_NO_ERROR();
7792 
7793     // Issue a fence
7794     glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
7795 
7796     EXPECT_EQ(getPerfCounters().renderPasses, expected.renderPasses);
7797 
7798     // Swap buffers.  The depth/stencil attachment's storeOp should be optimized to DONT_CARE.  This
7799     // would not have been possible if the previous glFenceSync caused a submission.
7800     swapBuffers();
7801 
7802     EXPECT_EQ(getPerfCounters().vkQueueSubmitCallsTotal, expected.vkQueueSubmitCallsTotal);
7803     EXPECT_DEPTH_OP_COUNTERS(getPerfCounters(), expected);
7804 }
7805 
7806 // Verify that ending transform feedback after a render pass is closed, doesn't cause the following
7807 // render pass to close when the transform feedback buffer is used.
TEST_P(VulkanPerformanceCounterTest,EndXfbAfterRenderPassClosed)7808 TEST_P(VulkanPerformanceCounterTest, EndXfbAfterRenderPassClosed)
7809 {
7810     // There should be two render passes; one for the transform feedback draw, one for the other two
7811     // draw calls.
7812     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 2;
7813 
7814     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
7815     glClear(GL_COLOR_BUFFER_BIT);
7816 
7817     // Set the program's transform feedback varyings (just gl_Position)
7818     std::vector<std::string> tfVaryings;
7819     tfVaryings.push_back("gl_Position");
7820     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(drawRed, essl3_shaders::vs::SimpleForPoints(),
7821                                         essl3_shaders::fs::Red(), tfVaryings,
7822                                         GL_INTERLEAVED_ATTRIBS);
7823 
7824     glUseProgram(drawRed);
7825     GLint positionLocation = glGetAttribLocation(drawRed, essl1_shaders::PositionAttrib());
7826 
7827     const GLfloat vertices[] = {
7828         -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f,
7829         -0.5f, 0.5f, 0.5f, 0.5f,  -0.5f, 0.5f, 0.5f, 0.5f,  0.5f,
7830     };
7831 
7832     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
7833     glEnableVertexAttribArray(positionLocation);
7834 
7835     // Bind the buffer for transform feedback output and start transform feedback
7836     GLBuffer xfbBuffer;
7837     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
7838     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 100, nullptr, GL_STATIC_DRAW);
7839     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
7840     glBeginTransformFeedback(GL_POINTS);
7841 
7842     glDrawArrays(GL_POINTS, 0, 6);
7843 
7844     // Break the render pass
7845     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7846 
7847     // End transform feedback after the render pass is closed
7848     glEndTransformFeedback();
7849 
7850     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
7851     EXPECT_GL_NO_ERROR();
7852 
7853     // Issue an unrelated draw call.
7854     ANGLE_GL_PROGRAM(drawGreen, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
7855     drawQuad(drawGreen, essl3_shaders::PositionAttrib(), 0.0f);
7856 
7857     // Issue a draw call using the transform feedback buffer.
7858     glBindBuffer(GL_ARRAY_BUFFER, xfbBuffer);
7859     glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
7860     glEnableVertexAttribArray(positionLocation);
7861 
7862     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
7863     glClear(GL_COLOR_BUFFER_BIT);
7864     glUseProgram(drawRed);
7865     glDrawArrays(GL_TRIANGLES, 0, 6);
7866 
7867     const int w = getWindowWidth();
7868     const int h = getWindowHeight();
7869 
7870     EXPECT_PIXEL_RECT_EQ(0, 0, w, h / 4, GLColor::black);
7871     EXPECT_PIXEL_RECT_EQ(0, 3 * h / 4, w, h / 4, GLColor::black);
7872     EXPECT_PIXEL_RECT_EQ(0, h / 4, w / 4, h / 2, GLColor::black);
7873     EXPECT_PIXEL_RECT_EQ(3 * w / 4, h / 4, w / 4, h / 2, GLColor::black);
7874 
7875     EXPECT_PIXEL_RECT_EQ(w / 4, h / 4, w / 2, h / 2, GLColor::red);
7876     EXPECT_GL_NO_ERROR();
7877 
7878     EXPECT_EQ(getPerfCounters().renderPasses, expectedRenderPassCount);
7879 }
7880 
7881 // Verify that monolithic pipeline handles correctly replace the linked pipelines, if
7882 // VK_EXT_graphics_pipeline_library is supported.
TEST_P(VulkanPerformanceCounterTest,AsyncMonolithicPipelineCreation)7883 TEST_P(VulkanPerformanceCounterTest, AsyncMonolithicPipelineCreation)
7884 {
7885     const bool hasAsyncMonolithicPipelineCreation =
7886         isFeatureEnabled(Feature::SupportsGraphicsPipelineLibrary) &&
7887         isFeatureEnabled(Feature::PreferMonolithicPipelinesOverLibraries);
7888     ANGLE_SKIP_TEST_IF(!hasAsyncMonolithicPipelineCreation);
7889 
7890     uint64_t expectedMonolithicPipelineCreationCount =
7891         getPerfCounters().monolithicPipelineCreation + 2;
7892 
7893     // Create two programs:
7894     ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
7895     ANGLE_GL_PROGRAM(drawGreen, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
7896 
7897     // Ping pong between the programs, letting async monolithic pipeline creation happen.
7898     uint32_t drawCount                 = 0;
7899     constexpr uint32_t kDrawCountLimit = 200;
7900 
7901     while (getPerfCounters().monolithicPipelineCreation < expectedMonolithicPipelineCreationCount)
7902     {
7903         drawQuad(drawGreen, essl3_shaders::PositionAttrib(), 0.0f);
7904         drawQuad(drawRed, essl3_shaders::PositionAttrib(), 0.0f);
7905 
7906         ++drawCount;
7907         if (drawCount > kDrawCountLimit)
7908         {
7909             drawCount = 0;
7910             EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7911         }
7912     }
7913 
7914     // Make sure the monolithic pipelines are replaced correctly
7915     drawQuad(drawGreen, essl3_shaders::PositionAttrib(), 0.0f);
7916     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7917 
7918     drawQuad(drawRed, essl3_shaders::PositionAttrib(), 0.0f);
7919     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7920 }
7921 
7922 // Verify that changing framebuffer and back doesn't break the render pass.
TEST_P(VulkanPerformanceCounterTest,FBOChangeAndBackDoesNotBreakRenderPass)7923 TEST_P(VulkanPerformanceCounterTest, FBOChangeAndBackDoesNotBreakRenderPass)
7924 {
7925     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
7926 
7927     ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
7928     drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0);
7929 
7930     GLFramebuffer fbo;
7931     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7932     glBindFramebuffer(GL_FRAMEBUFFER, 0);
7933 
7934     drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0);
7935 
7936     // Verify render pass count.
7937     EXPECT_EQ(getPerfCounters().renderPasses, expectedRenderPassCount);
7938 
7939     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7940 }
7941 
7942 // Verify that changing framebuffer and issue a (nop or deferred) clear and change framebuffer back
7943 // doesn't break the render pass.
TEST_P(VulkanPerformanceCounterTest,FBOChangeAndClearAndBackDoesNotBreakRenderPass)7944 TEST_P(VulkanPerformanceCounterTest, FBOChangeAndClearAndBackDoesNotBreakRenderPass)
7945 {
7946     // switch to FBO and issue clear on fbo and then switch back to default framebuffer
7947     GLFramebuffer framebuffer;
7948     GLTexture texture;
7949     setupForColorOpsTest(&framebuffer, &texture);
7950     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);  // clear to green
7951     glClear(GL_COLOR_BUFFER_BIT);
7952     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7953 
7954     uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
7955 
7956     glBindFramebuffer(GL_FRAMEBUFFER, 0);
7957     ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
7958     drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0);
7959 
7960     // switch to FBO and issue a deferred clear on fbo and then switch back to default framebuffer
7961     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
7962     glClear(GL_COLOR_BUFFER_BIT);
7963 
7964     glBindFramebuffer(GL_FRAMEBUFFER, 0);
7965     drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0);
7966 
7967     // Verify render pass count.
7968     EXPECT_EQ(getPerfCounters().renderPasses, expectedRenderPassCount);
7969 
7970     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7971 }
7972 
7973 // This is test for optimization in vulkan backend. efootball_pes_2021 usage shows this usage
7974 // pattern and we expect implementation to reuse the storage for performance.
TEST_P(VulkanPerformanceCounterTest,BufferDataWithSizeFollowedByZeroAndThenSizeAgainShouldReuseStorage)7975 TEST_P(VulkanPerformanceCounterTest,
7976        BufferDataWithSizeFollowedByZeroAndThenSizeAgainShouldReuseStorage)
7977 {
7978     GLBuffer buffer;
7979     glBindBuffer(GL_ARRAY_BUFFER, buffer);
7980     constexpr size_t count = 288;
7981     std::array<uint32_t, count> data;
7982     constexpr size_t bufferSize = data.size() * sizeof(uint32_t);
7983     data.fill(0x1234567);
7984 
7985     glBufferData(GL_ARRAY_BUFFER, bufferSize, data.data(), GL_DYNAMIC_DRAW);
7986     glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);
7987     // This should get back the original storage with proper BufferVk optimization
7988     data.fill(0x89abcdef);
7989     uint64_t expectedSuballocationCalls = getPerfCounters().bufferSuballocationCalls;
7990     glBufferData(GL_ARRAY_BUFFER, bufferSize, data.data(), GL_DYNAMIC_DRAW);
7991     EXPECT_EQ(getPerfCounters().bufferSuballocationCalls, expectedSuballocationCalls);
7992 
7993     uint32_t *mapPtr = reinterpret_cast<uint32_t *>(
7994         glMapBufferRange(GL_ARRAY_BUFFER, 0, bufferSize, GL_MAP_READ_BIT));
7995     ASSERT_NE(nullptr, mapPtr);
7996     EXPECT_EQ(0x89abcdef, mapPtr[0]);
7997     EXPECT_EQ(0x89abcdef, mapPtr[count - 1]);
7998     glUnmapBuffer(GL_ARRAY_BUFFER);
7999     ASSERT_GL_NO_ERROR();
8000 }
8001 
8002 class VulkanPerformanceCounterTest_AsyncCQ : public VulkanPerformanceCounterTest
8003 {};
8004 
8005 // Tests that submitting the outside command buffer during flushing staged updates and
8006 // "asyncCommandQueue" enabled, properly updates old command buffer with the new one.
TEST_P(VulkanPerformanceCounterTest_AsyncCQ,SubmittingOutsideCommandBufferAssertIsOpen)8007 TEST_P(VulkanPerformanceCounterTest_AsyncCQ, SubmittingOutsideCommandBufferAssertIsOpen)
8008 {
8009     // If VK_EXT_host_image_copy is used, uploads will all be done on the CPU and there would be no
8010     // submissions.
8011     ANGLE_SKIP_TEST_IF(hasSupportsHostImageCopy());
8012 
8013     uint64_t submitCommandsCount = getPerfCounters().vkQueueSubmitCallsTotal;
8014 
8015     ANGLE_GL_PROGRAM(textureProgram, essl1_shaders::vs::Texture2D(),
8016                      essl1_shaders::fs::Texture2D());
8017     glUseProgram(textureProgram);
8018     GLint textureLoc = glGetUniformLocation(textureProgram, essl1_shaders::Texture2DUniform());
8019     ASSERT_NE(-1, textureLoc);
8020     glUniform1i(textureLoc, 0);
8021 
8022     // This loop shouls update texture with multiple staged updates. When kMaxBufferToImageCopySize
8023     // threshold reached, outside command buffer will be submitted in the middle of staged updates
8024     // flushing. If "asyncCommandQueue" enabled and bug present, old command buffer will not be
8025     // replaced by a new one, casing "ASSERT(mIsOpen)" or UB in release.
8026     constexpr GLsizei kMaxOutsideRPCommandsSubmitCount = 10;
8027     constexpr GLsizei kTexDim                          = 1024;
8028     constexpr GLint kMaxSubOffset                      = 10;
8029     std::vector<GLColor> kInitialData(kTexDim * kTexDim, GLColor::green);
8030     while (getPerfCounters().vkQueueSubmitCallsTotal <
8031            submitCommandsCount + kMaxOutsideRPCommandsSubmitCount)
8032     {
8033         GLTexture newTexture;
8034         glBindTexture(GL_TEXTURE_2D, newTexture);
8035         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8036         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8037         // Provide data for the texture without previously defining a storage.
8038         // This should prevent immediate staged update flushing.
8039         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexDim, kTexDim, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8040                      kInitialData.data());
8041         // Append staged updates...
8042         for (GLsizei offset = 1; offset <= kMaxSubOffset; ++offset)
8043         {
8044             glTexSubImage2D(GL_TEXTURE_2D, 0, offset, offset, kTexDim - offset, kTexDim - offset,
8045                             GL_RGBA, GL_UNSIGNED_BYTE, kInitialData.data());
8046         }
8047         // This will flush multiple staged updates
8048         drawQuad(textureProgram, essl1_shaders::PositionAttrib(), 0.5f);
8049         ASSERT_GL_NO_ERROR();
8050     }
8051 
8052     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8053 }
8054 
8055 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanPerformanceCounterTest);
8056 ANGLE_INSTANTIATE_TEST(
8057     VulkanPerformanceCounterTest,
8058     ES3_VULKAN(),
8059     ES3_VULKAN().enable(Feature::PadBuffersToMaxVertexAttribStride),
8060     ES3_VULKAN_SWIFTSHADER().disable(Feature::PreferMonolithicPipelinesOverLibraries),
8061     ES3_VULKAN_SWIFTSHADER().enable(Feature::PreferMonolithicPipelinesOverLibraries),
8062     ES3_VULKAN_SWIFTSHADER()
8063         .enable(Feature::PreferMonolithicPipelinesOverLibraries)
8064         .enable(Feature::SlowDownMonolithicPipelineCreationForTesting),
8065     ES3_VULKAN_SWIFTSHADER()
8066         .enable(Feature::PreferMonolithicPipelinesOverLibraries)
8067         .disable(Feature::MergeProgramPipelineCachesToGlobalCache));
8068 
8069 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanPerformanceCounterTest_ES31);
8070 ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_ES31, ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER());
8071 
8072 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanPerformanceCounterTest_MSAA);
8073 ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_MSAA,
8074                        ES3_VULKAN(),
8075                        ES3_VULKAN_SWIFTSHADER(),
8076                        ES3_VULKAN().enable(Feature::EmulatedPrerotation90),
8077                        ES3_VULKAN().enable(Feature::EmulatedPrerotation180),
8078                        ES3_VULKAN().enable(Feature::EmulatedPrerotation270));
8079 
8080 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanPerformanceCounterTest_SingleBuffer);
8081 ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_SingleBuffer, ES3_VULKAN());
8082 
8083 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanPerformanceCounterTest_AsyncCQ);
8084 ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest_AsyncCQ,
8085                        ES3_VULKAN(),
8086                        ES3_VULKAN().enable(Feature::AsyncCommandQueue));
8087 
8088 }  // anonymous namespace
8089