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