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