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