• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 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 // ContextVk.cpp:
7 //    Implements the class methods for ContextVk.
8 //
9 
10 #include "libANGLE/renderer/vulkan/ContextVk.h"
11 
12 #include "common/bitset_utils.h"
13 #include "common/debug.h"
14 #include "common/system_utils.h"
15 #include "common/utilities.h"
16 #include "image_util/loadimage.h"
17 #include "libANGLE/Context.h"
18 #include "libANGLE/Display.h"
19 #include "libANGLE/Program.h"
20 #include "libANGLE/Semaphore.h"
21 #include "libANGLE/ShareGroup.h"
22 #include "libANGLE/Surface.h"
23 #include "libANGLE/angletypes.h"
24 #include "libANGLE/renderer/renderer_utils.h"
25 #include "libANGLE/renderer/vulkan/BufferVk.h"
26 #include "libANGLE/renderer/vulkan/CompilerVk.h"
27 #include "libANGLE/renderer/vulkan/DisplayVk.h"
28 #include "libANGLE/renderer/vulkan/FenceNVVk.h"
29 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
30 #include "libANGLE/renderer/vulkan/MemoryObjectVk.h"
31 #include "libANGLE/renderer/vulkan/OverlayVk.h"
32 #include "libANGLE/renderer/vulkan/ProgramPipelineVk.h"
33 #include "libANGLE/renderer/vulkan/ProgramVk.h"
34 #include "libANGLE/renderer/vulkan/QueryVk.h"
35 #include "libANGLE/renderer/vulkan/RenderbufferVk.h"
36 #include "libANGLE/renderer/vulkan/SamplerVk.h"
37 #include "libANGLE/renderer/vulkan/SemaphoreVk.h"
38 #include "libANGLE/renderer/vulkan/ShaderVk.h"
39 #include "libANGLE/renderer/vulkan/SurfaceVk.h"
40 #include "libANGLE/renderer/vulkan/SyncVk.h"
41 #include "libANGLE/renderer/vulkan/TextureVk.h"
42 #include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
43 #include "libANGLE/renderer/vulkan/VertexArrayVk.h"
44 #include "libANGLE/renderer/vulkan/vk_renderer.h"
45 
46 #include <fstream>
47 #include <iostream>
48 #include <sstream>
49 
50 namespace rx
51 {
52 namespace
53 {
54 // If the total size of copyBufferToImage commands in the outside command buffer reaches the
55 // threshold below, the latter is flushed.
56 static constexpr VkDeviceSize kMaxBufferToImageCopySize = 64 * 1024 * 1024;
57 // The number of queueSerials we will reserve for outsideRenderPassCommands when we generate one for
58 // RenderPassCommands.
59 static constexpr size_t kMaxReservedOutsideRenderPassQueueSerials = 15;
60 
61 // The number of minimum commands in the command buffer to prefer submit at FBO boundary or
62 // immediately submit when the device is idle after calling to flush.
63 static constexpr uint32_t kMinCommandCountToSubmit = 32;
64 
65 // Dumping the command stream is disabled by default.
66 static constexpr bool kEnableCommandStreamDiagnostics = false;
67 
68 // All glMemoryBarrier bits that related to texture usage
69 static constexpr GLbitfield kWriteAfterAccessImageMemoryBarriers =
70     GL_SHADER_IMAGE_ACCESS_BARRIER_BIT;
71 static constexpr GLbitfield kWriteAfterAccessMemoryBarriers =
72     kWriteAfterAccessImageMemoryBarriers | GL_SHADER_STORAGE_BARRIER_BIT;
73 
74 // For shader uniforms such as gl_DepthRange and the viewport size.
75 struct GraphicsDriverUniforms
76 {
77     // Contain packed 8-bit values for atomic counter buffer offsets.  These offsets are within
78     // Vulkan's minStorageBufferOffsetAlignment limit and are used to support unaligned offsets
79     // allowed in GL.
80     std::array<uint32_t, 2> acbBufferOffsets;
81 
82     // .x is near, .y is far
83     std::array<float, 2> depthRange;
84 
85     // Used to flip gl_FragCoord.  Packed uvec2
86     uint32_t renderArea;
87 
88     // Packed vec4 of snorm8
89     uint32_t flipXY;
90 
91     // Only the lower 16 bits used
92     uint32_t dither;
93 
94     // Various bits of state:
95     // - Surface rotation
96     // - Advanced blend equation
97     // - Sample count
98     // - Enabled clip planes
99     // - Depth transformation
100     // - layered FBO
101     uint32_t misc;
102 };
103 static_assert(sizeof(GraphicsDriverUniforms) % (sizeof(uint32_t) * 4) == 0,
104               "GraphicsDriverUniforms should be 16bytes aligned");
105 
106 // Only used when transform feedback is emulated.
107 struct GraphicsDriverUniformsExtended
108 {
109     GraphicsDriverUniforms common;
110 
111     // Only used with transform feedback emulation
112     std::array<int32_t, 4> xfbBufferOffsets;
113     int32_t xfbVerticesPerInstance;
114 
115     int32_t padding[3];
116 };
117 static_assert(sizeof(GraphicsDriverUniformsExtended) % (sizeof(uint32_t) * 4) == 0,
118               "GraphicsDriverUniformsExtended should be 16bytes aligned");
119 // Driver uniforms are updated using push constants and Vulkan spec guarantees universal support for
120 // 128 bytes worth of push constants. For maximum compatibility ensure
121 // GraphicsDriverUniformsExtended size is within that limit.
122 static_assert(sizeof(GraphicsDriverUniformsExtended) <= 128,
123               "Only 128 bytes are guranteed for push constants");
124 
125 struct ComputeDriverUniforms
126 {
127     // Atomic counter buffer offsets with the same layout as in GraphicsDriverUniforms.
128     std::array<uint32_t, 4> acbBufferOffsets;
129 };
130 
MakeFlipUniform(bool flipX,bool flipY,bool invertViewport)131 uint32_t MakeFlipUniform(bool flipX, bool flipY, bool invertViewport)
132 {
133     // Create snorm values of either -1 or 1, based on whether flipping is enabled or not
134     // respectively.
135     constexpr uint8_t kSnormOne      = 0x7F;
136     constexpr uint8_t kSnormMinusOne = 0x81;
137 
138     // .xy are flips for the fragment stage.
139     uint32_t x = flipX ? kSnormMinusOne : kSnormOne;
140     uint32_t y = flipY ? kSnormMinusOne : kSnormOne;
141 
142     // .zw are flips for the vertex stage.
143     uint32_t z = x;
144     uint32_t w = flipY != invertViewport ? kSnormMinusOne : kSnormOne;
145 
146     return x | y << 8 | z << 16 | w << 24;
147 }
148 
DefaultGLErrorCode(VkResult result)149 GLenum DefaultGLErrorCode(VkResult result)
150 {
151     switch (result)
152     {
153         case VK_ERROR_OUT_OF_HOST_MEMORY:
154         case VK_ERROR_OUT_OF_DEVICE_MEMORY:
155         case VK_ERROR_TOO_MANY_OBJECTS:
156             return GL_OUT_OF_MEMORY;
157         case VK_ERROR_DEVICE_LOST:
158             return GL_CONTEXT_LOST;
159         default:
160             return GL_INVALID_OPERATION;
161     }
162 }
163 
164 constexpr gl::ShaderMap<vk::ImageLayout> kShaderReadOnlyImageLayouts = {
165     {gl::ShaderType::Vertex, vk::ImageLayout::VertexShaderReadOnly},
166     {gl::ShaderType::TessControl, vk::ImageLayout::PreFragmentShadersReadOnly},
167     {gl::ShaderType::TessEvaluation, vk::ImageLayout::PreFragmentShadersReadOnly},
168     {gl::ShaderType::Geometry, vk::ImageLayout::PreFragmentShadersReadOnly},
169     {gl::ShaderType::Fragment, vk::ImageLayout::FragmentShaderReadOnly},
170     {gl::ShaderType::Compute, vk::ImageLayout::ComputeShaderReadOnly}};
171 
172 constexpr gl::ShaderMap<vk::ImageLayout> kShaderWriteImageLayouts = {
173     {gl::ShaderType::Vertex, vk::ImageLayout::VertexShaderWrite},
174     {gl::ShaderType::TessControl, vk::ImageLayout::PreFragmentShadersWrite},
175     {gl::ShaderType::TessEvaluation, vk::ImageLayout::PreFragmentShadersWrite},
176     {gl::ShaderType::Geometry, vk::ImageLayout::PreFragmentShadersWrite},
177     {gl::ShaderType::Fragment, vk::ImageLayout::FragmentShaderWrite},
178     {gl::ShaderType::Compute, vk::ImageLayout::ComputeShaderWrite}};
179 
180 constexpr VkBufferUsageFlags kVertexBufferUsage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
181 constexpr size_t kDynamicVertexDataSize         = 16 * 1024;
182 
CanMultiDrawIndirectUseCmd(ContextVk * contextVk,VertexArrayVk * vertexArray,gl::PrimitiveMode mode,GLsizei drawcount,GLsizei stride)183 bool CanMultiDrawIndirectUseCmd(ContextVk *contextVk,
184                                 VertexArrayVk *vertexArray,
185                                 gl::PrimitiveMode mode,
186                                 GLsizei drawcount,
187                                 GLsizei stride)
188 {
189     // Use the generic implementation if multiDrawIndirect is disabled, if line loop is being used
190     // for multiDraw, if drawcount is greater than maxDrawIndirectCount, or if there are streaming
191     // vertex attributes.
192     ASSERT(drawcount > 1);
193     const bool supportsMultiDrawIndirect =
194         contextVk->getFeatures().supportsMultiDrawIndirect.enabled;
195     const bool isMultiDrawLineLoop = (mode == gl::PrimitiveMode::LineLoop);
196     const bool isDrawCountBeyondLimit =
197         (static_cast<uint32_t>(drawcount) >
198          contextVk->getRenderer()->getPhysicalDeviceProperties().limits.maxDrawIndirectCount);
199     const bool isMultiDrawWithStreamingAttribs = vertexArray->getStreamingVertexAttribsMask().any();
200 
201     const bool canMultiDrawIndirectUseCmd = supportsMultiDrawIndirect && !isMultiDrawLineLoop &&
202                                             !isDrawCountBeyondLimit &&
203                                             !isMultiDrawWithStreamingAttribs;
204     return canMultiDrawIndirectUseCmd;
205 }
206 
GetCoverageSampleCount(const gl::State & glState,GLint samples)207 uint32_t GetCoverageSampleCount(const gl::State &glState, GLint samples)
208 {
209     ASSERT(glState.isSampleCoverageEnabled());
210 
211     // Get a fraction of the samples based on the coverage parameters.
212     // There are multiple ways to obtain an integer value from a float -
213     //     truncation, ceil and round
214     //
215     // round() provides a more even distribution of values but doesn't seem to play well
216     // with all vendors (AMD). A way to work around this is to increase the comparison threshold
217     // of deqp tests. Though this takes care of deqp tests other apps would still have issues.
218     //
219     // Truncation provides an uneven distribution near the edges of the interval but seems to
220     // play well with all vendors.
221     //
222     // We are going with truncation for expediency.
223     return static_cast<uint32_t>(glState.getSampleCoverageValue() * samples);
224 }
225 
ApplySampleCoverage(const gl::State & glState,uint32_t coverageSampleCount,uint32_t * maskOut)226 void ApplySampleCoverage(const gl::State &glState, uint32_t coverageSampleCount, uint32_t *maskOut)
227 {
228     ASSERT(glState.isSampleCoverageEnabled());
229 
230     uint32_t coverageMask = angle::BitMask<uint32_t>(coverageSampleCount);
231 
232     if (glState.getSampleCoverageInvert())
233     {
234         coverageMask = ~coverageMask;
235     }
236 
237     *maskOut &= coverageMask;
238 }
239 
DetermineSurfaceRotation(const gl::Framebuffer * framebuffer,const WindowSurfaceVk * windowSurface)240 SurfaceRotation DetermineSurfaceRotation(const gl::Framebuffer *framebuffer,
241                                          const WindowSurfaceVk *windowSurface)
242 {
243     if (windowSurface && framebuffer->isDefault())
244     {
245         switch (windowSurface->getPreTransform())
246         {
247             case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
248                 // Do not rotate gl_Position (surface matches the device's orientation):
249                 return SurfaceRotation::Identity;
250             case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
251                 // Rotate gl_Position 90 degrees:
252                 return SurfaceRotation::Rotated90Degrees;
253             case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
254                 // Rotate gl_Position 180 degrees:
255                 return SurfaceRotation::Rotated180Degrees;
256             case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
257                 // Rotate gl_Position 270 degrees:
258                 return SurfaceRotation::Rotated270Degrees;
259             default:
260                 UNREACHABLE();
261                 return SurfaceRotation::Identity;
262         }
263     }
264     else
265     {
266         // Do not rotate gl_Position (offscreen framebuffer):
267         return SurfaceRotation::Identity;
268     }
269 }
270 
271 // Should not generate a copy with modern C++.
GetTraceEventName(const char * title,uint64_t counter)272 EventName GetTraceEventName(const char *title, uint64_t counter)
273 {
274     EventName buf;
275     snprintf(buf.data(), kMaxGpuEventNameLen - 1, "%s %llu", title,
276              static_cast<unsigned long long>(counter));
277     return buf;
278 }
279 
GetColorAccess(const gl::State & state,const gl::FramebufferState & framebufferState,const gl::DrawBufferMask & emulatedAlphaMask,const gl::ProgramExecutable * executable,size_t colorIndexGL)280 vk::ResourceAccess GetColorAccess(const gl::State &state,
281                                   const gl::FramebufferState &framebufferState,
282                                   const gl::DrawBufferMask &emulatedAlphaMask,
283                                   const gl::ProgramExecutable *executable,
284                                   size_t colorIndexGL)
285 {
286     // No access if draw buffer is disabled altogether
287     // Without framebuffer fetch:
288     //   No access if color output is masked, or rasterizer discard is enabled
289     // With framebuffer fetch:
290     //   Read access if color output is masked, or rasterizer discard is enabled
291 
292     if (!framebufferState.getEnabledDrawBuffers().test(colorIndexGL))
293     {
294         return vk::ResourceAccess::Unused;
295     }
296 
297     const gl::BlendStateExt &blendStateExt = state.getBlendStateExt();
298     uint8_t colorMask                      = gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(
299         colorIndexGL, blendStateExt.getColorMaskBits());
300     if (emulatedAlphaMask[colorIndexGL])
301     {
302         colorMask &= ~VK_COLOR_COMPONENT_A_BIT;
303     }
304     const bool isOutputMasked = colorMask == 0 || state.isRasterizerDiscardEnabled();
305 
306     if (isOutputMasked)
307     {
308         const bool hasFramebufferFetch =
309             executable ? executable->usesColorFramebufferFetch() : false;
310         return hasFramebufferFetch ? vk::ResourceAccess::ReadOnly : vk::ResourceAccess::Unused;
311     }
312 
313     return vk::ResourceAccess::ReadWrite;
314 }
315 
GetDepthAccess(const gl::DepthStencilState & dsState,const gl::ProgramExecutable * executable,UpdateDepthFeedbackLoopReason reason)316 vk::ResourceAccess GetDepthAccess(const gl::DepthStencilState &dsState,
317                                   const gl::ProgramExecutable *executable,
318                                   UpdateDepthFeedbackLoopReason reason)
319 {
320     // Skip if depth/stencil not actually accessed.
321     if (reason == UpdateDepthFeedbackLoopReason::None)
322     {
323         return vk::ResourceAccess::Unused;
324     }
325 
326     // Note that clear commands don't respect depth test enable, only the mask
327     // Note Other state can be stated here too in the future, such as rasterizer discard.
328     if (!dsState.depthTest && reason != UpdateDepthFeedbackLoopReason::Clear)
329     {
330         return vk::ResourceAccess::Unused;
331     }
332 
333     if (dsState.isDepthMaskedOut())
334     {
335         const bool hasFramebufferFetch =
336             executable ? executable->usesDepthFramebufferFetch() : false;
337 
338         // If depthFunc is GL_ALWAYS or GL_NEVER, we do not need to load depth value.
339         return (dsState.depthFunc == GL_ALWAYS || dsState.depthFunc == GL_NEVER) &&
340                        !hasFramebufferFetch
341                    ? vk::ResourceAccess::Unused
342                    : vk::ResourceAccess::ReadOnly;
343     }
344 
345     return vk::ResourceAccess::ReadWrite;
346 }
347 
GetStencilAccess(const gl::DepthStencilState & dsState,GLuint framebufferStencilSize,const gl::ProgramExecutable * executable,UpdateDepthFeedbackLoopReason reason)348 vk::ResourceAccess GetStencilAccess(const gl::DepthStencilState &dsState,
349                                     GLuint framebufferStencilSize,
350                                     const gl::ProgramExecutable *executable,
351                                     UpdateDepthFeedbackLoopReason reason)
352 {
353     // Skip if depth/stencil not actually accessed.
354     if (reason == UpdateDepthFeedbackLoopReason::None)
355     {
356         return vk::ResourceAccess::Unused;
357     }
358 
359     // Note that clear commands don't respect stencil test enable, only the mask
360     // Note Other state can be stated here too in the future, such as rasterizer discard.
361     if (!dsState.stencilTest && reason != UpdateDepthFeedbackLoopReason::Clear)
362     {
363         return vk::ResourceAccess::Unused;
364     }
365 
366     const bool hasFramebufferFetch = executable ? executable->usesStencilFramebufferFetch() : false;
367 
368     return dsState.isStencilNoOp(framebufferStencilSize) &&
369                    dsState.isStencilBackNoOp(framebufferStencilSize) && !hasFramebufferFetch
370                ? vk::ResourceAccess::ReadOnly
371                : vk::ResourceAccess::ReadWrite;
372 }
373 
GetContextPriority(const gl::State & state)374 egl::ContextPriority GetContextPriority(const gl::State &state)
375 {
376     return egl::FromEGLenum<egl::ContextPriority>(state.getContextPriority());
377 }
378 
IsStencilSamplerBinding(const gl::ProgramExecutable & executable,size_t textureUnit)379 bool IsStencilSamplerBinding(const gl::ProgramExecutable &executable, size_t textureUnit)
380 {
381     const gl::SamplerFormat format = executable.getSamplerFormatForTextureUnitIndex(textureUnit);
382     const bool isStencilTexture    = format == gl::SamplerFormat::Unsigned;
383     return isStencilTexture;
384 }
385 
GetDepthStencilAttachmentImageReadLayout(const vk::ImageHelper & image,gl::ShaderType firstShader)386 vk::ImageLayout GetDepthStencilAttachmentImageReadLayout(const vk::ImageHelper &image,
387                                                          gl::ShaderType firstShader)
388 {
389     const bool isDepthTexture =
390         image.hasRenderPassUsageFlag(vk::RenderPassUsage::DepthTextureSampler);
391     const bool isStencilTexture =
392         image.hasRenderPassUsageFlag(vk::RenderPassUsage::StencilTextureSampler);
393 
394     const bool isDepthReadOnlyAttachment =
395         image.hasRenderPassUsageFlag(vk::RenderPassUsage::DepthReadOnlyAttachment);
396     const bool isStencilReadOnlyAttachment =
397         image.hasRenderPassUsageFlag(vk::RenderPassUsage::StencilReadOnlyAttachment);
398 
399     const bool isFS = firstShader == gl::ShaderType::Fragment;
400 
401     // Only called when at least one aspect of the image is bound as texture
402     ASSERT(isDepthTexture || isStencilTexture);
403 
404     // Check for feedback loop; this is when depth or stencil is both bound as a texture and is used
405     // in a non-read-only way as attachment.
406     if ((isDepthTexture && !isDepthReadOnlyAttachment) ||
407         (isStencilTexture && !isStencilReadOnlyAttachment))
408     {
409         return isFS ? vk::ImageLayout::DepthStencilFragmentShaderFeedback
410                     : vk::ImageLayout::DepthStencilAllShadersFeedback;
411     }
412 
413     if (isDepthReadOnlyAttachment)
414     {
415         if (isStencilReadOnlyAttachment)
416         {
417             // Depth read + stencil read
418             return isFS ? vk::ImageLayout::DepthReadStencilReadFragmentShaderRead
419                         : vk::ImageLayout::DepthReadStencilReadAllShadersRead;
420         }
421         else
422         {
423             // Depth read + stencil write
424             return isFS ? vk::ImageLayout::DepthReadStencilWriteFragmentShaderDepthRead
425                         : vk::ImageLayout::DepthReadStencilWriteAllShadersDepthRead;
426         }
427     }
428     else
429     {
430         if (isStencilReadOnlyAttachment)
431         {
432             // Depth write + stencil read
433             return isFS ? vk::ImageLayout::DepthWriteStencilReadFragmentShaderStencilRead
434                         : vk::ImageLayout::DepthWriteStencilReadAllShadersStencilRead;
435         }
436         else
437         {
438             // Depth write + stencil write: This is definitely a feedback loop and is handled above.
439             UNREACHABLE();
440             return vk::ImageLayout::DepthStencilAllShadersFeedback;
441         }
442     }
443 }
444 
GetImageReadLayout(TextureVk * textureVk,const gl::ProgramExecutable & executable,size_t textureUnit,PipelineType pipelineType)445 vk::ImageLayout GetImageReadLayout(TextureVk *textureVk,
446                                    const gl::ProgramExecutable &executable,
447                                    size_t textureUnit,
448                                    PipelineType pipelineType)
449 {
450     vk::ImageHelper &image = textureVk->getImage();
451 
452     // If this texture has been bound as image and the current executable program accesses images,
453     // we consider this image's layout as writeable.
454     if (textureVk->hasBeenBoundAsImage() && executable.hasImages())
455     {
456         return pipelineType == PipelineType::Compute ? vk::ImageLayout::ComputeShaderWrite
457                                                      : vk::ImageLayout::AllGraphicsShadersWrite;
458     }
459 
460     gl::ShaderBitSet remainingShaderBits =
461         executable.getSamplerShaderBitsForTextureUnitIndex(textureUnit);
462     ASSERT(remainingShaderBits.any());
463     gl::ShaderType firstShader = remainingShaderBits.first();
464     gl::ShaderType lastShader  = remainingShaderBits.last();
465     remainingShaderBits.reset(firstShader);
466     remainingShaderBits.reset(lastShader);
467 
468     const bool isFragmentShaderOnly = firstShader == gl::ShaderType::Fragment;
469     if (isFragmentShaderOnly)
470     {
471         ASSERT(remainingShaderBits.none() && lastShader == firstShader);
472     }
473 
474     if (image.hasRenderPassUsageFlag(vk::RenderPassUsage::RenderTargetAttachment))
475     {
476         // Right now we set the *TextureSampler flag only when RenderTargetAttachment is set since
477         // we do not track all textures in the render pass.
478 
479         if (image.isDepthOrStencil())
480         {
481             if (IsStencilSamplerBinding(executable, textureUnit))
482             {
483                 image.setRenderPassUsageFlag(vk::RenderPassUsage::StencilTextureSampler);
484             }
485             else
486             {
487                 image.setRenderPassUsageFlag(vk::RenderPassUsage::DepthTextureSampler);
488             }
489 
490             return GetDepthStencilAttachmentImageReadLayout(image, firstShader);
491         }
492 
493         image.setRenderPassUsageFlag(vk::RenderPassUsage::ColorTextureSampler);
494 
495         return isFragmentShaderOnly ? vk::ImageLayout::ColorWriteFragmentShaderFeedback
496                                     : vk::ImageLayout::ColorWriteAllShadersFeedback;
497     }
498 
499     if (image.isDepthOrStencil())
500     {
501         // We always use a depth-stencil read-only layout for any depth Textures to simplify
502         // our implementation's handling of depth-stencil read-only mode. We don't have to
503         // split a RenderPass to transition a depth texture from shader-read to read-only.
504         // This improves performance in Manhattan. Future optimizations are likely possible
505         // here including using specialized barriers without breaking the RenderPass.
506         return isFragmentShaderOnly ? vk::ImageLayout::DepthReadStencilReadFragmentShaderRead
507                                     : vk::ImageLayout::DepthReadStencilReadAllShadersRead;
508     }
509 
510     // We barrier against either:
511     // - Vertex only
512     // - Fragment only
513     // - Pre-fragment only (vertex, geometry and tessellation together)
514     if (remainingShaderBits.any() || firstShader != lastShader)
515     {
516         return lastShader == gl::ShaderType::Fragment ? vk::ImageLayout::AllGraphicsShadersReadOnly
517                                                       : vk::ImageLayout::PreFragmentShadersReadOnly;
518     }
519 
520     return kShaderReadOnlyImageLayouts[firstShader];
521 }
522 
GetImageWriteLayoutAndSubresource(const gl::ImageUnit & imageUnit,vk::ImageHelper & image,gl::ShaderBitSet shaderStages,gl::LevelIndex * levelOut,uint32_t * layerStartOut,uint32_t * layerCountOut)523 vk::ImageLayout GetImageWriteLayoutAndSubresource(const gl::ImageUnit &imageUnit,
524                                                   vk::ImageHelper &image,
525                                                   gl::ShaderBitSet shaderStages,
526                                                   gl::LevelIndex *levelOut,
527                                                   uint32_t *layerStartOut,
528                                                   uint32_t *layerCountOut)
529 {
530     *levelOut = gl::LevelIndex(static_cast<uint32_t>(imageUnit.level));
531 
532     *layerStartOut = 0;
533     *layerCountOut = image.getLayerCount();
534     if (imageUnit.layered)
535     {
536         *layerStartOut = imageUnit.layered;
537         *layerCountOut = 1;
538     }
539 
540     gl::ShaderType firstShader = shaderStages.first();
541     gl::ShaderType lastShader  = shaderStages.last();
542     shaderStages.reset(firstShader);
543     shaderStages.reset(lastShader);
544     // We barrier against either:
545     // - Vertex only
546     // - Fragment only
547     // - Pre-fragment only (vertex, geometry and tessellation together)
548     if (shaderStages.any() || firstShader != lastShader)
549     {
550         return lastShader == gl::ShaderType::Fragment ? vk::ImageLayout::AllGraphicsShadersWrite
551                                                       : vk::ImageLayout::PreFragmentShadersWrite;
552     }
553 
554     return kShaderWriteImageLayouts[firstShader];
555 }
556 
557 template <typename CommandBufferT>
OnTextureBufferRead(vk::Context * context,vk::BufferHelper * buffer,gl::ShaderBitSet stages,CommandBufferT * commandBufferHelper)558 void OnTextureBufferRead(vk::Context *context,
559                          vk::BufferHelper *buffer,
560                          gl::ShaderBitSet stages,
561                          CommandBufferT *commandBufferHelper)
562 {
563     ASSERT(stages.any());
564 
565     // TODO: accept multiple stages in bufferRead.  http://anglebug.com/42262235
566     for (gl::ShaderType stage : stages)
567     {
568         // Note: if another range of the same buffer is simultaneously used for storage,
569         // such as for transform feedback output, or SSBO, unnecessary barriers can be
570         // generated.
571         commandBufferHelper->bufferRead(context, VK_ACCESS_SHADER_READ_BIT,
572                                         vk::GetPipelineStage(stage), buffer);
573     }
574 }
575 
576 template <typename CommandBufferT>
OnImageBufferWrite(vk::Context * context,BufferVk * bufferVk,gl::ShaderBitSet stages,CommandBufferT * commandBufferHelper)577 void OnImageBufferWrite(vk::Context *context,
578                         BufferVk *bufferVk,
579                         gl::ShaderBitSet stages,
580                         CommandBufferT *commandBufferHelper)
581 {
582     vk::BufferHelper &buffer = bufferVk->getBuffer();
583     VkAccessFlags accessFlags = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
584     commandBufferHelper->bufferWrite(context, accessFlags, stages, &buffer);
585 }
586 
587 constexpr angle::PackedEnumMap<RenderPassClosureReason, const char *> kRenderPassClosureReason = {{
588     {RenderPassClosureReason::AlreadySpecifiedElsewhere, nullptr},
589     {RenderPassClosureReason::ContextDestruction, "Render pass closed due to context destruction"},
590     {RenderPassClosureReason::ContextChange, "Render pass closed due to context change"},
591     {RenderPassClosureReason::GLFlush, "Render pass closed due to glFlush()"},
592     {RenderPassClosureReason::GLFinish, "Render pass closed due to glFinish()"},
593     {RenderPassClosureReason::EGLSwapBuffers, "Render pass closed due to eglSwapBuffers()"},
594     {RenderPassClosureReason::EGLWaitClient, "Render pass closed due to eglWaitClient()"},
595     {RenderPassClosureReason::SurfaceUnMakeCurrent,
596      "Render pass closed due to onSurfaceUnMakeCurrent()"},
597     {RenderPassClosureReason::FramebufferBindingChange,
598      "Render pass closed due to framebuffer binding change"},
599     {RenderPassClosureReason::FramebufferChange, "Render pass closed due to framebuffer change"},
600     {RenderPassClosureReason::NewRenderPass,
601      "Render pass closed due to starting a new render pass"},
602     {RenderPassClosureReason::BufferUseThenXfbWrite,
603      "Render pass closed due to buffer use as transform feedback output after prior use in render "
604      "pass"},
605     {RenderPassClosureReason::XfbWriteThenVertexIndexBuffer,
606      "Render pass closed due to transform feedback buffer use as vertex/index input"},
607     {RenderPassClosureReason::XfbWriteThenIndirectDrawBuffer,
608      "Render pass closed due to indirect draw buffer previously used as transform feedback output "
609      "in render pass"},
610     {RenderPassClosureReason::XfbResumeAfterDrawBasedClear,
611      "Render pass closed due to transform feedback resume after clear through draw"},
612     {RenderPassClosureReason::DepthStencilUseInFeedbackLoop,
613      "Render pass closed due to depth/stencil attachment use under feedback loop"},
614     {RenderPassClosureReason::DepthStencilWriteAfterFeedbackLoop,
615      "Render pass closed due to depth/stencil attachment write after feedback loop"},
616     {RenderPassClosureReason::PipelineBindWhileXfbActive,
617      "Render pass closed due to graphics pipeline change while transform feedback is active"},
618     {RenderPassClosureReason::XfbWriteThenTextureBuffer,
619      "Render pass closed due to read of texture buffer previously used as transform feedback "
620      "output in render pass"},
621     {RenderPassClosureReason::BufferWriteThenMap,
622      "Render pass closed due to mapping buffer being written to by said render pass"},
623     {RenderPassClosureReason::BufferWriteThenOutOfRPRead,
624      "Render pass closed due to non-render-pass read of buffer that was written to in render pass"},
625     {RenderPassClosureReason::BufferUseThenOutOfRPWrite,
626      "Render pass closed due to non-render-pass write of buffer that was used in render pass"},
627     {RenderPassClosureReason::ImageUseThenOutOfRPRead,
628      "Render pass closed due to non-render-pass read of image that was used in render pass"},
629     {RenderPassClosureReason::ImageUseThenOutOfRPWrite,
630      "Render pass closed due to non-render-pass write of image that was used in render pass"},
631     {RenderPassClosureReason::XfbWriteThenComputeRead,
632      "Render pass closed due to compute read of buffer previously used as transform feedback "
633      "output in render pass"},
634     {RenderPassClosureReason::XfbWriteThenIndirectDispatchBuffer,
635      "Render pass closed due to indirect dispatch buffer previously used as transform feedback "
636      "output in render pass"},
637     {RenderPassClosureReason::ImageAttachmentThenComputeRead,
638      "Render pass closed due to compute read of image previously used as framebuffer attachment in "
639      "render pass"},
640     {RenderPassClosureReason::GetQueryResult, "Render pass closed due to getting query result"},
641     {RenderPassClosureReason::BeginNonRenderPassQuery,
642      "Render pass closed due to non-render-pass query begin"},
643     {RenderPassClosureReason::EndNonRenderPassQuery,
644      "Render pass closed due to non-render-pass query end"},
645     {RenderPassClosureReason::TimestampQuery, "Render pass closed due to timestamp query"},
646     {RenderPassClosureReason::EndRenderPassQuery,
647      "Render pass closed due to switch from query enabled draw to query disabled draw"},
648     {RenderPassClosureReason::GLReadPixels, "Render pass closed due to glReadPixels()"},
649     {RenderPassClosureReason::BufferUseThenReleaseToExternal,
650      "Render pass closed due to buffer (used by render pass) release to external"},
651     {RenderPassClosureReason::ImageUseThenReleaseToExternal,
652      "Render pass closed due to image (used by render pass) release to external"},
653     {RenderPassClosureReason::BufferInUseWhenSynchronizedMap,
654      "Render pass closed due to mapping buffer in use by GPU without GL_MAP_UNSYNCHRONIZED_BIT"},
655     {RenderPassClosureReason::GLMemoryBarrierThenStorageResource,
656      "Render pass closed due to glMemoryBarrier before storage output in render pass"},
657     {RenderPassClosureReason::StorageResourceUseThenGLMemoryBarrier,
658      "Render pass closed due to glMemoryBarrier after storage output in render pass"},
659     {RenderPassClosureReason::ExternalSemaphoreSignal,
660      "Render pass closed due to external semaphore signal"},
661     {RenderPassClosureReason::SyncObjectInit, "Render pass closed due to sync object insertion"},
662     {RenderPassClosureReason::SyncObjectWithFdInit,
663      "Render pass closed due to sync object with fd insertion"},
664     {RenderPassClosureReason::SyncObjectClientWait,
665      "Render pass closed due to sync object client wait"},
666     {RenderPassClosureReason::SyncObjectServerWait,
667      "Render pass closed due to sync object server wait"},
668     {RenderPassClosureReason::SyncObjectGetStatus,
669      "Render pass closed due to sync object get status"},
670     {RenderPassClosureReason::ForeignImageRelease,
671      "Render pass closed due to release of foreign image"},
672     {RenderPassClosureReason::XfbPause, "Render pass closed due to transform feedback pause"},
673     {RenderPassClosureReason::FramebufferFetchEmulation,
674      "Render pass closed due to framebuffer fetch emulation"},
675     {RenderPassClosureReason::ColorBufferWithEmulatedAlphaInvalidate,
676      "Render pass closed due to color attachment with emulated alpha channel being invalidated"},
677     {RenderPassClosureReason::GenerateMipmapOnCPU,
678      "Render pass closed due to fallback to CPU when generating mipmaps"},
679     {RenderPassClosureReason::CopyTextureOnCPU,
680      "Render pass closed due to fallback to CPU when copying texture"},
681     {RenderPassClosureReason::TextureReformatToRenderable,
682      "Render pass closed due to reformatting texture to a renderable fallback"},
683     {RenderPassClosureReason::DeviceLocalBufferMap,
684      "Render pass closed due to mapping device local buffer"},
685     {RenderPassClosureReason::PrepareForBlit, "Render pass closed prior to draw-based blit"},
686     {RenderPassClosureReason::PrepareForImageCopy,
687      "Render pass closed prior to draw-based image copy"},
688     {RenderPassClosureReason::TemporaryForImageClear,
689      "Temporary render pass used for image clear closed"},
690     {RenderPassClosureReason::TemporaryForImageCopy,
691      "Temporary render pass used for image copy closed"},
692     {RenderPassClosureReason::TemporaryForOverlayDraw,
693      "Temporary render pass used for overlay draw closed"},
694 }};
695 
GetLocalDependencyFlags(ContextVk * contextVk)696 VkDependencyFlags GetLocalDependencyFlags(ContextVk *contextVk)
697 {
698     VkDependencyFlags dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
699     if (contextVk->getCurrentViewCount() > 0)
700     {
701         dependencyFlags |= VK_DEPENDENCY_VIEW_LOCAL_BIT;
702     }
703     return dependencyFlags;
704 }
705 
BlendModeSupportsDither(const ContextVk * contextVk,size_t colorIndex)706 bool BlendModeSupportsDither(const ContextVk *contextVk, size_t colorIndex)
707 {
708     const gl::State &state = contextVk->getState();
709 
710     // Specific combinations of color blend modes are known to work with our dithering emulation.
711     // Note we specifically don't check alpha blend, as dither isn't applied to alpha.
712     // See http://b/232574868 for more discussion and reasoning.
713     gl::BlendFactorType srcBlendFactor = state.getBlendStateExt().getSrcColorIndexed(colorIndex);
714     gl::BlendFactorType dstBlendFactor = state.getBlendStateExt().getDstColorIndexed(colorIndex);
715 
716     const bool ditheringCompatibleBlendFactors =
717         (srcBlendFactor == gl::BlendFactorType::SrcAlpha &&
718          dstBlendFactor == gl::BlendFactorType::OneMinusSrcAlpha);
719 
720     const bool allowAdditionalBlendFactors =
721         contextVk->getFeatures().enableAdditionalBlendFactorsForDithering.enabled &&
722         (srcBlendFactor == gl::BlendFactorType::One &&
723          dstBlendFactor == gl::BlendFactorType::OneMinusSrcAlpha);
724 
725     return ditheringCompatibleBlendFactors || allowAdditionalBlendFactors;
726 }
727 
ShouldUseGraphicsDriverUniformsExtended(const vk::ErrorContext * context)728 bool ShouldUseGraphicsDriverUniformsExtended(const vk::ErrorContext *context)
729 {
730     return context->getFeatures().emulateTransformFeedback.enabled;
731 }
732 
IsAnySamplesQuery(gl::QueryType type)733 bool IsAnySamplesQuery(gl::QueryType type)
734 {
735     return type == gl::QueryType::AnySamples || type == gl::QueryType::AnySamplesConservative;
736 }
737 
QueueSerialsHaveDifferentIndexOrSmaller(const QueueSerial & queueSerial1,const QueueSerial & queueSerial2)738 bool QueueSerialsHaveDifferentIndexOrSmaller(const QueueSerial &queueSerial1,
739                                              const QueueSerial &queueSerial2)
740 {
741     return queueSerial1.getIndex() != queueSerial2.getIndex() || queueSerial1 < queueSerial2;
742 }
743 
UpdateImagesWithSharedCacheKey(const gl::ActiveTextureArray<TextureVk * > & activeImages,const std::vector<gl::ImageBinding> & imageBindings,const vk::SharedDescriptorSetCacheKey & sharedCacheKey)744 void UpdateImagesWithSharedCacheKey(const gl::ActiveTextureArray<TextureVk *> &activeImages,
745                                     const std::vector<gl::ImageBinding> &imageBindings,
746                                     const vk::SharedDescriptorSetCacheKey &sharedCacheKey)
747 {
748     for (const gl::ImageBinding &imageBinding : imageBindings)
749     {
750         uint32_t arraySize = static_cast<uint32_t>(imageBinding.boundImageUnits.size());
751         for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
752         {
753             GLuint imageUnit = imageBinding.boundImageUnits[arrayElement];
754             // For simplicity, we do not check if uniform is active or duplicate. The worst case is
755             // we unnecessarily delete the cache entry when image bound to inactive uniform is
756             // destroyed.
757             activeImages[imageUnit]->onNewDescriptorSet(sharedCacheKey);
758         }
759     }
760 }
761 
UpdateBufferWithSharedCacheKey(const gl::OffsetBindingPointer<gl::Buffer> & bufferBinding,const vk::SharedDescriptorSetCacheKey & sharedCacheKey)762 void UpdateBufferWithSharedCacheKey(const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding,
763                                     const vk::SharedDescriptorSetCacheKey &sharedCacheKey)
764 {
765     if (bufferBinding.get() != nullptr)
766     {
767         // For simplicity, we do not check if uniform is active or duplicate. The worst case is
768         // we unnecessarily delete the cache entry when buffer bound to inactive uniform is
769         // destroyed.
770         BufferVk *bufferVk             = vk::GetImpl(bufferBinding.get());
771         vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
772         bufferHelper.onNewDescriptorSet(sharedCacheKey);
773     }
774 }
775 
GenerateTextureUnitSamplerIndexMap(const std::vector<GLuint> & samplerBoundTextureUnits,std::unordered_map<size_t,uint32_t> * textureUnitSamplerIndexMapOut)776 void GenerateTextureUnitSamplerIndexMap(
777     const std::vector<GLuint> &samplerBoundTextureUnits,
778     std::unordered_map<size_t, uint32_t> *textureUnitSamplerIndexMapOut)
779 {
780     // Create a map of textureUnit <-> samplerIndex
781     for (size_t samplerIndex = 0; samplerIndex < samplerBoundTextureUnits.size(); samplerIndex++)
782     {
783         textureUnitSamplerIndexMapOut->insert(
784             {samplerBoundTextureUnits[samplerIndex], static_cast<uint32_t>(samplerIndex)});
785     }
786 }
787 }  // anonymous namespace
788 
flushDescriptorSetUpdates()789 void ContextVk::flushDescriptorSetUpdates()
790 {
791     mPerfCounters.writeDescriptorSets +=
792         mShareGroupVk->getUpdateDescriptorSetsBuilder()->flushDescriptorSetUpdates(getDevice());
793 }
794 
onRenderPassFinished(RenderPassClosureReason reason)795 ANGLE_INLINE void ContextVk::onRenderPassFinished(RenderPassClosureReason reason)
796 {
797     if (mRenderPassCommandBuffer != nullptr)
798     {
799         pauseRenderPassQueriesIfActive();
800 
801         // If reason is specified, add it to the command buffer right before ending the render pass,
802         // so it will show up in GPU debuggers.
803         const char *reasonText = kRenderPassClosureReason[reason];
804         if (reasonText)
805         {
806             insertEventMarkerImpl(GL_DEBUG_SOURCE_API, reasonText);
807         }
808 
809         mRenderPassCommandBuffer = nullptr;
810 
811         // Restart at subpass 0.
812         mGraphicsPipelineDesc->resetSubpass(&mGraphicsPipelineTransition);
813     }
814 
815     mGraphicsDirtyBits.set(DIRTY_BIT_RENDER_PASS);
816 }
817 
818 // ContextVk implementation.
ContextVk(const gl::State & state,gl::ErrorSet * errorSet,vk::Renderer * renderer)819 ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, vk::Renderer *renderer)
820     : ContextImpl(state, errorSet),
821       vk::Context(renderer),
822       mGraphicsDirtyBitHandlers{},
823       mComputeDirtyBitHandlers{},
824       mRenderPassCommandBuffer(nullptr),
825       mCurrentGraphicsPipeline(nullptr),
826       mCurrentGraphicsPipelineShaders(nullptr),
827       mCurrentComputePipeline(nullptr),
828       mCurrentDrawMode(gl::PrimitiveMode::InvalidEnum),
829       mCurrentWindowSurface(nullptr),
830       mCurrentRotationDrawFramebuffer(SurfaceRotation::Identity),
831       mCurrentRotationReadFramebuffer(SurfaceRotation::Identity),
832       mActiveRenderPassQueries{},
833       mLastIndexBufferOffset(nullptr),
834       mCurrentIndexBuffer(nullptr),
835       mCurrentIndexBufferOffset(0),
836       mCurrentDrawElementsType(gl::DrawElementsType::InvalidEnum),
837       mXfbBaseVertex(0),
838       mXfbVertexCountPerInstance(0),
839       mClearColorValue{},
840       mClearDepthStencilValue{},
841       mClearColorMasks(0),
842       mDeferredMemoryBarriers(0),
843       mFlipYForCurrentSurface(false),
844       mFlipViewportForDrawFramebuffer(false),
845       mFlipViewportForReadFramebuffer(false),
846       mIsAnyHostVisibleBufferWritten(false),
847       mCurrentQueueSerialIndex(kInvalidQueueSerialIndex),
848       mOutsideRenderPassCommands(nullptr),
849       mRenderPassCommands(nullptr),
850       mQueryEventType(GraphicsEventCmdBuf::NotInQueryCmd),
851       mGpuEventsEnabled(false),
852       mPrimaryBufferEventCounter(0),
853       mHasDeferredFlush(false),
854       mHasAnyCommandsPendingSubmission(false),
855       mIsInColorFramebufferFetchMode(false),
856       mAllowRenderPassToReactivate(true),
857       mTotalBufferToImageCopySize(0),
858       mEstimatedPendingImageGarbageSize(0),
859       mHasWaitSemaphoresPendingSubmission(false),
860       mGpuClockSync{std::numeric_limits<double>::max(), std::numeric_limits<double>::max()},
861       mGpuEventTimestampOrigin(0),
862       mInitialContextPriority(renderer->getDriverPriority(GetContextPriority(state))),
863       mContextPriority(mInitialContextPriority),
864       mProtectionType(vk::ConvertProtectionBoolToType(state.hasProtectedContent())),
865       mShareGroupVk(vk::GetImpl(state.getShareGroup())),
866       mCommandsPendingSubmissionCount(0)
867 {
868     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::ContextVk");
869     memset(&mClearColorValue, 0, sizeof(mClearColorValue));
870     memset(&mClearDepthStencilValue, 0, sizeof(mClearDepthStencilValue));
871     memset(&mViewport, 0, sizeof(mViewport));
872     memset(&mScissor, 0, sizeof(mScissor));
873 
874     // Ensure viewport is within Vulkan requirements
875     vk::ClampViewport(&mViewport);
876 
877     mNonIndexedDirtyBitsMask.set();
878     mNonIndexedDirtyBitsMask.reset(DIRTY_BIT_INDEX_BUFFER);
879 
880     mIndexedDirtyBitsMask.set();
881 
882     // Once a command buffer is ended, all bindings (through |vkCmdBind*| calls) are lost per Vulkan
883     // spec.  Once a new command buffer is allocated, we must make sure every previously bound
884     // resource is bound again.
885     //
886     // Note that currently these dirty bits are set every time a new render pass command buffer is
887     // begun.  However, using ANGLE's SecondaryCommandBuffer, the Vulkan command buffer (which is
888     // the primary command buffer) is not ended, so technically we don't need to rebind these.
889     mNewGraphicsCommandBufferDirtyBits = DirtyBits{
890         DIRTY_BIT_RENDER_PASS,      DIRTY_BIT_COLOR_ACCESS,     DIRTY_BIT_DEPTH_STENCIL_ACCESS,
891         DIRTY_BIT_PIPELINE_BINDING, DIRTY_BIT_TEXTURES,         DIRTY_BIT_VERTEX_BUFFERS,
892         DIRTY_BIT_INDEX_BUFFER,     DIRTY_BIT_SHADER_RESOURCES, DIRTY_BIT_DESCRIPTOR_SETS,
893         DIRTY_BIT_DRIVER_UNIFORMS,
894     };
895     if (getFeatures().supportsTransformFeedbackExtension.enabled ||
896         getFeatures().emulateTransformFeedback.enabled)
897     {
898         mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS);
899     }
900 
901     mNewComputeCommandBufferDirtyBits =
902         DirtyBits{DIRTY_BIT_PIPELINE_BINDING, DIRTY_BIT_TEXTURES, DIRTY_BIT_SHADER_RESOURCES,
903                   DIRTY_BIT_DESCRIPTOR_SETS, DIRTY_BIT_DRIVER_UNIFORMS};
904 
905     mDynamicStateDirtyBits = DirtyBits{
906         DIRTY_BIT_DYNAMIC_VIEWPORT,           DIRTY_BIT_DYNAMIC_SCISSOR,
907         DIRTY_BIT_DYNAMIC_LINE_WIDTH,         DIRTY_BIT_DYNAMIC_DEPTH_BIAS,
908         DIRTY_BIT_DYNAMIC_BLEND_CONSTANTS,    DIRTY_BIT_DYNAMIC_STENCIL_COMPARE_MASK,
909         DIRTY_BIT_DYNAMIC_STENCIL_WRITE_MASK, DIRTY_BIT_DYNAMIC_STENCIL_REFERENCE,
910     };
911     if (mRenderer->getFeatures().useVertexInputBindingStrideDynamicState.enabled ||
912         getFeatures().supportsVertexInputDynamicState.enabled)
913     {
914         mDynamicStateDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
915     }
916     if (mRenderer->getFeatures().useCullModeDynamicState.enabled)
917     {
918         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_CULL_MODE);
919     }
920     if (mRenderer->getFeatures().useFrontFaceDynamicState.enabled)
921     {
922         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_FRONT_FACE);
923     }
924     if (mRenderer->getFeatures().useDepthTestEnableDynamicState.enabled)
925     {
926         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_TEST_ENABLE);
927     }
928     if (mRenderer->getFeatures().useDepthWriteEnableDynamicState.enabled)
929     {
930         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_WRITE_ENABLE);
931     }
932     if (mRenderer->getFeatures().useDepthCompareOpDynamicState.enabled)
933     {
934         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_COMPARE_OP);
935     }
936     if (mRenderer->getFeatures().useStencilTestEnableDynamicState.enabled)
937     {
938         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_TEST_ENABLE);
939     }
940     if (mRenderer->getFeatures().useStencilOpDynamicState.enabled)
941     {
942         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_OP);
943     }
944     if (mRenderer->getFeatures().usePrimitiveRestartEnableDynamicState.enabled)
945     {
946         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_PRIMITIVE_RESTART_ENABLE);
947     }
948     if (mRenderer->getFeatures().useRasterizerDiscardEnableDynamicState.enabled)
949     {
950         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_RASTERIZER_DISCARD_ENABLE);
951     }
952     if (mRenderer->getFeatures().useDepthBiasEnableDynamicState.enabled)
953     {
954         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_BIAS_ENABLE);
955     }
956     if (mRenderer->getFeatures().supportsLogicOpDynamicState.enabled)
957     {
958         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_LOGIC_OP);
959     }
960     if (getFeatures().supportsFragmentShadingRate.enabled)
961     {
962         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_FRAGMENT_SHADING_RATE);
963     }
964 
965     mNewGraphicsCommandBufferDirtyBits |= mDynamicStateDirtyBits;
966 
967     mGraphicsDirtyBitHandlers[DIRTY_BIT_MEMORY_BARRIER] =
968         &ContextVk::handleDirtyGraphicsMemoryBarrier;
969     mGraphicsDirtyBitHandlers[DIRTY_BIT_DEFAULT_ATTRIBS] =
970         &ContextVk::handleDirtyGraphicsDefaultAttribs;
971     mGraphicsDirtyBitHandlers[DIRTY_BIT_PIPELINE_DESC] =
972         &ContextVk::handleDirtyGraphicsPipelineDesc;
973     mGraphicsDirtyBitHandlers[DIRTY_BIT_READ_ONLY_DEPTH_FEEDBACK_LOOP_MODE] =
974         &ContextVk::handleDirtyGraphicsReadOnlyDepthFeedbackLoopMode;
975     mGraphicsDirtyBitHandlers[DIRTY_BIT_ANY_SAMPLE_PASSED_QUERY_END] =
976         &ContextVk::handleDirtyAnySamplePassedQueryEnd;
977     mGraphicsDirtyBitHandlers[DIRTY_BIT_RENDER_PASS]  = &ContextVk::handleDirtyGraphicsRenderPass;
978     mGraphicsDirtyBitHandlers[DIRTY_BIT_EVENT_LOG]    = &ContextVk::handleDirtyGraphicsEventLog;
979     mGraphicsDirtyBitHandlers[DIRTY_BIT_COLOR_ACCESS] = &ContextVk::handleDirtyGraphicsColorAccess;
980     mGraphicsDirtyBitHandlers[DIRTY_BIT_DEPTH_STENCIL_ACCESS] =
981         &ContextVk::handleDirtyGraphicsDepthStencilAccess;
982     mGraphicsDirtyBitHandlers[DIRTY_BIT_PIPELINE_BINDING] =
983         &ContextVk::handleDirtyGraphicsPipelineBinding;
984     mGraphicsDirtyBitHandlers[DIRTY_BIT_TEXTURES] = &ContextVk::handleDirtyGraphicsTextures;
985     mGraphicsDirtyBitHandlers[DIRTY_BIT_VERTEX_BUFFERS] =
986         &ContextVk::handleDirtyGraphicsVertexBuffers;
987     mGraphicsDirtyBitHandlers[DIRTY_BIT_INDEX_BUFFER] = &ContextVk::handleDirtyGraphicsIndexBuffer;
988     mGraphicsDirtyBitHandlers[DIRTY_BIT_UNIFORMS]     = &ContextVk::handleDirtyGraphicsUniforms;
989     mGraphicsDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS] =
990         &ContextVk::handleDirtyGraphicsDriverUniforms;
991     mGraphicsDirtyBitHandlers[DIRTY_BIT_SHADER_RESOURCES] =
992         &ContextVk::handleDirtyGraphicsShaderResources;
993     mGraphicsDirtyBitHandlers[DIRTY_BIT_UNIFORM_BUFFERS] =
994         &ContextVk::handleDirtyGraphicsUniformBuffers;
995     mGraphicsDirtyBitHandlers[DIRTY_BIT_FRAMEBUFFER_FETCH_BARRIER] =
996         &ContextVk::handleDirtyGraphicsFramebufferFetchBarrier;
997     mGraphicsDirtyBitHandlers[DIRTY_BIT_BLEND_BARRIER] =
998         &ContextVk::handleDirtyGraphicsBlendBarrier;
999     if (getFeatures().supportsTransformFeedbackExtension.enabled)
1000     {
1001         mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS] =
1002             &ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension;
1003         mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME] =
1004             &ContextVk::handleDirtyGraphicsTransformFeedbackResume;
1005     }
1006     else if (getFeatures().emulateTransformFeedback.enabled)
1007     {
1008         mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS] =
1009             &ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation;
1010     }
1011 
1012     mGraphicsDirtyBitHandlers[DIRTY_BIT_DESCRIPTOR_SETS] =
1013         &ContextVk::handleDirtyGraphicsDescriptorSets;
1014 
1015     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_VIEWPORT] =
1016         &ContextVk::handleDirtyGraphicsDynamicViewport;
1017     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_SCISSOR] =
1018         &ContextVk::handleDirtyGraphicsDynamicScissor;
1019     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_LINE_WIDTH] =
1020         &ContextVk::handleDirtyGraphicsDynamicLineWidth;
1021     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_DEPTH_BIAS] =
1022         &ContextVk::handleDirtyGraphicsDynamicDepthBias;
1023     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_BLEND_CONSTANTS] =
1024         &ContextVk::handleDirtyGraphicsDynamicBlendConstants;
1025     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_STENCIL_COMPARE_MASK] =
1026         &ContextVk::handleDirtyGraphicsDynamicStencilCompareMask;
1027     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_STENCIL_WRITE_MASK] =
1028         &ContextVk::handleDirtyGraphicsDynamicStencilWriteMask;
1029     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_STENCIL_REFERENCE] =
1030         &ContextVk::handleDirtyGraphicsDynamicStencilReference;
1031     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_CULL_MODE] =
1032         &ContextVk::handleDirtyGraphicsDynamicCullMode;
1033     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_FRONT_FACE] =
1034         &ContextVk::handleDirtyGraphicsDynamicFrontFace;
1035     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_DEPTH_TEST_ENABLE] =
1036         &ContextVk::handleDirtyGraphicsDynamicDepthTestEnable;
1037     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_DEPTH_WRITE_ENABLE] =
1038         &ContextVk::handleDirtyGraphicsDynamicDepthWriteEnable;
1039     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_DEPTH_COMPARE_OP] =
1040         &ContextVk::handleDirtyGraphicsDynamicDepthCompareOp;
1041     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_STENCIL_TEST_ENABLE] =
1042         &ContextVk::handleDirtyGraphicsDynamicStencilTestEnable;
1043     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_STENCIL_OP] =
1044         &ContextVk::handleDirtyGraphicsDynamicStencilOp;
1045     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_RASTERIZER_DISCARD_ENABLE] =
1046         &ContextVk::handleDirtyGraphicsDynamicRasterizerDiscardEnable;
1047     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_DEPTH_BIAS_ENABLE] =
1048         &ContextVk::handleDirtyGraphicsDynamicDepthBiasEnable;
1049     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_LOGIC_OP] =
1050         &ContextVk::handleDirtyGraphicsDynamicLogicOp;
1051     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_PRIMITIVE_RESTART_ENABLE] =
1052         &ContextVk::handleDirtyGraphicsDynamicPrimitiveRestartEnable;
1053     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_FRAGMENT_SHADING_RATE] =
1054         &ContextVk::handleDirtyGraphicsDynamicFragmentShadingRate;
1055 
1056     mComputeDirtyBitHandlers[DIRTY_BIT_MEMORY_BARRIER] =
1057         &ContextVk::handleDirtyComputeMemoryBarrier;
1058     mComputeDirtyBitHandlers[DIRTY_BIT_EVENT_LOG]     = &ContextVk::handleDirtyComputeEventLog;
1059     mComputeDirtyBitHandlers[DIRTY_BIT_PIPELINE_DESC] = &ContextVk::handleDirtyComputePipelineDesc;
1060     mComputeDirtyBitHandlers[DIRTY_BIT_PIPELINE_BINDING] =
1061         &ContextVk::handleDirtyComputePipelineBinding;
1062     mComputeDirtyBitHandlers[DIRTY_BIT_TEXTURES] = &ContextVk::handleDirtyComputeTextures;
1063     mComputeDirtyBitHandlers[DIRTY_BIT_UNIFORMS] = &ContextVk::handleDirtyComputeUniforms;
1064     mComputeDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS] =
1065         &ContextVk::handleDirtyComputeDriverUniforms;
1066     mComputeDirtyBitHandlers[DIRTY_BIT_SHADER_RESOURCES] =
1067         &ContextVk::handleDirtyComputeShaderResources;
1068     mComputeDirtyBitHandlers[DIRTY_BIT_UNIFORM_BUFFERS] =
1069         &ContextVk::handleDirtyComputeUniformBuffers;
1070     mComputeDirtyBitHandlers[DIRTY_BIT_DESCRIPTOR_SETS] =
1071         &ContextVk::handleDirtyComputeDescriptorSets;
1072 
1073     mGraphicsDirtyBits = mNewGraphicsCommandBufferDirtyBits;
1074     mComputeDirtyBits  = mNewComputeCommandBufferDirtyBits;
1075 
1076     // If coherent framebuffer fetch is emulated, a barrier is implicitly issued between draw calls
1077     // that use framebuffer fetch.  As such, the corresponding dirty bit shouldn't be cleared until
1078     // a program without framebuffer fetch is used.
1079     if (mRenderer->isCoherentColorFramebufferFetchEmulated())
1080     {
1081         mPersistentGraphicsDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_FETCH_BARRIER);
1082     }
1083 
1084     FillWithNullptr(&mActiveImages);
1085 
1086     // The following dirty bits don't affect the program pipeline:
1087     //
1088     // - READ_FRAMEBUFFER_BINDING only affects operations that read from said framebuffer,
1089     // - CLEAR_* only affect following clear calls,
1090     // - PACK/UNPACK_STATE only affect texture data upload/download,
1091     // - *_BINDING only affect descriptor sets.
1092     //
1093     // Additionally, state that is set dynamically doesn't invalidate the program pipeline.
1094     //
1095     mPipelineDirtyBitsMask.set();
1096     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
1097     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_CLEAR_COLOR);
1098     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_CLEAR_DEPTH);
1099     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_CLEAR_STENCIL);
1100     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_UNPACK_STATE);
1101     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_UNPACK_BUFFER_BINDING);
1102     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_PACK_STATE);
1103     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_PACK_BUFFER_BINDING);
1104     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_RENDERBUFFER_BINDING);
1105     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING);
1106     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING);
1107     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_SAMPLER_BINDINGS);
1108     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_TEXTURE_BINDINGS);
1109     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_IMAGE_BINDINGS);
1110     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING);
1111     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
1112     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
1113     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
1114 
1115     // Dynamic state in core Vulkan 1.0:
1116     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_VIEWPORT);
1117     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_SCISSOR_TEST_ENABLED);
1118     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_SCISSOR);
1119     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_LINE_WIDTH);
1120     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_POLYGON_OFFSET);
1121     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_BLEND_COLOR);
1122     if (!getFeatures().useNonZeroStencilWriteMaskStaticState.enabled)
1123     {
1124         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
1125         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
1126     }
1127 
1128     // Dynamic state in VK_EXT_extended_dynamic_state:
1129     if (mRenderer->getFeatures().useCullModeDynamicState.enabled)
1130     {
1131         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_CULL_FACE_ENABLED);
1132         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_CULL_FACE);
1133     }
1134     if (mRenderer->getFeatures().useFrontFaceDynamicState.enabled)
1135     {
1136         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_FRONT_FACE);
1137     }
1138     if (mRenderer->getFeatures().useDepthTestEnableDynamicState.enabled)
1139     {
1140         // Depth test affects depth write state too in GraphicsPipelineDesc, so the pipeline needs
1141         // to stay dirty if depth test changes while depth write state is static.
1142         if (mRenderer->getFeatures().useDepthWriteEnableDynamicState.enabled)
1143         {
1144             mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_DEPTH_TEST_ENABLED);
1145         }
1146     }
1147     if (mRenderer->getFeatures().useDepthWriteEnableDynamicState.enabled)
1148     {
1149         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_DEPTH_MASK);
1150     }
1151     if (mRenderer->getFeatures().useDepthCompareOpDynamicState.enabled)
1152     {
1153         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_DEPTH_FUNC);
1154     }
1155     if (mRenderer->getFeatures().useStencilTestEnableDynamicState.enabled)
1156     {
1157         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_STENCIL_TEST_ENABLED);
1158     }
1159     if (mRenderer->getFeatures().useStencilOpDynamicState.enabled)
1160     {
1161         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_STENCIL_FUNCS_FRONT);
1162         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_STENCIL_FUNCS_BACK);
1163         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_STENCIL_OPS_FRONT);
1164         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_STENCIL_OPS_BACK);
1165     }
1166     // Dynamic state in VK_EXT_extended_dynamic_state2:
1167     if (mRenderer->getFeatures().usePrimitiveRestartEnableDynamicState.enabled)
1168     {
1169         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
1170     }
1171     if (mRenderer->getFeatures().useRasterizerDiscardEnableDynamicState.enabled)
1172     {
1173         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
1174     }
1175     if (mRenderer->getFeatures().useDepthBiasEnableDynamicState.enabled)
1176     {
1177         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
1178     }
1179     if (getFeatures().supportsVertexInputDynamicState.enabled)
1180     {
1181         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_VERTEX_ARRAY_BINDING);
1182     }
1183 
1184     // Stash the mRefCountedEventRecycler in vk::ErrorContext for ImageHelper to conveniently access
1185     mShareGroupRefCountedEventsGarbageRecycler =
1186         mShareGroupVk->getRefCountedEventsGarbageRecycler();
1187 
1188     mDeviceQueueIndex = renderer->getDeviceQueueIndex(mContextPriority);
1189 
1190     angle::PerfMonitorCounterGroup vulkanGroup;
1191     vulkanGroup.name = "vulkan";
1192 
1193 #define ANGLE_ADD_PERF_MONITOR_COUNTER_GROUP(COUNTER) \
1194     {                                                 \
1195         angle::PerfMonitorCounter counter;            \
1196         counter.name  = #COUNTER;                     \
1197         counter.value = 0;                            \
1198         vulkanGroup.counters.push_back(counter);      \
1199     }
1200 
1201     ANGLE_VK_PERF_COUNTERS_X(ANGLE_ADD_PERF_MONITOR_COUNTER_GROUP)
1202 
1203 #undef ANGLE_ADD_PERF_MONITOR_COUNTER_GROUP
1204 
1205     mPerfMonitorCounters.push_back(vulkanGroup);
1206 
1207     mCurrentGarbage.reserve(32);
1208 }
1209 
~ContextVk()1210 ContextVk::~ContextVk() {}
1211 
onDestroy(const gl::Context * context)1212 void ContextVk::onDestroy(const gl::Context *context)
1213 {
1214     // If there is a context lost, destroy all the command buffers and resources regardless of
1215     // whether they finished execution on GPU.
1216     if (mRenderer->isDeviceLost())
1217     {
1218         mRenderer->handleDeviceLost();
1219     }
1220 
1221     // This will not destroy any resources. It will release them to be collected after finish.
1222     mIncompleteTextures.onDestroy(context);
1223 
1224     // Flush and complete current outstanding work before destruction.
1225     (void)finishImpl(RenderPassClosureReason::ContextDestruction);
1226 
1227     // The finish call could also generate device loss.
1228     if (mRenderer->isDeviceLost())
1229     {
1230         mRenderer->handleDeviceLost();
1231     }
1232 
1233     // Everything must be finished
1234     ASSERT(mRenderer->hasResourceUseFinished(mSubmittedResourceUse));
1235 
1236     VkDevice device = getDevice();
1237 
1238     mShareGroupVk->cleanupRefCountedEventGarbage();
1239 
1240     mDefaultUniformStorage.release(this);
1241     mEmptyBuffer.release(this);
1242 
1243     for (vk::DynamicBuffer &defaultBuffer : mStreamedVertexBuffers)
1244     {
1245         defaultBuffer.destroy(mRenderer);
1246     }
1247 
1248     for (vk::DynamicQueryPool &queryPool : mQueryPools)
1249     {
1250         queryPool.destroy(device);
1251     }
1252 
1253     // Recycle current command buffers.
1254 
1255     // Release functions are only used for Vulkan secondary command buffers.
1256     mOutsideRenderPassCommands->releaseCommandPool();
1257     mRenderPassCommands->releaseCommandPool();
1258 
1259     // Detach functions are only used for ring buffer allocators.
1260     mOutsideRenderPassCommands->detachAllocator();
1261     mRenderPassCommands->detachAllocator();
1262 
1263     mRenderer->recycleOutsideRenderPassCommandBufferHelper(&mOutsideRenderPassCommands);
1264     mRenderer->recycleRenderPassCommandBufferHelper(&mRenderPassCommands);
1265 
1266     mInterfacePipelinesCache.destroy(device);
1267 
1268     mUtils.destroy(this);
1269 
1270     mRenderPassCache.destroy(this);
1271     mShaderLibrary.destroy(device);
1272     mGpuEventQueryPool.destroy(device);
1273 
1274     // Must release all Vulkan secondary command buffers before destroying the pools.
1275     if ((!vk::OutsideRenderPassCommandBuffer::ExecutesInline() ||
1276          !vk::RenderPassCommandBuffer::ExecutesInline()) &&
1277         mRenderer->isAsyncCommandBufferResetAndGarbageCleanupEnabled())
1278     {
1279         // This will also reset Primary command buffers which is REQUIRED on some buggy Vulkan
1280         // implementations.
1281         (void)mRenderer->releaseFinishedCommands(this);
1282     }
1283 
1284     mCommandPools.outsideRenderPassPool.destroy(device);
1285     mCommandPools.renderPassPool.destroy(device);
1286 
1287     ASSERT(mCurrentGarbage.empty());
1288 
1289     if (mCurrentQueueSerialIndex != kInvalidQueueSerialIndex)
1290     {
1291         releaseQueueSerialIndex();
1292     }
1293 
1294     mImageLoadContext = {};
1295 }
1296 
getVertexArray() const1297 VertexArrayVk *ContextVk::getVertexArray() const
1298 {
1299     return vk::GetImpl(mState.getVertexArray());
1300 }
1301 
getDrawFramebuffer() const1302 FramebufferVk *ContextVk::getDrawFramebuffer() const
1303 {
1304     return vk::GetImpl(mState.getDrawFramebuffer());
1305 }
1306 
getIncompleteTexture(const gl::Context * context,gl::TextureType type,gl::SamplerFormat format,gl::Texture ** textureOut)1307 angle::Result ContextVk::getIncompleteTexture(const gl::Context *context,
1308                                               gl::TextureType type,
1309                                               gl::SamplerFormat format,
1310                                               gl::Texture **textureOut)
1311 {
1312     return mIncompleteTextures.getIncompleteTexture(context, type, format, this, textureOut);
1313 }
1314 
initialize(const angle::ImageLoadContext & imageLoadContext)1315 angle::Result ContextVk::initialize(const angle::ImageLoadContext &imageLoadContext)
1316 {
1317     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::initialize");
1318 
1319     mImageLoadContext = imageLoadContext;
1320 
1321     ANGLE_TRY(mShareGroupVk->unifyContextsPriority(this));
1322 
1323     ANGLE_TRY(mQueryPools[gl::QueryType::AnySamples].init(this, VK_QUERY_TYPE_OCCLUSION,
1324                                                           vk::kDefaultOcclusionQueryPoolSize));
1325     ANGLE_TRY(mQueryPools[gl::QueryType::AnySamplesConservative].init(
1326         this, VK_QUERY_TYPE_OCCLUSION, vk::kDefaultOcclusionQueryPoolSize));
1327 
1328     // Only initialize the timestamp query pools if the extension is available.
1329     if (mRenderer->getQueueFamilyProperties().timestampValidBits > 0)
1330     {
1331         ANGLE_TRY(mQueryPools[gl::QueryType::Timestamp].init(this, VK_QUERY_TYPE_TIMESTAMP,
1332                                                              vk::kDefaultTimestampQueryPoolSize));
1333         ANGLE_TRY(mQueryPools[gl::QueryType::TimeElapsed].init(this, VK_QUERY_TYPE_TIMESTAMP,
1334                                                                vk::kDefaultTimestampQueryPoolSize));
1335     }
1336 
1337     if (getFeatures().supportsTransformFeedbackExtension.enabled)
1338     {
1339         ANGLE_TRY(mQueryPools[gl::QueryType::TransformFeedbackPrimitivesWritten].init(
1340             this, VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT,
1341             vk::kDefaultTransformFeedbackQueryPoolSize));
1342     }
1343 
1344     // If VK_EXT_primitives_generated_query is supported, use that to implement the OpenGL query.
1345     // Otherwise, the primitives generated query is provided through the Vulkan pipeline statistics
1346     // query if supported.
1347     if (getFeatures().supportsPrimitivesGeneratedQuery.enabled)
1348     {
1349         ANGLE_TRY(mQueryPools[gl::QueryType::PrimitivesGenerated].init(
1350             this, VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT,
1351             vk::kDefaultPrimitivesGeneratedQueryPoolSize));
1352     }
1353     else if (getFeatures().supportsPipelineStatisticsQuery.enabled)
1354     {
1355         ANGLE_TRY(mQueryPools[gl::QueryType::PrimitivesGenerated].init(
1356             this, VK_QUERY_TYPE_PIPELINE_STATISTICS, vk::kDefaultPrimitivesGeneratedQueryPoolSize));
1357     }
1358 
1359     // Init GLES to Vulkan index type map.
1360     initIndexTypeMap();
1361 
1362     mGraphicsPipelineDesc.reset(new vk::GraphicsPipelineDesc());
1363     mGraphicsPipelineDesc->initDefaults(this, vk::GraphicsPipelineSubset::Complete,
1364                                         pipelineRobustness(), pipelineProtectedAccess());
1365 
1366     // Initialize current value/default attribute buffers.
1367     for (vk::DynamicBuffer &buffer : mStreamedVertexBuffers)
1368     {
1369         buffer.init(mRenderer, kVertexBufferUsage, vk::kVertexBufferAlignment,
1370                     kDynamicVertexDataSize, true);
1371     }
1372 
1373 #if ANGLE_ENABLE_VULKAN_GPU_TRACE_EVENTS
1374     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
1375     ASSERT(platform);
1376 
1377     // GPU tracing workaround for anglebug.com/42261625.  The renderer should not emit gpu events
1378     // during platform discovery.
1379     const unsigned char *gpuEventsEnabled =
1380         platform->getTraceCategoryEnabledFlag(platform, "gpu.angle.gpu");
1381     mGpuEventsEnabled = gpuEventsEnabled && *gpuEventsEnabled;
1382 #endif
1383 
1384     // Assign initial command buffers from queue
1385     ANGLE_TRY(vk::OutsideRenderPassCommandBuffer::InitializeCommandPool(
1386         this, &mCommandPools.outsideRenderPassPool, mRenderer->getQueueFamilyIndex(),
1387         getProtectionType()));
1388     ANGLE_TRY(vk::RenderPassCommandBuffer::InitializeCommandPool(
1389         this, &mCommandPools.renderPassPool, mRenderer->getQueueFamilyIndex(),
1390         getProtectionType()));
1391     ANGLE_TRY(mRenderer->getOutsideRenderPassCommandBufferHelper(
1392         this, &mCommandPools.outsideRenderPassPool, &mOutsideRenderPassCommandsAllocator,
1393         &mOutsideRenderPassCommands));
1394     ANGLE_TRY(mRenderer->getRenderPassCommandBufferHelper(
1395         this, &mCommandPools.renderPassPool, &mRenderPassCommandsAllocator, &mRenderPassCommands));
1396 
1397     // Allocate queueSerial index and generate queue serial for commands.
1398     ANGLE_TRY(allocateQueueSerialIndex());
1399 
1400     // Initialize serials to be valid but appear submitted and finished.
1401     mLastFlushedQueueSerial   = QueueSerial(mCurrentQueueSerialIndex, Serial());
1402     mLastSubmittedQueueSerial = mLastFlushedQueueSerial;
1403 
1404     if (mGpuEventsEnabled)
1405     {
1406         // GPU events should only be available if timestamp queries are available.
1407         ASSERT(mRenderer->getQueueFamilyProperties().timestampValidBits > 0);
1408         // Calculate the difference between CPU and GPU clocks for GPU event reporting.
1409         ANGLE_TRY(mGpuEventQueryPool.init(this, VK_QUERY_TYPE_TIMESTAMP,
1410                                           vk::kDefaultTimestampQueryPoolSize));
1411         ANGLE_TRY(synchronizeCpuGpuTime());
1412 
1413         EventName eventName = GetTraceEventName("Primary", mPrimaryBufferEventCounter);
1414         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
1415                                 TRACE_EVENT_PHASE_BEGIN, eventName));
1416     }
1417 
1418     size_t minAlignment = static_cast<size_t>(
1419         mRenderer->getPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment);
1420     mDefaultUniformStorage.init(mRenderer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, minAlignment,
1421                                 mRenderer->getDefaultUniformBufferSize(), true);
1422 
1423     // Initialize an "empty" buffer for use with default uniform blocks where there are no uniforms,
1424     // or atomic counter buffer array indices that are unused.
1425     constexpr VkBufferUsageFlags kEmptyBufferUsage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
1426                                                      VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
1427                                                      VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
1428     VkBufferCreateInfo emptyBufferInfo          = {};
1429     emptyBufferInfo.sType                       = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1430     emptyBufferInfo.flags                       = 0;
1431     emptyBufferInfo.size                        = 16;
1432     emptyBufferInfo.usage                       = kEmptyBufferUsage;
1433     emptyBufferInfo.sharingMode                 = VK_SHARING_MODE_EXCLUSIVE;
1434     emptyBufferInfo.queueFamilyIndexCount       = 0;
1435     emptyBufferInfo.pQueueFamilyIndices         = nullptr;
1436     constexpr VkMemoryPropertyFlags kMemoryType = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
1437     ANGLE_TRY(mEmptyBuffer.init(this, emptyBufferInfo, kMemoryType));
1438 
1439     // If the share group has one context and is about to add the second one, the first context's
1440     // mutable textures should be flushed.
1441     if (isEligibleForMutableTextureFlush())
1442     {
1443         ASSERT(mShareGroupVk->getContexts().size() == 1);
1444         for (auto context : mShareGroupVk->getContexts())
1445         {
1446             ANGLE_TRY(vk::GetImpl(context.second)->flushOutsideRenderPassCommands());
1447         }
1448     }
1449 
1450     return angle::Result::Continue;
1451 }
1452 
isSingleBufferedWindowCurrent() const1453 bool ContextVk::isSingleBufferedWindowCurrent() const
1454 {
1455     return (mCurrentWindowSurface != nullptr && mCurrentWindowSurface->isSharedPresentMode());
1456 }
1457 
hasSomethingToFlush() const1458 bool ContextVk::hasSomethingToFlush() const
1459 {
1460     // Don't skip flushes for single-buffered windows with staged updates. It is expected that a
1461     // flush call on a single-buffered window ensures any pending updates reach the screen.
1462     const bool isSingleBufferedWindowWithStagedUpdates =
1463         isSingleBufferedWindowCurrent() && mCurrentWindowSurface->hasStagedUpdates();
1464 
1465     return mHasAnyCommandsPendingSubmission || hasActiveRenderPass() ||
1466            !mOutsideRenderPassCommands->empty() || isSingleBufferedWindowWithStagedUpdates ||
1467            hasForeignImagesToTransition();
1468 }
1469 
flushImpl(const gl::Context * context)1470 angle::Result ContextVk::flushImpl(const gl::Context *context)
1471 {
1472     // Skip if there's nothing to flush.
1473     if (!hasSomethingToFlush())
1474     {
1475         return angle::Result::Continue;
1476     }
1477 
1478     // Don't defer flushes when performing front buffer rendering. This can happen when -
1479     // 1. we have a single-buffered window, in this mode the application is not required to
1480     //    call eglSwapBuffers(), and glFlush() is expected to ensure that work is submitted.
1481     // 2. the framebuffer attachment has FRONT_BUFFER usage. Attachments being rendered to with such
1482     //    usage flags are expected to behave similar to a single-buffered window
1483     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
1484     ASSERT(drawFramebufferVk == vk::GetImpl(mState.getDrawFramebuffer()));
1485     const bool isSingleBufferedWindow = isSingleBufferedWindowCurrent();
1486     const bool frontBufferRenderingEnabled =
1487         isSingleBufferedWindow || drawFramebufferVk->hasFrontBufferUsage();
1488 
1489     // In case there is enough workload pending submission and the device is idle, we call for
1490     // submission to keep the device busy.
1491     uint32_t currentRPCommandCount =
1492         mRenderPassCommands->getCommandBuffer().getRenderPassWriteCommandCount() +
1493         mCommandsPendingSubmissionCount;
1494     if (currentRPCommandCount >= kMinCommandCountToSubmit)
1495     {
1496         if (!mRenderer->isInFlightCommandsEmpty())
1497         {
1498             ANGLE_TRY(mRenderer->checkCompletedCommands(this));
1499         }
1500 
1501         // If the device is now idle, the pending work should be submitted.
1502         if (mRenderer->isInFlightCommandsEmpty())
1503         {
1504             ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr, RenderPassClosureReason::GLFlush));
1505             return angle::Result::Continue;
1506         }
1507     }
1508 
1509     if (hasActiveRenderPass() && !frontBufferRenderingEnabled)
1510     {
1511         mHasDeferredFlush = true;
1512         return angle::Result::Continue;
1513     }
1514 
1515     if (isSingleBufferedWindow &&
1516         mRenderer->getFeatures().swapbuffersOnFlushOrFinishWithSingleBuffer.enabled)
1517     {
1518         return mCurrentWindowSurface->onSharedPresentContextFlush(this);
1519     }
1520 
1521     return flushAndSubmitCommands(nullptr, nullptr, RenderPassClosureReason::GLFlush);
1522 }
1523 
flush(const gl::Context * context)1524 angle::Result ContextVk::flush(const gl::Context *context)
1525 {
1526     ANGLE_TRY(flushImpl(context));
1527 
1528     if (!mCurrentWindowSurface || isSingleBufferedWindowCurrent())
1529     {
1530         ANGLE_TRY(onFramebufferBoundary(context));
1531     }
1532 
1533     return angle::Result::Continue;
1534 }
1535 
finish(const gl::Context * context)1536 angle::Result ContextVk::finish(const gl::Context *context)
1537 {
1538     const bool singleBufferedFlush = isSingleBufferedWindowCurrent() && hasSomethingToFlush();
1539 
1540     if (mRenderer->getFeatures().swapbuffersOnFlushOrFinishWithSingleBuffer.enabled &&
1541         singleBufferedFlush)
1542     {
1543         ANGLE_TRY(mCurrentWindowSurface->onSharedPresentContextFlush(this));
1544         // While call above performs implicit flush, don't skip |finishImpl| below, since we still
1545         // need to wait for submitted commands.
1546     }
1547 
1548     ANGLE_TRY(finishImpl(RenderPassClosureReason::GLFinish));
1549 
1550     syncObjectPerfCounters(mRenderer->getCommandQueuePerfCounters());
1551 
1552     if (!mCurrentWindowSurface || singleBufferedFlush)
1553     {
1554         ANGLE_TRY(onFramebufferBoundary(context));
1555     }
1556 
1557     return angle::Result::Continue;
1558 }
1559 
onFramebufferBoundary(const gl::Context * contextGL)1560 angle::Result ContextVk::onFramebufferBoundary(const gl::Context *contextGL)
1561 {
1562     mShareGroupVk->onFramebufferBoundary();
1563     return mRenderer->syncPipelineCacheVk(this, mRenderer->getGlobalOps(), contextGL);
1564 }
1565 
setupDraw(const gl::Context * context,gl::PrimitiveMode mode,GLint firstVertexOrInvalid,GLsizei vertexOrIndexCount,GLsizei instanceCount,gl::DrawElementsType indexTypeOrInvalid,const void * indices,DirtyBits dirtyBitMask)1566 angle::Result ContextVk::setupDraw(const gl::Context *context,
1567                                    gl::PrimitiveMode mode,
1568                                    GLint firstVertexOrInvalid,
1569                                    GLsizei vertexOrIndexCount,
1570                                    GLsizei instanceCount,
1571                                    gl::DrawElementsType indexTypeOrInvalid,
1572                                    const void *indices,
1573                                    DirtyBits dirtyBitMask)
1574 {
1575     // Set any dirty bits that depend on draw call parameters or other objects.
1576     if (mode != mCurrentDrawMode)
1577     {
1578         invalidateCurrentGraphicsPipeline();
1579         mCurrentDrawMode = mode;
1580         mGraphicsPipelineDesc->updateTopology(&mGraphicsPipelineTransition, mCurrentDrawMode);
1581     }
1582 
1583     // Must be called before the command buffer is started. Can call finish.
1584     VertexArrayVk *vertexArrayVk = getVertexArray();
1585     if (vertexArrayVk->getStreamingVertexAttribsMask().any())
1586     {
1587         // All client attribs & any emulated buffered attribs will be updated
1588         ANGLE_TRY(vertexArrayVk->updateStreamedAttribs(context, firstVertexOrInvalid,
1589                                                        vertexOrIndexCount, instanceCount,
1590                                                        indexTypeOrInvalid, indices));
1591 
1592         mGraphicsDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
1593     }
1594 
1595     ProgramExecutableVk *executableVk = vk::GetImpl(mState.getProgramExecutable());
1596     if (executableVk->updateAndCheckDirtyUniforms())
1597     {
1598         mGraphicsDirtyBits.set(DIRTY_BIT_UNIFORMS);
1599     }
1600 
1601     // Update transform feedback offsets on every draw call when emulating transform feedback.  This
1602     // relies on the fact that no geometry/tessellation, indirect or indexed calls are supported in
1603     // ES3.1 (and emulation is not done for ES3.2).
1604     if (getFeatures().emulateTransformFeedback.enabled &&
1605         mState.isTransformFeedbackActiveUnpaused())
1606     {
1607         ASSERT(firstVertexOrInvalid != -1);
1608         mXfbBaseVertex             = firstVertexOrInvalid;
1609         mXfbVertexCountPerInstance = vertexOrIndexCount;
1610         invalidateGraphicsDriverUniforms();
1611     }
1612 
1613     DirtyBits dirtyBits = mGraphicsDirtyBits & dirtyBitMask;
1614 
1615     if (dirtyBits.any())
1616     {
1617         // Flush any relevant dirty bits.
1618         for (DirtyBits::Iterator dirtyBitIter = dirtyBits.begin(); dirtyBitIter != dirtyBits.end();
1619              ++dirtyBitIter)
1620         {
1621             ASSERT(mGraphicsDirtyBitHandlers[*dirtyBitIter]);
1622             ANGLE_TRY(
1623                 (this->*mGraphicsDirtyBitHandlers[*dirtyBitIter])(&dirtyBitIter, dirtyBitMask));
1624         }
1625 
1626         // Reset the processed dirty bits, except for those that are expected to persist between
1627         // draw calls (such as the framebuffer fetch barrier which needs to be issued again and
1628         // again).
1629         mGraphicsDirtyBits &= (~dirtyBitMask | mPersistentGraphicsDirtyBits);
1630     }
1631 
1632     // Render pass must be always available at this point.
1633     ASSERT(hasActiveRenderPass());
1634 
1635     ASSERT(mState.getAndResetDirtyUniformBlocks().none());
1636 
1637     return angle::Result::Continue;
1638 }
1639 
setupIndexedDraw(const gl::Context * context,gl::PrimitiveMode mode,GLsizei indexCount,GLsizei instanceCount,gl::DrawElementsType indexType,const void * indices)1640 angle::Result ContextVk::setupIndexedDraw(const gl::Context *context,
1641                                           gl::PrimitiveMode mode,
1642                                           GLsizei indexCount,
1643                                           GLsizei instanceCount,
1644                                           gl::DrawElementsType indexType,
1645                                           const void *indices)
1646 {
1647     ASSERT(mode != gl::PrimitiveMode::LineLoop);
1648 
1649     if (indexType != mCurrentDrawElementsType)
1650     {
1651         mCurrentDrawElementsType = indexType;
1652         ANGLE_TRY(onIndexBufferChange(nullptr));
1653     }
1654 
1655     VertexArrayVk *vertexArrayVk         = getVertexArray();
1656     const gl::Buffer *elementArrayBuffer = vertexArrayVk->getState().getElementArrayBuffer();
1657     if (!elementArrayBuffer)
1658     {
1659         BufferBindingDirty bindingDirty;
1660         ANGLE_TRY(vertexArrayVk->convertIndexBufferCPU(this, indexType, indexCount, indices,
1661                                                        &bindingDirty));
1662         mCurrentIndexBufferOffset = 0;
1663 
1664         // We only set dirty bit when the bound buffer actually changed.
1665         if (bindingDirty == BufferBindingDirty::Yes)
1666         {
1667             mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
1668         }
1669     }
1670     else
1671     {
1672         mCurrentIndexBufferOffset = reinterpret_cast<VkDeviceSize>(indices);
1673 
1674         if (indices != mLastIndexBufferOffset)
1675         {
1676             mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
1677             mLastIndexBufferOffset = indices;
1678         }
1679 
1680         // When you draw with LineLoop mode or GL_UNSIGNED_BYTE type, we may allocate its own
1681         // element buffer and modify mCurrentElementArrayBuffer. When we switch out of that draw
1682         // mode, we must reset mCurrentElementArrayBuffer back to the vertexArray's element buffer.
1683         // Since in either case we set DIRTY_BIT_INDEX_BUFFER dirty bit, we use this bit to re-sync
1684         // mCurrentElementArrayBuffer.
1685         if (mGraphicsDirtyBits[DIRTY_BIT_INDEX_BUFFER])
1686         {
1687             vertexArrayVk->updateCurrentElementArrayBuffer();
1688         }
1689 
1690         if (shouldConvertUint8VkIndexType(indexType) && mGraphicsDirtyBits[DIRTY_BIT_INDEX_BUFFER])
1691         {
1692             ANGLE_VK_PERF_WARNING(this, GL_DEBUG_SEVERITY_LOW,
1693                                   "Potential inefficiency emulating uint8 vertex attributes due to "
1694                                   "lack of hardware support");
1695 
1696             BufferVk *bufferVk             = vk::GetImpl(elementArrayBuffer);
1697             vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
1698 
1699             if (bufferHelper.isHostVisible() &&
1700                 mRenderer->hasResourceUseFinished(bufferHelper.getResourceUse()))
1701             {
1702                 uint8_t *src = nullptr;
1703                 ANGLE_TRY(
1704                     bufferVk->mapImpl(this, GL_MAP_READ_BIT, reinterpret_cast<void **>(&src)));
1705                 // Note: bufferOffset is not added here because mapImpl already adds it.
1706                 src += reinterpret_cast<uintptr_t>(indices);
1707                 const size_t byteCount = static_cast<size_t>(elementArrayBuffer->getSize()) -
1708                                          reinterpret_cast<uintptr_t>(indices);
1709                 BufferBindingDirty bindingDirty;
1710                 ANGLE_TRY(vertexArrayVk->convertIndexBufferCPU(this, indexType, byteCount, src,
1711                                                                &bindingDirty));
1712                 ANGLE_TRY(bufferVk->unmapImpl(this));
1713             }
1714             else
1715             {
1716                 ANGLE_TRY(vertexArrayVk->convertIndexBufferGPU(this, bufferVk, indices));
1717             }
1718 
1719             mCurrentIndexBufferOffset = 0;
1720         }
1721     }
1722 
1723     mCurrentIndexBuffer = vertexArrayVk->getCurrentElementArrayBuffer();
1724     return setupDraw(context, mode, 0, indexCount, instanceCount, indexType, indices,
1725                      mIndexedDirtyBitsMask);
1726 }
1727 
setupIndirectDraw(const gl::Context * context,gl::PrimitiveMode mode,DirtyBits dirtyBitMask,vk::BufferHelper * indirectBuffer)1728 angle::Result ContextVk::setupIndirectDraw(const gl::Context *context,
1729                                            gl::PrimitiveMode mode,
1730                                            DirtyBits dirtyBitMask,
1731                                            vk::BufferHelper *indirectBuffer)
1732 {
1733     GLint firstVertex     = -1;
1734     GLsizei vertexCount   = 0;
1735     GLsizei instanceCount = 1;
1736 
1737     // Break the render pass if the indirect buffer was previously used as the output from transform
1738     // feedback.
1739     if (mCurrentTransformFeedbackQueueSerial.valid() &&
1740         indirectBuffer->writtenByCommandBuffer(mCurrentTransformFeedbackQueueSerial))
1741     {
1742         ANGLE_TRY(
1743             flushCommandsAndEndRenderPass(RenderPassClosureReason::XfbWriteThenIndirectDrawBuffer));
1744     }
1745 
1746     ANGLE_TRY(setupDraw(context, mode, firstVertex, vertexCount, instanceCount,
1747                         gl::DrawElementsType::InvalidEnum, nullptr, dirtyBitMask));
1748 
1749     // Process indirect buffer after render pass has started.
1750     mRenderPassCommands->bufferRead(this, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
1751                                     vk::PipelineStage::DrawIndirect, indirectBuffer);
1752 
1753     return angle::Result::Continue;
1754 }
1755 
setupIndexedIndirectDraw(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType indexType,vk::BufferHelper * indirectBuffer)1756 angle::Result ContextVk::setupIndexedIndirectDraw(const gl::Context *context,
1757                                                   gl::PrimitiveMode mode,
1758                                                   gl::DrawElementsType indexType,
1759                                                   vk::BufferHelper *indirectBuffer)
1760 {
1761     ASSERT(mode != gl::PrimitiveMode::LineLoop);
1762 
1763     VertexArrayVk *vertexArrayVk = getVertexArray();
1764     mCurrentIndexBuffer          = vertexArrayVk->getCurrentElementArrayBuffer();
1765     if (indexType != mCurrentDrawElementsType)
1766     {
1767         mCurrentDrawElementsType = indexType;
1768         ANGLE_TRY(onIndexBufferChange(nullptr));
1769     }
1770 
1771     return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, indirectBuffer);
1772 }
1773 
setupLineLoopIndexedIndirectDraw(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType indexType,vk::BufferHelper * srcIndexBuffer,vk::BufferHelper * srcIndirectBuffer,VkDeviceSize indirectBufferOffset,vk::BufferHelper ** indirectBufferOut)1774 angle::Result ContextVk::setupLineLoopIndexedIndirectDraw(const gl::Context *context,
1775                                                           gl::PrimitiveMode mode,
1776                                                           gl::DrawElementsType indexType,
1777                                                           vk::BufferHelper *srcIndexBuffer,
1778                                                           vk::BufferHelper *srcIndirectBuffer,
1779                                                           VkDeviceSize indirectBufferOffset,
1780                                                           vk::BufferHelper **indirectBufferOut)
1781 {
1782     ASSERT(mode == gl::PrimitiveMode::LineLoop);
1783 
1784     vk::BufferHelper *dstIndexBuffer    = nullptr;
1785     vk::BufferHelper *dstIndirectBuffer = nullptr;
1786 
1787     VertexArrayVk *vertexArrayVk = getVertexArray();
1788     ANGLE_TRY(vertexArrayVk->handleLineLoopIndexIndirect(this, indexType, srcIndexBuffer,
1789                                                          srcIndirectBuffer, indirectBufferOffset,
1790                                                          &dstIndexBuffer, &dstIndirectBuffer));
1791 
1792     mCurrentIndexBuffer = dstIndexBuffer;
1793     *indirectBufferOut  = dstIndirectBuffer;
1794 
1795     if (indexType != mCurrentDrawElementsType)
1796     {
1797         mCurrentDrawElementsType = indexType;
1798         ANGLE_TRY(onIndexBufferChange(nullptr));
1799     }
1800 
1801     return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, dstIndirectBuffer);
1802 }
1803 
setupLineLoopIndirectDraw(const gl::Context * context,gl::PrimitiveMode mode,vk::BufferHelper * indirectBuffer,VkDeviceSize indirectBufferOffset,vk::BufferHelper ** indirectBufferOut)1804 angle::Result ContextVk::setupLineLoopIndirectDraw(const gl::Context *context,
1805                                                    gl::PrimitiveMode mode,
1806                                                    vk::BufferHelper *indirectBuffer,
1807                                                    VkDeviceSize indirectBufferOffset,
1808                                                    vk::BufferHelper **indirectBufferOut)
1809 {
1810     ASSERT(mode == gl::PrimitiveMode::LineLoop);
1811 
1812     vk::BufferHelper *indexBufferHelperOut    = nullptr;
1813     vk::BufferHelper *indirectBufferHelperOut = nullptr;
1814 
1815     VertexArrayVk *vertexArrayVk = getVertexArray();
1816     ANGLE_TRY(vertexArrayVk->handleLineLoopIndirectDraw(context, indirectBuffer,
1817                                                         indirectBufferOffset, &indexBufferHelperOut,
1818                                                         &indirectBufferHelperOut));
1819 
1820     *indirectBufferOut = indirectBufferHelperOut;
1821     mCurrentIndexBuffer = indexBufferHelperOut;
1822 
1823     if (gl::DrawElementsType::UnsignedInt != mCurrentDrawElementsType)
1824     {
1825         mCurrentDrawElementsType = gl::DrawElementsType::UnsignedInt;
1826         ANGLE_TRY(onIndexBufferChange(nullptr));
1827     }
1828 
1829     return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, indirectBufferHelperOut);
1830 }
1831 
setupLineLoopDraw(const gl::Context * context,gl::PrimitiveMode mode,GLint firstVertex,GLsizei vertexOrIndexCount,gl::DrawElementsType indexTypeOrInvalid,const void * indices,uint32_t * numIndicesOut)1832 angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
1833                                            gl::PrimitiveMode mode,
1834                                            GLint firstVertex,
1835                                            GLsizei vertexOrIndexCount,
1836                                            gl::DrawElementsType indexTypeOrInvalid,
1837                                            const void *indices,
1838                                            uint32_t *numIndicesOut)
1839 {
1840     mCurrentIndexBufferOffset    = 0;
1841     vk::BufferHelper *dstIndexBuffer = mCurrentIndexBuffer;
1842 
1843     VertexArrayVk *vertexArrayVk = getVertexArray();
1844     ANGLE_TRY(vertexArrayVk->handleLineLoop(this, firstVertex, vertexOrIndexCount,
1845                                             indexTypeOrInvalid, indices, &dstIndexBuffer,
1846                                             numIndicesOut));
1847 
1848     mCurrentIndexBuffer = dstIndexBuffer;
1849     ANGLE_TRY(onIndexBufferChange(nullptr));
1850     mCurrentDrawElementsType = indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum
1851                                    ? indexTypeOrInvalid
1852                                    : gl::DrawElementsType::UnsignedInt;
1853     return setupDraw(context, mode, firstVertex, vertexOrIndexCount, 1, indexTypeOrInvalid, indices,
1854                      mIndexedDirtyBitsMask);
1855 }
1856 
setupDispatch(const gl::Context * context)1857 angle::Result ContextVk::setupDispatch(const gl::Context *context)
1858 {
1859     // TODO: We don't currently check if this flush is necessary.  It serves to make sure the
1860     // barriers issued during dirty bit handling aren't reordered too early.
1861     // http://anglebug.com/382090958
1862     ANGLE_TRY(flushOutsideRenderPassCommands());
1863 
1864     ProgramExecutableVk *executableVk = vk::GetImpl(mState.getProgramExecutable());
1865     if (executableVk->updateAndCheckDirtyUniforms())
1866     {
1867         mComputeDirtyBits.set(DIRTY_BIT_UNIFORMS);
1868     }
1869 
1870     DirtyBits dirtyBits = mComputeDirtyBits;
1871 
1872     // Flush any relevant dirty bits.
1873     for (DirtyBits::Iterator dirtyBitIter = dirtyBits.begin(); dirtyBitIter != dirtyBits.end();
1874          ++dirtyBitIter)
1875     {
1876         ASSERT(mComputeDirtyBitHandlers[*dirtyBitIter]);
1877         ANGLE_TRY((this->*mComputeDirtyBitHandlers[*dirtyBitIter])(&dirtyBitIter));
1878     }
1879 
1880     mComputeDirtyBits.reset();
1881 
1882     ASSERT(mState.getAndResetDirtyUniformBlocks().none());
1883 
1884     return angle::Result::Continue;
1885 }
1886 
handleDirtyGraphicsMemoryBarrier(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)1887 angle::Result ContextVk::handleDirtyGraphicsMemoryBarrier(DirtyBits::Iterator *dirtyBitsIterator,
1888                                                           DirtyBits dirtyBitMask)
1889 {
1890     return handleDirtyMemoryBarrierImpl(dirtyBitsIterator, dirtyBitMask);
1891 }
1892 
handleDirtyComputeMemoryBarrier(DirtyBits::Iterator * dirtyBitsIterator)1893 angle::Result ContextVk::handleDirtyComputeMemoryBarrier(DirtyBits::Iterator *dirtyBitsIterator)
1894 {
1895     return handleDirtyMemoryBarrierImpl(nullptr, {});
1896 }
1897 
renderPassUsesStorageResources() const1898 bool ContextVk::renderPassUsesStorageResources() const
1899 {
1900     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
1901     ASSERT(executable);
1902 
1903     if (!mRenderPassCommands->started())
1904     {
1905         return false;
1906     }
1907 
1908     // Storage images:
1909     for (size_t imageUnitIndex : executable->getActiveImagesMask())
1910     {
1911         const gl::Texture *texture = mState.getImageUnit(imageUnitIndex).texture.get();
1912         if (texture == nullptr)
1913         {
1914             continue;
1915         }
1916 
1917         TextureVk *textureVk = vk::GetImpl(texture);
1918 
1919         if (texture->getType() == gl::TextureType::Buffer)
1920         {
1921             vk::BufferHelper &buffer = vk::GetImpl(textureVk->getBuffer().get())->getBuffer();
1922             if (mRenderPassCommands->usesBuffer(buffer))
1923             {
1924                 return true;
1925             }
1926         }
1927         else
1928         {
1929             vk::ImageHelper &image = textureVk->getImage();
1930             // Images only need to close the render pass if they need a layout transition.  Outside
1931             // render pass command buffer doesn't need closing as the layout transition barriers are
1932             // recorded in sequence with the rest of the commands.
1933             if (mRenderPassCommands->usesImage(image))
1934             {
1935                 return true;
1936             }
1937         }
1938     }
1939 
1940     // Storage buffers:
1941     const std::vector<gl::InterfaceBlock> &blocks = executable->getShaderStorageBlocks();
1942     for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
1943     {
1944         const uint32_t binding = executable->getShaderStorageBlockBinding(bufferIndex);
1945         const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
1946             mState.getIndexedShaderStorageBuffer(binding);
1947 
1948         if (bufferBinding.get() == nullptr)
1949         {
1950             continue;
1951         }
1952 
1953         vk::BufferHelper &buffer = vk::GetImpl(bufferBinding.get())->getBuffer();
1954         if (mRenderPassCommands->usesBuffer(buffer))
1955         {
1956             return true;
1957         }
1958     }
1959 
1960     // Atomic counters:
1961     const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers =
1962         executable->getAtomicCounterBuffers();
1963     for (uint32_t bufferIndex = 0; bufferIndex < atomicCounterBuffers.size(); ++bufferIndex)
1964     {
1965         const uint32_t binding = executable->getAtomicCounterBufferBinding(bufferIndex);
1966         const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
1967             mState.getIndexedAtomicCounterBuffer(binding);
1968 
1969         if (bufferBinding.get() == nullptr)
1970         {
1971             continue;
1972         }
1973 
1974         vk::BufferHelper &buffer = vk::GetImpl(bufferBinding.get())->getBuffer();
1975         if (mRenderPassCommands->usesBuffer(buffer))
1976         {
1977             return true;
1978         }
1979     }
1980 
1981     return false;
1982 }
1983 
handleDirtyMemoryBarrierImpl(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)1984 angle::Result ContextVk::handleDirtyMemoryBarrierImpl(DirtyBits::Iterator *dirtyBitsIterator,
1985                                                       DirtyBits dirtyBitMask)
1986 {
1987     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
1988     ASSERT(executable);
1989 
1990     const bool hasImages         = executable->hasImages();
1991     const bool hasStorageBuffers = executable->hasStorageBuffers();
1992     const bool hasAtomicCounters = executable->hasAtomicCounterBuffers();
1993 
1994     if (!hasImages && !hasStorageBuffers && !hasAtomicCounters)
1995     {
1996         return angle::Result::Continue;
1997     }
1998 
1999     // Break the render pass if necessary.  This is only needed for write-after-read situations, and
2000     // is done by checking whether current storage buffers and images are used in the render pass.
2001     if (renderPassUsesStorageResources())
2002     {
2003         // Either set later bits (if called during handling of graphics dirty bits), or set the
2004         // dirty bits directly (if called during handling of compute dirty bits).
2005         if (dirtyBitsIterator)
2006         {
2007             return flushDirtyGraphicsRenderPass(
2008                 dirtyBitsIterator, dirtyBitMask,
2009                 RenderPassClosureReason::GLMemoryBarrierThenStorageResource);
2010         }
2011         else
2012         {
2013             return flushCommandsAndEndRenderPass(
2014                 RenderPassClosureReason::GLMemoryBarrierThenStorageResource);
2015         }
2016     }
2017 
2018     // Flushing outside render pass commands is cheap.  If a memory barrier has been issued in its
2019     // life time, just flush it instead of wasting time trying to figure out if it's necessary.
2020     if (mOutsideRenderPassCommands->hasGLMemoryBarrierIssued())
2021     {
2022         ANGLE_TRY(flushOutsideRenderPassCommands());
2023     }
2024 
2025     return angle::Result::Continue;
2026 }
2027 
handleDirtyGraphicsEventLog(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2028 angle::Result ContextVk::handleDirtyGraphicsEventLog(DirtyBits::Iterator *dirtyBitsIterator,
2029                                                      DirtyBits dirtyBitMask)
2030 {
2031     return handleDirtyEventLogImpl(mRenderPassCommandBuffer);
2032 }
2033 
handleDirtyComputeEventLog(DirtyBits::Iterator * dirtyBitsIterator)2034 angle::Result ContextVk::handleDirtyComputeEventLog(DirtyBits::Iterator *dirtyBitsIterator)
2035 {
2036     return handleDirtyEventLogImpl(&mOutsideRenderPassCommands->getCommandBuffer());
2037 }
2038 
2039 template <typename CommandBufferT>
handleDirtyEventLogImpl(CommandBufferT * commandBuffer)2040 angle::Result ContextVk::handleDirtyEventLogImpl(CommandBufferT *commandBuffer)
2041 {
2042     // This method is called when a draw or dispatch command is being processed.  It's purpose is
2043     // to call the vkCmd*DebugUtilsLabelEXT functions in order to communicate to debuggers
2044     // (e.g. AGI) the OpenGL ES commands that the application uses.
2045 
2046     // Exit early if no OpenGL ES commands have been logged, or if no command buffer (for a no-op
2047     // draw), or if calling the vkCmd*DebugUtilsLabelEXT functions is not enabled.
2048     if (mEventLog.empty() || commandBuffer == nullptr || !mRenderer->angleDebuggerMode())
2049     {
2050         return angle::Result::Continue;
2051     }
2052 
2053     // Insert OpenGL ES commands into debug label.  We create a 3-level cascade here for
2054     // OpenGL-ES-first debugging in AGI.  Here's the general outline of commands:
2055     // -glDrawCommand
2056     // --vkCmdBeginDebugUtilsLabelEXT() #1 for "glDrawCommand"
2057     // --OpenGL ES Commands
2058     // ---vkCmdBeginDebugUtilsLabelEXT() #2 for "OpenGL ES Commands"
2059     // ---Individual OpenGL ES Commands leading up to glDrawCommand
2060     // ----vkCmdBeginDebugUtilsLabelEXT() #3 for each individual OpenGL ES Command
2061     // ----vkCmdEndDebugUtilsLabelEXT() #3 for each individual OpenGL ES Command
2062     // ----...More Individual OGL Commands...
2063     // ----Final Individual OGL command will be the same glDrawCommand shown in #1 above
2064     // ---vkCmdEndDebugUtilsLabelEXT() #2 for "OpenGL ES Commands"
2065     // --VK SetupDraw & Draw-related commands will be embedded here under glDraw #1
2066     // --vkCmdEndDebugUtilsLabelEXT() #1 is called after each vkDraw* or vkDispatch* call
2067 
2068     // AGI desires no parameters on the top-level of the hierarchy.
2069     std::string topLevelCommand = mEventLog.back();
2070     size_t startOfParameters    = topLevelCommand.find("(");
2071     if (startOfParameters != std::string::npos)
2072     {
2073         topLevelCommand = topLevelCommand.substr(0, startOfParameters);
2074     }
2075     VkDebugUtilsLabelEXT label = {VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
2076                                   nullptr,
2077                                   topLevelCommand.c_str(),
2078                                   {0.0f, 0.0f, 0.0f, 0.0f}};
2079     // This is #1 from comment above
2080     commandBuffer->beginDebugUtilsLabelEXT(label);
2081     std::string oglCmds = "OpenGL ES Commands";
2082     label.pLabelName    = oglCmds.c_str();
2083     // This is #2 from comment above
2084     commandBuffer->beginDebugUtilsLabelEXT(label);
2085     for (uint32_t i = 0; i < mEventLog.size(); ++i)
2086     {
2087         label.pLabelName = mEventLog[i].c_str();
2088         // NOTE: We have to use a begin/end pair here because AGI does not promote the
2089         // pLabelName from an insertDebugUtilsLabelEXT() call to the Commands panel.
2090         // Internal bug b/169243237 is tracking this and once the insert* call shows the
2091         // pLabelName similar to begin* call, we can switch these to insert* calls instead.
2092         // This is #3 from comment above.
2093         commandBuffer->beginDebugUtilsLabelEXT(label);
2094         commandBuffer->endDebugUtilsLabelEXT();
2095     }
2096     commandBuffer->endDebugUtilsLabelEXT();
2097     // The final end* call for #1 above is made in the ContextVk::draw* or
2098     //  ContextVk::dispatch* function calls.
2099 
2100     mEventLog.clear();
2101     return angle::Result::Continue;
2102 }
2103 
handleDirtyGraphicsDefaultAttribs(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2104 angle::Result ContextVk::handleDirtyGraphicsDefaultAttribs(DirtyBits::Iterator *dirtyBitsIterator,
2105                                                            DirtyBits dirtyBitMask)
2106 {
2107     ASSERT(mDirtyDefaultAttribsMask.any());
2108 
2109     gl::AttributesMask attribsMask =
2110         mDirtyDefaultAttribsMask & mState.getProgramExecutable()->getAttributesMask();
2111     VertexArrayVk *vertexArrayVk = getVertexArray();
2112     for (size_t attribIndex : attribsMask)
2113     {
2114         ANGLE_TRY(vertexArrayVk->updateDefaultAttrib(this, attribIndex));
2115     }
2116 
2117     mDirtyDefaultAttribsMask.reset();
2118     return angle::Result::Continue;
2119 }
2120 
createGraphicsPipeline()2121 angle::Result ContextVk::createGraphicsPipeline()
2122 {
2123     ASSERT(mState.getProgramExecutable() != nullptr);
2124     ProgramExecutableVk *executableVk = vk::GetImpl(mState.getProgramExecutable());
2125     ASSERT(executableVk);
2126 
2127     // Wait for any warm up task if necessary
2128     executableVk->waitForGraphicsPostLinkTasks(this, *mGraphicsPipelineDesc);
2129 
2130     vk::PipelineCacheAccess pipelineCache;
2131     ANGLE_TRY(mRenderer->getPipelineCache(this, &pipelineCache));
2132 
2133     vk::PipelineHelper *oldGraphicsPipeline = mCurrentGraphicsPipeline;
2134 
2135     // Attempt to use an existing pipeline.
2136     const vk::GraphicsPipelineDesc *descPtr = nullptr;
2137     ANGLE_TRY(executableVk->getGraphicsPipeline(this, vk::GraphicsPipelineSubset::Complete,
2138                                                 *mGraphicsPipelineDesc, &descPtr,
2139                                                 &mCurrentGraphicsPipeline));
2140 
2141     // If no such pipeline exists:
2142     //
2143     // - If VK_EXT_graphics_pipeline_library is not supported, create a new monolithic pipeline
2144     // - If VK_EXT_graphics_pipeline_library is supported:
2145     //   * Create the Shaders subset of the pipeline through the program executable
2146     //   * Create the complete pipeline by providing the VertexInput and FragmentOutput states as
2147     //     well as the Shaders library.
2148     if (mCurrentGraphicsPipeline == nullptr)
2149     {
2150         // Not found in cache
2151         ASSERT(descPtr == nullptr);
2152         if (!getFeatures().supportsGraphicsPipelineLibrary.enabled)
2153         {
2154             ANGLE_TRY(executableVk->createGraphicsPipeline(
2155                 this, vk::GraphicsPipelineSubset::Complete, &pipelineCache, PipelineSource::Draw,
2156                 *mGraphicsPipelineDesc, &descPtr, &mCurrentGraphicsPipeline));
2157         }
2158         else
2159         {
2160             const vk::GraphicsPipelineTransitionBits kShadersTransitionBitsMask =
2161                 vk::GetGraphicsPipelineTransitionBitsMask(vk::GraphicsPipelineSubset::Shaders);
2162 
2163             // Recreate the Shaders subset if necessary
2164             const vk::GraphicsPipelineTransitionBits shadersTransitionBits =
2165                 mGraphicsPipelineLibraryTransition & kShadersTransitionBitsMask;
2166             if (mCurrentGraphicsPipelineShaders == nullptr || shadersTransitionBits.any())
2167             {
2168                 bool shouldRecreatePipeline = true;
2169                 if (mCurrentGraphicsPipelineShaders != nullptr)
2170                 {
2171                     ASSERT(mCurrentGraphicsPipelineShaders->valid());
2172                     shouldRecreatePipeline = !mCurrentGraphicsPipelineShaders->findTransition(
2173                         shadersTransitionBits, *mGraphicsPipelineDesc,
2174                         &mCurrentGraphicsPipelineShaders);
2175                 }
2176 
2177                 if (shouldRecreatePipeline)
2178                 {
2179                     vk::PipelineHelper *oldGraphicsPipelineShaders =
2180                         mCurrentGraphicsPipelineShaders;
2181 
2182                     const vk::GraphicsPipelineDesc *shadersDescPtr = nullptr;
2183                     ANGLE_TRY(executableVk->getGraphicsPipeline(
2184                         this, vk::GraphicsPipelineSubset::Shaders, *mGraphicsPipelineDesc,
2185                         &shadersDescPtr, &mCurrentGraphicsPipelineShaders));
2186                     if (shadersDescPtr == nullptr)
2187                     {
2188                         ANGLE_TRY(executableVk->createGraphicsPipeline(
2189                             this, vk::GraphicsPipelineSubset::Shaders, &pipelineCache,
2190                             PipelineSource::Draw, *mGraphicsPipelineDesc, &shadersDescPtr,
2191                             &mCurrentGraphicsPipelineShaders));
2192                     }
2193                     if (oldGraphicsPipelineShaders)
2194                     {
2195                         oldGraphicsPipelineShaders->addTransition(
2196                             shadersTransitionBits, shadersDescPtr, mCurrentGraphicsPipelineShaders);
2197                     }
2198                 }
2199             }
2200 
2201             // Link the shaders subset into a complete pipeline that includes vertex input and
2202             // fragment output subsets.
2203             ANGLE_TRY(executableVk->createLinkedGraphicsPipeline(
2204                 this, &pipelineCache, *mGraphicsPipelineDesc, mCurrentGraphicsPipelineShaders,
2205                 &descPtr, &mCurrentGraphicsPipeline));
2206 
2207             // Reset the transition bits for pipeline libraries, they are only made to be up-to-date
2208             // here.
2209             mGraphicsPipelineLibraryTransition.reset();
2210         }
2211     }
2212 
2213     // Maintain the transition cache
2214     if (oldGraphicsPipeline)
2215     {
2216         oldGraphicsPipeline->addTransition(mGraphicsPipelineTransition, descPtr,
2217                                            mCurrentGraphicsPipeline);
2218     }
2219 
2220     return angle::Result::Continue;
2221 }
2222 
handleDirtyGraphicsPipelineDesc(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2223 angle::Result ContextVk::handleDirtyGraphicsPipelineDesc(DirtyBits::Iterator *dirtyBitsIterator,
2224                                                          DirtyBits dirtyBitMask)
2225 {
2226     const VkPipeline previousPipeline = mCurrentGraphicsPipeline
2227                                             ? mCurrentGraphicsPipeline->getPipeline().getHandle()
2228                                             : VK_NULL_HANDLE;
2229 
2230     // Accumulate transition bits for the sake of pipeline libraries.  If a cache is hit in this
2231     // path, |mGraphicsPipelineTransition| is reset while the partial pipelines are left stale.  A
2232     // future partial library recreation would need to know the bits that have changed since.
2233     mGraphicsPipelineLibraryTransition |= mGraphicsPipelineTransition;
2234 
2235     // Recreate the pipeline if necessary.
2236     bool shouldRecreatePipeline =
2237         mCurrentGraphicsPipeline == nullptr || mGraphicsPipelineTransition.any();
2238 
2239     // If one can be found in the transition cache, recover it.
2240     if (mCurrentGraphicsPipeline != nullptr && mGraphicsPipelineTransition.any())
2241     {
2242         ASSERT(mCurrentGraphicsPipeline->valid());
2243         shouldRecreatePipeline = !mCurrentGraphicsPipeline->findTransition(
2244             mGraphicsPipelineTransition, *mGraphicsPipelineDesc, &mCurrentGraphicsPipeline);
2245     }
2246 
2247     // Otherwise either retrieve the pipeline from the cache, or create a new one.
2248     if (shouldRecreatePipeline)
2249     {
2250         ANGLE_TRY(createGraphicsPipeline());
2251     }
2252 
2253     mGraphicsPipelineTransition.reset();
2254 
2255     // Update the queue serial for the pipeline object.
2256     ASSERT(mCurrentGraphicsPipeline && mCurrentGraphicsPipeline->valid());
2257 
2258     const VkPipeline newPipeline = mCurrentGraphicsPipeline->getPipeline().getHandle();
2259 
2260     // If there's no change in pipeline, avoid rebinding it later.  If the rebind is due to a new
2261     // command buffer or UtilsVk, it will happen anyway with DIRTY_BIT_PIPELINE_BINDING.
2262     if (newPipeline == previousPipeline)
2263     {
2264         return angle::Result::Continue;
2265     }
2266 
2267     // VK_EXT_transform_feedback disallows binding pipelines while transform feedback is active.
2268     // If a new pipeline needs to be bound, the render pass should necessarily be broken (which
2269     // implicitly pauses transform feedback), as resuming requires a barrier on the transform
2270     // feedback counter buffer.
2271     if (mRenderPassCommands->started())
2272     {
2273         mCurrentGraphicsPipeline->retainInRenderPass(mRenderPassCommands);
2274 
2275         if (mRenderPassCommands->isTransformFeedbackActiveUnpaused())
2276         {
2277             ANGLE_TRY(
2278                 flushDirtyGraphicsRenderPass(dirtyBitsIterator, dirtyBitMask,
2279                                              RenderPassClosureReason::PipelineBindWhileXfbActive));
2280 
2281             dirtyBitsIterator->setLaterBit(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
2282         }
2283     }
2284 
2285     // The pipeline needs to rebind because it's changed.
2286     dirtyBitsIterator->setLaterBit(DIRTY_BIT_PIPELINE_BINDING);
2287 
2288     return angle::Result::Continue;
2289 }
2290 
updateRenderPassDepthFeedbackLoopMode(UpdateDepthFeedbackLoopReason depthReason,UpdateDepthFeedbackLoopReason stencilReason)2291 angle::Result ContextVk::updateRenderPassDepthFeedbackLoopMode(
2292     UpdateDepthFeedbackLoopReason depthReason,
2293     UpdateDepthFeedbackLoopReason stencilReason)
2294 {
2295     return switchOutReadOnlyDepthStencilMode(nullptr, {}, depthReason, stencilReason);
2296 }
2297 
switchOutReadOnlyDepthStencilMode(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask,UpdateDepthFeedbackLoopReason depthReason,UpdateDepthFeedbackLoopReason stencilReason)2298 angle::Result ContextVk::switchOutReadOnlyDepthStencilMode(
2299     DirtyBits::Iterator *dirtyBitsIterator,
2300     DirtyBits dirtyBitMask,
2301     UpdateDepthFeedbackLoopReason depthReason,
2302     UpdateDepthFeedbackLoopReason stencilReason)
2303 {
2304     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
2305     if (!hasActiveRenderPass() || drawFramebufferVk->getDepthStencilRenderTarget() == nullptr)
2306     {
2307         return angle::Result::Continue;
2308     }
2309 
2310     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2311     const gl::DepthStencilState &dsState = mState.getDepthStencilState();
2312     vk::ResourceAccess depthAccess          = GetDepthAccess(dsState, executable, depthReason);
2313     vk::ResourceAccess stencilAccess        = GetStencilAccess(
2314         dsState, mState.getDrawFramebuffer()->getStencilBitCount(), executable, stencilReason);
2315 
2316     if ((HasResourceWriteAccess(depthAccess) &&
2317          mDepthStencilAttachmentFlags[vk::RenderPassUsage::DepthReadOnlyAttachment]) ||
2318         (HasResourceWriteAccess(stencilAccess) &&
2319          mDepthStencilAttachmentFlags[vk::RenderPassUsage::StencilReadOnlyAttachment]))
2320     {
2321         // We should not in the actual feedback mode
2322         ASSERT((mDepthStencilAttachmentFlags & vk::kDepthStencilFeedbackModeBits).none());
2323 
2324         // If we are switching out of read only mode and we are in feedback loop, we must end
2325         // render pass here. Otherwise, updating it to writeable layout will produce a writable
2326         // feedback loop that is illegal in vulkan and will trigger validation errors that depth
2327         // texture is using the writable layout.
2328         if (dirtyBitsIterator)
2329         {
2330             ANGLE_TRY(flushDirtyGraphicsRenderPass(
2331                 dirtyBitsIterator, dirtyBitMask,
2332                 RenderPassClosureReason::DepthStencilWriteAfterFeedbackLoop));
2333         }
2334         else
2335         {
2336             ANGLE_TRY(flushCommandsAndEndRenderPass(
2337                 RenderPassClosureReason::DepthStencilWriteAfterFeedbackLoop));
2338         }
2339         // Clear read-only depth/stencil feedback mode.
2340         mDepthStencilAttachmentFlags &= ~vk::kDepthStencilReadOnlyBits;
2341     }
2342 
2343     return angle::Result::Continue;
2344 }
2345 
handleDirtyGraphicsReadOnlyDepthFeedbackLoopMode(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2346 angle::Result ContextVk::handleDirtyGraphicsReadOnlyDepthFeedbackLoopMode(
2347     DirtyBits::Iterator *dirtyBitsIterator,
2348     DirtyBits dirtyBitMask)
2349 {
2350     return switchOutReadOnlyDepthStencilMode(dirtyBitsIterator, dirtyBitMask,
2351                                              UpdateDepthFeedbackLoopReason::Draw,
2352                                              UpdateDepthFeedbackLoopReason::Draw);
2353 }
2354 
handleDirtyAnySamplePassedQueryEnd(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2355 angle::Result ContextVk::handleDirtyAnySamplePassedQueryEnd(DirtyBits::Iterator *dirtyBitsIterator,
2356                                                             DirtyBits dirtyBitMask)
2357 {
2358     if (mRenderPassCommands->started())
2359     {
2360         // When we switch from query enabled draw to query disabled draw, we do immediate flush to
2361         // ensure the query result will be ready early so that application thread calling
2362         // getQueryResult gets unblocked sooner.
2363         dirtyBitsIterator->setLaterBit(DIRTY_BIT_RENDER_PASS);
2364 
2365         // Don't let next render pass end up reactivate and reuse the current render pass, which
2366         // defeats the purpose of it.
2367         mAllowRenderPassToReactivate = false;
2368         mHasDeferredFlush            = true;
2369     }
2370     return angle::Result::Continue;
2371 }
2372 
handleDirtyGraphicsRenderPass(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2373 angle::Result ContextVk::handleDirtyGraphicsRenderPass(DirtyBits::Iterator *dirtyBitsIterator,
2374                                                        DirtyBits dirtyBitMask)
2375 {
2376     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
2377 
2378     gl::Rectangle renderArea = drawFramebufferVk->getRenderArea(this);
2379     // Check to see if we can reactivate the current renderPass, if all arguments that we use to
2380     // start the render pass is the same. We don't need to check clear values since mid render pass
2381     // clear are handled differently.
2382     bool reactivateStartedRenderPass =
2383         hasStartedRenderPassWithQueueSerial(drawFramebufferVk->getLastRenderPassQueueSerial()) &&
2384         mAllowRenderPassToReactivate && renderArea == mRenderPassCommands->getRenderArea();
2385     if (reactivateStartedRenderPass)
2386     {
2387         INFO() << "Reactivate already started render pass on draw.";
2388         mRenderPassCommandBuffer = &mRenderPassCommands->getCommandBuffer();
2389         ASSERT(!drawFramebufferVk->hasDeferredClears());
2390         ASSERT(hasActiveRenderPass());
2391 
2392         vk::RenderPassDesc framebufferRenderPassDesc = drawFramebufferVk->getRenderPassDesc();
2393         if (getFeatures().preferDynamicRendering.enabled)
2394         {
2395             // With dynamic rendering, drawFramebufferVk's render pass desc does not track
2396             // framebuffer fetch mode.  For the purposes of the following ASSERT, assume they are
2397             // the same.
2398             framebufferRenderPassDesc.setFramebufferFetchMode(
2399                 mRenderPassCommands->getRenderPassDesc().framebufferFetchMode());
2400         }
2401         ASSERT(framebufferRenderPassDesc == mRenderPassCommands->getRenderPassDesc());
2402 
2403         ANGLE_TRY(resumeRenderPassQueriesIfActive());
2404 
2405         return angle::Result::Continue;
2406     }
2407 
2408     // If the render pass needs to be recreated, close it using the special mid-dirty-bit-handling
2409     // function, so later dirty bits can be set.
2410     if (mRenderPassCommands->started())
2411     {
2412         ANGLE_TRY(flushDirtyGraphicsRenderPass(dirtyBitsIterator,
2413                                                dirtyBitMask & ~DirtyBits{DIRTY_BIT_RENDER_PASS},
2414                                                RenderPassClosureReason::AlreadySpecifiedElsewhere));
2415     }
2416 
2417     bool renderPassDescChanged = false;
2418 
2419     ANGLE_TRY(startRenderPass(renderArea, nullptr, &renderPassDescChanged));
2420 
2421     // The render pass desc can change when starting the render pass, for example due to
2422     // multisampled-render-to-texture needs based on loadOps.  In that case, recreate the graphics
2423     // pipeline.
2424     if (renderPassDescChanged)
2425     {
2426         ANGLE_TRY(handleDirtyGraphicsPipelineDesc(dirtyBitsIterator, dirtyBitMask));
2427     }
2428 
2429     return angle::Result::Continue;
2430 }
2431 
handleDirtyGraphicsColorAccess(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2432 angle::Result ContextVk::handleDirtyGraphicsColorAccess(DirtyBits::Iterator *dirtyBitsIterator,
2433                                                         DirtyBits dirtyBitMask)
2434 {
2435     FramebufferVk *drawFramebufferVk             = getDrawFramebuffer();
2436     const gl::FramebufferState &framebufferState = drawFramebufferVk->getState();
2437 
2438     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2439     ASSERT(executable);
2440 
2441     // Update color attachment accesses
2442     vk::PackedAttachmentIndex colorIndexVk(0);
2443     for (size_t colorIndexGL : framebufferState.getColorAttachmentsMask())
2444     {
2445         if (framebufferState.getEnabledDrawBuffers().test(colorIndexGL))
2446         {
2447             vk::ResourceAccess colorAccess = GetColorAccess(
2448                 mState, framebufferState, drawFramebufferVk->getEmulatedAlphaAttachmentMask(),
2449                 executable, colorIndexGL);
2450             mRenderPassCommands->onColorAccess(colorIndexVk, colorAccess);
2451         }
2452         ++colorIndexVk;
2453     }
2454 
2455     return angle::Result::Continue;
2456 }
2457 
handleDirtyGraphicsDepthStencilAccess(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2458 angle::Result ContextVk::handleDirtyGraphicsDepthStencilAccess(
2459     DirtyBits::Iterator *dirtyBitsIterator,
2460     DirtyBits dirtyBitMask)
2461 {
2462     const FramebufferVk &drawFramebufferVk = *getDrawFramebuffer();
2463     if (drawFramebufferVk.getDepthStencilRenderTarget() == nullptr)
2464     {
2465         return angle::Result::Continue;
2466     }
2467 
2468     // Update depth/stencil attachment accesses
2469     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2470     const gl::DepthStencilState &dsState = mState.getDepthStencilState();
2471     vk::ResourceAccess depthAccess =
2472         GetDepthAccess(dsState, executable, UpdateDepthFeedbackLoopReason::Draw);
2473     vk::ResourceAccess stencilAccess =
2474         GetStencilAccess(dsState, mState.getDrawFramebuffer()->getStencilBitCount(), executable,
2475                          UpdateDepthFeedbackLoopReason::Draw);
2476     mRenderPassCommands->onDepthAccess(depthAccess);
2477     mRenderPassCommands->onStencilAccess(stencilAccess);
2478 
2479     mRenderPassCommands->updateDepthReadOnlyMode(mDepthStencilAttachmentFlags);
2480     mRenderPassCommands->updateStencilReadOnlyMode(mDepthStencilAttachmentFlags);
2481 
2482     return angle::Result::Continue;
2483 }
2484 
handleDirtyGraphicsPipelineBinding(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2485 angle::Result ContextVk::handleDirtyGraphicsPipelineBinding(DirtyBits::Iterator *dirtyBitsIterator,
2486                                                             DirtyBits dirtyBitMask)
2487 {
2488     ASSERT(mCurrentGraphicsPipeline);
2489 
2490     const vk::Pipeline *pipeline = nullptr;
2491     ANGLE_TRY(mCurrentGraphicsPipeline->getPreferredPipeline(this, &pipeline));
2492 
2493     mRenderPassCommandBuffer->bindGraphicsPipeline(*pipeline);
2494 
2495     return angle::Result::Continue;
2496 }
2497 
handleDirtyComputePipelineDesc(DirtyBits::Iterator * dirtyBitsIterator)2498 angle::Result ContextVk::handleDirtyComputePipelineDesc(DirtyBits::Iterator *dirtyBitsIterator)
2499 {
2500     if (mCurrentComputePipeline == nullptr)
2501     {
2502         vk::PipelineCacheAccess pipelineCache;
2503         ANGLE_TRY(mRenderer->getPipelineCache(this, &pipelineCache));
2504 
2505         ProgramExecutableVk *executableVk = vk::GetImpl(mState.getProgramExecutable());
2506         ASSERT(executableVk);
2507 
2508         executableVk->waitForComputePostLinkTasks(this);
2509         ANGLE_TRY(executableVk->getOrCreateComputePipeline(
2510             this, &pipelineCache, PipelineSource::Draw, pipelineRobustness(),
2511             pipelineProtectedAccess(), &mCurrentComputePipeline));
2512     }
2513 
2514     ASSERT(mComputeDirtyBits.test(DIRTY_BIT_PIPELINE_BINDING));
2515 
2516     return angle::Result::Continue;
2517 }
2518 
handleDirtyComputePipelineBinding(DirtyBits::Iterator * dirtyBitsIterator)2519 angle::Result ContextVk::handleDirtyComputePipelineBinding(DirtyBits::Iterator *dirtyBitsIterator)
2520 {
2521     ASSERT(mCurrentComputePipeline);
2522 
2523     mOutsideRenderPassCommands->getCommandBuffer().bindComputePipeline(
2524         mCurrentComputePipeline->getPipeline());
2525     mOutsideRenderPassCommands->retainResource(mCurrentComputePipeline);
2526 
2527     return angle::Result::Continue;
2528 }
2529 
2530 template <typename CommandBufferHelperT>
handleDirtyTexturesImpl(CommandBufferHelperT * commandBufferHelper,PipelineType pipelineType)2531 ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
2532     CommandBufferHelperT *commandBufferHelper,
2533     PipelineType pipelineType)
2534 {
2535     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2536     ASSERT(executable);
2537     const gl::ActiveTextureMask &activeTextures = executable->getActiveSamplersMask();
2538 
2539     for (size_t textureUnit : activeTextures)
2540     {
2541         TextureVk *textureVk = mActiveTextures[textureUnit];
2542 
2543         // If it's a texture buffer, get the attached buffer.
2544         if (textureVk->getBuffer().get() != nullptr)
2545         {
2546             vk::BufferHelper *buffer = textureVk->getPossiblyEmulatedTextureBuffer(this);
2547             const gl::ShaderBitSet stages =
2548                 executable->getSamplerShaderBitsForTextureUnitIndex(textureUnit);
2549 
2550             OnTextureBufferRead(this, buffer, stages, commandBufferHelper);
2551 
2552             textureVk->retainBufferViews(commandBufferHelper);
2553             continue;
2554         }
2555 
2556         // The image should be flushed and ready to use at this point. There may still be
2557         // lingering staged updates in its staging buffer for unused texture mip levels or
2558         // layers. Therefore we can't verify it has no staged updates right here.
2559         vk::ImageHelper &image = textureVk->getImage();
2560 
2561         const vk::ImageLayout imageLayout =
2562             GetImageReadLayout(textureVk, *executable, textureUnit, pipelineType);
2563 
2564         // Ensure the image is in the desired layout
2565         commandBufferHelper->imageRead(this, image.getAspectFlags(), imageLayout, &image);
2566     }
2567 
2568     if (executable->hasTextures())
2569     {
2570         ProgramExecutableVk *executableVk = vk::GetImpl(executable);
2571         ANGLE_TRY(executableVk->updateTexturesDescriptorSet(
2572             this, getCurrentFrameCount(), mActiveTextures, mState.getSamplers(), pipelineType,
2573             mShareGroupVk->getUpdateDescriptorSetsBuilder()));
2574     }
2575 
2576     return angle::Result::Continue;
2577 }
2578 
handleDirtyGraphicsTextures(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2579 angle::Result ContextVk::handleDirtyGraphicsTextures(DirtyBits::Iterator *dirtyBitsIterator,
2580                                                      DirtyBits dirtyBitMask)
2581 {
2582     return handleDirtyTexturesImpl(mRenderPassCommands, PipelineType::Graphics);
2583 }
2584 
handleDirtyComputeTextures(DirtyBits::Iterator * dirtyBitsIterator)2585 angle::Result ContextVk::handleDirtyComputeTextures(DirtyBits::Iterator *dirtyBitsIterator)
2586 {
2587     return handleDirtyTexturesImpl(mOutsideRenderPassCommands, PipelineType::Compute);
2588 }
2589 
handleDirtyGraphicsVertexBuffers(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2590 angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(DirtyBits::Iterator *dirtyBitsIterator,
2591                                                           DirtyBits dirtyBitMask)
2592 {
2593     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2594     VertexArrayVk *vertexArrayVk            = getVertexArray();
2595     uint32_t maxAttrib = mState.getProgramExecutable()->getMaxActiveAttribLocation();
2596     const gl::AttribArray<VkBuffer> &bufferHandles = vertexArrayVk->getCurrentArrayBufferHandles();
2597     const gl::AttribArray<VkDeviceSize> &bufferOffsets =
2598         vertexArrayVk->getCurrentArrayBufferOffsets();
2599 
2600     if (mRenderer->getFeatures().useVertexInputBindingStrideDynamicState.enabled ||
2601         getFeatures().supportsVertexInputDynamicState.enabled)
2602     {
2603         const gl::AttribArray<GLuint> &bufferStrides =
2604             vertexArrayVk->getCurrentArrayBufferStrides();
2605         const gl::AttribArray<angle::FormatID> &bufferFormats =
2606             vertexArrayVk->getCurrentArrayBufferFormats();
2607         gl::AttribArray<VkDeviceSize> strides = {};
2608         const gl::AttribArray<GLuint> &bufferDivisors =
2609             vertexArrayVk->getCurrentArrayBufferDivisors();
2610         const gl::AttribArray<GLuint> &bufferRelativeOffsets =
2611             vertexArrayVk->getCurrentArrayBufferRelativeOffsets();
2612         const gl::AttributesMask &bufferCompressed =
2613             vertexArrayVk->getCurrentArrayBufferCompressed();
2614 
2615         gl::AttribVector<VkVertexInputBindingDescription2EXT> bindingDescs;
2616         gl::AttribVector<VkVertexInputAttributeDescription2EXT> attributeDescs;
2617 
2618         // Set stride to 0 for mismatching formats between the program's declared attribute and that
2619         // which is specified in glVertexAttribPointer.  See comment in vk_cache_utils.cpp
2620         // (initializePipeline) for more details.
2621         const gl::AttributesMask &activeAttribLocations =
2622             executable->getNonBuiltinAttribLocationsMask();
2623         const gl::ComponentTypeMask &programAttribsTypeMask = executable->getAttributesTypeMask();
2624 
2625         for (size_t attribIndex : activeAttribLocations)
2626         {
2627             const angle::Format &intendedFormat =
2628                 mRenderer->getFormat(bufferFormats[attribIndex]).getIntendedFormat();
2629 
2630             const gl::ComponentType attribType = GetVertexAttributeComponentType(
2631                 intendedFormat.isPureInt(), intendedFormat.vertexAttribType);
2632             const gl::ComponentType programAttribType =
2633                 gl::GetComponentTypeMask(programAttribsTypeMask, attribIndex);
2634 
2635             const bool mismatchingType =
2636                 attribType != programAttribType && (programAttribType == gl::ComponentType::Float ||
2637                                                     attribType == gl::ComponentType::Float);
2638             strides[attribIndex] = mismatchingType ? 0 : bufferStrides[attribIndex];
2639 
2640             if (getFeatures().supportsVertexInputDynamicState.enabled)
2641             {
2642                 VkVertexInputBindingDescription2EXT bindingDesc  = {};
2643                 VkVertexInputAttributeDescription2EXT attribDesc = {};
2644                 bindingDesc.sType   = VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT;
2645                 bindingDesc.binding = static_cast<uint32_t>(attribIndex);
2646                 bindingDesc.stride  = static_cast<uint32_t>(strides[attribIndex]);
2647                 bindingDesc.divisor =
2648                     bufferDivisors[attribIndex] > mRenderer->getMaxVertexAttribDivisor()
2649                         ? 1
2650                         : bufferDivisors[attribIndex];
2651                 if (bindingDesc.divisor != 0)
2652                 {
2653                     bindingDesc.inputRate =
2654                         static_cast<VkVertexInputRate>(VK_VERTEX_INPUT_RATE_INSTANCE);
2655                 }
2656                 else
2657                 {
2658                     bindingDesc.inputRate =
2659                         static_cast<VkVertexInputRate>(VK_VERTEX_INPUT_RATE_VERTEX);
2660                     // Divisor value is ignored by the implementation when using
2661                     // VK_VERTEX_INPUT_RATE_VERTEX, but it is set to 1 to avoid a validation error
2662                     // due to a validation layer issue.
2663                     bindingDesc.divisor = 1;
2664                 }
2665 
2666                 attribDesc.sType   = VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT;
2667                 attribDesc.binding = static_cast<uint32_t>(attribIndex);
2668                 attribDesc.format  = vk::GraphicsPipelineDesc::getPipelineVertexInputStateFormat(
2669                     this, bufferFormats[attribIndex], bufferCompressed[attribIndex],
2670                     programAttribType, static_cast<uint32_t>(attribIndex));
2671                 attribDesc.location = static_cast<uint32_t>(attribIndex);
2672                 attribDesc.offset   = bufferRelativeOffsets[attribIndex];
2673 
2674                 bindingDescs.push_back(bindingDesc);
2675                 attributeDescs.push_back(attribDesc);
2676             }
2677         }
2678 
2679         if (getFeatures().supportsVertexInputDynamicState.enabled)
2680         {
2681             mRenderPassCommandBuffer->setVertexInput(
2682                 static_cast<uint32_t>(bindingDescs.size()), bindingDescs.data(),
2683                 static_cast<uint32_t>(attributeDescs.size()), attributeDescs.data());
2684             if (bindingDescs.size() != 0)
2685             {
2686 
2687                 mRenderPassCommandBuffer->bindVertexBuffers(0, maxAttrib, bufferHandles.data(),
2688                                                             bufferOffsets.data());
2689             }
2690         }
2691         else
2692         {
2693             // TODO: Use the sizes parameters here to fix the robustness issue worked around in
2694             // crbug.com/1310038
2695             mRenderPassCommandBuffer->bindVertexBuffers2(
2696                 0, maxAttrib, bufferHandles.data(), bufferOffsets.data(), nullptr, strides.data());
2697         }
2698     }
2699     else
2700     {
2701         mRenderPassCommandBuffer->bindVertexBuffers(0, maxAttrib, bufferHandles.data(),
2702                                                     bufferOffsets.data());
2703     }
2704 
2705     const gl::AttribArray<vk::BufferHelper *> &arrayBufferResources =
2706         vertexArrayVk->getCurrentArrayBuffers();
2707 
2708     // Mark all active vertex buffers as accessed.
2709     for (uint32_t attribIndex = 0; attribIndex < maxAttrib; ++attribIndex)
2710     {
2711         vk::BufferHelper *arrayBuffer = arrayBufferResources[attribIndex];
2712         if (arrayBuffer)
2713         {
2714             mRenderPassCommands->bufferRead(this, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
2715                                             vk::PipelineStage::VertexInput, arrayBuffer);
2716         }
2717     }
2718 
2719     return angle::Result::Continue;
2720 }
2721 
handleDirtyGraphicsIndexBuffer(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2722 angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(DirtyBits::Iterator *dirtyBitsIterator,
2723                                                         DirtyBits dirtyBitMask)
2724 {
2725     vk::BufferHelper *elementArrayBuffer = mCurrentIndexBuffer;
2726     ASSERT(elementArrayBuffer != nullptr);
2727 
2728     VkDeviceSize bufferOffset;
2729     const vk::Buffer &buffer = elementArrayBuffer->getBufferForVertexArray(
2730         this, elementArrayBuffer->getSize(), &bufferOffset);
2731 
2732     mRenderPassCommandBuffer->bindIndexBuffer(buffer, bufferOffset + mCurrentIndexBufferOffset,
2733                                               getVkIndexType(mCurrentDrawElementsType));
2734 
2735     mRenderPassCommands->bufferRead(this, VK_ACCESS_INDEX_READ_BIT, vk::PipelineStage::VertexInput,
2736                                     elementArrayBuffer);
2737 
2738     return angle::Result::Continue;
2739 }
2740 
handleDirtyGraphicsFramebufferFetchBarrier(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2741 angle::Result ContextVk::handleDirtyGraphicsFramebufferFetchBarrier(
2742     DirtyBits::Iterator *dirtyBitsIterator,
2743     DirtyBits dirtyBitMask)
2744 {
2745     VkMemoryBarrier memoryBarrier = {};
2746     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2747     memoryBarrier.srcAccessMask   = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
2748     memoryBarrier.dstAccessMask   = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
2749 
2750     mRenderPassCommandBuffer->pipelineBarrier(
2751         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
2752         GetLocalDependencyFlags(this), 1, &memoryBarrier, 0, nullptr, 0, nullptr);
2753 
2754     return angle::Result::Continue;
2755 }
2756 
handleDirtyGraphicsBlendBarrier(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2757 angle::Result ContextVk::handleDirtyGraphicsBlendBarrier(DirtyBits::Iterator *dirtyBitsIterator,
2758                                                          DirtyBits dirtyBitMask)
2759 {
2760     if (getFeatures().supportsBlendOperationAdvancedCoherent.enabled)
2761     {
2762         return angle::Result::Continue;
2763     }
2764 
2765     VkMemoryBarrier memoryBarrier = {};
2766     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2767     memoryBarrier.srcAccessMask   = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
2768     memoryBarrier.dstAccessMask   = VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT;
2769 
2770     mRenderPassCommandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2771                                               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2772                                               GetLocalDependencyFlags(this), 1, &memoryBarrier, 0,
2773                                               nullptr, 0, nullptr);
2774 
2775     return angle::Result::Continue;
2776 }
2777 
2778 template <typename CommandBufferHelperT>
handleDirtyShaderResourcesImpl(CommandBufferHelperT * commandBufferHelper,PipelineType pipelineType,DirtyBits::Iterator * dirtyBitsIterator)2779 angle::Result ContextVk::handleDirtyShaderResourcesImpl(CommandBufferHelperT *commandBufferHelper,
2780                                                         PipelineType pipelineType,
2781                                                         DirtyBits::Iterator *dirtyBitsIterator)
2782 {
2783     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2784     ASSERT(executable);
2785 
2786     // DIRTY_BIT_UNIFORM_BUFFERS is set when uniform buffer bindings change.
2787     // DIRTY_BIT_SHADER_RESOURCES gets set when the program executable has changed. In that case,
2788     // this function will update entire the shader resource descriptorSet.  This means there is no
2789     // need to process uniform buffer bindings again.
2790     dirtyBitsIterator->resetLaterBit(DIRTY_BIT_UNIFORM_BUFFERS);
2791 
2792     // This function processes uniform buffers, so it doesn't matter which are dirty.  The following
2793     // makes sure the dirty bits are reset.
2794     mState.getAndResetDirtyUniformBlocks();
2795 
2796     const bool hasImages               = executable->hasImages();
2797     const bool hasStorageBuffers       = executable->hasStorageBuffers();
2798     const bool hasAtomicCounterBuffers = executable->hasAtomicCounterBuffers();
2799     const bool hasUniformBuffers       = executable->hasUniformBuffers();
2800     const bool hasFramebufferFetch     = executable->usesColorFramebufferFetch() ||
2801                                      executable->usesDepthFramebufferFetch() ||
2802                                      executable->usesStencilFramebufferFetch();
2803 
2804     if (!hasUniformBuffers && !hasStorageBuffers && !hasAtomicCounterBuffers && !hasImages &&
2805         !hasFramebufferFetch)
2806     {
2807         return angle::Result::Continue;
2808     }
2809 
2810     const VkPhysicalDeviceLimits &limits = mRenderer->getPhysicalDeviceProperties().limits;
2811     ProgramExecutableVk *executableVk    = vk::GetImpl(executable);
2812     const ShaderInterfaceVariableInfoMap &variableInfoMap = executableVk->getVariableInfoMap();
2813 
2814     mShaderBufferWriteDescriptorDescs = executableVk->getShaderResourceWriteDescriptorDescs();
2815     // Update writeDescriptorDescs with inputAttachments
2816     mShaderBufferWriteDescriptorDescs.updateInputAttachments(
2817         *executable, variableInfoMap, vk::GetImpl(mState.getDrawFramebuffer()));
2818 
2819     mShaderBuffersDescriptorDesc.resize(
2820         mShaderBufferWriteDescriptorDescs.getTotalDescriptorCount());
2821     if (hasUniformBuffers)
2822     {
2823         mShaderBuffersDescriptorDesc.updateShaderBuffers(
2824             this, commandBufferHelper, *executable, variableInfoMap,
2825             mState.getOffsetBindingPointerUniformBuffers(), executable->getUniformBlocks(),
2826             executableVk->getUniformBufferDescriptorType(), limits.maxUniformBufferRange,
2827             mEmptyBuffer, mShaderBufferWriteDescriptorDescs, mDeferredMemoryBarriers);
2828     }
2829     if (hasStorageBuffers)
2830     {
2831         mShaderBuffersDescriptorDesc.updateShaderBuffers(
2832             this, commandBufferHelper, *executable, variableInfoMap,
2833             mState.getOffsetBindingPointerShaderStorageBuffers(),
2834             executable->getShaderStorageBlocks(), executableVk->getStorageBufferDescriptorType(),
2835             limits.maxStorageBufferRange, mEmptyBuffer, mShaderBufferWriteDescriptorDescs,
2836             mDeferredMemoryBarriers);
2837     }
2838     if (hasAtomicCounterBuffers)
2839     {
2840         mShaderBuffersDescriptorDesc.updateAtomicCounters(
2841             this, commandBufferHelper, *executable, variableInfoMap,
2842             mState.getOffsetBindingPointerAtomicCounterBuffers(),
2843             executable->getAtomicCounterBuffers(), limits.minStorageBufferOffsetAlignment,
2844             mEmptyBuffer, mShaderBufferWriteDescriptorDescs);
2845     }
2846     if (hasImages)
2847     {
2848         ANGLE_TRY(updateActiveImages(commandBufferHelper));
2849         ANGLE_TRY(mShaderBuffersDescriptorDesc.updateImages(this, *executable, variableInfoMap,
2850                                                             mActiveImages, mState.getImageUnits(),
2851                                                             mShaderBufferWriteDescriptorDescs));
2852     }
2853     if (hasFramebufferFetch)
2854     {
2855         ANGLE_TRY(mShaderBuffersDescriptorDesc.updateInputAttachments(
2856             this, *executable, variableInfoMap, vk::GetImpl(mState.getDrawFramebuffer()),
2857             mShaderBufferWriteDescriptorDescs));
2858     }
2859 
2860     mDeferredMemoryBarriers = 0;
2861 
2862     vk::SharedDescriptorSetCacheKey newSharedCacheKey;
2863     ANGLE_TRY(executableVk->updateShaderResourcesDescriptorSet(
2864         this, getCurrentFrameCount(), mShareGroupVk->getUpdateDescriptorSetsBuilder(),
2865         mShaderBufferWriteDescriptorDescs, mShaderBuffersDescriptorDesc, &newSharedCacheKey));
2866 
2867     if (newSharedCacheKey)
2868     {
2869         // A new cache entry has been created. We record this cache key in the images and buffers so
2870         // that the descriptorSet cache can be destroyed when buffer/image is destroyed.
2871         updateShaderResourcesWithSharedCacheKey(newSharedCacheKey);
2872     }
2873 
2874     // Record usage of storage buffers and images in the command buffer to aid handling of
2875     // glMemoryBarrier.
2876     if (hasImages || hasStorageBuffers || hasAtomicCounterBuffers)
2877     {
2878         commandBufferHelper->setHasShaderStorageOutput();
2879     }
2880 
2881     return angle::Result::Continue;
2882 }
2883 
handleDirtyGraphicsShaderResources(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2884 angle::Result ContextVk::handleDirtyGraphicsShaderResources(DirtyBits::Iterator *dirtyBitsIterator,
2885                                                             DirtyBits dirtyBitMask)
2886 {
2887     return handleDirtyShaderResourcesImpl(mRenderPassCommands, PipelineType::Graphics,
2888                                           dirtyBitsIterator);
2889 }
2890 
handleDirtyComputeShaderResources(DirtyBits::Iterator * dirtyBitsIterator)2891 angle::Result ContextVk::handleDirtyComputeShaderResources(DirtyBits::Iterator *dirtyBitsIterator)
2892 {
2893     return handleDirtyShaderResourcesImpl(mOutsideRenderPassCommands, PipelineType::Compute,
2894                                           dirtyBitsIterator);
2895 }
2896 
2897 template <typename CommandBufferT>
handleDirtyUniformBuffersImpl(CommandBufferT * commandBufferHelper)2898 angle::Result ContextVk::handleDirtyUniformBuffersImpl(CommandBufferT *commandBufferHelper)
2899 {
2900     gl::ProgramExecutable *executable = mState.getProgramExecutable();
2901     ASSERT(executable);
2902     ASSERT(executable->hasUniformBuffers());
2903 
2904     const VkPhysicalDeviceLimits &limits = mRenderer->getPhysicalDeviceProperties().limits;
2905     ProgramExecutableVk *executableVk    = vk::GetImpl(executable);
2906     const ShaderInterfaceVariableInfoMap &variableInfoMap = executableVk->getVariableInfoMap();
2907 
2908     gl::ProgramUniformBlockMask dirtyBits = mState.getAndResetDirtyUniformBlocks();
2909     for (size_t blockIndex : dirtyBits)
2910     {
2911         const GLuint binding = executable->getUniformBlockBinding(blockIndex);
2912         mShaderBuffersDescriptorDesc.updateOneShaderBuffer(
2913             this, commandBufferHelper, variableInfoMap,
2914             mState.getOffsetBindingPointerUniformBuffers(),
2915             executable->getUniformBlocks()[blockIndex], binding,
2916             executableVk->getUniformBufferDescriptorType(), limits.maxUniformBufferRange,
2917             mEmptyBuffer, mShaderBufferWriteDescriptorDescs, mDeferredMemoryBarriers);
2918     }
2919 
2920     vk::SharedDescriptorSetCacheKey newSharedCacheKey;
2921     ANGLE_TRY(executableVk->updateShaderResourcesDescriptorSet(
2922         this, getCurrentFrameCount(), mShareGroupVk->getUpdateDescriptorSetsBuilder(),
2923         mShaderBufferWriteDescriptorDescs, mShaderBuffersDescriptorDesc, &newSharedCacheKey));
2924 
2925     if (newSharedCacheKey)
2926     {
2927         // A new cache entry has been created. We record this cache key in the images and
2928         // buffers so that the descriptorSet cache can be destroyed when buffer/image is
2929         // destroyed.
2930         updateShaderResourcesWithSharedCacheKey(newSharedCacheKey);
2931     }
2932 
2933     return angle::Result::Continue;
2934 }
2935 
handleDirtyGraphicsUniformBuffers(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2936 angle::Result ContextVk::handleDirtyGraphicsUniformBuffers(DirtyBits::Iterator *dirtyBitsIterator,
2937                                                            DirtyBits dirtyBitMask)
2938 {
2939     return handleDirtyUniformBuffersImpl(mRenderPassCommands);
2940 }
2941 
handleDirtyComputeUniformBuffers(DirtyBits::Iterator * dirtyBitsIterator)2942 angle::Result ContextVk::handleDirtyComputeUniformBuffers(DirtyBits::Iterator *dirtyBitsIterator)
2943 {
2944     return handleDirtyUniformBuffersImpl(mOutsideRenderPassCommands);
2945 }
2946 
handleDirtyGraphicsTransformFeedbackBuffersEmulation(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2947 angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation(
2948     DirtyBits::Iterator *dirtyBitsIterator,
2949     DirtyBits dirtyBitMask)
2950 {
2951     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2952     ASSERT(executable);
2953 
2954     if (!executable->hasTransformFeedbackOutput())
2955     {
2956         return angle::Result::Continue;
2957     }
2958 
2959     TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(mState.getCurrentTransformFeedback());
2960 
2961     if (mState.isTransformFeedbackActiveUnpaused())
2962     {
2963         size_t bufferCount = executable->getTransformFeedbackBufferCount();
2964         const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &bufferHelpers =
2965             transformFeedbackVk->getBufferHelpers();
2966 
2967         for (size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
2968         {
2969             vk::BufferHelper *bufferHelper = bufferHelpers[bufferIndex];
2970             ASSERT(bufferHelper);
2971             mRenderPassCommands->bufferWrite(this, VK_ACCESS_SHADER_WRITE_BIT,
2972                                              vk::PipelineStage::VertexShader, bufferHelper);
2973         }
2974 
2975         mCurrentTransformFeedbackQueueSerial = mRenderPassCommands->getQueueSerial();
2976     }
2977 
2978     ProgramExecutableVk *executableVk      = vk::GetImpl(executable);
2979     vk::BufferHelper *currentUniformBuffer = mDefaultUniformStorage.getCurrentBuffer();
2980 
2981     const vk::WriteDescriptorDescs &writeDescriptorDescs =
2982         executableVk->getDefaultUniformWriteDescriptorDescs(transformFeedbackVk);
2983 
2984     vk::DescriptorSetDescBuilder uniformsAndXfbDesc(writeDescriptorDescs.getTotalDescriptorCount());
2985     uniformsAndXfbDesc.updateUniformsAndXfb(
2986         this, *executable, writeDescriptorDescs, currentUniformBuffer, mEmptyBuffer,
2987         mState.isTransformFeedbackActiveUnpaused(), transformFeedbackVk);
2988 
2989     vk::SharedDescriptorSetCacheKey newSharedCacheKey;
2990     ANGLE_TRY(executableVk->updateUniformsAndXfbDescriptorSet(
2991         this, getCurrentFrameCount(), mShareGroupVk->getUpdateDescriptorSetsBuilder(),
2992         writeDescriptorDescs, currentUniformBuffer, &uniformsAndXfbDesc, &newSharedCacheKey));
2993 
2994     if (newSharedCacheKey)
2995     {
2996         transformFeedbackVk->onNewDescriptorSet(*executable, newSharedCacheKey);
2997     }
2998 
2999     return angle::Result::Continue;
3000 }
3001 
handleDirtyGraphicsTransformFeedbackBuffersExtension(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3002 angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension(
3003     DirtyBits::Iterator *dirtyBitsIterator,
3004     DirtyBits dirtyBitMask)
3005 {
3006     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
3007     ASSERT(executable);
3008 
3009     if (!executable->hasTransformFeedbackOutput() || !mState.isTransformFeedbackActive())
3010     {
3011         return angle::Result::Continue;
3012     }
3013 
3014     TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(mState.getCurrentTransformFeedback());
3015     size_t bufferCount                       = executable->getTransformFeedbackBufferCount();
3016 
3017     const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &buffers =
3018         transformFeedbackVk->getBufferHelpers();
3019     gl::TransformFeedbackBuffersArray<vk::BufferHelper> &counterBuffers =
3020         transformFeedbackVk->getCounterBufferHelpers();
3021 
3022     // Issue necessary barriers for the transform feedback buffers.
3023     for (size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
3024     {
3025         vk::BufferHelper *bufferHelper = buffers[bufferIndex];
3026         ASSERT(bufferHelper);
3027         mRenderPassCommands->bufferWrite(this, VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT,
3028                                          vk::PipelineStage::TransformFeedback, bufferHelper);
3029     }
3030 
3031     // Issue necessary barriers for the transform feedback counter buffer.  Note that the barrier is
3032     // issued only on the first buffer (which uses a global memory barrier), as all the counter
3033     // buffers of the transform feedback object are used together.  The rest of the buffers are
3034     // simply retained so they don't get deleted too early.
3035     ASSERT(counterBuffers[0].valid());
3036     mRenderPassCommands->bufferWrite(this,
3037                                      VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT |
3038                                          VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT,
3039                                      vk::PipelineStage::TransformFeedback, &counterBuffers[0]);
3040     for (size_t bufferIndex = 1; bufferIndex < bufferCount; ++bufferIndex)
3041     {
3042         mRenderPassCommands->retainResourceForWrite(&counterBuffers[bufferIndex]);
3043     }
3044 
3045     const gl::TransformFeedbackBuffersArray<VkBuffer> &bufferHandles =
3046         transformFeedbackVk->getBufferHandles();
3047     const gl::TransformFeedbackBuffersArray<VkDeviceSize> &bufferOffsets =
3048         transformFeedbackVk->getBufferOffsets();
3049     const gl::TransformFeedbackBuffersArray<VkDeviceSize> &bufferSizes =
3050         transformFeedbackVk->getBufferSizes();
3051 
3052     mRenderPassCommandBuffer->bindTransformFeedbackBuffers(
3053         0, static_cast<uint32_t>(bufferCount), bufferHandles.data(), bufferOffsets.data(),
3054         bufferSizes.data());
3055 
3056     if (!mState.isTransformFeedbackActiveUnpaused())
3057     {
3058         return angle::Result::Continue;
3059     }
3060 
3061     // We should have same number of counter buffers as xfb buffers have
3062     const gl::TransformFeedbackBuffersArray<VkBuffer> &counterBufferHandles =
3063         transformFeedbackVk->getCounterBufferHandles();
3064     const gl::TransformFeedbackBuffersArray<VkDeviceSize> &counterBufferOffsets =
3065         transformFeedbackVk->getCounterBufferOffsets();
3066 
3067     bool rebindBuffers = transformFeedbackVk->getAndResetBufferRebindState();
3068 
3069     mRenderPassCommands->beginTransformFeedback(bufferCount, counterBufferHandles.data(),
3070                                                 counterBufferOffsets.data(), rebindBuffers);
3071 
3072     mCurrentTransformFeedbackQueueSerial = mRenderPassCommands->getQueueSerial();
3073 
3074     return angle::Result::Continue;
3075 }
3076 
handleDirtyGraphicsTransformFeedbackResume(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3077 angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackResume(
3078     DirtyBits::Iterator *dirtyBitsIterator,
3079     DirtyBits dirtyBitMask)
3080 {
3081     if (mRenderPassCommands->isTransformFeedbackStarted())
3082     {
3083         mRenderPassCommands->resumeTransformFeedback();
3084     }
3085 
3086     ANGLE_TRY(resumeXfbRenderPassQueriesIfActive());
3087 
3088     return angle::Result::Continue;
3089 }
3090 
handleDirtyGraphicsDescriptorSets(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3091 angle::Result ContextVk::handleDirtyGraphicsDescriptorSets(DirtyBits::Iterator *dirtyBitsIterator,
3092                                                            DirtyBits dirtyBitMask)
3093 {
3094     return handleDirtyDescriptorSetsImpl(mRenderPassCommands, PipelineType::Graphics);
3095 }
3096 
handleDirtyGraphicsUniforms(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3097 angle::Result ContextVk::handleDirtyGraphicsUniforms(DirtyBits::Iterator *dirtyBitsIterator,
3098                                                      DirtyBits dirtyBitMask)
3099 {
3100     return handleDirtyUniformsImpl(dirtyBitsIterator);
3101 }
3102 
handleDirtyComputeUniforms(DirtyBits::Iterator * dirtyBitsIterator)3103 angle::Result ContextVk::handleDirtyComputeUniforms(DirtyBits::Iterator *dirtyBitsIterator)
3104 {
3105     return handleDirtyUniformsImpl(dirtyBitsIterator);
3106 }
3107 
handleDirtyUniformsImpl(DirtyBits::Iterator * dirtyBitsIterator)3108 angle::Result ContextVk::handleDirtyUniformsImpl(DirtyBits::Iterator *dirtyBitsIterator)
3109 {
3110     dirtyBitsIterator->setLaterBit(DIRTY_BIT_DESCRIPTOR_SETS);
3111 
3112     ProgramExecutableVk *executableVk = vk::GetImpl(mState.getProgramExecutable());
3113     TransformFeedbackVk *transformFeedbackVk =
3114         vk::SafeGetImpl(mState.getCurrentTransformFeedback());
3115     ANGLE_TRY(executableVk->updateUniforms(
3116         this, getCurrentFrameCount(), mShareGroupVk->getUpdateDescriptorSetsBuilder(),
3117         &mEmptyBuffer, &mDefaultUniformStorage, mState.isTransformFeedbackActiveUnpaused(),
3118         transformFeedbackVk));
3119 
3120     return angle::Result::Continue;
3121 }
3122 
handleDirtyGraphicsDynamicViewport(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3123 angle::Result ContextVk::handleDirtyGraphicsDynamicViewport(DirtyBits::Iterator *dirtyBitsIterator,
3124                                                             DirtyBits dirtyBitMask)
3125 {
3126     mRenderPassCommandBuffer->setViewport(0, 1, &mViewport);
3127     return angle::Result::Continue;
3128 }
3129 
handleDirtyGraphicsDynamicScissor(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3130 angle::Result ContextVk::handleDirtyGraphicsDynamicScissor(DirtyBits::Iterator *dirtyBitsIterator,
3131                                                            DirtyBits dirtyBitMask)
3132 {
3133     handleDirtyGraphicsDynamicScissorImpl(mState.isQueryActive(gl::QueryType::PrimitivesGenerated));
3134     return angle::Result::Continue;
3135 }
3136 
handleDirtyGraphicsDynamicLineWidth(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3137 angle::Result ContextVk::handleDirtyGraphicsDynamicLineWidth(DirtyBits::Iterator *dirtyBitsIterator,
3138                                                              DirtyBits dirtyBitMask)
3139 {
3140     // Clamp line width to min/max allowed values. It's not invalid GL to
3141     // provide out-of-range line widths, but it _is_ invalid Vulkan.
3142     const float lineWidth = gl::clamp(mState.getLineWidth(), mState.getCaps().minAliasedLineWidth,
3143                                       mState.getCaps().maxAliasedLineWidth);
3144     mRenderPassCommandBuffer->setLineWidth(lineWidth);
3145     return angle::Result::Continue;
3146 }
3147 
handleDirtyGraphicsDynamicDepthBias(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3148 angle::Result ContextVk::handleDirtyGraphicsDynamicDepthBias(DirtyBits::Iterator *dirtyBitsIterator,
3149                                                              DirtyBits dirtyBitMask)
3150 {
3151     const gl::RasterizerState &rasterState = mState.getRasterizerState();
3152 
3153     float depthBiasConstantFactor = rasterState.polygonOffsetUnits;
3154     if (getFeatures().doubleDepthBiasConstantFactor.enabled)
3155     {
3156         depthBiasConstantFactor *= 2.0f;
3157     }
3158 
3159     // Note: depth bias clamp is only exposed in EXT_polygon_offset_clamp.
3160     mRenderPassCommandBuffer->setDepthBias(depthBiasConstantFactor, rasterState.polygonOffsetClamp,
3161                                            rasterState.polygonOffsetFactor);
3162     return angle::Result::Continue;
3163 }
3164 
handleDirtyGraphicsDynamicBlendConstants(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3165 angle::Result ContextVk::handleDirtyGraphicsDynamicBlendConstants(
3166     DirtyBits::Iterator *dirtyBitsIterator,
3167     DirtyBits dirtyBitMask)
3168 {
3169     const gl::ColorF &color = mState.getBlendColor();
3170     mRenderPassCommandBuffer->setBlendConstants(color.data());
3171     return angle::Result::Continue;
3172 }
3173 
handleDirtyGraphicsDynamicStencilCompareMask(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3174 angle::Result ContextVk::handleDirtyGraphicsDynamicStencilCompareMask(
3175     DirtyBits::Iterator *dirtyBitsIterator,
3176     DirtyBits dirtyBitMask)
3177 {
3178     const gl::DepthStencilState &depthStencilState = mState.getDepthStencilState();
3179     mRenderPassCommandBuffer->setStencilCompareMask(depthStencilState.stencilMask,
3180                                                     depthStencilState.stencilBackMask);
3181     return angle::Result::Continue;
3182 }
3183 
handleDirtyGraphicsDynamicStencilWriteMask(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3184 angle::Result ContextVk::handleDirtyGraphicsDynamicStencilWriteMask(
3185     DirtyBits::Iterator *dirtyBitsIterator,
3186     DirtyBits dirtyBitMask)
3187 {
3188     const gl::DepthStencilState &depthStencilState = mState.getDepthStencilState();
3189     const gl::Framebuffer *drawFramebuffer         = mState.getDrawFramebuffer();
3190     uint32_t frontWritemask                        = 0;
3191     uint32_t backWritemask                         = 0;
3192     // Don't write to stencil buffers that should not exist
3193     if (drawFramebuffer->hasStencil())
3194     {
3195         frontWritemask = depthStencilState.stencilWritemask;
3196         backWritemask  = depthStencilState.stencilBackWritemask;
3197     }
3198 
3199     mRenderPassCommandBuffer->setStencilWriteMask(frontWritemask, backWritemask);
3200     return angle::Result::Continue;
3201 }
3202 
handleDirtyGraphicsDynamicStencilReference(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3203 angle::Result ContextVk::handleDirtyGraphicsDynamicStencilReference(
3204     DirtyBits::Iterator *dirtyBitsIterator,
3205     DirtyBits dirtyBitMask)
3206 {
3207     mRenderPassCommandBuffer->setStencilReference(mState.getStencilRef(),
3208                                                   mState.getStencilBackRef());
3209     return angle::Result::Continue;
3210 }
3211 
handleDirtyGraphicsDynamicCullMode(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3212 angle::Result ContextVk::handleDirtyGraphicsDynamicCullMode(DirtyBits::Iterator *dirtyBitsIterator,
3213                                                             DirtyBits dirtyBitMask)
3214 {
3215     const gl::RasterizerState &rasterState = mState.getRasterizerState();
3216     mRenderPassCommandBuffer->setCullMode(gl_vk::GetCullMode(rasterState));
3217     return angle::Result::Continue;
3218 }
3219 
handleDirtyGraphicsDynamicFrontFace(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3220 angle::Result ContextVk::handleDirtyGraphicsDynamicFrontFace(DirtyBits::Iterator *dirtyBitsIterator,
3221                                                              DirtyBits dirtyBitMask)
3222 {
3223     const gl::RasterizerState &rasterState = mState.getRasterizerState();
3224     mRenderPassCommandBuffer->setFrontFace(
3225         gl_vk::GetFrontFace(rasterState.frontFace, isYFlipEnabledForDrawFBO()));
3226     return angle::Result::Continue;
3227 }
3228 
handleDirtyGraphicsDynamicDepthTestEnable(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3229 angle::Result ContextVk::handleDirtyGraphicsDynamicDepthTestEnable(
3230     DirtyBits::Iterator *dirtyBitsIterator,
3231     DirtyBits dirtyBitMask)
3232 {
3233     const gl::DepthStencilState &depthStencilState = mState.getDepthStencilState();
3234     gl::Framebuffer *drawFramebuffer              = mState.getDrawFramebuffer();
3235 
3236     // Only enable the depth test if the draw framebuffer has a depth buffer.
3237     mRenderPassCommandBuffer->setDepthTestEnable(depthStencilState.depthTest &&
3238                                                  drawFramebuffer->hasDepth());
3239     return angle::Result::Continue;
3240 }
3241 
handleDirtyGraphicsDynamicDepthWriteEnable(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3242 angle::Result ContextVk::handleDirtyGraphicsDynamicDepthWriteEnable(
3243     DirtyBits::Iterator *dirtyBitsIterator,
3244     DirtyBits dirtyBitMask)
3245 {
3246     const gl::DepthStencilState &depthStencilState = mState.getDepthStencilState();
3247     gl::Framebuffer *drawFramebuffer              = mState.getDrawFramebuffer();
3248 
3249     // Only enable the depth write if the draw framebuffer has a depth buffer.
3250     const bool depthWriteEnabled =
3251         drawFramebuffer->hasDepth() && depthStencilState.depthTest && depthStencilState.depthMask;
3252     mRenderPassCommandBuffer->setDepthWriteEnable(depthWriteEnabled);
3253     return angle::Result::Continue;
3254 }
3255 
handleDirtyGraphicsDynamicDepthCompareOp(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3256 angle::Result ContextVk::handleDirtyGraphicsDynamicDepthCompareOp(
3257     DirtyBits::Iterator *dirtyBitsIterator,
3258     DirtyBits dirtyBitMask)
3259 {
3260     const gl::DepthStencilState &depthStencilState = mState.getDepthStencilState();
3261     mRenderPassCommandBuffer->setDepthCompareOp(gl_vk::GetCompareOp(depthStencilState.depthFunc));
3262     return angle::Result::Continue;
3263 }
3264 
handleDirtyGraphicsDynamicStencilTestEnable(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3265 angle::Result ContextVk::handleDirtyGraphicsDynamicStencilTestEnable(
3266     DirtyBits::Iterator *dirtyBitsIterator,
3267     DirtyBits dirtyBitMask)
3268 {
3269     const gl::DepthStencilState &depthStencilState = mState.getDepthStencilState();
3270     gl::Framebuffer *drawFramebuffer              = mState.getDrawFramebuffer();
3271 
3272     // Only enable the stencil test if the draw framebuffer has a stencil buffer.
3273     mRenderPassCommandBuffer->setStencilTestEnable(depthStencilState.stencilTest &&
3274                                                    drawFramebuffer->hasStencil());
3275     return angle::Result::Continue;
3276 }
3277 
handleDirtyGraphicsDynamicStencilOp(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3278 angle::Result ContextVk::handleDirtyGraphicsDynamicStencilOp(DirtyBits::Iterator *dirtyBitsIterator,
3279                                                              DirtyBits dirtyBitMask)
3280 {
3281     const gl::DepthStencilState &depthStencilState = mState.getDepthStencilState();
3282     mRenderPassCommandBuffer->setStencilOp(
3283         VK_STENCIL_FACE_FRONT_BIT, gl_vk::GetStencilOp(depthStencilState.stencilFail),
3284         gl_vk::GetStencilOp(depthStencilState.stencilPassDepthPass),
3285         gl_vk::GetStencilOp(depthStencilState.stencilPassDepthFail),
3286         gl_vk::GetCompareOp(depthStencilState.stencilFunc));
3287     mRenderPassCommandBuffer->setStencilOp(
3288         VK_STENCIL_FACE_BACK_BIT, gl_vk::GetStencilOp(depthStencilState.stencilBackFail),
3289         gl_vk::GetStencilOp(depthStencilState.stencilBackPassDepthPass),
3290         gl_vk::GetStencilOp(depthStencilState.stencilBackPassDepthFail),
3291         gl_vk::GetCompareOp(depthStencilState.stencilBackFunc));
3292     return angle::Result::Continue;
3293 }
3294 
handleDirtyGraphicsDynamicRasterizerDiscardEnable(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3295 angle::Result ContextVk::handleDirtyGraphicsDynamicRasterizerDiscardEnable(
3296     DirtyBits::Iterator *dirtyBitsIterator,
3297     DirtyBits dirtyBitMask)
3298 {
3299     const bool isEmulatingRasterizerDiscard =
3300         isEmulatingRasterizerDiscardDuringPrimitivesGeneratedQuery(
3301             mState.isQueryActive(gl::QueryType::PrimitivesGenerated));
3302     const bool isRasterizerDiscardEnabled = mState.isRasterizerDiscardEnabled();
3303 
3304     mRenderPassCommandBuffer->setRasterizerDiscardEnable(isRasterizerDiscardEnabled &&
3305                                                          !isEmulatingRasterizerDiscard);
3306     return angle::Result::Continue;
3307 }
3308 
handleDirtyGraphicsDynamicDepthBiasEnable(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3309 angle::Result ContextVk::handleDirtyGraphicsDynamicDepthBiasEnable(
3310     DirtyBits::Iterator *dirtyBitsIterator,
3311     DirtyBits dirtyBitMask)
3312 {
3313     mRenderPassCommandBuffer->setDepthBiasEnable(mState.isPolygonOffsetEnabled());
3314     return angle::Result::Continue;
3315 }
3316 
handleDirtyGraphicsDynamicLogicOp(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3317 angle::Result ContextVk::handleDirtyGraphicsDynamicLogicOp(DirtyBits::Iterator *dirtyBitsIterator,
3318                                                            DirtyBits dirtyBitMask)
3319 {
3320     mRenderPassCommandBuffer->setLogicOp(gl_vk::GetLogicOp(gl::ToGLenum(mState.getLogicOp())));
3321     return angle::Result::Continue;
3322 }
3323 
handleDirtyGraphicsDynamicPrimitiveRestartEnable(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3324 angle::Result ContextVk::handleDirtyGraphicsDynamicPrimitiveRestartEnable(
3325     DirtyBits::Iterator *dirtyBitsIterator,
3326     DirtyBits dirtyBitMask)
3327 {
3328     mRenderPassCommandBuffer->setPrimitiveRestartEnable(mState.isPrimitiveRestartEnabled());
3329     return angle::Result::Continue;
3330 }
3331 
handleDirtyGraphicsDynamicFragmentShadingRate(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3332 angle::Result ContextVk::handleDirtyGraphicsDynamicFragmentShadingRate(
3333     DirtyBits::Iterator *dirtyBitsIterator,
3334     DirtyBits dirtyBitMask)
3335 {
3336     FramebufferVk *drawFramebufferVk = vk::GetImpl(mState.getDrawFramebuffer());
3337     const bool isFoveationEnabled    = drawFramebufferVk->isFoveationEnabled();
3338 
3339     gl::ShadingRate shadingRate =
3340         isFoveationEnabled ? gl::ShadingRate::_1x1 : getState().getShadingRate();
3341     if (shadingRate == gl::ShadingRate::Undefined)
3342     {
3343         // Shading rate has not been set. Since this is dynamic state, set it to 1x1
3344         shadingRate = gl::ShadingRate::_1x1;
3345     }
3346 
3347     const bool shadingRateSupported = mRenderer->isShadingRateSupported(shadingRate);
3348     VkExtent2D fragmentSize         = {};
3349 
3350     switch (shadingRate)
3351     {
3352         case gl::ShadingRate::_1x1:
3353             ASSERT(shadingRateSupported);
3354             fragmentSize.width  = 1;
3355             fragmentSize.height = 1;
3356             break;
3357         case gl::ShadingRate::_1x2:
3358             ASSERT(shadingRateSupported);
3359             fragmentSize.width  = 1;
3360             fragmentSize.height = 2;
3361             break;
3362         case gl::ShadingRate::_2x1:
3363             ASSERT(shadingRateSupported);
3364             fragmentSize.width  = 2;
3365             fragmentSize.height = 1;
3366             break;
3367         case gl::ShadingRate::_2x2:
3368             ASSERT(shadingRateSupported);
3369             fragmentSize.width  = 2;
3370             fragmentSize.height = 2;
3371             break;
3372         case gl::ShadingRate::_4x2:
3373             if (shadingRateSupported)
3374             {
3375                 fragmentSize.width  = 4;
3376                 fragmentSize.height = 2;
3377             }
3378             else
3379             {
3380                 // Fallback to shading rate that preserves aspect ratio
3381                 fragmentSize.width  = 2;
3382                 fragmentSize.height = 1;
3383             }
3384             break;
3385         case gl::ShadingRate::_4x4:
3386             if (shadingRateSupported)
3387             {
3388                 fragmentSize.width  = 4;
3389                 fragmentSize.height = 4;
3390             }
3391             else
3392             {
3393                 // Fallback to shading rate that preserves aspect ratio
3394                 fragmentSize.width  = 2;
3395                 fragmentSize.height = 2;
3396             }
3397             break;
3398         default:
3399             UNREACHABLE();
3400             return angle::Result::Stop;
3401     }
3402 
3403     VkFragmentShadingRateCombinerOpKHR shadingRateCombinerOp[2] = {
3404         VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
3405         VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR};
3406 
3407     // If foveated rendering is enabled update combiner op
3408     if (isFoveationEnabled)
3409     {
3410         shadingRateCombinerOp[1] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR;
3411     }
3412 
3413     ASSERT(hasActiveRenderPass());
3414     mRenderPassCommandBuffer->setFragmentShadingRate(&fragmentSize, shadingRateCombinerOp);
3415 
3416     return angle::Result::Continue;
3417 }
3418 
handleDirtyGraphicsDynamicScissorImpl(bool isPrimitivesGeneratedQueryActive)3419 void ContextVk::handleDirtyGraphicsDynamicScissorImpl(bool isPrimitivesGeneratedQueryActive)
3420 {
3421     // If primitives generated query and rasterizer discard are both active, but the Vulkan
3422     // implementation of the query does not support rasterizer discard, use an empty scissor to
3423     // emulate it.
3424     if (isEmulatingRasterizerDiscardDuringPrimitivesGeneratedQuery(
3425             isPrimitivesGeneratedQueryActive))
3426     {
3427         VkRect2D emptyScissor = {};
3428         mRenderPassCommandBuffer->setScissor(0, 1, &emptyScissor);
3429     }
3430     else
3431     {
3432         mRenderPassCommandBuffer->setScissor(0, 1, &mScissor);
3433     }
3434 }
3435 
handleDirtyComputeDescriptorSets(DirtyBits::Iterator * dirtyBitsIterator)3436 angle::Result ContextVk::handleDirtyComputeDescriptorSets(DirtyBits::Iterator *dirtyBitsIterator)
3437 {
3438     return handleDirtyDescriptorSetsImpl(mOutsideRenderPassCommands, PipelineType::Compute);
3439 }
3440 
3441 template <typename CommandBufferHelperT>
handleDirtyDescriptorSetsImpl(CommandBufferHelperT * commandBufferHelper,PipelineType pipelineType)3442 angle::Result ContextVk::handleDirtyDescriptorSetsImpl(CommandBufferHelperT *commandBufferHelper,
3443                                                        PipelineType pipelineType)
3444 {
3445     // When using Vulkan secondary command buffers, the descriptor sets need to be updated before
3446     // they are bound.
3447     if (!CommandBufferHelperT::ExecutesInline())
3448     {
3449         flushDescriptorSetUpdates();
3450     }
3451 
3452     ProgramExecutableVk *executableVk = vk::GetImpl(mState.getProgramExecutable());
3453     return executableVk->bindDescriptorSets(this, getCurrentFrameCount(), commandBufferHelper,
3454                                             &commandBufferHelper->getCommandBuffer(), pipelineType);
3455 }
3456 
syncObjectPerfCounters(const angle::VulkanPerfCounters & commandQueuePerfCounters)3457 void ContextVk::syncObjectPerfCounters(const angle::VulkanPerfCounters &commandQueuePerfCounters)
3458 {
3459     if (!mState.isPerfMonitorActive())
3460     {
3461         return;
3462     }
3463 
3464     mPerfCounters.descriptorSetCacheTotalSize                = 0;
3465     mPerfCounters.descriptorSetCacheKeySizeBytes             = 0;
3466     mPerfCounters.uniformsAndXfbDescriptorSetCacheHits       = 0;
3467     mPerfCounters.uniformsAndXfbDescriptorSetCacheMisses     = 0;
3468     mPerfCounters.uniformsAndXfbDescriptorSetCacheTotalSize  = 0;
3469     mPerfCounters.textureDescriptorSetCacheHits              = 0;
3470     mPerfCounters.textureDescriptorSetCacheMisses            = 0;
3471     mPerfCounters.textureDescriptorSetCacheTotalSize         = 0;
3472     mPerfCounters.shaderResourcesDescriptorSetCacheHits      = 0;
3473     mPerfCounters.shaderResourcesDescriptorSetCacheMisses    = 0;
3474     mPerfCounters.shaderResourcesDescriptorSetCacheTotalSize = 0;
3475     mPerfCounters.dynamicBufferAllocations                   = 0;
3476 
3477     // Share group descriptor set allocations and caching stats.
3478     memset(mVulkanCacheStats.data(), 0, sizeof(CacheStats) * mVulkanCacheStats.size());
3479     if (getFeatures().descriptorSetCache.enabled)
3480     {
3481         mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::UniformsAndXfb]
3482             .accumulateDescriptorCacheStats(VulkanCacheType::UniformsAndXfbDescriptors, this);
3483         mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::Texture]
3484             .accumulateDescriptorCacheStats(VulkanCacheType::TextureDescriptors, this);
3485         mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::ShaderResource]
3486             .accumulateDescriptorCacheStats(VulkanCacheType::ShaderResourcesDescriptors, this);
3487 
3488         const CacheStats &uniCacheStats =
3489             mVulkanCacheStats[VulkanCacheType::UniformsAndXfbDescriptors];
3490         mPerfCounters.uniformsAndXfbDescriptorSetCacheHits      = uniCacheStats.getHitCount();
3491         mPerfCounters.uniformsAndXfbDescriptorSetCacheMisses    = uniCacheStats.getMissCount();
3492         mPerfCounters.uniformsAndXfbDescriptorSetCacheTotalSize = uniCacheStats.getSize();
3493 
3494         const CacheStats &texCacheStats = mVulkanCacheStats[VulkanCacheType::TextureDescriptors];
3495         mPerfCounters.textureDescriptorSetCacheHits      = texCacheStats.getHitCount();
3496         mPerfCounters.textureDescriptorSetCacheMisses    = texCacheStats.getMissCount();
3497         mPerfCounters.textureDescriptorSetCacheTotalSize = texCacheStats.getSize();
3498 
3499         const CacheStats &resCacheStats =
3500             mVulkanCacheStats[VulkanCacheType::ShaderResourcesDescriptors];
3501         mPerfCounters.shaderResourcesDescriptorSetCacheHits      = resCacheStats.getHitCount();
3502         mPerfCounters.shaderResourcesDescriptorSetCacheMisses    = resCacheStats.getMissCount();
3503         mPerfCounters.shaderResourcesDescriptorSetCacheTotalSize = resCacheStats.getSize();
3504 
3505         mPerfCounters.descriptorSetCacheTotalSize =
3506             uniCacheStats.getSize() + texCacheStats.getSize() + resCacheStats.getSize() +
3507             mVulkanCacheStats[VulkanCacheType::DriverUniformsDescriptors].getSize();
3508 
3509         mPerfCounters.descriptorSetCacheKeySizeBytes = 0;
3510 
3511         for (DescriptorSetIndex descriptorSetIndex : angle::AllEnums<DescriptorSetIndex>())
3512         {
3513             vk::MetaDescriptorPool &descriptorPool =
3514                 mShareGroupVk->getMetaDescriptorPools()[descriptorSetIndex];
3515             mPerfCounters.descriptorSetCacheKeySizeBytes +=
3516                 descriptorPool.getTotalCacheKeySizeBytes();
3517         }
3518     }
3519 
3520     // Update perf counters from the renderer as well
3521     mPerfCounters.commandQueueSubmitCallsTotal =
3522         commandQueuePerfCounters.commandQueueSubmitCallsTotal;
3523     mPerfCounters.commandQueueSubmitCallsPerFrame =
3524         commandQueuePerfCounters.commandQueueSubmitCallsPerFrame;
3525     mPerfCounters.vkQueueSubmitCallsTotal    = commandQueuePerfCounters.vkQueueSubmitCallsTotal;
3526     mPerfCounters.vkQueueSubmitCallsPerFrame = commandQueuePerfCounters.vkQueueSubmitCallsPerFrame;
3527     mPerfCounters.commandQueueWaitSemaphoresTotal =
3528         commandQueuePerfCounters.commandQueueWaitSemaphoresTotal;
3529 
3530     // Return current drawFramebuffer's cache stats
3531     mPerfCounters.framebufferCacheSize = mShareGroupVk->getFramebufferCache().getSize();
3532 
3533     mPerfCounters.pendingSubmissionGarbageObjects =
3534         static_cast<uint64_t>(mRenderer->getPendingSubmissionGarbageSize());
3535 }
3536 
updateOverlayOnPresent()3537 void ContextVk::updateOverlayOnPresent()
3538 {
3539     const gl::OverlayType *overlay = mState.getOverlay();
3540     ASSERT(overlay->isEnabled());
3541 
3542     angle::VulkanPerfCounters commandQueuePerfCounters = mRenderer->getCommandQueuePerfCounters();
3543     syncObjectPerfCounters(commandQueuePerfCounters);
3544 
3545     // Update overlay if active.
3546     {
3547         gl::RunningGraphWidget *renderPassCount =
3548             overlay->getRunningGraphWidget(gl::WidgetId::VulkanRenderPassCount);
3549         renderPassCount->add(mRenderPassCommands->getAndResetCounter());
3550         renderPassCount->next();
3551     }
3552 
3553     {
3554         gl::RunningGraphWidget *writeDescriptorSetCount =
3555             overlay->getRunningGraphWidget(gl::WidgetId::VulkanWriteDescriptorSetCount);
3556         writeDescriptorSetCount->add(mPerfCounters.writeDescriptorSets);
3557         writeDescriptorSetCount->next();
3558     }
3559 
3560     {
3561         gl::RunningGraphWidget *descriptorSetAllocationCount =
3562             overlay->getRunningGraphWidget(gl::WidgetId::VulkanDescriptorSetAllocations);
3563         descriptorSetAllocationCount->add(mPerfCounters.descriptorSetAllocations);
3564         descriptorSetAllocationCount->next();
3565     }
3566 
3567     {
3568         gl::RunningGraphWidget *shaderResourceHitRate =
3569             overlay->getRunningGraphWidget(gl::WidgetId::VulkanShaderResourceDSHitRate);
3570         uint64_t numCacheAccesses = mPerfCounters.shaderResourcesDescriptorSetCacheHits +
3571                                     mPerfCounters.shaderResourcesDescriptorSetCacheMisses;
3572         if (numCacheAccesses > 0)
3573         {
3574             float hitRateFloat =
3575                 static_cast<float>(mPerfCounters.shaderResourcesDescriptorSetCacheHits) /
3576                 static_cast<float>(numCacheAccesses);
3577             size_t hitRate = static_cast<size_t>(hitRateFloat * 100.0f);
3578             shaderResourceHitRate->add(hitRate);
3579             shaderResourceHitRate->next();
3580         }
3581     }
3582 
3583     {
3584         gl::RunningGraphWidget *dynamicBufferAllocations =
3585             overlay->getRunningGraphWidget(gl::WidgetId::VulkanDynamicBufferAllocations);
3586         dynamicBufferAllocations->next();
3587     }
3588 
3589     {
3590         gl::CountWidget *cacheKeySize =
3591             overlay->getCountWidget(gl::WidgetId::VulkanDescriptorCacheKeySize);
3592         cacheKeySize->reset();
3593         cacheKeySize->add(mPerfCounters.descriptorSetCacheKeySizeBytes);
3594     }
3595 
3596     {
3597         gl::RunningGraphWidget *dynamicBufferAllocations =
3598             overlay->getRunningGraphWidget(gl::WidgetId::VulkanDynamicBufferAllocations);
3599         dynamicBufferAllocations->add(mPerfCounters.dynamicBufferAllocations);
3600     }
3601 
3602     {
3603         gl::RunningGraphWidget *attemptedSubmissionsWidget =
3604             overlay->getRunningGraphWidget(gl::WidgetId::VulkanAttemptedSubmissions);
3605         attemptedSubmissionsWidget->add(commandQueuePerfCounters.commandQueueSubmitCallsPerFrame);
3606         attemptedSubmissionsWidget->next();
3607 
3608         gl::RunningGraphWidget *actualSubmissionsWidget =
3609             overlay->getRunningGraphWidget(gl::WidgetId::VulkanActualSubmissions);
3610         actualSubmissionsWidget->add(commandQueuePerfCounters.vkQueueSubmitCallsPerFrame);
3611         actualSubmissionsWidget->next();
3612     }
3613 
3614     {
3615         gl::RunningGraphWidget *cacheLookupsWidget =
3616             overlay->getRunningGraphWidget(gl::WidgetId::VulkanPipelineCacheLookups);
3617         cacheLookupsWidget->add(mPerfCounters.pipelineCreationCacheHits +
3618                                 mPerfCounters.pipelineCreationCacheMisses);
3619         cacheLookupsWidget->next();
3620 
3621         gl::RunningGraphWidget *cacheMissesWidget =
3622             overlay->getRunningGraphWidget(gl::WidgetId::VulkanPipelineCacheMisses);
3623         cacheMissesWidget->add(mPerfCounters.pipelineCreationCacheMisses);
3624         cacheMissesWidget->next();
3625 
3626         overlay->getCountWidget(gl::WidgetId::VulkanTotalPipelineCacheHitTimeMs)
3627             ->set(mPerfCounters.pipelineCreationTotalCacheHitsDurationNs / 1000'000);
3628         overlay->getCountWidget(gl::WidgetId::VulkanTotalPipelineCacheMissTimeMs)
3629             ->set(mPerfCounters.pipelineCreationTotalCacheMissesDurationNs / 1000'000);
3630     }
3631 }
3632 
addOverlayUsedBuffersCount(vk::CommandBufferHelperCommon * commandBuffer)3633 void ContextVk::addOverlayUsedBuffersCount(vk::CommandBufferHelperCommon *commandBuffer)
3634 {
3635     const gl::OverlayType *overlay = mState.getOverlay();
3636     if (!overlay->isEnabled())
3637     {
3638         return;
3639     }
3640 
3641     {
3642         gl::RunningGraphWidget *textureDescriptorCacheSize =
3643             overlay->getRunningGraphWidget(gl::WidgetId::VulkanTextureDescriptorCacheSize);
3644         textureDescriptorCacheSize->add(mPerfCounters.textureDescriptorSetCacheTotalSize);
3645         textureDescriptorCacheSize->next();
3646     }
3647 
3648     {
3649         gl::RunningGraphWidget *uniformDescriptorCacheSize =
3650             overlay->getRunningGraphWidget(gl::WidgetId::VulkanUniformDescriptorCacheSize);
3651         uniformDescriptorCacheSize->add(mPerfCounters.uniformsAndXfbDescriptorSetCacheTotalSize);
3652         uniformDescriptorCacheSize->next();
3653     }
3654 
3655     {
3656         gl::RunningGraphWidget *descriptorCacheSize =
3657             overlay->getRunningGraphWidget(gl::WidgetId::VulkanDescriptorCacheSize);
3658         descriptorCacheSize->add(mPerfCounters.descriptorSetCacheTotalSize);
3659         descriptorCacheSize->next();
3660     }
3661 }
3662 
submitCommands(const vk::Semaphore * signalSemaphore,const vk::SharedExternalFence * externalFence,Submit submission)3663 angle::Result ContextVk::submitCommands(const vk::Semaphore *signalSemaphore,
3664                                         const vk::SharedExternalFence *externalFence,
3665                                         Submit submission)
3666 {
3667     if (kEnableCommandStreamDiagnostics)
3668     {
3669         dumpCommandStreamDiagnostics();
3670     }
3671 
3672     if (!mCurrentGarbage.empty() && submission == Submit::AllCommands)
3673     {
3674         // Clean up garbage.
3675         vk::ResourceUse use(mLastFlushedQueueSerial);
3676         size_t capacity = mCurrentGarbage.capacity();
3677         mRenderer->collectGarbage(use, std::move(mCurrentGarbage));
3678         // Make sure we don't lose capacity after the move to avoid storage reallocation.
3679         mCurrentGarbage.reserve(capacity);
3680     }
3681 
3682     ASSERT(mLastFlushedQueueSerial.valid());
3683     ASSERT(QueueSerialsHaveDifferentIndexOrSmaller(mLastSubmittedQueueSerial,
3684                                                    mLastFlushedQueueSerial));
3685 
3686     finalizeAllForeignImages();
3687     ANGLE_TRY(mRenderer->submitCommands(
3688         this, getProtectionType(), mContextPriority, signalSemaphore, externalFence,
3689         std::move(mImagesToTransitionToForeign), mLastFlushedQueueSerial));
3690 
3691     mLastSubmittedQueueSerial = mLastFlushedQueueSerial;
3692     mSubmittedResourceUse.setQueueSerial(mLastSubmittedQueueSerial);
3693 
3694     // Now that we have submitted commands, some of pending garbage may no longer pending
3695     // and should be moved to garbage list.
3696     mRenderer->cleanupPendingSubmissionGarbage();
3697     // In case of big amount of render/submission within one frame, if we accumulate excessive
3698     // amount of garbage, also trigger the cleanup.
3699     mShareGroupVk->cleanupExcessiveRefCountedEventGarbage();
3700 
3701     mComputeDirtyBits |= mNewComputeCommandBufferDirtyBits;
3702 
3703     if (mGpuEventsEnabled)
3704     {
3705         ANGLE_TRY(checkCompletedGpuEvents());
3706     }
3707 
3708     mTotalBufferToImageCopySize       = 0;
3709     mEstimatedPendingImageGarbageSize = 0;
3710 
3711     // If we have destroyed a lot of memory, also prune to ensure memory gets freed as soon as
3712     // possible. For example we may end here when game launches and uploads a lot of textures before
3713     // draw the first frame.
3714     if (mRenderer->getSuballocationDestroyedSize() >= kMaxTotalEmptyBufferBytes)
3715     {
3716         mShareGroupVk->pruneDefaultBufferPools();
3717     }
3718 
3719     return angle::Result::Continue;
3720 }
3721 
onCopyUpdate(VkDeviceSize size,bool * commandBufferWasFlushedOut)3722 angle::Result ContextVk::onCopyUpdate(VkDeviceSize size, bool *commandBufferWasFlushedOut)
3723 {
3724     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::onCopyUpdate");
3725     *commandBufferWasFlushedOut = false;
3726 
3727     mTotalBufferToImageCopySize += size;
3728     // If the copy size exceeds the specified threshold, submit the outside command buffer.
3729     if (mTotalBufferToImageCopySize >= kMaxBufferToImageCopySize)
3730     {
3731         ANGLE_TRY(flushAndSubmitOutsideRenderPassCommands());
3732         *commandBufferWasFlushedOut = true;
3733     }
3734     return angle::Result::Continue;
3735 }
3736 
addToPendingImageGarbage(vk::ResourceUse use,VkDeviceSize size)3737 void ContextVk::addToPendingImageGarbage(vk::ResourceUse use, VkDeviceSize size)
3738 {
3739     if (!mRenderer->hasResourceUseFinished(use))
3740     {
3741         mEstimatedPendingImageGarbageSize += size;
3742     }
3743 }
3744 
hasExcessPendingGarbage() const3745 bool ContextVk::hasExcessPendingGarbage() const
3746 {
3747     VkDeviceSize trackedPendingGarbage =
3748         mRenderer->getPendingSuballocationGarbageSize() + mEstimatedPendingImageGarbageSize;
3749     return trackedPendingGarbage >= mRenderer->getPendingGarbageSizeLimit();
3750 }
3751 
synchronizeCpuGpuTime()3752 angle::Result ContextVk::synchronizeCpuGpuTime()
3753 {
3754     ASSERT(mGpuEventsEnabled);
3755 
3756     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
3757     ASSERT(platform);
3758 
3759     // To synchronize CPU and GPU times, we need to get the CPU timestamp as close as possible
3760     // to the GPU timestamp.  The process of getting the GPU timestamp is as follows:
3761     //
3762     //             CPU                            GPU
3763     //
3764     //     Record command buffer
3765     //     with timestamp query
3766     //
3767     //     Submit command buffer
3768     //
3769     //     Post-submission work             Begin execution
3770     //
3771     //            ????                    Write timestamp Tgpu
3772     //
3773     //            ????                       End execution
3774     //
3775     //            ????                    Return query results
3776     //
3777     //            ????
3778     //
3779     //       Get query results
3780     //
3781     // The areas of unknown work (????) on the CPU indicate that the CPU may or may not have
3782     // finished post-submission work while the GPU is executing in parallel. With no further
3783     // work, querying CPU timestamps before submission and after getting query results give the
3784     // bounds to Tgpu, which could be quite large.
3785     //
3786     // Using VkEvents, the GPU can be made to wait for the CPU and vice versa, in an effort to
3787     // reduce this range. This function implements the following procedure:
3788     //
3789     //             CPU                            GPU
3790     //
3791     //     Record command buffer
3792     //     with timestamp query
3793     //
3794     //     Submit command buffer
3795     //
3796     //     Post-submission work             Begin execution
3797     //
3798     //            ????                    Set Event GPUReady
3799     //
3800     //    Wait on Event GPUReady         Wait on Event CPUReady
3801     //
3802     //       Get CPU Time Ts             Wait on Event CPUReady
3803     //
3804     //      Set Event CPUReady           Wait on Event CPUReady
3805     //
3806     //      Get CPU Time Tcpu              Get GPU Time Tgpu
3807     //
3808     //    Wait on Event GPUDone            Set Event GPUDone
3809     //
3810     //       Get CPU Time Te                 End Execution
3811     //
3812     //            Idle                    Return query results
3813     //
3814     //      Get query results
3815     //
3816     // If Te-Ts > epsilon, a GPU or CPU interruption can be assumed and the operation can be
3817     // retried.  Once Te-Ts < epsilon, Tcpu can be taken to presumably match Tgpu.  Finding an
3818     // epsilon that's valid for all devices may be difficult, so the loop can be performed only
3819     // a limited number of times and the Tcpu,Tgpu pair corresponding to smallest Te-Ts used for
3820     // calibration.
3821     //
3822     // Note: Once VK_EXT_calibrated_timestamps is ubiquitous, this should be redone.
3823 
3824     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::synchronizeCpuGpuTime");
3825 
3826     // Create a query used to receive the GPU timestamp
3827     vk::QueryHelper timestampQuery;
3828     ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, &timestampQuery, 1));
3829 
3830     // Create the three events
3831     VkEventCreateInfo eventCreateInfo = {};
3832     eventCreateInfo.sType             = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
3833     eventCreateInfo.flags             = 0;
3834 
3835     VkDevice device = getDevice();
3836     vk::DeviceScoped<vk::Event> cpuReady(device), gpuReady(device), gpuDone(device);
3837     ANGLE_VK_TRY(this, cpuReady.get().init(device, eventCreateInfo));
3838     ANGLE_VK_TRY(this, gpuReady.get().init(device, eventCreateInfo));
3839     ANGLE_VK_TRY(this, gpuDone.get().init(device, eventCreateInfo));
3840 
3841     constexpr uint32_t kRetries = 10;
3842 
3843     // Time suffixes used are S for seconds and Cycles for cycles
3844     double tightestRangeS = 1e6f;
3845     double TcpuS          = 0;
3846     uint64_t TgpuCycles   = 0;
3847     for (uint32_t i = 0; i < kRetries; ++i)
3848     {
3849         // Reset the events
3850         ANGLE_VK_TRY(this, cpuReady.get().reset(device));
3851         ANGLE_VK_TRY(this, gpuReady.get().reset(device));
3852         ANGLE_VK_TRY(this, gpuDone.get().reset(device));
3853 
3854         // Record the command buffer
3855         vk::ScopedPrimaryCommandBuffer scopedCommandBuffer(device);
3856 
3857         ANGLE_TRY(
3858             mRenderer->getCommandBufferOneOff(this, getProtectionType(), &scopedCommandBuffer));
3859         vk::PrimaryCommandBuffer &commandBuffer = scopedCommandBuffer.get();
3860 
3861         commandBuffer.setEvent(gpuReady.get().getHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
3862         commandBuffer.waitEvents(1, cpuReady.get().ptr(), VK_PIPELINE_STAGE_HOST_BIT,
3863                                  VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, nullptr, 0, nullptr, 0,
3864                                  nullptr);
3865         timestampQuery.writeTimestampToPrimary(this, &commandBuffer);
3866 
3867         commandBuffer.setEvent(gpuDone.get().getHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
3868 
3869         ANGLE_VK_TRY(this, commandBuffer.end());
3870 
3871         QueueSerial submitSerial;
3872         // vkEvent's are externally synchronized, therefore need work to be submitted before calling
3873         // vkGetEventStatus
3874         ANGLE_TRY(mRenderer->queueSubmitOneOff(this, std::move(scopedCommandBuffer),
3875                                                getProtectionType(), mContextPriority,
3876                                                VK_NULL_HANDLE, 0, &submitSerial));
3877 
3878         // Track it with the submitSerial.
3879         timestampQuery.setQueueSerial(submitSerial);
3880 
3881         // Wait for GPU to be ready.  This is a short busy wait.
3882         VkResult result = VK_EVENT_RESET;
3883         do
3884         {
3885             result = gpuReady.get().getStatus(device);
3886             if (result != VK_EVENT_SET && result != VK_EVENT_RESET)
3887             {
3888                 ANGLE_VK_TRY(this, result);
3889             }
3890         } while (result == VK_EVENT_RESET);
3891 
3892         double TsS = platform->monotonicallyIncreasingTime(platform);
3893 
3894         // Tell the GPU to go ahead with the timestamp query.
3895         ANGLE_VK_TRY(this, cpuReady.get().set(device));
3896         double cpuTimestampS = platform->monotonicallyIncreasingTime(platform);
3897 
3898         // Wait for GPU to be done.  Another short busy wait.
3899         do
3900         {
3901             result = gpuDone.get().getStatus(device);
3902             if (result != VK_EVENT_SET && result != VK_EVENT_RESET)
3903             {
3904                 ANGLE_VK_TRY(this, result);
3905             }
3906         } while (result == VK_EVENT_RESET);
3907 
3908         double TeS = platform->monotonicallyIncreasingTime(platform);
3909 
3910         // Get the query results
3911         ANGLE_TRY(mRenderer->finishQueueSerial(this, submitSerial));
3912 
3913         vk::QueryResult gpuTimestampCycles(1);
3914         ANGLE_TRY(timestampQuery.getUint64Result(this, &gpuTimestampCycles));
3915 
3916         // Use the first timestamp queried as origin.
3917         if (mGpuEventTimestampOrigin == 0)
3918         {
3919             mGpuEventTimestampOrigin =
3920                 gpuTimestampCycles.getResult(vk::QueryResult::kDefaultResultIndex);
3921         }
3922 
3923         // Take these CPU and GPU timestamps if there is better confidence.
3924         double confidenceRangeS = TeS - TsS;
3925         if (confidenceRangeS < tightestRangeS)
3926         {
3927             tightestRangeS = confidenceRangeS;
3928             TcpuS          = cpuTimestampS;
3929             TgpuCycles     = gpuTimestampCycles.getResult(vk::QueryResult::kDefaultResultIndex);
3930         }
3931     }
3932 
3933     mGpuEventQueryPool.freeQuery(this, &timestampQuery);
3934 
3935     // timestampPeriod gives nanoseconds/cycle.
3936     double TgpuS =
3937         (TgpuCycles - mGpuEventTimestampOrigin) *
3938         static_cast<double>(getRenderer()->getPhysicalDeviceProperties().limits.timestampPeriod) /
3939         1'000'000'000.0;
3940 
3941     flushGpuEvents(TgpuS, TcpuS);
3942 
3943     mGpuClockSync.gpuTimestampS = TgpuS;
3944     mGpuClockSync.cpuTimestampS = TcpuS;
3945 
3946     return angle::Result::Continue;
3947 }
3948 
traceGpuEventImpl(vk::OutsideRenderPassCommandBuffer * commandBuffer,char phase,const EventName & name)3949 angle::Result ContextVk::traceGpuEventImpl(vk::OutsideRenderPassCommandBuffer *commandBuffer,
3950                                            char phase,
3951                                            const EventName &name)
3952 {
3953     ASSERT(mGpuEventsEnabled);
3954 
3955     GpuEventQuery gpuEvent;
3956     gpuEvent.name  = name;
3957     gpuEvent.phase = phase;
3958     ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, &gpuEvent.queryHelper, 1));
3959 
3960     gpuEvent.queryHelper.writeTimestamp(this, commandBuffer);
3961 
3962     mInFlightGpuEventQueries.push_back(std::move(gpuEvent));
3963     return angle::Result::Continue;
3964 }
3965 
checkCompletedGpuEvents()3966 angle::Result ContextVk::checkCompletedGpuEvents()
3967 {
3968     ASSERT(mGpuEventsEnabled);
3969 
3970     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
3971     ASSERT(platform);
3972 
3973     int finishedCount = 0;
3974 
3975     for (GpuEventQuery &eventQuery : mInFlightGpuEventQueries)
3976     {
3977         ASSERT(mRenderer->hasResourceUseSubmitted(eventQuery.queryHelper.getResourceUse()));
3978         // Only check the timestamp query if the submission has finished.
3979         if (!mRenderer->hasResourceUseFinished(eventQuery.queryHelper.getResourceUse()))
3980         {
3981             break;
3982         }
3983 
3984         // See if the results are available.
3985         vk::QueryResult gpuTimestampCycles(1);
3986         bool available = false;
3987         ANGLE_TRY(eventQuery.queryHelper.getUint64ResultNonBlocking(this, &gpuTimestampCycles,
3988                                                                     &available));
3989         if (!available)
3990         {
3991             break;
3992         }
3993 
3994         mGpuEventQueryPool.freeQuery(this, &eventQuery.queryHelper);
3995 
3996         GpuEvent gpuEvent;
3997         gpuEvent.gpuTimestampCycles =
3998             gpuTimestampCycles.getResult(vk::QueryResult::kDefaultResultIndex);
3999         gpuEvent.name  = eventQuery.name;
4000         gpuEvent.phase = eventQuery.phase;
4001 
4002         mGpuEvents.emplace_back(gpuEvent);
4003 
4004         ++finishedCount;
4005     }
4006 
4007     mInFlightGpuEventQueries.erase(mInFlightGpuEventQueries.begin(),
4008                                    mInFlightGpuEventQueries.begin() + finishedCount);
4009 
4010     return angle::Result::Continue;
4011 }
4012 
flushGpuEvents(double nextSyncGpuTimestampS,double nextSyncCpuTimestampS)4013 void ContextVk::flushGpuEvents(double nextSyncGpuTimestampS, double nextSyncCpuTimestampS)
4014 {
4015     if (mGpuEvents.empty())
4016     {
4017         return;
4018     }
4019 
4020     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
4021     ASSERT(platform);
4022 
4023     // Find the slope of the clock drift for adjustment
4024     double lastGpuSyncTimeS  = mGpuClockSync.gpuTimestampS;
4025     double lastGpuSyncDiffS  = mGpuClockSync.cpuTimestampS - mGpuClockSync.gpuTimestampS;
4026     double gpuSyncDriftSlope = 0;
4027 
4028     double nextGpuSyncTimeS = nextSyncGpuTimestampS;
4029     double nextGpuSyncDiffS = nextSyncCpuTimestampS - nextSyncGpuTimestampS;
4030 
4031     // No gpu trace events should have been generated before the clock sync, so if there is no
4032     // "previous" clock sync, there should be no gpu events (i.e. the function early-outs
4033     // above).
4034     ASSERT(mGpuClockSync.gpuTimestampS != std::numeric_limits<double>::max() &&
4035            mGpuClockSync.cpuTimestampS != std::numeric_limits<double>::max());
4036 
4037     gpuSyncDriftSlope =
4038         (nextGpuSyncDiffS - lastGpuSyncDiffS) / (nextGpuSyncTimeS - lastGpuSyncTimeS);
4039 
4040     for (const GpuEvent &gpuEvent : mGpuEvents)
4041     {
4042         double gpuTimestampS =
4043             (gpuEvent.gpuTimestampCycles - mGpuEventTimestampOrigin) *
4044             static_cast<double>(
4045                 getRenderer()->getPhysicalDeviceProperties().limits.timestampPeriod) *
4046             1e-9;
4047 
4048         // Account for clock drift.
4049         gpuTimestampS += lastGpuSyncDiffS + gpuSyncDriftSlope * (gpuTimestampS - lastGpuSyncTimeS);
4050 
4051         // Generate the trace now that the GPU timestamp is available and clock drifts are
4052         // accounted for.
4053         static long long eventId = 1;
4054         static const unsigned char *categoryEnabled =
4055             TRACE_EVENT_API_GET_CATEGORY_ENABLED(platform, "gpu.angle.gpu");
4056         platform->addTraceEvent(platform, gpuEvent.phase, categoryEnabled, gpuEvent.name.data(),
4057                                 eventId++, gpuTimestampS, 0, nullptr, nullptr, nullptr,
4058                                 TRACE_EVENT_FLAG_NONE);
4059     }
4060 
4061     mGpuEvents.clear();
4062 }
4063 
clearAllGarbage()4064 void ContextVk::clearAllGarbage()
4065 {
4066     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::clearAllGarbage");
4067 
4068     // The VMA virtual allocator code has assertion to ensure all sub-ranges are freed before
4069     // virtual block gets freed. We need to ensure all completed garbage objects are actually freed
4070     // to avoid hitting that assertion.
4071     mRenderer->cleanupGarbage(nullptr);
4072 
4073     for (vk::GarbageObject &garbage : mCurrentGarbage)
4074     {
4075         garbage.destroy(mRenderer);
4076     }
4077     mCurrentGarbage.clear();
4078 }
4079 
handleDeviceLost()4080 void ContextVk::handleDeviceLost()
4081 {
4082     vk::SecondaryCommandBufferCollector collector;
4083     (void)mOutsideRenderPassCommands->reset(this, &collector);
4084     (void)mRenderPassCommands->reset(this, &collector);
4085     collector.releaseCommandBuffers();
4086 
4087     mRenderer->notifyDeviceLost();
4088 }
4089 
drawArrays(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count)4090 angle::Result ContextVk::drawArrays(const gl::Context *context,
4091                                     gl::PrimitiveMode mode,
4092                                     GLint first,
4093                                     GLsizei count)
4094 {
4095     uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
4096 
4097     if (mode == gl::PrimitiveMode::LineLoop)
4098     {
4099         uint32_t numIndices;
4100         ANGLE_TRY(setupLineLoopDraw(context, mode, first, count, gl::DrawElementsType::InvalidEnum,
4101                                     nullptr, &numIndices));
4102         LineLoopHelper::Draw(numIndices, 0, mRenderPassCommandBuffer);
4103     }
4104     else
4105     {
4106         ANGLE_TRY(setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum,
4107                             nullptr, mNonIndexedDirtyBitsMask));
4108         mRenderPassCommandBuffer->draw(clampedVertexCount, first);
4109     }
4110 
4111     return angle::Result::Continue;
4112 }
4113 
drawArraysInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instances)4114 angle::Result ContextVk::drawArraysInstanced(const gl::Context *context,
4115                                              gl::PrimitiveMode mode,
4116                                              GLint first,
4117                                              GLsizei count,
4118                                              GLsizei instances)
4119 {
4120     if (mode == gl::PrimitiveMode::LineLoop)
4121     {
4122         uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
4123         uint32_t numIndices;
4124         ANGLE_TRY(setupLineLoopDraw(context, mode, first, clampedVertexCount,
4125                                     gl::DrawElementsType::InvalidEnum, nullptr, &numIndices));
4126         mRenderPassCommandBuffer->drawIndexedInstanced(numIndices, instances);
4127         return angle::Result::Continue;
4128     }
4129 
4130     ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
4131                         nullptr, mNonIndexedDirtyBitsMask));
4132     mRenderPassCommandBuffer->drawInstanced(gl::GetClampedVertexCount<uint32_t>(count), instances,
4133                                             first);
4134     return angle::Result::Continue;
4135 }
4136 
drawArraysInstancedBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instances,GLuint baseInstance)4137 angle::Result ContextVk::drawArraysInstancedBaseInstance(const gl::Context *context,
4138                                                          gl::PrimitiveMode mode,
4139                                                          GLint first,
4140                                                          GLsizei count,
4141                                                          GLsizei instances,
4142                                                          GLuint baseInstance)
4143 {
4144     if (mode == gl::PrimitiveMode::LineLoop)
4145     {
4146         uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
4147         uint32_t numIndices;
4148         ANGLE_TRY(setupLineLoopDraw(context, mode, first, clampedVertexCount,
4149                                     gl::DrawElementsType::InvalidEnum, nullptr, &numIndices));
4150         mRenderPassCommandBuffer->drawIndexedInstancedBaseVertexBaseInstance(numIndices, instances,
4151                                                                              0, 0, baseInstance);
4152         return angle::Result::Continue;
4153     }
4154 
4155     ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
4156                         nullptr, mNonIndexedDirtyBitsMask));
4157     mRenderPassCommandBuffer->drawInstancedBaseInstance(gl::GetClampedVertexCount<uint32_t>(count),
4158                                                         instances, first, baseInstance);
4159     return angle::Result::Continue;
4160 }
4161 
drawElements(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices)4162 angle::Result ContextVk::drawElements(const gl::Context *context,
4163                                       gl::PrimitiveMode mode,
4164                                       GLsizei count,
4165                                       gl::DrawElementsType type,
4166                                       const void *indices)
4167 {
4168     if (mode == gl::PrimitiveMode::LineLoop)
4169     {
4170         uint32_t indexCount;
4171         ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
4172         LineLoopHelper::Draw(indexCount, 0, mRenderPassCommandBuffer);
4173     }
4174     else
4175     {
4176         ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices));
4177         mRenderPassCommandBuffer->drawIndexed(count);
4178     }
4179 
4180     return angle::Result::Continue;
4181 }
4182 
drawElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)4183 angle::Result ContextVk::drawElementsBaseVertex(const gl::Context *context,
4184                                                 gl::PrimitiveMode mode,
4185                                                 GLsizei count,
4186                                                 gl::DrawElementsType type,
4187                                                 const void *indices,
4188                                                 GLint baseVertex)
4189 {
4190     if (mode == gl::PrimitiveMode::LineLoop)
4191     {
4192         uint32_t indexCount;
4193         ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
4194         LineLoopHelper::Draw(indexCount, baseVertex, mRenderPassCommandBuffer);
4195     }
4196     else
4197     {
4198         ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices));
4199         mRenderPassCommandBuffer->drawIndexedBaseVertex(count, baseVertex);
4200     }
4201 
4202     return angle::Result::Continue;
4203 }
4204 
drawElementsInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances)4205 angle::Result ContextVk::drawElementsInstanced(const gl::Context *context,
4206                                                gl::PrimitiveMode mode,
4207                                                GLsizei count,
4208                                                gl::DrawElementsType type,
4209                                                const void *indices,
4210                                                GLsizei instances)
4211 {
4212     if (mode == gl::PrimitiveMode::LineLoop)
4213     {
4214         uint32_t indexCount;
4215         ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
4216         count = indexCount;
4217     }
4218     else
4219     {
4220         ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices));
4221     }
4222 
4223     mRenderPassCommandBuffer->drawIndexedInstanced(count, instances);
4224     return angle::Result::Continue;
4225 }
4226 
drawElementsInstancedBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex)4227 angle::Result ContextVk::drawElementsInstancedBaseVertex(const gl::Context *context,
4228                                                          gl::PrimitiveMode mode,
4229                                                          GLsizei count,
4230                                                          gl::DrawElementsType type,
4231                                                          const void *indices,
4232                                                          GLsizei instances,
4233                                                          GLint baseVertex)
4234 {
4235     if (mode == gl::PrimitiveMode::LineLoop)
4236     {
4237         uint32_t indexCount;
4238         ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
4239         count = indexCount;
4240     }
4241     else
4242     {
4243         ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices));
4244     }
4245 
4246     mRenderPassCommandBuffer->drawIndexedInstancedBaseVertex(count, instances, baseVertex);
4247     return angle::Result::Continue;
4248 }
4249 
drawElementsInstancedBaseVertexBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex,GLuint baseInstance)4250 angle::Result ContextVk::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
4251                                                                      gl::PrimitiveMode mode,
4252                                                                      GLsizei count,
4253                                                                      gl::DrawElementsType type,
4254                                                                      const void *indices,
4255                                                                      GLsizei instances,
4256                                                                      GLint baseVertex,
4257                                                                      GLuint baseInstance)
4258 {
4259     if (mode == gl::PrimitiveMode::LineLoop)
4260     {
4261         uint32_t indexCount;
4262         ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
4263         count = indexCount;
4264     }
4265     else
4266     {
4267         ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices));
4268     }
4269 
4270     mRenderPassCommandBuffer->drawIndexedInstancedBaseVertexBaseInstance(count, instances, 0,
4271                                                                          baseVertex, baseInstance);
4272     return angle::Result::Continue;
4273 }
4274 
drawRangeElements(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices)4275 angle::Result ContextVk::drawRangeElements(const gl::Context *context,
4276                                            gl::PrimitiveMode mode,
4277                                            GLuint start,
4278                                            GLuint end,
4279                                            GLsizei count,
4280                                            gl::DrawElementsType type,
4281                                            const void *indices)
4282 {
4283     return drawElements(context, mode, count, type, indices);
4284 }
4285 
drawRangeElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)4286 angle::Result ContextVk::drawRangeElementsBaseVertex(const gl::Context *context,
4287                                                      gl::PrimitiveMode mode,
4288                                                      GLuint start,
4289                                                      GLuint end,
4290                                                      GLsizei count,
4291                                                      gl::DrawElementsType type,
4292                                                      const void *indices,
4293                                                      GLint baseVertex)
4294 {
4295     return drawElementsBaseVertex(context, mode, count, type, indices, baseVertex);
4296 }
4297 
getDevice() const4298 VkDevice ContextVk::getDevice() const
4299 {
4300     return mRenderer->getDevice();
4301 }
4302 
drawArraysIndirect(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect)4303 angle::Result ContextVk::drawArraysIndirect(const gl::Context *context,
4304                                             gl::PrimitiveMode mode,
4305                                             const void *indirect)
4306 {
4307     return multiDrawArraysIndirectHelper(context, mode, indirect, 1, 0);
4308 }
4309 
drawElementsIndirect(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect)4310 angle::Result ContextVk::drawElementsIndirect(const gl::Context *context,
4311                                               gl::PrimitiveMode mode,
4312                                               gl::DrawElementsType type,
4313                                               const void *indirect)
4314 {
4315     return multiDrawElementsIndirectHelper(context, mode, type, indirect, 1, 0);
4316 }
4317 
multiDrawArrays(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,GLsizei drawcount)4318 angle::Result ContextVk::multiDrawArrays(const gl::Context *context,
4319                                          gl::PrimitiveMode mode,
4320                                          const GLint *firsts,
4321                                          const GLsizei *counts,
4322                                          GLsizei drawcount)
4323 {
4324     return rx::MultiDrawArraysGeneral(this, context, mode, firsts, counts, drawcount);
4325 }
4326 
multiDrawArraysInstanced(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,GLsizei drawcount)4327 angle::Result ContextVk::multiDrawArraysInstanced(const gl::Context *context,
4328                                                   gl::PrimitiveMode mode,
4329                                                   const GLint *firsts,
4330                                                   const GLsizei *counts,
4331                                                   const GLsizei *instanceCounts,
4332                                                   GLsizei drawcount)
4333 {
4334     return rx::MultiDrawArraysInstancedGeneral(this, context, mode, firsts, counts, instanceCounts,
4335                                                drawcount);
4336 }
4337 
multiDrawArraysIndirect(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect,GLsizei drawcount,GLsizei stride)4338 angle::Result ContextVk::multiDrawArraysIndirect(const gl::Context *context,
4339                                                  gl::PrimitiveMode mode,
4340                                                  const void *indirect,
4341                                                  GLsizei drawcount,
4342                                                  GLsizei stride)
4343 {
4344     return multiDrawArraysIndirectHelper(context, mode, indirect, drawcount, stride);
4345 }
4346 
multiDrawArraysIndirectHelper(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect,GLsizei drawcount,GLsizei stride)4347 angle::Result ContextVk::multiDrawArraysIndirectHelper(const gl::Context *context,
4348                                                        gl::PrimitiveMode mode,
4349                                                        const void *indirect,
4350                                                        GLsizei drawcount,
4351                                                        GLsizei stride)
4352 {
4353     VertexArrayVk *vertexArrayVk = getVertexArray();
4354     if (drawcount > 1 && !CanMultiDrawIndirectUseCmd(this, vertexArrayVk, mode, drawcount, stride))
4355     {
4356         return rx::MultiDrawArraysIndirectGeneral(this, context, mode, indirect, drawcount, stride);
4357     }
4358 
4359     // Stride must be a multiple of the size of VkDrawIndirectCommand (stride = 0 is invalid when
4360     // drawcount > 1).
4361     uint32_t vkStride = (stride == 0 && drawcount > 1) ? sizeof(VkDrawIndirectCommand) : stride;
4362 
4363     gl::Buffer *indirectBuffer            = mState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
4364     vk::BufferHelper *currentIndirectBuf  = &vk::GetImpl(indirectBuffer)->getBuffer();
4365     VkDeviceSize currentIndirectBufOffset = reinterpret_cast<VkDeviceSize>(indirect);
4366 
4367     if (vertexArrayVk->getStreamingVertexAttribsMask().any())
4368     {
4369         // Handling instanced vertex attributes is not covered for drawcount > 1.
4370         ASSERT(drawcount <= 1);
4371 
4372         // We have instanced vertex attributes that need to be emulated for Vulkan.
4373         // invalidate any cache and map the buffer so that we can read the indirect data.
4374         // Mapping the buffer will cause a flush.
4375         ANGLE_TRY(currentIndirectBuf->invalidate(mRenderer, 0, sizeof(VkDrawIndirectCommand)));
4376         uint8_t *buffPtr;
4377         ANGLE_TRY(currentIndirectBuf->map(this, &buffPtr));
4378         const VkDrawIndirectCommand *indirectData =
4379             reinterpret_cast<VkDrawIndirectCommand *>(buffPtr + currentIndirectBufOffset);
4380 
4381         ANGLE_TRY(drawArraysInstanced(context, mode, indirectData->firstVertex,
4382                                       indirectData->vertexCount, indirectData->instanceCount));
4383 
4384         currentIndirectBuf->unmap(mRenderer);
4385         return angle::Result::Continue;
4386     }
4387 
4388     if (mode == gl::PrimitiveMode::LineLoop)
4389     {
4390         // Line loop only supports handling at most one indirect parameter.
4391         ASSERT(drawcount <= 1);
4392 
4393         ASSERT(indirectBuffer);
4394         vk::BufferHelper *dstIndirectBuf = nullptr;
4395 
4396         ANGLE_TRY(setupLineLoopIndirectDraw(context, mode, currentIndirectBuf,
4397                                             currentIndirectBufOffset, &dstIndirectBuf));
4398 
4399         mRenderPassCommandBuffer->drawIndexedIndirect(
4400             dstIndirectBuf->getBuffer(), dstIndirectBuf->getOffset(), drawcount, vkStride);
4401         return angle::Result::Continue;
4402     }
4403 
4404     ANGLE_TRY(setupIndirectDraw(context, mode, mNonIndexedDirtyBitsMask, currentIndirectBuf));
4405 
4406     mRenderPassCommandBuffer->drawIndirect(
4407         currentIndirectBuf->getBuffer(), currentIndirectBuf->getOffset() + currentIndirectBufOffset,
4408         drawcount, vkStride);
4409 
4410     return angle::Result::Continue;
4411 }
4412 
multiDrawElements(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,GLsizei drawcount)4413 angle::Result ContextVk::multiDrawElements(const gl::Context *context,
4414                                            gl::PrimitiveMode mode,
4415                                            const GLsizei *counts,
4416                                            gl::DrawElementsType type,
4417                                            const GLvoid *const *indices,
4418                                            GLsizei drawcount)
4419 {
4420     return rx::MultiDrawElementsGeneral(this, context, mode, counts, type, indices, drawcount);
4421 }
4422 
multiDrawElementsInstanced(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,GLsizei drawcount)4423 angle::Result ContextVk::multiDrawElementsInstanced(const gl::Context *context,
4424                                                     gl::PrimitiveMode mode,
4425                                                     const GLsizei *counts,
4426                                                     gl::DrawElementsType type,
4427                                                     const GLvoid *const *indices,
4428                                                     const GLsizei *instanceCounts,
4429                                                     GLsizei drawcount)
4430 {
4431     return rx::MultiDrawElementsInstancedGeneral(this, context, mode, counts, type, indices,
4432                                                  instanceCounts, drawcount);
4433 }
4434 
multiDrawElementsIndirect(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect,GLsizei drawcount,GLsizei stride)4435 angle::Result ContextVk::multiDrawElementsIndirect(const gl::Context *context,
4436                                                    gl::PrimitiveMode mode,
4437                                                    gl::DrawElementsType type,
4438                                                    const void *indirect,
4439                                                    GLsizei drawcount,
4440                                                    GLsizei stride)
4441 {
4442     return multiDrawElementsIndirectHelper(context, mode, type, indirect, drawcount, stride);
4443 }
4444 
multiDrawElementsIndirectHelper(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect,GLsizei drawcount,GLsizei stride)4445 angle::Result ContextVk::multiDrawElementsIndirectHelper(const gl::Context *context,
4446                                                          gl::PrimitiveMode mode,
4447                                                          gl::DrawElementsType type,
4448                                                          const void *indirect,
4449                                                          GLsizei drawcount,
4450                                                          GLsizei stride)
4451 {
4452     VertexArrayVk *vertexArrayVk = getVertexArray();
4453     if (drawcount > 1 && !CanMultiDrawIndirectUseCmd(this, vertexArrayVk, mode, drawcount, stride))
4454     {
4455         return rx::MultiDrawElementsIndirectGeneral(this, context, mode, type, indirect, drawcount,
4456                                                     stride);
4457     }
4458 
4459     // Stride must be a multiple of the size of VkDrawIndexedIndirectCommand (stride = 0 is invalid
4460     // when drawcount > 1).
4461     uint32_t vkStride =
4462         (stride == 0 && drawcount > 1) ? sizeof(VkDrawIndexedIndirectCommand) : stride;
4463 
4464     gl::Buffer *indirectBuffer = mState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
4465     ASSERT(indirectBuffer);
4466     vk::BufferHelper *currentIndirectBuf  = &vk::GetImpl(indirectBuffer)->getBuffer();
4467     VkDeviceSize currentIndirectBufOffset = reinterpret_cast<VkDeviceSize>(indirect);
4468 
4469     // Reset the index buffer offset
4470     mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
4471     mCurrentIndexBufferOffset = 0;
4472 
4473     if (vertexArrayVk->getStreamingVertexAttribsMask().any())
4474     {
4475         // Handling instanced vertex attributes is not covered for drawcount > 1.
4476         ASSERT(drawcount <= 1);
4477 
4478         // We have instanced vertex attributes that need to be emulated for Vulkan.
4479         // invalidate any cache and map the buffer so that we can read the indirect data.
4480         // Mapping the buffer will cause a flush.
4481         ANGLE_TRY(
4482             currentIndirectBuf->invalidate(mRenderer, 0, sizeof(VkDrawIndexedIndirectCommand)));
4483         uint8_t *buffPtr;
4484         ANGLE_TRY(currentIndirectBuf->map(this, &buffPtr));
4485         const VkDrawIndexedIndirectCommand *indirectData =
4486             reinterpret_cast<VkDrawIndexedIndirectCommand *>(buffPtr + currentIndirectBufOffset);
4487 
4488         ANGLE_TRY(drawElementsInstanced(context, mode, indirectData->indexCount, type, nullptr,
4489                                         indirectData->instanceCount));
4490 
4491         currentIndirectBuf->unmap(mRenderer);
4492         return angle::Result::Continue;
4493     }
4494 
4495     if (shouldConvertUint8VkIndexType(type) && mGraphicsDirtyBits[DIRTY_BIT_INDEX_BUFFER])
4496     {
4497         ANGLE_VK_PERF_WARNING(
4498             this, GL_DEBUG_SEVERITY_LOW,
4499             "Potential inefficiency emulating uint8 vertex attributes due to lack "
4500             "of hardware support");
4501 
4502         ANGLE_TRY(vertexArrayVk->convertIndexBufferIndirectGPU(
4503             this, currentIndirectBuf, currentIndirectBufOffset, &currentIndirectBuf));
4504         currentIndirectBufOffset = 0;
4505     }
4506 
4507     // If the line-loop handling function modifies the element array buffer in the vertex array,
4508     // there is a possibility that the modified version is used as a source for the next line-loop
4509     // draw, which can lead to errors. To avoid this, a local index buffer pointer is used to pass
4510     // the current index buffer (after translation, in case it is needed) and use the resulting
4511     // index buffer for draw.
4512     vk::BufferHelper *currentIndexBuf = vertexArrayVk->getCurrentElementArrayBuffer();
4513     if (mode == gl::PrimitiveMode::LineLoop)
4514     {
4515         // Line loop only supports handling at most one indirect parameter.
4516         ASSERT(drawcount <= 1);
4517         ANGLE_TRY(setupLineLoopIndexedIndirectDraw(context, mode, type, currentIndexBuf,
4518                                                    currentIndirectBuf, currentIndirectBufOffset,
4519                                                    &currentIndirectBuf));
4520         currentIndirectBufOffset = 0;
4521     }
4522     else
4523     {
4524         ANGLE_TRY(setupIndexedIndirectDraw(context, mode, type, currentIndirectBuf));
4525     }
4526 
4527     mRenderPassCommandBuffer->drawIndexedIndirect(
4528         currentIndirectBuf->getBuffer(), currentIndirectBuf->getOffset() + currentIndirectBufOffset,
4529         drawcount, vkStride);
4530 
4531     return angle::Result::Continue;
4532 }
4533 
multiDrawArraysInstancedBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,const GLuint * baseInstances,GLsizei drawcount)4534 angle::Result ContextVk::multiDrawArraysInstancedBaseInstance(const gl::Context *context,
4535                                                               gl::PrimitiveMode mode,
4536                                                               const GLint *firsts,
4537                                                               const GLsizei *counts,
4538                                                               const GLsizei *instanceCounts,
4539                                                               const GLuint *baseInstances,
4540                                                               GLsizei drawcount)
4541 {
4542     return rx::MultiDrawArraysInstancedBaseInstanceGeneral(
4543         this, context, mode, firsts, counts, instanceCounts, baseInstances, drawcount);
4544 }
4545 
multiDrawElementsInstancedBaseVertexBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,const GLint * baseVertices,const GLuint * baseInstances,GLsizei drawcount)4546 angle::Result ContextVk::multiDrawElementsInstancedBaseVertexBaseInstance(
4547     const gl::Context *context,
4548     gl::PrimitiveMode mode,
4549     const GLsizei *counts,
4550     gl::DrawElementsType type,
4551     const GLvoid *const *indices,
4552     const GLsizei *instanceCounts,
4553     const GLint *baseVertices,
4554     const GLuint *baseInstances,
4555     GLsizei drawcount)
4556 {
4557     return rx::MultiDrawElementsInstancedBaseVertexBaseInstanceGeneral(
4558         this, context, mode, counts, type, indices, instanceCounts, baseVertices, baseInstances,
4559         drawcount);
4560 }
4561 
optimizeRenderPassForPresent(vk::ImageViewHelper * colorImageView,vk::ImageHelper * colorImage,vk::ImageHelper * colorImageMS,bool isSharedPresentMode,bool * imageResolved)4562 angle::Result ContextVk::optimizeRenderPassForPresent(vk::ImageViewHelper *colorImageView,
4563                                                       vk::ImageHelper *colorImage,
4564                                                       vk::ImageHelper *colorImageMS,
4565                                                       bool isSharedPresentMode,
4566                                                       bool *imageResolved)
4567 {
4568     // Note: mRenderPassCommandBuffer may be nullptr because the render pass is marked for closure.
4569     // That doesn't matter and the render pass can continue to be modified.  This function shouldn't
4570     // rely on mRenderPassCommandBuffer.
4571 
4572     // The caller must have verified this is the right render pass by calling
4573     // |hasStartedRenderPassWithSwapchainFramebuffer()|.
4574     ASSERT(mRenderPassCommands->started());
4575 
4576     // EGL1.5 spec: The contents of ancillary buffers are always undefined after calling
4577     // eglSwapBuffers
4578     FramebufferVk *drawFramebufferVk         = getDrawFramebuffer();
4579     RenderTargetVk *depthStencilRenderTarget = drawFramebufferVk->getDepthStencilRenderTarget();
4580     if (depthStencilRenderTarget != nullptr)
4581     {
4582         // Change depth/stencil attachment storeOp to DONT_CARE
4583         const gl::DepthStencilState &dsState = mState.getDepthStencilState();
4584         mRenderPassCommands->invalidateRenderPassDepthAttachment(
4585             dsState, mRenderPassCommands->getRenderArea());
4586         mRenderPassCommands->invalidateRenderPassStencilAttachment(
4587             dsState, mState.getDrawFramebuffer()->getStencilBitCount(),
4588             mRenderPassCommands->getRenderArea());
4589     }
4590 
4591     // Resolve the multisample image
4592     vk::RenderPassCommandBufferHelper &commandBufferHelper = getStartedRenderPassCommands();
4593     gl::Rectangle renderArea                               = commandBufferHelper.getRenderArea();
4594     const gl::Rectangle fullExtent(0, 0, colorImageMS->getRotatedExtents().width,
4595                                    colorImageMS->getRotatedExtents().height);
4596     const bool resolveWithRenderPass = colorImageMS->valid() && renderArea == fullExtent;
4597 
4598     // Handle transition to PRESENT_SRC automatically as part of the render pass.  If the swapchain
4599     // image is the target of resolve, but that resolve cannot happen with the render pass, do not
4600     // apply this optimization; the image has to be moved out of PRESENT_SRC to be resolved after
4601     // this call.
4602     if (getFeatures().supportsPresentation.enabled && !isSharedPresentMode &&
4603         (!colorImageMS->valid() || resolveWithRenderPass))
4604     {
4605         ASSERT(colorImage != nullptr);
4606         mRenderPassCommands->setImageOptimizeForPresent(colorImage);
4607     }
4608 
4609     if (resolveWithRenderPass)
4610     {
4611         // Due to lack of support for GL_MESA_framebuffer_flip_y, it is currently impossible for the
4612         // application to resolve the default framebuffer into an FBO with a resolve attachment.  If
4613         // that is ever supported, the path that adds the resolve attachment would invalidate the
4614         // framebuffer that the render pass holds on to, in which case this function is not called.
4615         // Either way, there cannot be a resolve attachment here already.
4616         ASSERT(!mRenderPassCommands->getFramebuffer().hasColorResolveAttachment(0));
4617 
4618         // Add the resolve attachment to the render pass
4619         const vk::ImageView *resolveImageView = nullptr;
4620         ANGLE_TRY(colorImageView->getLevelLayerDrawImageView(this, *colorImage, vk::LevelIndex(0),
4621                                                              0, &resolveImageView));
4622 
4623         mRenderPassCommands->addColorResolveAttachment(0, colorImage, resolveImageView->getHandle(),
4624                                                        gl::LevelIndex(0), 0, 1, {});
4625         onImageRenderPassWrite(gl::LevelIndex(0), 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
4626                                vk::ImageLayout::ColorWrite, colorImage);
4627 
4628         // Invalidate the surface.
4629         // See comment in WindowSurfaceVk::doDeferredAcquireNextImageWithUsableSwapchain on why this
4630         // is not done when in shared present mode.
4631         if (!isSharedPresentMode)
4632         {
4633             commandBufferHelper.invalidateRenderPassColorAttachment(
4634                 mState, 0, vk::PackedAttachmentIndex(0), fullExtent);
4635         }
4636 
4637         *imageResolved = true;
4638 
4639         mPerfCounters.swapchainResolveInSubpass++;
4640     }
4641 
4642     return angle::Result::Continue;
4643 }
4644 
getResetStatus()4645 gl::GraphicsResetStatus ContextVk::getResetStatus()
4646 {
4647     if (mRenderer->isDeviceLost())
4648     {
4649         // TODO(geofflang): It may be possible to track which context caused the device lost and
4650         // return either GL_GUILTY_CONTEXT_RESET or GL_INNOCENT_CONTEXT_RESET.
4651         // http://anglebug.com/42261488
4652         return gl::GraphicsResetStatus::UnknownContextReset;
4653     }
4654 
4655     return gl::GraphicsResetStatus::NoError;
4656 }
4657 
insertEventMarker(GLsizei length,const char * marker)4658 angle::Result ContextVk::insertEventMarker(GLsizei length, const char *marker)
4659 {
4660     insertEventMarkerImpl(GL_DEBUG_SOURCE_APPLICATION, marker);
4661     return angle::Result::Continue;
4662 }
4663 
insertEventMarkerImpl(GLenum source,const char * marker)4664 void ContextVk::insertEventMarkerImpl(GLenum source, const char *marker)
4665 {
4666     if (!isDebugEnabled())
4667     {
4668         return;
4669     }
4670 
4671     VkDebugUtilsLabelEXT label;
4672     vk::MakeDebugUtilsLabel(source, marker, &label);
4673 
4674     if (hasActiveRenderPass())
4675     {
4676         mRenderPassCommandBuffer->insertDebugUtilsLabelEXT(label);
4677     }
4678     else
4679     {
4680         mOutsideRenderPassCommands->getCommandBuffer().insertDebugUtilsLabelEXT(label);
4681     }
4682 }
4683 
pushGroupMarker(GLsizei length,const char * marker)4684 angle::Result ContextVk::pushGroupMarker(GLsizei length, const char *marker)
4685 {
4686     return pushDebugGroupImpl(GL_DEBUG_SOURCE_APPLICATION, 0, marker);
4687 }
4688 
popGroupMarker()4689 angle::Result ContextVk::popGroupMarker()
4690 {
4691     return popDebugGroupImpl();
4692 }
4693 
pushDebugGroup(const gl::Context * context,GLenum source,GLuint id,const std::string & message)4694 angle::Result ContextVk::pushDebugGroup(const gl::Context *context,
4695                                         GLenum source,
4696                                         GLuint id,
4697                                         const std::string &message)
4698 {
4699     return pushDebugGroupImpl(source, id, message.c_str());
4700 }
4701 
popDebugGroup(const gl::Context * context)4702 angle::Result ContextVk::popDebugGroup(const gl::Context *context)
4703 {
4704     return popDebugGroupImpl();
4705 }
4706 
pushDebugGroupImpl(GLenum source,GLuint id,const char * message)4707 angle::Result ContextVk::pushDebugGroupImpl(GLenum source, GLuint id, const char *message)
4708 {
4709     if (!isDebugEnabled())
4710     {
4711         return angle::Result::Continue;
4712     }
4713 
4714     VkDebugUtilsLabelEXT label;
4715     vk::MakeDebugUtilsLabel(source, message, &label);
4716 
4717     if (hasActiveRenderPass())
4718     {
4719         mRenderPassCommandBuffer->beginDebugUtilsLabelEXT(label);
4720     }
4721     else
4722     {
4723         mOutsideRenderPassCommands->getCommandBuffer().beginDebugUtilsLabelEXT(label);
4724     }
4725 
4726     return angle::Result::Continue;
4727 }
4728 
popDebugGroupImpl()4729 angle::Result ContextVk::popDebugGroupImpl()
4730 {
4731     if (!isDebugEnabled())
4732     {
4733         return angle::Result::Continue;
4734     }
4735 
4736     if (hasActiveRenderPass())
4737     {
4738         mRenderPassCommandBuffer->endDebugUtilsLabelEXT();
4739     }
4740     else
4741     {
4742         mOutsideRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
4743     }
4744 
4745     return angle::Result::Continue;
4746 }
4747 
logEvent(const char * eventString)4748 void ContextVk::logEvent(const char *eventString)
4749 {
4750     if (!mRenderer->angleDebuggerMode())
4751     {
4752         return;
4753     }
4754 
4755     // Save this event (about an OpenGL ES command being called).
4756     mEventLog.push_back(eventString);
4757 
4758     // Set a dirty bit in order to stay off the "hot path" for when not logging.
4759     mGraphicsDirtyBits.set(DIRTY_BIT_EVENT_LOG);
4760     mComputeDirtyBits.set(DIRTY_BIT_EVENT_LOG);
4761 }
4762 
endEventLog(angle::EntryPoint entryPoint,PipelineType pipelineType)4763 void ContextVk::endEventLog(angle::EntryPoint entryPoint, PipelineType pipelineType)
4764 {
4765     if (!mRenderer->angleDebuggerMode())
4766     {
4767         return;
4768     }
4769 
4770     if (pipelineType == PipelineType::Graphics)
4771     {
4772         ASSERT(mRenderPassCommands);
4773         mRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
4774     }
4775     else
4776     {
4777         ASSERT(pipelineType == PipelineType::Compute);
4778         ASSERT(mOutsideRenderPassCommands);
4779         mOutsideRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
4780     }
4781 }
endEventLogForClearOrQuery()4782 void ContextVk::endEventLogForClearOrQuery()
4783 {
4784     if (!mRenderer->angleDebuggerMode())
4785     {
4786         return;
4787     }
4788 
4789     switch (mQueryEventType)
4790     {
4791         case GraphicsEventCmdBuf::InOutsideCmdBufQueryCmd:
4792             ASSERT(mOutsideRenderPassCommands);
4793             mOutsideRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
4794             break;
4795         case GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd:
4796             ASSERT(mRenderPassCommands);
4797             mRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
4798             break;
4799         case GraphicsEventCmdBuf::NotInQueryCmd:
4800             // The glClear* or gl*Query* command was noop'd or otherwise ended early.  We could
4801             // call handleDirtyEventLogImpl() to start the hierarchy, but it isn't clear which (if
4802             // any) command buffer to use.  We'll just skip processing this command (other than to
4803             // let it stay queued for the next time handleDirtyEventLogImpl() is called.
4804             return;
4805         default:
4806             UNREACHABLE();
4807     }
4808 
4809     mQueryEventType = GraphicsEventCmdBuf::NotInQueryCmd;
4810 }
4811 
handleNoopDrawEvent()4812 angle::Result ContextVk::handleNoopDrawEvent()
4813 {
4814     // Even though this draw call is being no-op'd, we still must handle the dirty event log
4815     return handleDirtyEventLogImpl(mRenderPassCommandBuffer);
4816 }
4817 
handleGraphicsEventLog(GraphicsEventCmdBuf queryEventType)4818 angle::Result ContextVk::handleGraphicsEventLog(GraphicsEventCmdBuf queryEventType)
4819 {
4820     ASSERT(mQueryEventType == GraphicsEventCmdBuf::NotInQueryCmd || mEventLog.empty());
4821     if (!mRenderer->angleDebuggerMode())
4822     {
4823         return angle::Result::Continue;
4824     }
4825 
4826     mQueryEventType = queryEventType;
4827 
4828     switch (mQueryEventType)
4829     {
4830         case GraphicsEventCmdBuf::InOutsideCmdBufQueryCmd:
4831             ASSERT(mOutsideRenderPassCommands);
4832             return handleDirtyEventLogImpl(&mOutsideRenderPassCommands->getCommandBuffer());
4833         case GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd:
4834             ASSERT(mRenderPassCommands);
4835             return handleDirtyEventLogImpl(&mRenderPassCommands->getCommandBuffer());
4836         default:
4837             UNREACHABLE();
4838             return angle::Result::Stop;
4839     }
4840 }
4841 
isViewportFlipEnabledForDrawFBO() const4842 bool ContextVk::isViewportFlipEnabledForDrawFBO() const
4843 {
4844     return mFlipViewportForDrawFramebuffer && mFlipYForCurrentSurface;
4845 }
4846 
isViewportFlipEnabledForReadFBO() const4847 bool ContextVk::isViewportFlipEnabledForReadFBO() const
4848 {
4849     return mFlipViewportForReadFramebuffer;
4850 }
4851 
isRotatedAspectRatioForDrawFBO() const4852 bool ContextVk::isRotatedAspectRatioForDrawFBO() const
4853 {
4854     return IsRotatedAspectRatio(mCurrentRotationDrawFramebuffer);
4855 }
4856 
isRotatedAspectRatioForReadFBO() const4857 bool ContextVk::isRotatedAspectRatioForReadFBO() const
4858 {
4859     return IsRotatedAspectRatio(mCurrentRotationReadFramebuffer);
4860 }
4861 
getRotationDrawFramebuffer() const4862 SurfaceRotation ContextVk::getRotationDrawFramebuffer() const
4863 {
4864     return mCurrentRotationDrawFramebuffer;
4865 }
4866 
getRotationReadFramebuffer() const4867 SurfaceRotation ContextVk::getRotationReadFramebuffer() const
4868 {
4869     return mCurrentRotationReadFramebuffer;
4870 }
4871 
getSurfaceRotationImpl(const gl::Framebuffer * framebuffer,const egl::Surface * surface)4872 SurfaceRotation ContextVk::getSurfaceRotationImpl(const gl::Framebuffer *framebuffer,
4873                                                   const egl::Surface *surface)
4874 {
4875     SurfaceRotation surfaceRotation = SurfaceRotation::Identity;
4876     if (surface && surface->getType() == EGL_WINDOW_BIT)
4877     {
4878         const WindowSurfaceVk *windowSurface = GetImplAs<WindowSurfaceVk>(surface);
4879         surfaceRotation                      = DetermineSurfaceRotation(framebuffer, windowSurface);
4880     }
4881     return surfaceRotation;
4882 }
4883 
updateColorMasks()4884 void ContextVk::updateColorMasks()
4885 {
4886     const gl::BlendStateExt &blendStateExt = mState.getBlendStateExt();
4887 
4888     mClearColorMasks = blendStateExt.getColorMaskBits();
4889 
4890     FramebufferVk *framebufferVk = vk::GetImpl(mState.getDrawFramebuffer());
4891     mGraphicsPipelineDesc->updateColorWriteMasks(&mGraphicsPipelineTransition, mClearColorMasks,
4892                                                  framebufferVk->getEmulatedAlphaAttachmentMask(),
4893                                                  framebufferVk->getState().getEnabledDrawBuffers());
4894 
4895     // This function may be called outside of ContextVk::syncState, and so invalidates the graphics
4896     // pipeline.
4897     invalidateCurrentGraphicsPipeline();
4898 
4899     onColorAccessChange();
4900 }
4901 
updateMissingAttachments()4902 void ContextVk::updateMissingAttachments()
4903 {
4904     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
4905     if (executable == nullptr)
4906     {
4907         return;
4908     }
4909 
4910     // Handle missing color outputs
4911     const gl::DrawBufferMask framebufferMask    = mState.getDrawFramebuffer()->getDrawBufferMask();
4912     const gl::DrawBufferMask shaderOutMask      = executable->getActiveOutputVariablesMask();
4913     const gl::DrawBufferMask missingOutputsMask = ~shaderOutMask & framebufferMask;
4914 
4915     mGraphicsPipelineDesc->updateMissingOutputsMask(&mGraphicsPipelineTransition,
4916                                                     missingOutputsMask);
4917 
4918     // Handle missing depth/stencil attachment input.  If gl_LastFragDepth/StencilARM is used by the
4919     // shader but there is no depth/stencil attachment, the shader is changed not to read from the
4920     // input attachment.
4921     if (executable->usesDepthFramebufferFetch() || executable->usesStencilFramebufferFetch())
4922     {
4923         invalidateCurrentGraphicsPipeline();
4924     }
4925 }
4926 
updateBlendFuncsAndEquations()4927 void ContextVk::updateBlendFuncsAndEquations()
4928 {
4929     const gl::BlendStateExt &blendStateExt = mState.getBlendStateExt();
4930 
4931     FramebufferVk *framebufferVk              = vk::GetImpl(mState.getDrawFramebuffer());
4932     mCachedDrawFramebufferColorAttachmentMask = framebufferVk->getState().getEnabledDrawBuffers();
4933 
4934     mGraphicsPipelineDesc->updateBlendFuncs(&mGraphicsPipelineTransition, blendStateExt,
4935                                             mCachedDrawFramebufferColorAttachmentMask);
4936 
4937     mGraphicsPipelineDesc->updateBlendEquations(&mGraphicsPipelineTransition, blendStateExt,
4938                                                 mCachedDrawFramebufferColorAttachmentMask);
4939 
4940     // This function may be called outside of ContextVk::syncState, and so invalidates the graphics
4941     // pipeline.
4942     invalidateCurrentGraphicsPipeline();
4943 }
4944 
updateSampleMaskWithRasterizationSamples(const uint32_t rasterizationSamples)4945 void ContextVk::updateSampleMaskWithRasterizationSamples(const uint32_t rasterizationSamples)
4946 {
4947     static_assert(sizeof(uint32_t) == sizeof(GLbitfield), "Vulkan assumes 32-bit sample masks");
4948     ASSERT(mState.getMaxSampleMaskWords() == 1);
4949 
4950     uint32_t mask = std::numeric_limits<uint16_t>::max();
4951 
4952     // The following assumes that supported sample counts for multisampled
4953     // rendering does not include 1. This is true in the Vulkan backend,
4954     // where 1x multisampling is disallowed.
4955     if (rasterizationSamples > 1)
4956     {
4957         if (mState.isSampleMaskEnabled())
4958         {
4959             mask = mState.getSampleMaskWord(0) & angle::BitMask<uint32_t>(rasterizationSamples);
4960         }
4961 
4962         // If sample coverage is enabled, emulate it by generating and applying a mask on top of the
4963         // sample mask.
4964         if (mState.isSampleCoverageEnabled())
4965         {
4966             ApplySampleCoverage(mState, GetCoverageSampleCount(mState, rasterizationSamples),
4967                                 &mask);
4968         }
4969     }
4970 
4971     mGraphicsPipelineDesc->updateSampleMask(&mGraphicsPipelineTransition, 0, mask);
4972 }
4973 
updateAlphaToCoverageWithRasterizationSamples(const uint32_t rasterizationSamples)4974 void ContextVk::updateAlphaToCoverageWithRasterizationSamples(const uint32_t rasterizationSamples)
4975 {
4976     // The following assumes that supported sample counts for multisampled
4977     // rendering does not include 1. This is true in the Vulkan backend,
4978     // where 1x multisampling is disallowed.
4979     mGraphicsPipelineDesc->updateAlphaToCoverageEnable(
4980         &mGraphicsPipelineTransition,
4981         mState.isSampleAlphaToCoverageEnabled() && rasterizationSamples > 1);
4982 }
4983 
updateFrameBufferFetchSamples(const uint32_t prevSamples,const uint32_t curSamples)4984 void ContextVk::updateFrameBufferFetchSamples(const uint32_t prevSamples, const uint32_t curSamples)
4985 {
4986     const bool isPrevMultisampled = prevSamples > 1;
4987     const bool isCurMultisampled  = curSamples > 1;
4988     if (isPrevMultisampled != isCurMultisampled)
4989     {
4990         // If we change from single sample to multisample, we need to use the Shader Program with
4991         // ProgramTransformOptions.multisampleFramebufferFetch == true. Invalidate the graphics
4992         // pipeline so that we can fetch the shader with the correct permutation option in
4993         // handleDirtyGraphicsPipelineDesc()
4994         invalidateCurrentGraphicsPipeline();
4995     }
4996 }
4997 
getCorrectedViewport(const gl::Rectangle & viewport) const4998 gl::Rectangle ContextVk::getCorrectedViewport(const gl::Rectangle &viewport) const
4999 {
5000     const gl::Caps &caps                   = getCaps();
5001     const VkPhysicalDeviceLimits &limitsVk = mRenderer->getPhysicalDeviceProperties().limits;
5002     const int viewportBoundsRangeLow       = static_cast<int>(limitsVk.viewportBoundsRange[0]);
5003     const int viewportBoundsRangeHigh      = static_cast<int>(limitsVk.viewportBoundsRange[1]);
5004 
5005     // Clamp the viewport values to what Vulkan specifies
5006 
5007     // width must be greater than 0.0 and less than or equal to
5008     // VkPhysicalDeviceLimits::maxViewportDimensions[0]
5009     int correctedWidth = std::min<int>(viewport.width, caps.maxViewportWidth);
5010     correctedWidth     = std::max<int>(correctedWidth, 0);
5011     // height must be greater than 0.0 and less than or equal to
5012     // VkPhysicalDeviceLimits::maxViewportDimensions[1]
5013     int correctedHeight = std::min<int>(viewport.height, caps.maxViewportHeight);
5014     correctedHeight     = std::max<int>(correctedHeight, 0);
5015     // x and y must each be between viewportBoundsRange[0] and viewportBoundsRange[1], inclusive.
5016     // Viewport size cannot be 0 so ensure there is always size for a 1x1 viewport
5017     int correctedX = std::min<int>(viewport.x, viewportBoundsRangeHigh - 1);
5018     correctedX     = std::max<int>(correctedX, viewportBoundsRangeLow);
5019     int correctedY = std::min<int>(viewport.y, viewportBoundsRangeHigh - 1);
5020     correctedY     = std::max<int>(correctedY, viewportBoundsRangeLow);
5021     // x + width must be less than or equal to viewportBoundsRange[1]
5022     if ((correctedX + correctedWidth) > viewportBoundsRangeHigh)
5023     {
5024         correctedWidth = viewportBoundsRangeHigh - correctedX;
5025     }
5026     // y + height must be less than or equal to viewportBoundsRange[1]
5027     if ((correctedY + correctedHeight) > viewportBoundsRangeHigh)
5028     {
5029         correctedHeight = viewportBoundsRangeHigh - correctedY;
5030     }
5031 
5032     return gl::Rectangle(correctedX, correctedY, correctedWidth, correctedHeight);
5033 }
5034 
updateViewport(FramebufferVk * framebufferVk,const gl::Rectangle & viewport,float nearPlane,float farPlane)5035 void ContextVk::updateViewport(FramebufferVk *framebufferVk,
5036                                const gl::Rectangle &viewport,
5037                                float nearPlane,
5038                                float farPlane)
5039 {
5040 
5041     gl::Box fbDimensions        = framebufferVk->getState().getDimensions();
5042     gl::Rectangle correctedRect = getCorrectedViewport(viewport);
5043     gl::Rectangle rotatedRect;
5044     RotateRectangle(getRotationDrawFramebuffer(), false, fbDimensions.width, fbDimensions.height,
5045                     correctedRect, &rotatedRect);
5046 
5047     const bool invertViewport = isViewportFlipEnabledForDrawFBO();
5048 
5049     gl_vk::GetViewport(
5050         rotatedRect, nearPlane, farPlane, invertViewport,
5051         // If clip space origin is upper left, viewport origin's y value will be offset by the
5052         // height of the viewport when clip space is mapped into screen space.
5053         mState.getClipOrigin() == gl::ClipOrigin::UpperLeft,
5054         // If the surface is rotated 90/270 degrees, use the framebuffer's width instead of the
5055         // height for calculating the final viewport.
5056         isRotatedAspectRatioForDrawFBO() ? fbDimensions.width : fbDimensions.height, &mViewport);
5057 
5058     // Ensure viewport is within Vulkan requirements
5059     vk::ClampViewport(&mViewport);
5060 
5061     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_VIEWPORT);
5062 }
5063 
updateFrontFace()5064 void ContextVk::updateFrontFace()
5065 {
5066     if (mRenderer->getFeatures().useFrontFaceDynamicState.enabled)
5067     {
5068         mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_FRONT_FACE);
5069     }
5070     else
5071     {
5072         mGraphicsPipelineDesc->updateFrontFace(
5073             &mGraphicsPipelineTransition, mState.getRasterizerState(), isYFlipEnabledForDrawFBO());
5074     }
5075 }
5076 
updateDepthRange(float nearPlane,float farPlane)5077 void ContextVk::updateDepthRange(float nearPlane, float farPlane)
5078 {
5079     // GLES2.0 Section 2.12.1: Each of n and f are clamped to lie within [0, 1], as are all
5080     // arguments of type clampf.
5081     ASSERT(nearPlane >= 0.0f && nearPlane <= 1.0f);
5082     ASSERT(farPlane >= 0.0f && farPlane <= 1.0f);
5083     mViewport.minDepth = nearPlane;
5084     mViewport.maxDepth = farPlane;
5085 
5086     invalidateGraphicsDriverUniforms();
5087     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_VIEWPORT);
5088 }
5089 
updateScissor(const gl::State & glState)5090 void ContextVk::updateScissor(const gl::State &glState)
5091 {
5092     FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer());
5093     gl::Rectangle renderArea     = framebufferVk->getNonRotatedCompleteRenderArea();
5094 
5095     // Clip the render area to the viewport.
5096     gl::Rectangle viewportClippedRenderArea;
5097     if (!gl::ClipRectangle(renderArea, getCorrectedViewport(glState.getViewport()),
5098                            &viewportClippedRenderArea))
5099     {
5100         viewportClippedRenderArea = gl::Rectangle();
5101     }
5102 
5103     gl::Rectangle scissoredArea = ClipRectToScissor(getState(), viewportClippedRenderArea, false);
5104     gl::Rectangle rotatedScissoredArea;
5105     RotateRectangle(getRotationDrawFramebuffer(), isViewportFlipEnabledForDrawFBO(),
5106                     renderArea.width, renderArea.height, scissoredArea, &rotatedScissoredArea);
5107     mScissor = gl_vk::GetRect(rotatedScissoredArea);
5108     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_SCISSOR);
5109 
5110     // If the scissor has grown beyond the previous scissoredRenderArea, grow the render pass render
5111     // area.  The only undesirable effect this may have is that if the render area does not cover a
5112     // previously invalidated area, that invalidate will have to be discarded.
5113     if (mRenderPassCommandBuffer &&
5114         !mRenderPassCommands->getRenderArea().encloses(rotatedScissoredArea))
5115     {
5116         ASSERT(mRenderPassCommands->started());
5117         mRenderPassCommands->growRenderArea(this, rotatedScissoredArea);
5118     }
5119 }
5120 
updateDepthStencil(const gl::State & glState)5121 void ContextVk::updateDepthStencil(const gl::State &glState)
5122 {
5123     updateDepthTestEnabled(glState);
5124     updateDepthWriteEnabled(glState);
5125     updateStencilTestEnabled(glState);
5126     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_WRITE_MASK);
5127 }
5128 
updateDepthTestEnabled(const gl::State & glState)5129 void ContextVk::updateDepthTestEnabled(const gl::State &glState)
5130 {
5131     const gl::DepthStencilState &depthStencilState = glState.getDepthStencilState();
5132     gl::Framebuffer *drawFramebuffer              = glState.getDrawFramebuffer();
5133 
5134     if (mRenderer->getFeatures().useDepthTestEnableDynamicState.enabled)
5135     {
5136         mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_TEST_ENABLE);
5137     }
5138     else
5139     {
5140         mGraphicsPipelineDesc->updateDepthTestEnabled(&mGraphicsPipelineTransition,
5141                                                       depthStencilState, drawFramebuffer);
5142     }
5143 }
5144 
updateDepthWriteEnabled(const gl::State & glState)5145 void ContextVk::updateDepthWriteEnabled(const gl::State &glState)
5146 {
5147     const gl::DepthStencilState &depthStencilState = glState.getDepthStencilState();
5148     gl::Framebuffer *drawFramebuffer              = glState.getDrawFramebuffer();
5149 
5150     if (mRenderer->getFeatures().useDepthWriteEnableDynamicState.enabled)
5151     {
5152         mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_WRITE_ENABLE);
5153     }
5154     else
5155     {
5156         mGraphicsPipelineDesc->updateDepthWriteEnabled(&mGraphicsPipelineTransition,
5157                                                        depthStencilState, drawFramebuffer);
5158     }
5159 }
5160 
updateDepthFunc(const gl::State & glState)5161 void ContextVk::updateDepthFunc(const gl::State &glState)
5162 {
5163     if (mRenderer->getFeatures().useDepthCompareOpDynamicState.enabled)
5164     {
5165         mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_COMPARE_OP);
5166     }
5167     else
5168     {
5169         mGraphicsPipelineDesc->updateDepthFunc(&mGraphicsPipelineTransition,
5170                                                glState.getDepthStencilState());
5171     }
5172 }
5173 
updateStencilTestEnabled(const gl::State & glState)5174 void ContextVk::updateStencilTestEnabled(const gl::State &glState)
5175 {
5176     const gl::DepthStencilState &depthStencilState = glState.getDepthStencilState();
5177     gl::Framebuffer *drawFramebuffer              = glState.getDrawFramebuffer();
5178 
5179     if (mRenderer->getFeatures().useStencilTestEnableDynamicState.enabled)
5180     {
5181         mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_TEST_ENABLE);
5182     }
5183     else
5184     {
5185         mGraphicsPipelineDesc->updateStencilTestEnabled(&mGraphicsPipelineTransition,
5186                                                         depthStencilState, drawFramebuffer);
5187     }
5188 }
5189 
5190 // If the target is a single-sampled target, sampleShading should be disabled, to use Bresenham line
5191 // rasterization feature.
updateSampleShadingWithRasterizationSamples(const uint32_t rasterizationSamples)5192 void ContextVk::updateSampleShadingWithRasterizationSamples(const uint32_t rasterizationSamples)
5193 {
5194     bool sampleShadingEnable =
5195         (rasterizationSamples <= 1 ? false : mState.isSampleShadingEnabled());
5196     float minSampleShading = mState.getMinSampleShading();
5197 
5198     // If sample shading is not enabled, check if it should be implicitly enabled according to the
5199     // program.  Normally the driver should do this, but some drivers don't.
5200     if (rasterizationSamples > 1 && !sampleShadingEnable &&
5201         getFeatures().explicitlyEnablePerSampleShading.enabled)
5202     {
5203         const gl::ProgramExecutable *executable = mState.getProgramExecutable();
5204         if (executable && executable->enablesPerSampleShading())
5205         {
5206             sampleShadingEnable = true;
5207             minSampleShading    = 1.0;
5208         }
5209     }
5210 
5211     mGraphicsPipelineDesc->updateSampleShading(&mGraphicsPipelineTransition, sampleShadingEnable,
5212                                                minSampleShading);
5213 }
5214 
5215 // If the target is switched between a single-sampled and multisample, the dependency related to the
5216 // rasterization sample should be updated.
updateRasterizationSamples(const uint32_t rasterizationSamples)5217 void ContextVk::updateRasterizationSamples(const uint32_t rasterizationSamples)
5218 {
5219     uint32_t prevSampleCount = mGraphicsPipelineDesc->getRasterizationSamples();
5220     updateFrameBufferFetchSamples(prevSampleCount, rasterizationSamples);
5221     mGraphicsPipelineDesc->updateRasterizationSamples(&mGraphicsPipelineTransition,
5222                                                       rasterizationSamples);
5223     updateSampleShadingWithRasterizationSamples(rasterizationSamples);
5224     updateSampleMaskWithRasterizationSamples(rasterizationSamples);
5225     updateAlphaToCoverageWithRasterizationSamples(rasterizationSamples);
5226 }
5227 
updateRasterizerDiscardEnabled(bool isPrimitivesGeneratedQueryActive)5228 void ContextVk::updateRasterizerDiscardEnabled(bool isPrimitivesGeneratedQueryActive)
5229 {
5230     // On some devices, when rasterizerDiscardEnable is enabled, the
5231     // VK_EXT_primitives_generated_query as well as the pipeline statistics query used to emulate it
5232     // are non-functional.  For VK_EXT_primitives_generated_query there's a feature bit but not for
5233     // pipeline statistics query.  If the primitives generated query is active (and rasterizer
5234     // discard is not supported), rasterizerDiscardEnable is set to false and the functionality
5235     // is otherwise emulated (by using an empty scissor).
5236 
5237     // If the primitives generated query implementation supports rasterizer discard, just set
5238     // rasterizer discard as requested.  Otherwise disable it.
5239     const bool isEmulatingRasterizerDiscard =
5240         isEmulatingRasterizerDiscardDuringPrimitivesGeneratedQuery(
5241             isPrimitivesGeneratedQueryActive);
5242 
5243     if (mRenderer->getFeatures().useRasterizerDiscardEnableDynamicState.enabled)
5244     {
5245         mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_RASTERIZER_DISCARD_ENABLE);
5246     }
5247     else
5248     {
5249         const bool isRasterizerDiscardEnabled = mState.isRasterizerDiscardEnabled();
5250 
5251         mGraphicsPipelineDesc->updateRasterizerDiscardEnabled(
5252             &mGraphicsPipelineTransition,
5253             isRasterizerDiscardEnabled && !isEmulatingRasterizerDiscard);
5254 
5255         invalidateCurrentGraphicsPipeline();
5256     }
5257 
5258     if (isEmulatingRasterizerDiscard)
5259     {
5260         // If we are emulating rasterizer discard, update the scissor to use an empty one if
5261         // rasterizer discard is enabled.
5262         mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_SCISSOR);
5263     }
5264 }
5265 
updateAdvancedBlendEquations(const gl::ProgramExecutable * executable)5266 void ContextVk::updateAdvancedBlendEquations(const gl::ProgramExecutable *executable)
5267 {
5268     if (!getFeatures().emulateAdvancedBlendEquations.enabled || executable == nullptr)
5269     {
5270         return;
5271     }
5272 
5273     // If advanced blend equations is emulated and the program uses advanced equations, update the
5274     // driver uniforms to pass the equation to the shader.
5275     if (executable->getAdvancedBlendEquations().any())
5276     {
5277         invalidateGraphicsDriverUniforms();
5278     }
5279 }
5280 
updateDither()5281 void ContextVk::updateDither()
5282 {
5283     if (getFeatures().supportsLegacyDithering.enabled)
5284     {
5285         FramebufferVk *framebufferVk = vk::GetImpl(mState.getDrawFramebuffer());
5286         if (framebufferVk->updateLegacyDither(this))
5287         {
5288             // Can't reactivate: same framebuffer but the render pass desc has changed.
5289             mAllowRenderPassToReactivate = false;
5290 
5291             onRenderPassFinished(RenderPassClosureReason::LegacyDithering);
5292         }
5293 
5294         // update GraphicsPipelineDesc renderpass legacy dithering bit
5295         if (isDitherEnabled() != mGraphicsPipelineDesc->isLegacyDitherEnabled())
5296         {
5297             const vk::FramebufferFetchMode framebufferFetchMode =
5298                 vk::GetProgramFramebufferFetchMode(mState.getProgramExecutable());
5299             mGraphicsPipelineDesc->updateRenderPassDesc(&mGraphicsPipelineTransition, getFeatures(),
5300                                                         framebufferVk->getRenderPassDesc(),
5301                                                         framebufferFetchMode);
5302             invalidateCurrentGraphicsPipeline();
5303         }
5304     }
5305 
5306     if (!getFeatures().emulateDithering.enabled)
5307     {
5308         return;
5309     }
5310 
5311     FramebufferVk *framebufferVk = vk::GetImpl(mState.getDrawFramebuffer());
5312 
5313     // Dithering in OpenGL is vaguely defined, to the extent that no dithering is also a valid
5314     // dithering algorithm.  Dithering is enabled by default, but emulating it has a non-negligible
5315     // cost.  Similarly to some other GLES drivers, ANGLE enables dithering only on low-bit formats
5316     // where visual banding is particularly common; namely RGBA4444, RGBA5551 and RGB565.
5317     //
5318     // Dithering is emulated in the fragment shader and is controlled by a spec constant.  Every 2
5319     // bits of the spec constant correspond to one attachment, with the value indicating:
5320     //
5321     // - 00: No dithering
5322     // - 01: Dither for RGBA4444
5323     // - 10: Dither for RGBA5551
5324     // - 11: Dither for RGB565
5325     //
5326     uint16_t ditherControl = 0;
5327     if (mState.isDitherEnabled())
5328     {
5329         const gl::DrawBufferMask attachmentMask =
5330             framebufferVk->getState().getColorAttachmentsMask();
5331 
5332         for (size_t colorIndex : attachmentMask)
5333         {
5334             // As dithering is emulated in the fragment shader itself, there are a number of
5335             // situations that can lead to incorrect blending.  We only allow blending with specific
5336             // combinations know to not interfere with dithering.
5337             if (mState.isBlendEnabledIndexed(static_cast<GLuint>(colorIndex)) &&
5338                 !BlendModeSupportsDither(this, colorIndex))
5339             {
5340                 continue;
5341             }
5342 
5343             RenderTargetVk *attachment = framebufferVk->getColorDrawRenderTarget(colorIndex);
5344 
5345             const angle::FormatID format = attachment->getImageActualFormatID();
5346 
5347             uint16_t attachmentDitherControl = sh::vk::kDitherControlNoDither;
5348             switch (format)
5349             {
5350                 case angle::FormatID::R4G4B4A4_UNORM:
5351                 case angle::FormatID::B4G4R4A4_UNORM:
5352                     attachmentDitherControl = sh::vk::kDitherControlDither4444;
5353                     break;
5354                 case angle::FormatID::R5G5B5A1_UNORM:
5355                 case angle::FormatID::B5G5R5A1_UNORM:
5356                 case angle::FormatID::A1R5G5B5_UNORM:
5357                     attachmentDitherControl = sh::vk::kDitherControlDither5551;
5358                     break;
5359                 case angle::FormatID::R5G6B5_UNORM:
5360                 case angle::FormatID::B5G6R5_UNORM:
5361                     attachmentDitherControl = sh::vk::kDitherControlDither565;
5362                     break;
5363                 default:
5364                     break;
5365             }
5366 
5367             ditherControl |= static_cast<uint16_t>(attachmentDitherControl << 2 * colorIndex);
5368         }
5369     }
5370 
5371     if (ditherControl != mGraphicsPipelineDesc->getEmulatedDitherControl())
5372     {
5373         mGraphicsPipelineDesc->updateEmulatedDitherControl(&mGraphicsPipelineTransition,
5374                                                            ditherControl);
5375         invalidateCurrentGraphicsPipeline();
5376     }
5377 }
5378 
updateStencilWriteWorkaround()5379 void ContextVk::updateStencilWriteWorkaround()
5380 {
5381     if (!getFeatures().useNonZeroStencilWriteMaskStaticState.enabled)
5382     {
5383         return;
5384     }
5385 
5386     // On certain drivers, having a stencil write mask of 0 in static state enables optimizations
5387     // that make the interaction of the stencil write mask dynamic state with discard and alpha to
5388     // coverage broken.  When the program has discard, or when alpha to coverage is enabled, these
5389     // optimizations are disabled by specifying a non-zero static state for stencil write mask.
5390     const bool programHasDiscard        = mState.getProgramExecutable()->hasDiscard();
5391     const bool isAlphaToCoverageEnabled = mState.isSampleAlphaToCoverageEnabled();
5392 
5393     mGraphicsPipelineDesc->updateNonZeroStencilWriteMaskWorkaround(
5394         &mGraphicsPipelineTransition, programHasDiscard || isAlphaToCoverageEnabled);
5395 }
5396 
invalidateProgramExecutableHelper(const gl::Context * context)5397 angle::Result ContextVk::invalidateProgramExecutableHelper(const gl::Context *context)
5398 {
5399     const gl::State &glState                = context->getState();
5400     const gl::ProgramExecutable *executable = glState.getProgramExecutable();
5401 
5402     if (executable->hasLinkedShaderStage(gl::ShaderType::Compute))
5403     {
5404         invalidateCurrentComputePipeline();
5405     }
5406 
5407     if (executable->hasLinkedShaderStage(gl::ShaderType::Vertex))
5408     {
5409         invalidateCurrentGraphicsPipeline();
5410         // No additional work is needed here. We will update the pipeline desc
5411         // later.
5412         invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask());
5413         invalidateVertexAndIndexBuffers();
5414         // If VK_EXT_vertex_input_dynamic_state is enabled then vkCmdSetVertexInputEXT must be
5415         // called in the current command buffer prior to the draw command, even if there are no
5416         // active vertex attributes.
5417         const bool useVertexBuffer = (executable->getMaxActiveAttribLocation() > 0) ||
5418                                      getFeatures().supportsVertexInputDynamicState.enabled;
5419         mNonIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer);
5420         mIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer);
5421         resetCurrentGraphicsPipeline();
5422 
5423         const vk::FramebufferFetchMode framebufferFetchMode =
5424             vk::GetProgramFramebufferFetchMode(executable);
5425         const bool hasColorFramebufferFetch =
5426             framebufferFetchMode != vk::FramebufferFetchMode::None;
5427         if (getFeatures().preferDynamicRendering.enabled)
5428         {
5429             // Update the framebuffer fetch mode on the pipeline desc directly.  This is an inherent
5430             // property of the executable. Even if the bit is placed in RenderPassDesc because of
5431             // the non-dynamic-rendering path, updating it without affecting the transition bits is
5432             // valid because there cannot be a transition link between pipelines of different
5433             // programs.  This is attested by the fact that |resetCurrentGraphicsPipeline| above
5434             // sets |mCurrentGraphicsPipeline| to nullptr.
5435             mGraphicsPipelineDesc->setRenderPassFramebufferFetchMode(framebufferFetchMode);
5436 
5437             if (framebufferFetchMode != vk::FramebufferFetchMode::None)
5438             {
5439                 onFramebufferFetchUse(framebufferFetchMode);
5440             }
5441         }
5442         else
5443         {
5444             ASSERT(!FramebufferFetchModeHasDepthStencil(framebufferFetchMode));
5445             if (mIsInColorFramebufferFetchMode != hasColorFramebufferFetch)
5446             {
5447                 ASSERT(getDrawFramebuffer()->getRenderPassDesc().hasColorFramebufferFetch() ==
5448                        mIsInColorFramebufferFetchMode);
5449 
5450                 ANGLE_TRY(switchToColorFramebufferFetchMode(hasColorFramebufferFetch));
5451 
5452                 // When framebuffer fetch is enabled, attachments can be read from even if output is
5453                 // masked, so update their access.
5454                 onColorAccessChange();
5455             }
5456 
5457             // If permanentlySwitchToFramebufferFetchMode is enabled,
5458             // mIsInColorFramebufferFetchMode will remain true throughout the entire time.
5459             // If we switch from a program that doesn't use framebuffer fetch and doesn't
5460             // read/write to the framebuffer color attachment, to a
5461             // program that uses framebuffer fetch and needs to read from the framebuffer
5462             // color attachment, we will miss the call
5463             // onColorAccessChange() above and miss setting the dirty bit
5464             // DIRTY_BIT_COLOR_ACCESS. This means we will not call
5465             // handleDirtyGraphicsColorAccess that updates the access value of
5466             // framebuffer color attachment from unused to readonly. This makes the
5467             // color attachment to continue using LoadOpNone, and the second program
5468             // will not be able to read the value in the color attachment.
5469             if (getFeatures().permanentlySwitchToFramebufferFetchMode.enabled &&
5470                 hasColorFramebufferFetch)
5471             {
5472                 onColorAccessChange();
5473             }
5474         }
5475 
5476         // If framebuffer fetch is exposed but is internally non-coherent, make sure a framebuffer
5477         // fetch barrier is issued before each draw call as long as a program with framebuffer fetch
5478         // is used.  If the application would have correctly used non-coherent framebuffer fetch, it
5479         // would have been optimal _not_ to expose the coherent extension.  However, lots of
5480         // Android applications expect coherent framebuffer fetch to be available.
5481         if (mRenderer->isCoherentColorFramebufferFetchEmulated())
5482         {
5483             mGraphicsDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_FETCH_BARRIER, hasColorFramebufferFetch);
5484         }
5485 
5486         updateStencilWriteWorkaround();
5487 
5488         mGraphicsPipelineDesc->updateVertexShaderComponentTypes(
5489             &mGraphicsPipelineTransition, executable->getNonBuiltinAttribLocationsMask(),
5490             executable->getAttributesTypeMask());
5491 
5492         updateMissingAttachments();
5493     }
5494 
5495     return angle::Result::Continue;
5496 }
5497 
syncState(const gl::Context * context,const gl::state::DirtyBits dirtyBits,const gl::state::DirtyBits bitMask,const gl::state::ExtendedDirtyBits extendedDirtyBits,const gl::state::ExtendedDirtyBits extendedBitMask,gl::Command command)5498 angle::Result ContextVk::syncState(const gl::Context *context,
5499                                    const gl::state::DirtyBits dirtyBits,
5500                                    const gl::state::DirtyBits bitMask,
5501                                    const gl::state::ExtendedDirtyBits extendedDirtyBits,
5502                                    const gl::state::ExtendedDirtyBits extendedBitMask,
5503                                    gl::Command command)
5504 {
5505     const gl::State &glState                       = context->getState();
5506     const gl::ProgramExecutable *programExecutable = glState.getProgramExecutable();
5507 
5508     if ((dirtyBits & mPipelineDirtyBitsMask).any() &&
5509         (programExecutable == nullptr || command != gl::Command::Dispatch))
5510     {
5511         invalidateCurrentGraphicsPipeline();
5512     }
5513 
5514     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
5515     VertexArrayVk *vertexArrayVk     = getVertexArray();
5516 
5517     for (auto iter = dirtyBits.begin(), endIter = dirtyBits.end(); iter != endIter; ++iter)
5518     {
5519         size_t dirtyBit = *iter;
5520         switch (dirtyBit)
5521         {
5522             case gl::state::DIRTY_BIT_SCISSOR_TEST_ENABLED:
5523             case gl::state::DIRTY_BIT_SCISSOR:
5524                 updateScissor(glState);
5525                 break;
5526             case gl::state::DIRTY_BIT_VIEWPORT:
5527             {
5528                 FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer());
5529                 updateViewport(framebufferVk, glState.getViewport(), glState.getNearPlane(),
5530                                glState.getFarPlane());
5531                 // Update the scissor, which will be constrained to the viewport
5532                 updateScissor(glState);
5533                 break;
5534             }
5535             case gl::state::DIRTY_BIT_DEPTH_RANGE:
5536                 updateDepthRange(glState.getNearPlane(), glState.getFarPlane());
5537                 break;
5538             case gl::state::DIRTY_BIT_BLEND_ENABLED:
5539                 mGraphicsPipelineDesc->updateBlendEnabled(
5540                     &mGraphicsPipelineTransition, glState.getBlendStateExt().getEnabledMask());
5541                 updateDither();
5542                 updateAdvancedBlendEquations(programExecutable);
5543                 break;
5544             case gl::state::DIRTY_BIT_BLEND_COLOR:
5545                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_BLEND_CONSTANTS);
5546                 break;
5547             case gl::state::DIRTY_BIT_BLEND_FUNCS:
5548                 mGraphicsPipelineDesc->updateBlendFuncs(
5549                     &mGraphicsPipelineTransition, glState.getBlendStateExt(),
5550                     drawFramebufferVk->getState().getColorAttachmentsMask());
5551                 break;
5552             case gl::state::DIRTY_BIT_BLEND_EQUATIONS:
5553                 mGraphicsPipelineDesc->updateBlendEquations(
5554                     &mGraphicsPipelineTransition, glState.getBlendStateExt(),
5555                     drawFramebufferVk->getState().getColorAttachmentsMask());
5556                 updateAdvancedBlendEquations(programExecutable);
5557                 break;
5558             case gl::state::DIRTY_BIT_COLOR_MASK:
5559                 updateColorMasks();
5560                 break;
5561             case gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
5562                 updateAlphaToCoverageWithRasterizationSamples(drawFramebufferVk->getSamples());
5563                 updateStencilWriteWorkaround();
5564 
5565                 static_assert(gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE >
5566                                   gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED,
5567                               "Dirty bit order");
5568                 iter.setLaterBit(gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE);
5569                 break;
5570             case gl::state::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED:
5571                 updateSampleMaskWithRasterizationSamples(drawFramebufferVk->getSamples());
5572                 break;
5573             case gl::state::DIRTY_BIT_SAMPLE_COVERAGE:
5574                 updateSampleMaskWithRasterizationSamples(drawFramebufferVk->getSamples());
5575                 break;
5576             case gl::state::DIRTY_BIT_SAMPLE_MASK_ENABLED:
5577                 updateSampleMaskWithRasterizationSamples(drawFramebufferVk->getSamples());
5578                 break;
5579             case gl::state::DIRTY_BIT_SAMPLE_MASK:
5580                 updateSampleMaskWithRasterizationSamples(drawFramebufferVk->getSamples());
5581                 break;
5582             case gl::state::DIRTY_BIT_DEPTH_TEST_ENABLED:
5583                 updateDepthTestEnabled(glState);
5584                 iter.setLaterBit(gl::state::DIRTY_BIT_DEPTH_MASK);
5585                 break;
5586             case gl::state::DIRTY_BIT_DEPTH_FUNC:
5587                 updateDepthFunc(glState);
5588                 onDepthStencilAccessChange();
5589                 break;
5590             case gl::state::DIRTY_BIT_DEPTH_MASK:
5591                 updateDepthWriteEnabled(glState);
5592                 onDepthStencilAccessChange();
5593                 break;
5594             case gl::state::DIRTY_BIT_STENCIL_TEST_ENABLED:
5595                 updateStencilTestEnabled(glState);
5596                 onDepthStencilAccessChange();
5597                 break;
5598             case gl::state::DIRTY_BIT_STENCIL_FUNCS_FRONT:
5599                 if (mRenderer->getFeatures().useStencilOpDynamicState.enabled)
5600                 {
5601                     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_OP);
5602                 }
5603                 else
5604                 {
5605                     mGraphicsPipelineDesc->updateStencilFrontFuncs(&mGraphicsPipelineTransition,
5606                                                                    glState.getDepthStencilState());
5607                 }
5608                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_COMPARE_MASK);
5609                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_REFERENCE);
5610                 onDepthStencilAccessChange();
5611                 break;
5612             case gl::state::DIRTY_BIT_STENCIL_FUNCS_BACK:
5613                 if (mRenderer->getFeatures().useStencilOpDynamicState.enabled)
5614                 {
5615                     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_OP);
5616                 }
5617                 else
5618                 {
5619                     mGraphicsPipelineDesc->updateStencilBackFuncs(&mGraphicsPipelineTransition,
5620                                                                   glState.getDepthStencilState());
5621                 }
5622                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_COMPARE_MASK);
5623                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_REFERENCE);
5624                 onDepthStencilAccessChange();
5625                 break;
5626             case gl::state::DIRTY_BIT_STENCIL_OPS_FRONT:
5627                 if (mRenderer->getFeatures().useStencilOpDynamicState.enabled)
5628                 {
5629                     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_OP);
5630                 }
5631                 else
5632                 {
5633                     mGraphicsPipelineDesc->updateStencilFrontOps(&mGraphicsPipelineTransition,
5634                                                                  glState.getDepthStencilState());
5635                 }
5636                 onDepthStencilAccessChange();
5637                 break;
5638             case gl::state::DIRTY_BIT_STENCIL_OPS_BACK:
5639                 if (mRenderer->getFeatures().useStencilOpDynamicState.enabled)
5640                 {
5641                     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_OP);
5642                 }
5643                 else
5644                 {
5645                     mGraphicsPipelineDesc->updateStencilBackOps(&mGraphicsPipelineTransition,
5646                                                                 glState.getDepthStencilState());
5647                 }
5648                 onDepthStencilAccessChange();
5649                 break;
5650             case gl::state::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
5651             case gl::state::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
5652                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_WRITE_MASK);
5653                 onDepthStencilAccessChange();
5654                 break;
5655             case gl::state::DIRTY_BIT_CULL_FACE_ENABLED:
5656             case gl::state::DIRTY_BIT_CULL_FACE:
5657                 if (mRenderer->getFeatures().useCullModeDynamicState.enabled)
5658                 {
5659                     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_CULL_MODE);
5660                 }
5661                 else
5662                 {
5663                     mGraphicsPipelineDesc->updateCullMode(&mGraphicsPipelineTransition,
5664                                                           glState.getRasterizerState());
5665                 }
5666                 break;
5667             case gl::state::DIRTY_BIT_FRONT_FACE:
5668                 updateFrontFace();
5669                 break;
5670             case gl::state::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
5671                 if (mRenderer->getFeatures().useDepthBiasEnableDynamicState.enabled)
5672                 {
5673                     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_BIAS_ENABLE);
5674                 }
5675                 else
5676                 {
5677                     mGraphicsPipelineDesc->updatePolygonOffsetEnabled(
5678                         &mGraphicsPipelineTransition, glState.isPolygonOffsetEnabled());
5679                 }
5680                 break;
5681             case gl::state::DIRTY_BIT_POLYGON_OFFSET:
5682                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_BIAS);
5683                 break;
5684             case gl::state::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
5685                 updateRasterizerDiscardEnabled(
5686                     mState.isQueryActive(gl::QueryType::PrimitivesGenerated));
5687                 onColorAccessChange();
5688                 break;
5689             case gl::state::DIRTY_BIT_LINE_WIDTH:
5690                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_LINE_WIDTH);
5691                 break;
5692             case gl::state::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED:
5693                 if (mRenderer->getFeatures().usePrimitiveRestartEnableDynamicState.enabled)
5694                 {
5695                     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_PRIMITIVE_RESTART_ENABLE);
5696                 }
5697                 else
5698                 {
5699                     mGraphicsPipelineDesc->updatePrimitiveRestartEnabled(
5700                         &mGraphicsPipelineTransition, glState.isPrimitiveRestartEnabled());
5701                 }
5702                 // Additionally set the index buffer dirty if conversion from uint8 might have been
5703                 // necessary.  Otherwise if primitive restart is enabled and the index buffer is
5704                 // translated to uint16_t with a value of 0xFFFF, it cannot be reused when primitive
5705                 // restart is disabled.
5706                 if (!mRenderer->getFeatures().supportsIndexTypeUint8.enabled)
5707                 {
5708                     mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
5709                 }
5710                 break;
5711             case gl::state::DIRTY_BIT_CLEAR_COLOR:
5712                 mClearColorValue.color.float32[0] = glState.getColorClearValue().red;
5713                 mClearColorValue.color.float32[1] = glState.getColorClearValue().green;
5714                 mClearColorValue.color.float32[2] = glState.getColorClearValue().blue;
5715                 mClearColorValue.color.float32[3] = glState.getColorClearValue().alpha;
5716                 break;
5717             case gl::state::DIRTY_BIT_CLEAR_DEPTH:
5718                 mClearDepthStencilValue.depthStencil.depth = glState.getDepthClearValue();
5719                 break;
5720             case gl::state::DIRTY_BIT_CLEAR_STENCIL:
5721                 mClearDepthStencilValue.depthStencil.stencil =
5722                     static_cast<uint32_t>(glState.getStencilClearValue());
5723                 break;
5724             case gl::state::DIRTY_BIT_UNPACK_STATE:
5725                 // This is a no-op, it's only important to use the right unpack state when we do
5726                 // setImage or setSubImage in TextureVk, which is plumbed through the frontend
5727                 // call
5728                 break;
5729             case gl::state::DIRTY_BIT_UNPACK_BUFFER_BINDING:
5730                 break;
5731             case gl::state::DIRTY_BIT_PACK_STATE:
5732                 // This is a no-op, its only important to use the right pack state when we do
5733                 // call readPixels later on.
5734                 break;
5735             case gl::state::DIRTY_BIT_PACK_BUFFER_BINDING:
5736                 break;
5737             case gl::state::DIRTY_BIT_DITHER_ENABLED:
5738                 updateDither();
5739                 break;
5740             case gl::state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING:
5741                 updateFlipViewportReadFramebuffer(context->getState());
5742                 updateSurfaceRotationReadFramebuffer(glState, context->getCurrentReadSurface());
5743                 break;
5744             case gl::state::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
5745             {
5746                 // FramebufferVk::syncState signals that we should start a new command buffer.
5747                 // But changing the binding can skip FramebufferVk::syncState if the Framebuffer
5748                 // has no dirty bits. Thus we need to explicitly clear the current command
5749                 // buffer to ensure we start a new one. We don't actually close the render pass here
5750                 // as some optimizations in non-draw commands require the render pass to remain
5751                 // open, such as invalidate or blit. Note that we always start a new command buffer
5752                 // because we currently can only support one open RenderPass at a time.
5753                 //
5754                 // The render pass is not closed if binding is changed to the same framebuffer as
5755                 // before.
5756                 if (hasActiveRenderPass() && hasStartedRenderPassWithQueueSerial(
5757                                                  drawFramebufferVk->getLastRenderPassQueueSerial()))
5758                 {
5759                     break;
5760                 }
5761 
5762                 onRenderPassFinished(RenderPassClosureReason::FramebufferBindingChange);
5763                 // If we are switching from user FBO to system frame buffer, we always submit work
5764                 // first so that these FBO rendering will not have to wait for ANI semaphore (which
5765                 // draw to system frame buffer must wait for).
5766 
5767                 // To reduce CPU overhead if submission at FBO boundary is preferred, the deferred
5768                 // flush is triggered after the currently accumulated command count for the render
5769                 // pass command buffer hits a threshold (kMinCommandCountToSubmit). However,
5770                 // currently in the case of a clear or invalidate GL command, a deferred flush is
5771                 // still triggered.
5772                 uint32_t currentRPCommandCount =
5773                     mRenderPassCommands->getCommandBuffer().getRenderPassWriteCommandCount() +
5774                     mCommandsPendingSubmissionCount;
5775                 bool allowExceptionForSubmitAtBoundary = command == gl::Command::Clear ||
5776                                                          command == gl::Command::Invalidate ||
5777                                                          mRenderer->isInFlightCommandsEmpty();
5778                 bool shouldSubmitAtFBOBoundary =
5779                     getFeatures().preferSubmitAtFBOBoundary.enabled &&
5780                     (currentRPCommandCount >= kMinCommandCountToSubmit ||
5781                      allowExceptionForSubmitAtBoundary);
5782 
5783                 if ((shouldSubmitAtFBOBoundary || mState.getDrawFramebuffer()->isDefault()) &&
5784                     mRenderPassCommands->started())
5785                 {
5786                     // This will behave as if user called glFlush, but the actual flush will be
5787                     // triggered at endRenderPass time.
5788                     mHasDeferredFlush = true;
5789                 }
5790 
5791                 mDepthStencilAttachmentFlags.reset();
5792                 updateFlipViewportDrawFramebuffer(glState);
5793                 updateSurfaceRotationDrawFramebuffer(glState, context->getCurrentDrawSurface());
5794                 updateViewport(drawFramebufferVk, glState.getViewport(), glState.getNearPlane(),
5795                                glState.getFarPlane());
5796                 updateColorMasks();
5797                 updateMissingAttachments();
5798                 updateRasterizationSamples(drawFramebufferVk->getSamples());
5799                 updateRasterizerDiscardEnabled(
5800                     mState.isQueryActive(gl::QueryType::PrimitivesGenerated));
5801 
5802                 updateFrontFace();
5803                 updateScissor(glState);
5804                 updateDepthStencil(glState);
5805                 updateDither();
5806 
5807                 // Clear the blend funcs/equations for color attachment indices that no longer
5808                 // exist.
5809                 gl::DrawBufferMask newColorAttachmentMask =
5810                     drawFramebufferVk->getState().getColorAttachmentsMask();
5811                 mGraphicsPipelineDesc->resetBlendFuncsAndEquations(
5812                     &mGraphicsPipelineTransition, glState.getBlendStateExt(),
5813                     mCachedDrawFramebufferColorAttachmentMask, newColorAttachmentMask);
5814                 mCachedDrawFramebufferColorAttachmentMask = newColorAttachmentMask;
5815 
5816                 if (!getFeatures().preferDynamicRendering.enabled)
5817                 {
5818                     // The framebuffer may not be in sync with usage of framebuffer fetch programs.
5819                     drawFramebufferVk->switchToColorFramebufferFetchMode(
5820                         this, mIsInColorFramebufferFetchMode);
5821                 }
5822 
5823                 onDrawFramebufferRenderPassDescChange(drawFramebufferVk, nullptr);
5824 
5825                 break;
5826             }
5827             case gl::state::DIRTY_BIT_RENDERBUFFER_BINDING:
5828                 break;
5829             case gl::state::DIRTY_BIT_VERTEX_ARRAY_BINDING:
5830             {
5831                 invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask());
5832                 ANGLE_TRY(vertexArrayVk->updateActiveAttribInfo(this));
5833                 ANGLE_TRY(onIndexBufferChange(vertexArrayVk->getCurrentElementArrayBuffer()));
5834                 break;
5835             }
5836             case gl::state::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
5837                 break;
5838             case gl::state::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING:
5839                 break;
5840             case gl::state::DIRTY_BIT_PROGRAM_BINDING:
5841                 static_assert(
5842                     gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE > gl::state::DIRTY_BIT_PROGRAM_BINDING,
5843                     "Dirty bit order");
5844                 iter.setLaterBit(gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE);
5845                 break;
5846             case gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE:
5847             {
5848                 ASSERT(programExecutable);
5849                 invalidateCurrentDefaultUniforms();
5850                 updateAdvancedBlendEquations(programExecutable);
5851                 vk::GetImpl(programExecutable)->onProgramBind();
5852                 static_assert(
5853                     gl::state::DIRTY_BIT_TEXTURE_BINDINGS > gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE,
5854                     "Dirty bit order");
5855                 iter.setLaterBit(gl::state::DIRTY_BIT_TEXTURE_BINDINGS);
5856                 ANGLE_TRY(invalidateCurrentShaderResources(command));
5857                 ANGLE_TRY(invalidateProgramExecutableHelper(context));
5858 
5859                 static_assert(
5860                     gl::state::DIRTY_BIT_SAMPLE_SHADING > gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE,
5861                     "Dirty bit order");
5862                 if (getFeatures().explicitlyEnablePerSampleShading.enabled)
5863                 {
5864                     iter.setLaterBit(gl::state::DIRTY_BIT_SAMPLE_SHADING);
5865                 }
5866 
5867                 break;
5868             }
5869             case gl::state::DIRTY_BIT_SAMPLER_BINDINGS:
5870             {
5871                 static_assert(
5872                     gl::state::DIRTY_BIT_TEXTURE_BINDINGS > gl::state::DIRTY_BIT_SAMPLER_BINDINGS,
5873                     "Dirty bit order");
5874                 iter.setLaterBit(gl::state::DIRTY_BIT_TEXTURE_BINDINGS);
5875                 break;
5876             }
5877             case gl::state::DIRTY_BIT_TEXTURE_BINDINGS:
5878                 ANGLE_TRY(invalidateCurrentTextures(context, command));
5879                 break;
5880             case gl::state::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
5881                 // Nothing to do.
5882                 break;
5883             case gl::state::DIRTY_BIT_IMAGE_BINDINGS:
5884                 static_assert(gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING >
5885                                   gl::state::DIRTY_BIT_IMAGE_BINDINGS,
5886                               "Dirty bit order");
5887                 iter.setLaterBit(gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
5888                 break;
5889             case gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
5890                 static_assert(gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING >
5891                                   gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING,
5892                               "Dirty bit order");
5893                 iter.setLaterBit(gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
5894                 break;
5895             case gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
5896                 ANGLE_TRY(invalidateCurrentShaderUniformBuffers(command));
5897                 break;
5898             case gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
5899                 ANGLE_TRY(invalidateCurrentShaderResources(command));
5900                 invalidateDriverUniforms();
5901                 break;
5902             case gl::state::DIRTY_BIT_MULTISAMPLING:
5903                 // When disabled, this should configure the pipeline to render as if single-sampled,
5904                 // and write the results to all samples of a pixel regardless of coverage. See
5905                 // EXT_multisample_compatibility.  This is not possible in Vulkan without some
5906                 // gymnastics, so continue multisampled rendering anyway.
5907                 // http://anglebug.com/42266123
5908                 //
5909                 // Potentially, the GLES1 renderer can switch rendering between two images and blit
5910                 // from one to the other when the mode changes.  Then this extension wouldn't need
5911                 // to be exposed.
5912                 iter.setLaterBit(gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
5913                 break;
5914             case gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE:
5915                 // This is part of EXT_multisample_compatibility, and requires the alphaToOne Vulkan
5916                 // feature.
5917                 // http://anglebug.com/42266123
5918                 mGraphicsPipelineDesc->updateAlphaToOneEnable(
5919                     &mGraphicsPipelineTransition,
5920                     glState.isMultisamplingEnabled() && glState.isSampleAlphaToOneEnabled());
5921                 break;
5922             case gl::state::DIRTY_BIT_SAMPLE_SHADING:
5923                 updateSampleShadingWithRasterizationSamples(drawFramebufferVk->getSamples());
5924                 break;
5925             case gl::state::DIRTY_BIT_COVERAGE_MODULATION:
5926                 break;
5927             case gl::state::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE:
5928                 break;
5929             case gl::state::DIRTY_BIT_CURRENT_VALUES:
5930             {
5931                 invalidateDefaultAttributes(glState.getAndResetDirtyCurrentValues());
5932                 break;
5933             }
5934             case gl::state::DIRTY_BIT_PROVOKING_VERTEX:
5935                 break;
5936             case gl::state::DIRTY_BIT_EXTENDED:
5937             {
5938                 for (auto extendedIter    = extendedDirtyBits.begin(),
5939                           extendedEndIter = extendedDirtyBits.end();
5940                      extendedIter != extendedEndIter; ++extendedIter)
5941                 {
5942                     const size_t extendedDirtyBit = *extendedIter;
5943                     switch (extendedDirtyBit)
5944                     {
5945                         case gl::state::EXTENDED_DIRTY_BIT_CLIP_CONTROL:
5946                             updateViewport(vk::GetImpl(glState.getDrawFramebuffer()),
5947                                            glState.getViewport(), glState.getNearPlane(),
5948                                            glState.getFarPlane());
5949                             // Since we are flipping the y coordinate, update front face state
5950                             updateFrontFace();
5951                             updateScissor(glState);
5952 
5953                             // If VK_EXT_depth_clip_control is not enabled, there's nothing needed
5954                             // for depth correction for EXT_clip_control.
5955                             // glState will be used to toggle control path of depth correction code
5956                             // in SPIR-V transform options.
5957                             if (getFeatures().supportsDepthClipControl.enabled)
5958                             {
5959                                 mGraphicsPipelineDesc->updateDepthClipControl(
5960                                     &mGraphicsPipelineTransition,
5961                                     !glState.isClipDepthModeZeroToOne());
5962                             }
5963                             else
5964                             {
5965                                 invalidateGraphicsDriverUniforms();
5966                             }
5967                             break;
5968                         case gl::state::EXTENDED_DIRTY_BIT_CLIP_DISTANCES:
5969                             invalidateGraphicsDriverUniforms();
5970                             break;
5971                         case gl::state::EXTENDED_DIRTY_BIT_DEPTH_CLAMP_ENABLED:
5972                             // TODO(https://anglebug.com/42266182): Use EDS3
5973                             mGraphicsPipelineDesc->updateDepthClampEnabled(
5974                                 &mGraphicsPipelineTransition, glState.isDepthClampEnabled());
5975                             break;
5976                         case gl::state::EXTENDED_DIRTY_BIT_MIPMAP_GENERATION_HINT:
5977                             break;
5978                         case gl::state::EXTENDED_DIRTY_BIT_POLYGON_MODE:
5979                             // TODO(https://anglebug.com/42266182): Use EDS3
5980                             mGraphicsPipelineDesc->updatePolygonMode(&mGraphicsPipelineTransition,
5981                                                                      glState.getPolygonMode());
5982                             // When polygon mode is changed, depth bias might need to be toggled.
5983                             static_assert(
5984                                 gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED >
5985                                     gl::state::EXTENDED_DIRTY_BIT_POLYGON_MODE,
5986                                 "Dirty bit order");
5987                             extendedIter.setLaterBit(
5988                                 gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED);
5989                             break;
5990                         case gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_POINT_ENABLED:
5991                         case gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED:
5992                             if (mRenderer->getFeatures().useDepthBiasEnableDynamicState.enabled)
5993                             {
5994                                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_BIAS_ENABLE);
5995                             }
5996                             else
5997                             {
5998                                 mGraphicsPipelineDesc->updatePolygonOffsetEnabled(
5999                                     &mGraphicsPipelineTransition, glState.isPolygonOffsetEnabled());
6000                             }
6001                             break;
6002                         case gl::state::EXTENDED_DIRTY_BIT_SHADER_DERIVATIVE_HINT:
6003                             break;
6004                         case gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED:
6005                             mGraphicsPipelineDesc->updateLogicOpEnabled(
6006                                 &mGraphicsPipelineTransition, glState.isLogicOpEnabled());
6007                             break;
6008                         case gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP:
6009                             if (mRenderer->getFeatures().supportsLogicOpDynamicState.enabled)
6010                             {
6011                                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_LOGIC_OP);
6012                             }
6013                             else
6014                             {
6015                                 mGraphicsPipelineDesc->updateLogicOp(
6016                                     &mGraphicsPipelineTransition,
6017                                     gl_vk::GetLogicOp(gl::ToGLenum(glState.getLogicOp())));
6018                             }
6019                             break;
6020                         case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE:
6021                             if (getFeatures().supportsFragmentShadingRate.enabled)
6022                             {
6023                                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_FRAGMENT_SHADING_RATE);
6024                             }
6025                             break;
6026                         case gl::state::EXTENDED_DIRTY_BIT_BLEND_ADVANCED_COHERENT:
6027                             break;
6028                         default:
6029                             UNREACHABLE();
6030                     }
6031                 }
6032                 break;
6033             }
6034             case gl::state::DIRTY_BIT_PATCH_VERTICES:
6035                 mGraphicsPipelineDesc->updatePatchVertices(&mGraphicsPipelineTransition,
6036                                                            glState.getPatchVertices());
6037                 break;
6038             default:
6039                 UNREACHABLE();
6040                 break;
6041         }
6042     }
6043 
6044     return angle::Result::Continue;
6045 }
6046 
getGPUDisjoint()6047 GLint ContextVk::getGPUDisjoint()
6048 {
6049     // No extension seems to be available to query this information.
6050     return 0;
6051 }
6052 
getTimestamp()6053 GLint64 ContextVk::getTimestamp()
6054 {
6055     // This function should only be called if timestamp queries are available.
6056     ASSERT(mRenderer->getQueueFamilyProperties().timestampValidBits > 0);
6057 
6058     uint64_t timestamp = 0;
6059 
6060     (void)getTimestamp(&timestamp);
6061 
6062     return static_cast<GLint64>(timestamp);
6063 }
6064 
onMakeCurrent(const gl::Context * context)6065 angle::Result ContextVk::onMakeCurrent(const gl::Context *context)
6066 {
6067     mRenderer->reloadVolkIfNeeded();
6068 
6069     if (mCurrentQueueSerialIndex == kInvalidQueueSerialIndex)
6070     {
6071         ANGLE_TRY(allocateQueueSerialIndex());
6072     }
6073 
6074     // Flip viewports if the user did not request that the surface is flipped.
6075     const egl::Surface *drawSurface = context->getCurrentDrawSurface();
6076     const egl::Surface *readSurface = context->getCurrentReadSurface();
6077     mFlipYForCurrentSurface =
6078         drawSurface != nullptr &&
6079         !IsMaskFlagSet(drawSurface->getOrientation(), EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE);
6080 
6081     if (drawSurface && drawSurface->getType() == EGL_WINDOW_BIT)
6082     {
6083         mCurrentWindowSurface = GetImplAs<WindowSurfaceVk>(drawSurface);
6084     }
6085     else
6086     {
6087         mCurrentWindowSurface = nullptr;
6088     }
6089 
6090     const gl::State &glState = context->getState();
6091     updateFlipViewportDrawFramebuffer(glState);
6092     updateFlipViewportReadFramebuffer(glState);
6093     updateSurfaceRotationDrawFramebuffer(glState, drawSurface);
6094     updateSurfaceRotationReadFramebuffer(glState, readSurface);
6095 
6096     invalidateDriverUniforms();
6097 
6098     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6099     if (executable && executable->hasTransformFeedbackOutput() &&
6100         mState.isTransformFeedbackActive())
6101     {
6102         onTransformFeedbackStateChanged();
6103         if (getFeatures().supportsTransformFeedbackExtension.enabled)
6104         {
6105             mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
6106         }
6107     }
6108 
6109     return angle::Result::Continue;
6110 }
6111 
onUnMakeCurrent(const gl::Context * context)6112 angle::Result ContextVk::onUnMakeCurrent(const gl::Context *context)
6113 {
6114     ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr, RenderPassClosureReason::ContextChange));
6115     mCurrentWindowSurface = nullptr;
6116 
6117     if (mCurrentQueueSerialIndex != kInvalidQueueSerialIndex)
6118     {
6119         releaseQueueSerialIndex();
6120     }
6121     return angle::Result::Continue;
6122 }
6123 
onSurfaceUnMakeCurrent(WindowSurfaceVk * surface)6124 angle::Result ContextVk::onSurfaceUnMakeCurrent(WindowSurfaceVk *surface)
6125 {
6126     // It is possible to destroy "WindowSurfaceVk" while not all rendering commands are submitted:
6127     // 1. Make "WindowSurfaceVk" current.
6128     // 2. Draw something.
6129     // 3. Make other Surface current (same Context).
6130     // 4. (optional) Draw something.
6131     // 5. Delete "WindowSurfaceVk".
6132     // 6. UnMake the Context from current.
6133     // Flush all command to the GPU while still having access to the Context.
6134 
6135     // The above "onUnMakeCurrent()" may have already been called.
6136     if (mCurrentQueueSerialIndex != kInvalidQueueSerialIndex)
6137     {
6138         // May be nullptr if only used as a readSurface.
6139         ASSERT(mCurrentWindowSurface == surface || mCurrentWindowSurface == nullptr);
6140         ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr,
6141                                          RenderPassClosureReason::SurfaceUnMakeCurrent));
6142         mCurrentWindowSurface = nullptr;
6143     }
6144     ASSERT(mCurrentWindowSurface == nullptr);
6145 
6146     // Everything must be flushed and submitted.
6147     ASSERT(mOutsideRenderPassCommands->empty());
6148     ASSERT(!mRenderPassCommands->started());
6149     ASSERT(mWaitSemaphores.empty());
6150     ASSERT(!mHasWaitSemaphoresPendingSubmission);
6151     ASSERT(mLastSubmittedQueueSerial == mLastFlushedQueueSerial);
6152     return angle::Result::Continue;
6153 }
6154 
onSurfaceUnMakeCurrent(OffscreenSurfaceVk * surface)6155 angle::Result ContextVk::onSurfaceUnMakeCurrent(OffscreenSurfaceVk *surface)
6156 {
6157     // It is possible to destroy "OffscreenSurfaceVk" while RenderPass is still opened:
6158     // 1. Make "OffscreenSurfaceVk" current.
6159     // 2. Draw something with RenderPass.
6160     // 3. Make other Surface current (same Context)
6161     // 4. Delete "OffscreenSurfaceVk".
6162     // 5. UnMake the Context from current.
6163     // End RenderPass to avoid crash in the "RenderPassCommandBufferHelper::endRenderPass()".
6164     // Flush commands unconditionally even if surface is not used in the RenderPass to fix possible
6165     // problems related to other accesses. "flushAndSubmitCommands()" is not required because
6166     // "OffscreenSurfaceVk" uses GC.
6167 
6168     // The above "onUnMakeCurrent()" may have already been called.
6169     if (mCurrentQueueSerialIndex != kInvalidQueueSerialIndex)
6170     {
6171         ANGLE_TRY(flushCommandsAndEndRenderPass(RenderPassClosureReason::SurfaceUnMakeCurrent));
6172     }
6173 
6174     // Everything must be flushed but may be pending submission.
6175     ASSERT(mOutsideRenderPassCommands->empty());
6176     ASSERT(!mRenderPassCommands->started());
6177     ASSERT(mWaitSemaphores.empty());
6178     return angle::Result::Continue;
6179 }
6180 
updateFlipViewportDrawFramebuffer(const gl::State & glState)6181 void ContextVk::updateFlipViewportDrawFramebuffer(const gl::State &glState)
6182 {
6183     // The default framebuffer (originating from the swapchain) is rendered upside-down due to the
6184     // difference in the coordinate systems of Vulkan and GLES.  Rendering upside-down has the
6185     // effect that rendering is done the same way as OpenGL.  The KHR_MAINTENANCE_1 extension is
6186     // subsequently enabled to allow negative viewports.  We inverse rendering to the backbuffer by
6187     // reversing the height of the viewport and increasing Y by the height.  So if the viewport was
6188     // (0, 0, width, height), it becomes (0, height, width, -height).  Unfortunately, when we start
6189     // doing this, we also need to adjust a number of places since the rendering now happens
6190     // upside-down.  Affected places so far:
6191     //
6192     // - readPixels
6193     // - copyTexImage
6194     // - framebuffer blit
6195     // - generating mipmaps
6196     // - Point sprites tests
6197     // - texStorage
6198     gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
6199     mFlipViewportForDrawFramebuffer  = drawFramebuffer->isDefault();
6200 }
6201 
updateFlipViewportReadFramebuffer(const gl::State & glState)6202 void ContextVk::updateFlipViewportReadFramebuffer(const gl::State &glState)
6203 {
6204     gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
6205     mFlipViewportForReadFramebuffer  = readFramebuffer->isDefault();
6206 }
6207 
updateSurfaceRotationDrawFramebuffer(const gl::State & glState,const egl::Surface * currentDrawSurface)6208 void ContextVk::updateSurfaceRotationDrawFramebuffer(const gl::State &glState,
6209                                                      const egl::Surface *currentDrawSurface)
6210 {
6211     const SurfaceRotation rotation =
6212         getSurfaceRotationImpl(glState.getDrawFramebuffer(), currentDrawSurface);
6213     mCurrentRotationDrawFramebuffer = rotation;
6214 
6215     if (!getFeatures().preferDriverUniformOverSpecConst.enabled)
6216     {
6217         const bool isRotatedAspectRatio = IsRotatedAspectRatio(rotation);
6218         // Update spec consts
6219         if (isRotatedAspectRatio != mGraphicsPipelineDesc->getSurfaceRotation())
6220         {
6221             // surface rotation are specialization constants, which affects program compilation.
6222             // When rotation changes, we need to update GraphicsPipelineDesc so that the correct
6223             // pipeline program object will be retrieved.
6224             mGraphicsPipelineDesc->updateSurfaceRotation(&mGraphicsPipelineTransition,
6225                                                          isRotatedAspectRatio);
6226             invalidateCurrentGraphicsPipeline();
6227         }
6228     }
6229 }
6230 
updateSurfaceRotationReadFramebuffer(const gl::State & glState,const egl::Surface * currentReadSurface)6231 void ContextVk::updateSurfaceRotationReadFramebuffer(const gl::State &glState,
6232                                                      const egl::Surface *currentReadSurface)
6233 {
6234     mCurrentRotationReadFramebuffer =
6235         getSurfaceRotationImpl(glState.getReadFramebuffer(), currentReadSurface);
6236 }
6237 
getNativeCaps() const6238 gl::Caps ContextVk::getNativeCaps() const
6239 {
6240     return mRenderer->getNativeCaps();
6241 }
6242 
getNativeTextureCaps() const6243 const gl::TextureCapsMap &ContextVk::getNativeTextureCaps() const
6244 {
6245     return mRenderer->getNativeTextureCaps();
6246 }
6247 
getNativeExtensions() const6248 const gl::Extensions &ContextVk::getNativeExtensions() const
6249 {
6250     return mRenderer->getNativeExtensions();
6251 }
6252 
getNativeLimitations() const6253 const gl::Limitations &ContextVk::getNativeLimitations() const
6254 {
6255     return mRenderer->getNativeLimitations();
6256 }
6257 
getNativePixelLocalStorageOptions() const6258 const ShPixelLocalStorageOptions &ContextVk::getNativePixelLocalStorageOptions() const
6259 {
6260     return mRenderer->getNativePixelLocalStorageOptions();
6261 }
6262 
createCompiler()6263 CompilerImpl *ContextVk::createCompiler()
6264 {
6265     return new CompilerVk();
6266 }
6267 
createShader(const gl::ShaderState & state)6268 ShaderImpl *ContextVk::createShader(const gl::ShaderState &state)
6269 {
6270     return new ShaderVk(state);
6271 }
6272 
createProgram(const gl::ProgramState & state)6273 ProgramImpl *ContextVk::createProgram(const gl::ProgramState &state)
6274 {
6275     return new ProgramVk(state);
6276 }
6277 
createProgramExecutable(const gl::ProgramExecutable * executable)6278 ProgramExecutableImpl *ContextVk::createProgramExecutable(const gl::ProgramExecutable *executable)
6279 {
6280     return new ProgramExecutableVk(executable);
6281 }
6282 
createFramebuffer(const gl::FramebufferState & state)6283 FramebufferImpl *ContextVk::createFramebuffer(const gl::FramebufferState &state)
6284 {
6285     return new FramebufferVk(mRenderer, state);
6286 }
6287 
createTexture(const gl::TextureState & state)6288 TextureImpl *ContextVk::createTexture(const gl::TextureState &state)
6289 {
6290     return new TextureVk(state, mRenderer);
6291 }
6292 
createRenderbuffer(const gl::RenderbufferState & state)6293 RenderbufferImpl *ContextVk::createRenderbuffer(const gl::RenderbufferState &state)
6294 {
6295     return new RenderbufferVk(state);
6296 }
6297 
createBuffer(const gl::BufferState & state)6298 BufferImpl *ContextVk::createBuffer(const gl::BufferState &state)
6299 {
6300     return new BufferVk(state);
6301 }
6302 
createVertexArray(const gl::VertexArrayState & state)6303 VertexArrayImpl *ContextVk::createVertexArray(const gl::VertexArrayState &state)
6304 {
6305     return new VertexArrayVk(this, state);
6306 }
6307 
createQuery(gl::QueryType type)6308 QueryImpl *ContextVk::createQuery(gl::QueryType type)
6309 {
6310     return new QueryVk(type);
6311 }
6312 
createFenceNV()6313 FenceNVImpl *ContextVk::createFenceNV()
6314 {
6315     return new FenceNVVk();
6316 }
6317 
createSync()6318 SyncImpl *ContextVk::createSync()
6319 {
6320     return new SyncVk();
6321 }
6322 
createTransformFeedback(const gl::TransformFeedbackState & state)6323 TransformFeedbackImpl *ContextVk::createTransformFeedback(const gl::TransformFeedbackState &state)
6324 {
6325     return new TransformFeedbackVk(state);
6326 }
6327 
createSampler(const gl::SamplerState & state)6328 SamplerImpl *ContextVk::createSampler(const gl::SamplerState &state)
6329 {
6330     return new SamplerVk(state);
6331 }
6332 
createProgramPipeline(const gl::ProgramPipelineState & state)6333 ProgramPipelineImpl *ContextVk::createProgramPipeline(const gl::ProgramPipelineState &state)
6334 {
6335     return new ProgramPipelineVk(state);
6336 }
6337 
createMemoryObject()6338 MemoryObjectImpl *ContextVk::createMemoryObject()
6339 {
6340     return new MemoryObjectVk();
6341 }
6342 
createSemaphore()6343 SemaphoreImpl *ContextVk::createSemaphore()
6344 {
6345     return new SemaphoreVk();
6346 }
6347 
createOverlay(const gl::OverlayState & state)6348 OverlayImpl *ContextVk::createOverlay(const gl::OverlayState &state)
6349 {
6350     return new OverlayVk(state);
6351 }
6352 
invalidateCurrentDefaultUniforms()6353 void ContextVk::invalidateCurrentDefaultUniforms()
6354 {
6355     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6356     ASSERT(executable);
6357 
6358     if (executable->hasDefaultUniforms())
6359     {
6360         mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
6361         mComputeDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
6362     }
6363 }
6364 
invalidateCurrentTextures(const gl::Context * context,gl::Command command)6365 angle::Result ContextVk::invalidateCurrentTextures(const gl::Context *context, gl::Command command)
6366 {
6367     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6368     ASSERT(executable);
6369 
6370     if (executable->hasTextures())
6371     {
6372         mGraphicsDirtyBits |= kTexturesAndDescSetDirtyBits;
6373         mComputeDirtyBits |= kTexturesAndDescSetDirtyBits;
6374 
6375         ANGLE_TRY(updateActiveTextures(context, command));
6376 
6377         if (command == gl::Command::Dispatch)
6378         {
6379             ANGLE_TRY(endRenderPassIfComputeAccessAfterGraphicsImageAccess());
6380         }
6381     }
6382     return angle::Result::Continue;
6383 }
6384 
invalidateCurrentShaderResources(gl::Command command)6385 angle::Result ContextVk::invalidateCurrentShaderResources(gl::Command command)
6386 {
6387     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6388     ASSERT(executable);
6389 
6390     const bool hasImages = executable->hasImages();
6391     const bool hasStorageBuffers =
6392         executable->hasStorageBuffers() || executable->hasAtomicCounterBuffers();
6393     const bool hasUniformBuffers = executable->hasUniformBuffers();
6394 
6395     if (hasUniformBuffers || hasStorageBuffers || hasImages ||
6396         executable->usesColorFramebufferFetch() || executable->usesDepthFramebufferFetch() ||
6397         executable->usesStencilFramebufferFetch())
6398     {
6399         mGraphicsDirtyBits |= kResourcesAndDescSetDirtyBits;
6400         mComputeDirtyBits |= kResourcesAndDescSetDirtyBits;
6401     }
6402 
6403     // Take care of read-after-write hazards that require implicit synchronization.
6404     if (hasUniformBuffers && command == gl::Command::Dispatch)
6405     {
6406         ANGLE_TRY(endRenderPassIfComputeReadAfterTransformFeedbackWrite());
6407     }
6408 
6409     // Take care of implicit layout transition by compute program access-after-read.
6410     if (hasImages && command == gl::Command::Dispatch)
6411     {
6412         ANGLE_TRY(endRenderPassIfComputeAccessAfterGraphicsImageAccess());
6413     }
6414 
6415     // If memory barrier has been issued but the command buffers haven't been flushed, make sure
6416     // they get a chance to do so if necessary on program and storage buffer/image binding change.
6417     const bool hasGLMemoryBarrierIssuedInCommandBuffers =
6418         mOutsideRenderPassCommands->hasGLMemoryBarrierIssued() ||
6419         mRenderPassCommands->hasGLMemoryBarrierIssued();
6420 
6421     if ((hasStorageBuffers || hasImages) && hasGLMemoryBarrierIssuedInCommandBuffers)
6422     {
6423         mGraphicsDirtyBits.set(DIRTY_BIT_MEMORY_BARRIER);
6424         mComputeDirtyBits.set(DIRTY_BIT_MEMORY_BARRIER);
6425     }
6426 
6427     return angle::Result::Continue;
6428 }
6429 
invalidateCurrentShaderUniformBuffers(gl::Command command)6430 angle::Result ContextVk::invalidateCurrentShaderUniformBuffers(gl::Command command)
6431 {
6432     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6433     ASSERT(executable);
6434 
6435     if (executable->hasUniformBuffers())
6436     {
6437         if (executable->hasLinkedShaderStage(gl::ShaderType::Compute))
6438         {
6439             mComputeDirtyBits |= kUniformBuffersAndDescSetDirtyBits;
6440         }
6441         else
6442         {
6443             mGraphicsDirtyBits |= kUniformBuffersAndDescSetDirtyBits;
6444         }
6445 
6446         if (command == gl::Command::Dispatch)
6447         {
6448             // Take care of read-after-write hazards that require implicit synchronization.
6449             ANGLE_TRY(endRenderPassIfComputeReadAfterTransformFeedbackWrite());
6450         }
6451     }
6452     return angle::Result::Continue;
6453 }
6454 
updateShaderResourcesWithSharedCacheKey(const vk::SharedDescriptorSetCacheKey & sharedCacheKey)6455 void ContextVk::updateShaderResourcesWithSharedCacheKey(
6456     const vk::SharedDescriptorSetCacheKey &sharedCacheKey)
6457 {
6458     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6459     ProgramExecutableVk *executableVk       = vk::GetImpl(executable);
6460 
6461     // Dynamic descriptor type uses the underlying BufferBlock in the descriptorSet. There could be
6462     // many BufferHelper objects sub-allocated from the same BufferBlock. And each BufferHelper
6463     // could combine with other buffers to form a descriptorSet. This means the descriptorSet
6464     // numbers for BufferBlock could potentially very large, in thousands with some app traces like
6465     // seeing in honkai_star_rail. The overhead of maintaining mDescriptorSetCacheManager for
6466     // BufferBlock could be too big. We chose to not maintain mDescriptorSetCacheManager in this
6467     // case. The only downside is that when BufferBlock gets destroyed, we will not able to
6468     // immediately destroy all cached descriptorSets that it is part of. They will still gets
6469     // evicted later on if needed.
6470     if (executable->hasUniformBuffers() && !executableVk->usesDynamicUniformBufferDescriptors())
6471     {
6472         const std::vector<gl::InterfaceBlock> &blocks = executable->getUniformBlocks();
6473         for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
6474         {
6475             const GLuint binding = executable->getUniformBlockBinding(bufferIndex);
6476             UpdateBufferWithSharedCacheKey(mState.getOffsetBindingPointerUniformBuffers()[binding],
6477                                            sharedCacheKey);
6478         }
6479     }
6480     if (executable->hasStorageBuffers() &&
6481         !executableVk->usesDynamicShaderStorageBufferDescriptors())
6482     {
6483         const std::vector<gl::InterfaceBlock> &blocks = executable->getShaderStorageBlocks();
6484         for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
6485         {
6486             const GLuint binding = executable->getShaderStorageBlockBinding(bufferIndex);
6487             UpdateBufferWithSharedCacheKey(
6488                 mState.getOffsetBindingPointerShaderStorageBuffers()[binding], sharedCacheKey);
6489         }
6490     }
6491     if (executable->hasAtomicCounterBuffers() &&
6492         !executableVk->usesDynamicAtomicCounterBufferDescriptors())
6493     {
6494         const std::vector<gl::AtomicCounterBuffer> &blocks = executable->getAtomicCounterBuffers();
6495         for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
6496         {
6497             const GLuint binding = executable->getAtomicCounterBufferBinding(bufferIndex);
6498             UpdateBufferWithSharedCacheKey(
6499                 mState.getOffsetBindingPointerAtomicCounterBuffers()[binding], sharedCacheKey);
6500         }
6501     }
6502     if (executable->hasImages())
6503     {
6504         UpdateImagesWithSharedCacheKey(mActiveImages, executable->getImageBindings(),
6505                                        sharedCacheKey);
6506     }
6507 }
6508 
invalidateGraphicsDriverUniforms()6509 void ContextVk::invalidateGraphicsDriverUniforms()
6510 {
6511     mGraphicsDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
6512 }
6513 
invalidateDriverUniforms()6514 void ContextVk::invalidateDriverUniforms()
6515 {
6516     mGraphicsDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
6517     mComputeDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
6518 }
6519 
onFramebufferChange(FramebufferVk * framebufferVk,gl::Command command)6520 angle::Result ContextVk::onFramebufferChange(FramebufferVk *framebufferVk, gl::Command command)
6521 {
6522     // This is called from FramebufferVk::syncState.  Skip these updates if the framebuffer being
6523     // synced is the read framebuffer (which is not equal the draw framebuffer).
6524     if (framebufferVk != vk::GetImpl(mState.getDrawFramebuffer()))
6525     {
6526         return angle::Result::Continue;
6527     }
6528 
6529     // Always consider the render pass finished.  FramebufferVk::syncState (caller of this function)
6530     // normally closes the render pass, except for blit to allow an optimization.  The following
6531     // code nevertheless must treat the render pass closed.
6532     onRenderPassFinished(RenderPassClosureReason::FramebufferChange);
6533 
6534     // Ensure that the pipeline description is updated.
6535     if (mGraphicsPipelineDesc->getRasterizationSamples() !=
6536         static_cast<uint32_t>(framebufferVk->getSamples()))
6537     {
6538         updateRasterizationSamples(framebufferVk->getSamples());
6539     }
6540 
6541     // Update scissor.
6542     updateScissor(mState);
6543 
6544     // Update depth and stencil.
6545     updateDepthStencil(mState);
6546 
6547     // Update dither based on attachment formats.
6548     updateDither();
6549 
6550     // Attachments might have changed.
6551     updateMissingAttachments();
6552 
6553     if (mState.getProgramExecutable())
6554     {
6555         ANGLE_TRY(invalidateCurrentShaderResources(command));
6556     }
6557 
6558     onDrawFramebufferRenderPassDescChange(framebufferVk, nullptr);
6559     return angle::Result::Continue;
6560 }
6561 
onDrawFramebufferRenderPassDescChange(FramebufferVk * framebufferVk,bool * renderPassDescChangedOut)6562 void ContextVk::onDrawFramebufferRenderPassDescChange(FramebufferVk *framebufferVk,
6563                                                       bool *renderPassDescChangedOut)
6564 {
6565     ASSERT(getFeatures().supportsFragmentShadingRate.enabled ||
6566            !framebufferVk->isFoveationEnabled());
6567 
6568     const vk::FramebufferFetchMode framebufferFetchMode =
6569         vk::GetProgramFramebufferFetchMode(mState.getProgramExecutable());
6570     mGraphicsPipelineDesc->updateRenderPassDesc(&mGraphicsPipelineTransition, getFeatures(),
6571                                                 framebufferVk->getRenderPassDesc(),
6572                                                 framebufferFetchMode);
6573 
6574     if (renderPassDescChangedOut)
6575     {
6576         // If render pass desc has changed while processing the dirty bits, notify the caller.
6577         // In most paths, |renderPassDescChangedOut| is nullptr and the pipeline will be
6578         // invalidated.
6579         //
6580         // |renderPassDescChangedOut| only serves |ContextVk::handleDirtyGraphicsRenderPass|, which
6581         // may need to reprocess the pipeline while processing dirty bits.  At that point, marking
6582         // the pipeline dirty is ineffective, and the pipeline dirty bit handler is directly called
6583         // as a result of setting this variable to true.
6584         *renderPassDescChangedOut = true;
6585     }
6586     else
6587     {
6588         // Otherwise mark the pipeline as dirty.
6589         invalidateCurrentGraphicsPipeline();
6590     }
6591 
6592     // Update render area in the driver uniforms.
6593     invalidateGraphicsDriverUniforms();
6594 }
6595 
invalidateCurrentTransformFeedbackBuffers()6596 void ContextVk::invalidateCurrentTransformFeedbackBuffers()
6597 {
6598     if (getFeatures().supportsTransformFeedbackExtension.enabled)
6599     {
6600         mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS);
6601     }
6602     else if (getFeatures().emulateTransformFeedback.enabled)
6603     {
6604         mGraphicsDirtyBits |= kXfbBuffersAndDescSetDirtyBits;
6605     }
6606 }
6607 
onTransformFeedbackStateChanged()6608 void ContextVk::onTransformFeedbackStateChanged()
6609 {
6610     if (getFeatures().supportsTransformFeedbackExtension.enabled)
6611     {
6612         mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS);
6613     }
6614     else if (getFeatures().emulateTransformFeedback.enabled)
6615     {
6616         invalidateGraphicsDriverUniforms();
6617         invalidateCurrentTransformFeedbackBuffers();
6618 
6619         // Invalidate the graphics pipeline too.  On transform feedback state change, the current
6620         // program may be used again, and it should switch between outputting transform feedback and
6621         // not.
6622         invalidateCurrentGraphicsPipeline();
6623         resetCurrentGraphicsPipeline();
6624     }
6625 }
6626 
onBeginTransformFeedback(size_t bufferCount,const gl::TransformFeedbackBuffersArray<vk::BufferHelper * > & buffers,const gl::TransformFeedbackBuffersArray<vk::BufferHelper> & counterBuffers)6627 angle::Result ContextVk::onBeginTransformFeedback(
6628     size_t bufferCount,
6629     const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &buffers,
6630     const gl::TransformFeedbackBuffersArray<vk::BufferHelper> &counterBuffers)
6631 {
6632     onTransformFeedbackStateChanged();
6633 
6634     bool shouldEndRenderPass = false;
6635 
6636     if (hasActiveRenderPass())
6637     {
6638         // If any of the buffers were previously used in the render pass, break the render pass as a
6639         // barrier is needed.
6640         for (size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
6641         {
6642             const vk::BufferHelper *buffer = buffers[bufferIndex];
6643             if (mRenderPassCommands->usesBuffer(*buffer))
6644             {
6645                 shouldEndRenderPass = true;
6646                 break;
6647             }
6648         }
6649     }
6650 
6651     if (getFeatures().supportsTransformFeedbackExtension.enabled)
6652     {
6653         // Break the render pass if the counter buffers are used too.  Note that Vulkan requires a
6654         // barrier on the counter buffer between pause and resume, so it cannot be resumed in the
6655         // same render pass.  Note additionally that we don't need to test all counters being used
6656         // in the render pass, as outside of the transform feedback object these buffers are
6657         // inaccessible and are therefore always used together.
6658         if (!shouldEndRenderPass && isRenderPassStartedAndUsesBuffer(counterBuffers[0]))
6659         {
6660             shouldEndRenderPass = true;
6661         }
6662 
6663         mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
6664     }
6665 
6666     if (shouldEndRenderPass)
6667     {
6668         ANGLE_TRY(flushCommandsAndEndRenderPass(RenderPassClosureReason::BufferUseThenXfbWrite));
6669     }
6670 
6671     return angle::Result::Continue;
6672 }
6673 
onEndTransformFeedback()6674 void ContextVk::onEndTransformFeedback()
6675 {
6676     if (getFeatures().supportsTransformFeedbackExtension.enabled)
6677     {
6678         if (mRenderPassCommands->isTransformFeedbackStarted())
6679         {
6680             mRenderPassCommands->endTransformFeedback();
6681         }
6682     }
6683     else if (getFeatures().emulateTransformFeedback.enabled)
6684     {
6685         onTransformFeedbackStateChanged();
6686     }
6687 }
6688 
onPauseTransformFeedback()6689 angle::Result ContextVk::onPauseTransformFeedback()
6690 {
6691     if (getFeatures().supportsTransformFeedbackExtension.enabled)
6692     {
6693         // If transform feedback was already active on this render pass, break it.  This
6694         // is for simplicity to avoid tracking multiple simultaneously active transform feedback
6695         // settings in the render pass.
6696         if (mRenderPassCommands->isTransformFeedbackActiveUnpaused())
6697         {
6698             return flushCommandsAndEndRenderPass(RenderPassClosureReason::XfbPause);
6699         }
6700     }
6701     onTransformFeedbackStateChanged();
6702     return angle::Result::Continue;
6703 }
6704 
invalidateGraphicsPipelineBinding()6705 void ContextVk::invalidateGraphicsPipelineBinding()
6706 {
6707     mGraphicsDirtyBits.set(DIRTY_BIT_PIPELINE_BINDING);
6708 }
6709 
invalidateComputePipelineBinding()6710 void ContextVk::invalidateComputePipelineBinding()
6711 {
6712     mComputeDirtyBits.set(DIRTY_BIT_PIPELINE_BINDING);
6713 }
6714 
invalidateGraphicsDescriptorSet(DescriptorSetIndex usedDescriptorSet)6715 void ContextVk::invalidateGraphicsDescriptorSet(DescriptorSetIndex usedDescriptorSet)
6716 {
6717     // UtilsVk currently only uses set 0
6718     ASSERT(usedDescriptorSet == DescriptorSetIndex::Internal);
6719     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6720 
6721     if (executable && executable->hasUniformBuffers())
6722     {
6723         mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
6724         return;
6725     }
6726 }
6727 
invalidateComputeDescriptorSet(DescriptorSetIndex usedDescriptorSet)6728 void ContextVk::invalidateComputeDescriptorSet(DescriptorSetIndex usedDescriptorSet)
6729 {
6730     // UtilsVk currently only uses set 0
6731     ASSERT(usedDescriptorSet == DescriptorSetIndex::Internal);
6732     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6733 
6734     if (executable && executable->hasUniformBuffers())
6735     {
6736         mComputeDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
6737         return;
6738     }
6739 }
6740 
invalidateAllDynamicState()6741 void ContextVk::invalidateAllDynamicState()
6742 {
6743     mGraphicsDirtyBits |= mDynamicStateDirtyBits;
6744 }
6745 
dispatchCompute(const gl::Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)6746 angle::Result ContextVk::dispatchCompute(const gl::Context *context,
6747                                          GLuint numGroupsX,
6748                                          GLuint numGroupsY,
6749                                          GLuint numGroupsZ)
6750 {
6751     ANGLE_TRY(setupDispatch(context));
6752 
6753     mOutsideRenderPassCommands->getCommandBuffer().dispatch(numGroupsX, numGroupsY, numGroupsZ);
6754     // Track completion of compute.
6755     mOutsideRenderPassCommands->flushSetEvents(this);
6756 
6757     return angle::Result::Continue;
6758 }
6759 
dispatchComputeIndirect(const gl::Context * context,GLintptr indirect)6760 angle::Result ContextVk::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
6761 {
6762     gl::Buffer *glBuffer     = getState().getTargetBuffer(gl::BufferBinding::DispatchIndirect);
6763     vk::BufferHelper &buffer = vk::GetImpl(glBuffer)->getBuffer();
6764 
6765     // Break the render pass if the indirect buffer was previously used as the output from transform
6766     // feedback.
6767     if (mCurrentTransformFeedbackQueueSerial.valid() &&
6768         buffer.writtenByCommandBuffer(mCurrentTransformFeedbackQueueSerial))
6769     {
6770         ANGLE_TRY(flushCommandsAndEndRenderPass(
6771             RenderPassClosureReason::XfbWriteThenIndirectDispatchBuffer));
6772     }
6773 
6774     ANGLE_TRY(setupDispatch(context));
6775 
6776     // Process indirect buffer after command buffer has started.
6777     mOutsideRenderPassCommands->bufferRead(this, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
6778                                            vk::PipelineStage::DrawIndirect, &buffer);
6779 
6780     mOutsideRenderPassCommands->getCommandBuffer().dispatchIndirect(buffer.getBuffer(),
6781                                                                     buffer.getOffset() + indirect);
6782 
6783     // Track completion of compute.
6784     mOutsideRenderPassCommands->flushSetEvents(this);
6785 
6786     return angle::Result::Continue;
6787 }
6788 
memoryBarrier(const gl::Context * context,GLbitfield barriers)6789 angle::Result ContextVk::memoryBarrier(const gl::Context *context, GLbitfield barriers)
6790 {
6791     // First, turn GL_ALL_BARRIER_BITS into a mask that has only the valid barriers set.
6792     constexpr GLbitfield kAllMemoryBarrierBits = kBufferMemoryBarrierBits | kImageMemoryBarrierBits;
6793     barriers &= kAllMemoryBarrierBits;
6794 
6795     // GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT specifies that a fence sync or glFinish must be used
6796     // after the barrier for the CPU to to see the shader writes.  Since host-visible buffer writes
6797     // always issue a barrier automatically for the sake of glMapBuffer() (see
6798     // comment on |mIsAnyHostVisibleBufferWritten|), there's nothing to do for
6799     // GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT.
6800     barriers &= ~GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT;
6801 
6802     // If no other barrier, early out.
6803     if (barriers == 0)
6804     {
6805         return angle::Result::Continue;
6806     }
6807 
6808     // glMemoryBarrier for barrier bit X_BARRIER_BIT implies:
6809     //
6810     // - An execution+memory barrier: shader writes are made visible to subsequent X accesses
6811     //
6812     // Additionally, SHADER_IMAGE_ACCESS_BARRIER_BIT and SHADER_STORAGE_BARRIER_BIT imply:
6813     //
6814     // - An execution+memory barrier: all accesses are finished before image/buffer writes
6815     //
6816     // For the first barrier, we can simplify the implementation by assuming that prior writes are
6817     // expected to be used right after this barrier, so we can close the render pass or flush the
6818     // outside render pass commands right away if they have had any writes.
6819     //
6820     // It's noteworthy that some barrier bits affect draw/dispatch calls only, while others affect
6821     // other commands.  For the latter, since storage buffer and images are not tracked in command
6822     // buffers, we can't rely on the command buffers being flushed in the usual way when recording
6823     // these commands (i.e. through |getOutsideRenderPassCommandBuffer()| and
6824     // |vk::CommandBufferAccess|).  Conservatively flushing command buffers with any storage output
6825     // simplifies this use case.  If this needs to be avoided in the future,
6826     // |getOutsideRenderPassCommandBuffer()| can be modified to flush the command buffers if they
6827     // have had any storage output.
6828     //
6829     // For the second barrier, we need to defer closing the render pass until there's a draw or
6830     // dispatch call that uses storage buffers or images that were previously used in the render
6831     // pass.  This allows the render pass to remain open in scenarios such as this:
6832     //
6833     // - Draw using resource X
6834     // - glMemoryBarrier
6835     // - Draw/dispatch with storage buffer/image Y
6836     //
6837     // To achieve this, a dirty bit is added that breaks the render pass if any storage
6838     // buffer/images are used in it.  Until the render pass breaks, changing the program or storage
6839     // buffer/image bindings should set this dirty bit again.
6840 
6841     if (mRenderPassCommands->hasShaderStorageOutput())
6842     {
6843         // Break the render pass if necessary as future non-draw commands can't know if they should.
6844         ANGLE_TRY(flushCommandsAndEndRenderPass(
6845             RenderPassClosureReason::StorageResourceUseThenGLMemoryBarrier));
6846     }
6847     else if (mOutsideRenderPassCommands->hasShaderStorageOutput())
6848     {
6849         // Otherwise flush the outside render pass commands if necessary.
6850         ANGLE_TRY(flushOutsideRenderPassCommands());
6851     }
6852 
6853     if ((barriers & kWriteAfterAccessMemoryBarriers) == 0)
6854     {
6855         return angle::Result::Continue;
6856     }
6857 
6858     // Accumulate unprocessed memoryBarrier bits
6859     mDeferredMemoryBarriers |= barriers;
6860 
6861     // Defer flushing the command buffers until a draw/dispatch with storage buffer/image is
6862     // encountered.
6863     mGraphicsDirtyBits.set(DIRTY_BIT_MEMORY_BARRIER);
6864     mComputeDirtyBits.set(DIRTY_BIT_MEMORY_BARRIER);
6865 
6866     // Make sure memory barrier is issued for future usages of storage buffers and images even if
6867     // there's no binding change.
6868     mGraphicsDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
6869     mComputeDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
6870 
6871     // Mark the command buffers as affected by glMemoryBarrier, so future program and storage
6872     // buffer/image binding changes can set DIRTY_BIT_MEMORY_BARRIER again.
6873     mOutsideRenderPassCommands->setGLMemoryBarrierIssued();
6874     mRenderPassCommands->setGLMemoryBarrierIssued();
6875 
6876     return angle::Result::Continue;
6877 }
6878 
memoryBarrierByRegion(const gl::Context * context,GLbitfield barriers)6879 angle::Result ContextVk::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers)
6880 {
6881     // Note: memoryBarrierByRegion is expected to affect only the fragment pipeline, but is
6882     // otherwise similar to memoryBarrier in function.
6883     //
6884     // TODO: Optimize memoryBarrierByRegion by issuing an in-subpass pipeline barrier instead of
6885     // breaking the render pass.  http://anglebug.com/42263695
6886     return memoryBarrier(context, barriers);
6887 }
6888 
framebufferFetchBarrier()6889 void ContextVk::framebufferFetchBarrier()
6890 {
6891     // No need for a barrier with VK_EXT_rasterization_order_attachment_access.
6892     if (getFeatures().supportsRasterizationOrderAttachmentAccess.enabled)
6893     {
6894         return;
6895     }
6896 
6897     mGraphicsDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_FETCH_BARRIER);
6898 }
6899 
blendBarrier()6900 void ContextVk::blendBarrier()
6901 {
6902     if (getFeatures().emulateAdvancedBlendEquations.enabled)
6903     {
6904         // When emulated, advanced blend is implemented through framebuffer fetch.
6905         framebufferFetchBarrier();
6906     }
6907     else
6908     {
6909         mGraphicsDirtyBits.set(DIRTY_BIT_BLEND_BARRIER);
6910     }
6911 }
6912 
acquireTextures(const gl::Context * context,const gl::TextureBarrierVector & textureBarriers)6913 angle::Result ContextVk::acquireTextures(const gl::Context *context,
6914                                          const gl::TextureBarrierVector &textureBarriers)
6915 {
6916     for (const gl::TextureAndLayout &textureBarrier : textureBarriers)
6917     {
6918         TextureVk *textureVk   = vk::GetImpl(textureBarrier.texture);
6919         vk::ImageHelper &image = textureVk->getImage();
6920         vk::ImageLayout layout = vk::GetImageLayoutFromGLImageLayout(this, textureBarrier.layout);
6921         // Image should not be accessed while unowned. Emulated formats may have staged updates
6922         // to clear the image after initialization.
6923         ASSERT(!image.hasStagedUpdatesInAllocatedLevels() || image.hasEmulatedImageChannels());
6924         image.setCurrentImageLayout(getRenderer(), layout);
6925     }
6926     return angle::Result::Continue;
6927 }
6928 
releaseTextures(const gl::Context * context,gl::TextureBarrierVector * textureBarriers)6929 angle::Result ContextVk::releaseTextures(const gl::Context *context,
6930                                          gl::TextureBarrierVector *textureBarriers)
6931 {
6932     for (gl::TextureAndLayout &textureBarrier : *textureBarriers)
6933     {
6934         TextureVk *textureVk = vk::GetImpl(textureBarrier.texture);
6935 
6936         ANGLE_TRY(textureVk->ensureImageInitialized(this, ImageMipLevels::EnabledLevels));
6937 
6938         vk::ImageHelper &image = textureVk->getImage();
6939         ANGLE_TRY(onImageReleaseToExternal(image));
6940 
6941         textureBarrier.layout =
6942             vk::ConvertImageLayoutToGLImageLayout(image.getCurrentImageLayout());
6943     }
6944 
6945     return flushAndSubmitCommands(nullptr, nullptr,
6946                                   RenderPassClosureReason::ImageUseThenReleaseToExternal);
6947 }
6948 
getQueryPool(gl::QueryType queryType)6949 vk::DynamicQueryPool *ContextVk::getQueryPool(gl::QueryType queryType)
6950 {
6951     ASSERT(queryType == gl::QueryType::AnySamples ||
6952            queryType == gl::QueryType::AnySamplesConservative ||
6953            queryType == gl::QueryType::PrimitivesGenerated ||
6954            queryType == gl::QueryType::TransformFeedbackPrimitivesWritten ||
6955            queryType == gl::QueryType::Timestamp || queryType == gl::QueryType::TimeElapsed);
6956 
6957     // For PrimitivesGenerated queries:
6958     //
6959     // - If VK_EXT_primitives_generated_query is supported, use that.
6960     // - Otherwise, if pipelineStatisticsQuery is supported, use that,
6961     // - Otherwise, use the same pool as TransformFeedbackPrimitivesWritten and share the query as
6962     //   the Vulkan transform feedback query produces both results.  This option is non-conformant
6963     //   as the primitives generated query will not be functional without transform feedback.
6964     //
6965     if (queryType == gl::QueryType::PrimitivesGenerated &&
6966         !getFeatures().supportsPrimitivesGeneratedQuery.enabled &&
6967         !getFeatures().supportsPipelineStatisticsQuery.enabled)
6968     {
6969         queryType = gl::QueryType::TransformFeedbackPrimitivesWritten;
6970     }
6971 
6972     // Assert that timestamp extension is available if needed.
6973     ASSERT((queryType != gl::QueryType::Timestamp && queryType != gl::QueryType::TimeElapsed) ||
6974            mRenderer->getQueueFamilyProperties().timestampValidBits > 0);
6975     ASSERT(mQueryPools[queryType].isValid());
6976     return &mQueryPools[queryType];
6977 }
6978 
getClearColorValue() const6979 const VkClearValue &ContextVk::getClearColorValue() const
6980 {
6981     return mClearColorValue;
6982 }
6983 
getClearDepthStencilValue() const6984 const VkClearValue &ContextVk::getClearDepthStencilValue() const
6985 {
6986     return mClearDepthStencilValue;
6987 }
6988 
getClearColorMasks() const6989 gl::BlendStateExt::ColorMaskStorage::Type ContextVk::getClearColorMasks() const
6990 {
6991     return mClearColorMasks;
6992 }
6993 
writeAtomicCounterBufferDriverUniformOffsets(uint32_t * offsetsOut,size_t offsetsSize)6994 void ContextVk::writeAtomicCounterBufferDriverUniformOffsets(uint32_t *offsetsOut,
6995                                                              size_t offsetsSize)
6996 {
6997     const VkDeviceSize offsetAlignment =
6998         mRenderer->getPhysicalDeviceProperties().limits.minStorageBufferOffsetAlignment;
6999     size_t atomicCounterBufferCount = mState.getAtomicCounterBufferCount();
7000 
7001     ASSERT(atomicCounterBufferCount <= offsetsSize * 4);
7002 
7003     for (uint32_t bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
7004     {
7005         uint32_t offsetDiff = 0;
7006 
7007         const gl::OffsetBindingPointer<gl::Buffer> *atomicCounterBuffer =
7008             &mState.getIndexedAtomicCounterBuffer(bufferIndex);
7009         if (atomicCounterBuffer->get())
7010         {
7011             VkDeviceSize offset        = atomicCounterBuffer->getOffset();
7012             VkDeviceSize alignedOffset = (offset / offsetAlignment) * offsetAlignment;
7013 
7014             // GL requires the atomic counter buffer offset to be aligned with uint.
7015             ASSERT((offset - alignedOffset) % sizeof(uint32_t) == 0);
7016             offsetDiff = static_cast<uint32_t>((offset - alignedOffset) / sizeof(uint32_t));
7017 
7018             // We expect offsetDiff to fit in an 8-bit value.  The maximum difference is
7019             // minStorageBufferOffsetAlignment / 4, where minStorageBufferOffsetAlignment
7020             // currently has a maximum value of 256 on any device.
7021             ASSERT(offsetDiff < (1 << 8));
7022         }
7023 
7024         // The output array is already cleared prior to this call.
7025         ASSERT(bufferIndex % 4 != 0 || offsetsOut[bufferIndex / 4] == 0);
7026 
7027         offsetsOut[bufferIndex / 4] |= static_cast<uint8_t>(offsetDiff) << ((bufferIndex % 4) * 8);
7028     }
7029 }
7030 
pauseTransformFeedbackIfActiveUnpaused()7031 void ContextVk::pauseTransformFeedbackIfActiveUnpaused()
7032 {
7033     if (mRenderPassCommands->isTransformFeedbackActiveUnpaused())
7034     {
7035         ASSERT(getFeatures().supportsTransformFeedbackExtension.enabled);
7036         mRenderPassCommands->pauseTransformFeedback();
7037 
7038         // Note that this function is called when render pass break is imminent
7039         // (flushCommandsAndEndRenderPass(), or UtilsVk::clearFramebuffer which will close the
7040         // render pass after the clear).  This dirty bit allows transform feedback to resume
7041         // automatically on next render pass.
7042         mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
7043     }
7044 }
7045 
handleDirtyGraphicsDriverUniforms(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)7046 angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(DirtyBits::Iterator *dirtyBitsIterator,
7047                                                            DirtyBits dirtyBitMask)
7048 {
7049     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
7050 
7051     static_assert(gl::IMPLEMENTATION_MAX_FRAMEBUFFER_SIZE <= 0xFFFF,
7052                   "Not enough bits for render area");
7053     static_assert(gl::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE <= 0xFFFF,
7054                   "Not enough bits for render area");
7055     uint16_t renderAreaWidth, renderAreaHeight;
7056     SetBitField(renderAreaWidth, drawFramebufferVk->getState().getDimensions().width);
7057     SetBitField(renderAreaHeight, drawFramebufferVk->getState().getDimensions().height);
7058     const uint32_t renderArea = renderAreaHeight << 16 | renderAreaWidth;
7059 
7060     bool flipX = false;
7061     bool flipY = false;
7062     // Y-axis flipping only comes into play with the default framebuffer (i.e. a swapchain
7063     // image). For 0-degree rotation, an FBO or pbuffer could be the draw framebuffer, and so we
7064     // must check whether flipY should be positive or negative.  All other rotations, will be to
7065     // the default framebuffer, and so the value of isViewportFlipEnabledForDrawFBO() is assumed
7066     // true; the appropriate flipY value is chosen such that gl_FragCoord is positioned at the
7067     // lower-left corner of the window.
7068     switch (mCurrentRotationDrawFramebuffer)
7069     {
7070         case SurfaceRotation::Identity:
7071             flipY = isViewportFlipEnabledForDrawFBO();
7072             break;
7073         case SurfaceRotation::Rotated90Degrees:
7074             ASSERT(isViewportFlipEnabledForDrawFBO());
7075             break;
7076         case SurfaceRotation::Rotated180Degrees:
7077             ASSERT(isViewportFlipEnabledForDrawFBO());
7078             flipX = true;
7079             break;
7080         case SurfaceRotation::Rotated270Degrees:
7081             ASSERT(isViewportFlipEnabledForDrawFBO());
7082             flipX = true;
7083             flipY = true;
7084             break;
7085         default:
7086             UNREACHABLE();
7087             break;
7088     }
7089 
7090     const bool invertViewport = isViewportFlipEnabledForDrawFBO();
7091 
7092     // Create the extended driver uniform, and populate the extended data fields if necessary.
7093     GraphicsDriverUniformsExtended driverUniformsExt = {};
7094     if (ShouldUseGraphicsDriverUniformsExtended(this))
7095     {
7096         if (mState.isTransformFeedbackActiveUnpaused())
7097         {
7098             TransformFeedbackVk *transformFeedbackVk =
7099                 vk::GetImpl(mState.getCurrentTransformFeedback());
7100             transformFeedbackVk->getBufferOffsets(this, mXfbBaseVertex,
7101                                                   driverUniformsExt.xfbBufferOffsets.data(),
7102                                                   driverUniformsExt.xfbBufferOffsets.size());
7103         }
7104         driverUniformsExt.xfbVerticesPerInstance = static_cast<int32_t>(mXfbVertexCountPerInstance);
7105     }
7106 
7107     // Create the driver uniform object that will be used as push constant argument.
7108     GraphicsDriverUniforms *driverUniforms = &driverUniformsExt.common;
7109     uint32_t driverUniformSize             = GetDriverUniformSize(this, PipelineType::Graphics);
7110 
7111     const float depthRangeNear = mState.getNearPlane();
7112     const float depthRangeFar  = mState.getFarPlane();
7113     const uint32_t numSamples  = drawFramebufferVk->getSamples();
7114     const uint32_t isLayered   = drawFramebufferVk->getLayerCount() > 1;
7115 
7116     uint32_t advancedBlendEquation = 0;
7117     if (getFeatures().emulateAdvancedBlendEquations.enabled && mState.isBlendEnabled())
7118     {
7119         // Pass the advanced blend equation to shader as-is.  If the equation is not one of the
7120         // advanced ones, 0 is expected.
7121         const gl::BlendStateExt &blendStateExt = mState.getBlendStateExt();
7122         if (blendStateExt.getUsesAdvancedBlendEquationMask().test(0))
7123         {
7124             advancedBlendEquation =
7125                 static_cast<uint32_t>(getState().getBlendStateExt().getEquationColorIndexed(0));
7126         }
7127     }
7128 
7129     const uint32_t swapXY               = IsRotatedAspectRatio(mCurrentRotationDrawFramebuffer);
7130     const uint32_t enabledClipDistances = mState.getEnabledClipDistances().bits();
7131     const uint32_t transformDepth =
7132         getFeatures().supportsDepthClipControl.enabled ? 0 : !mState.isClipDepthModeZeroToOne();
7133 
7134     static_assert(angle::BitMask<uint32_t>(gl::IMPLEMENTATION_MAX_CLIP_DISTANCES) <=
7135                       sh::vk::kDriverUniformsMiscEnabledClipPlanesMask,
7136                   "Not enough bits for enabled clip planes");
7137 
7138     ASSERT((swapXY & ~sh::vk::kDriverUniformsMiscSwapXYMask) == 0);
7139     ASSERT((advancedBlendEquation & ~sh::vk::kDriverUniformsMiscAdvancedBlendEquationMask) == 0);
7140     ASSERT((numSamples & ~sh::vk::kDriverUniformsMiscSampleCountMask) == 0);
7141     ASSERT((enabledClipDistances & ~sh::vk::kDriverUniformsMiscEnabledClipPlanesMask) == 0);
7142     ASSERT((transformDepth & ~sh::vk::kDriverUniformsMiscTransformDepthMask) == 0);
7143 
7144     const uint32_t misc =
7145         swapXY | advancedBlendEquation << sh::vk::kDriverUniformsMiscAdvancedBlendEquationOffset |
7146         numSamples << sh::vk::kDriverUniformsMiscSampleCountOffset |
7147         enabledClipDistances << sh::vk::kDriverUniformsMiscEnabledClipPlanesOffset |
7148         transformDepth << sh::vk::kDriverUniformsMiscTransformDepthOffset |
7149         isLayered << sh::vk::kDriverUniformsMiscLayeredFramebufferOffset;
7150 
7151     // Copy and flush to the device.
7152     *driverUniforms = {
7153         {},
7154         {depthRangeNear, depthRangeFar},
7155         renderArea,
7156         MakeFlipUniform(flipX, flipY, invertViewport),
7157         mGraphicsPipelineDesc->getEmulatedDitherControl(),
7158         misc,
7159     };
7160 
7161     if (mState.hasValidAtomicCounterBuffer())
7162     {
7163         writeAtomicCounterBufferDriverUniformOffsets(driverUniforms->acbBufferOffsets.data(),
7164                                                      driverUniforms->acbBufferOffsets.size());
7165     }
7166 
7167     // Update push constant driver uniforms.
7168     ProgramExecutableVk *executableVk = vk::GetImpl(mState.getProgramExecutable());
7169     mRenderPassCommands->getCommandBuffer().pushConstants(
7170         executableVk->getPipelineLayout(), getRenderer()->getSupportedVulkanShaderStageMask(), 0,
7171         driverUniformSize, driverUniforms);
7172     mPerfCounters.graphicsDriverUniformsUpdated++;
7173 
7174     return angle::Result::Continue;
7175 }
7176 
handleDirtyComputeDriverUniforms(DirtyBits::Iterator * dirtyBitsIterator)7177 angle::Result ContextVk::handleDirtyComputeDriverUniforms(DirtyBits::Iterator *dirtyBitsIterator)
7178 {
7179     // Create the driver uniform object that will be used as push constant argument.
7180     ComputeDriverUniforms driverUniforms = {};
7181     uint32_t driverUniformSize           = GetDriverUniformSize(this, PipelineType::Compute);
7182 
7183     if (mState.hasValidAtomicCounterBuffer())
7184     {
7185         writeAtomicCounterBufferDriverUniformOffsets(driverUniforms.acbBufferOffsets.data(),
7186                                                      driverUniforms.acbBufferOffsets.size());
7187     }
7188 
7189     // Update push constant driver uniforms.
7190     ProgramExecutableVk *executableVk = vk::GetImpl(mState.getProgramExecutable());
7191     mOutsideRenderPassCommands->getCommandBuffer().pushConstants(
7192         executableVk->getPipelineLayout(), getRenderer()->getSupportedVulkanShaderStageMask(), 0,
7193         driverUniformSize, &driverUniforms);
7194     mPerfCounters.graphicsDriverUniformsUpdated++;
7195 
7196     return angle::Result::Continue;
7197 }
7198 
handleError(VkResult errorCode,const char * file,const char * function,unsigned int line)7199 void ContextVk::handleError(VkResult errorCode,
7200                             const char *file,
7201                             const char *function,
7202                             unsigned int line)
7203 {
7204     ASSERT(errorCode != VK_SUCCESS);
7205 
7206     GLenum glErrorCode = DefaultGLErrorCode(errorCode);
7207 
7208     std::stringstream errorStream;
7209     errorStream << "Internal Vulkan error (" << errorCode << "): " << VulkanResultString(errorCode)
7210                 << ".";
7211 
7212     getRenderer()->getMemoryAllocationTracker()->logMemoryStatsOnError();
7213 
7214     if (errorCode == VK_ERROR_DEVICE_LOST)
7215     {
7216         VkResult deviceLostInfoErrorCode = getRenderer()->retrieveDeviceLostDetails();
7217         if (deviceLostInfoErrorCode != VK_SUCCESS)
7218         {
7219             errorStream << std::endl
7220                         << "Unable to retrieve VK_ERROR_DEVICE_LOST details due to Vulkan error ("
7221                         << deviceLostInfoErrorCode
7222                         << "): " << VulkanResultString(deviceLostInfoErrorCode) << ".";
7223         }
7224 
7225         WARN() << errorStream.str();
7226         handleDeviceLost();
7227     }
7228 
7229     mErrors->handleError(glErrorCode, errorStream.str().c_str(), file, function, line);
7230 }
7231 
initBufferAllocation(vk::BufferHelper * bufferHelper,uint32_t memoryTypeIndex,size_t allocationSize,size_t alignment,BufferUsageType bufferUsageType)7232 angle::Result ContextVk::initBufferAllocation(vk::BufferHelper *bufferHelper,
7233                                               uint32_t memoryTypeIndex,
7234                                               size_t allocationSize,
7235                                               size_t alignment,
7236                                               BufferUsageType bufferUsageType)
7237 {
7238     vk::BufferPool *pool = getDefaultBufferPool(allocationSize, memoryTypeIndex, bufferUsageType);
7239     VkResult result      = bufferHelper->initSuballocation(this, memoryTypeIndex, allocationSize,
7240                                                            alignment, bufferUsageType, pool);
7241     if (ANGLE_LIKELY(result == VK_SUCCESS))
7242     {
7243         if (mRenderer->getFeatures().allocateNonZeroMemory.enabled)
7244         {
7245             ANGLE_TRY(bufferHelper->initializeNonZeroMemory(
7246                 this, GetDefaultBufferUsageFlags(mRenderer), allocationSize));
7247         }
7248 
7249         return angle::Result::Continue;
7250     }
7251 
7252     // If the error is not OOM, we should stop and handle the error. In case of OOM, we can try
7253     // other options.
7254     bool shouldTryFallback = (result == VK_ERROR_OUT_OF_DEVICE_MEMORY);
7255     ANGLE_VK_CHECK(this, shouldTryFallback, result);
7256 
7257     // If memory allocation fails, it is possible to retry the allocation after cleaning the garbage
7258     // and waiting for submitted commands to finish if necessary.
7259     bool anyGarbageCleaned  = false;
7260     bool someGarbageCleaned = false;
7261     do
7262     {
7263         ANGLE_TRY(mRenderer->cleanupSomeGarbage(this, &anyGarbageCleaned));
7264         if (anyGarbageCleaned)
7265         {
7266             someGarbageCleaned = true;
7267             result = bufferHelper->initSuballocation(this, memoryTypeIndex, allocationSize,
7268                                                      alignment, bufferUsageType, pool);
7269         }
7270     } while (result != VK_SUCCESS && anyGarbageCleaned);
7271 
7272     if (someGarbageCleaned)
7273     {
7274         INFO() << "Initial allocation failed. Cleaned some garbage | Allocation result: "
7275                << ((result == VK_SUCCESS) ? "SUCCESS" : "FAIL");
7276     }
7277 
7278     // If memory allocation fails, it is possible retry after flushing the context and cleaning all
7279     // the garbage.
7280     if (result != VK_SUCCESS)
7281     {
7282         ANGLE_TRY(finishImpl(RenderPassClosureReason::OutOfMemory));
7283         INFO() << "Context flushed due to out-of-memory error.";
7284         result = bufferHelper->initSuballocation(this, memoryTypeIndex, allocationSize, alignment,
7285                                                  bufferUsageType, pool);
7286     }
7287 
7288     // If the allocation continues to fail despite all the fallback options, the error must be
7289     // returned.
7290     ANGLE_VK_CHECK(this, result == VK_SUCCESS, result);
7291 
7292     // Initialize with non-zero value if needed.
7293     if (mRenderer->getFeatures().allocateNonZeroMemory.enabled)
7294     {
7295         ANGLE_TRY(bufferHelper->initializeNonZeroMemory(this, GetDefaultBufferUsageFlags(mRenderer),
7296                                                         allocationSize));
7297     }
7298 
7299     return angle::Result::Continue;
7300 }
7301 
initImageAllocation(vk::ImageHelper * imageHelper,bool hasProtectedContent,const vk::MemoryProperties & memoryProperties,VkMemoryPropertyFlags flags,vk::MemoryAllocationType allocationType)7302 angle::Result ContextVk::initImageAllocation(vk::ImageHelper *imageHelper,
7303                                              bool hasProtectedContent,
7304                                              const vk::MemoryProperties &memoryProperties,
7305                                              VkMemoryPropertyFlags flags,
7306                                              vk::MemoryAllocationType allocationType)
7307 {
7308     VkMemoryPropertyFlags oomExcludedFlags = 0;
7309     VkMemoryPropertyFlags outputFlags;
7310     VkDeviceSize outputSize;
7311 
7312     if (hasProtectedContent)
7313     {
7314         flags |= VK_MEMORY_PROPERTY_PROTECTED_BIT;
7315     }
7316 
7317     // Get memory requirements for the allocation.
7318     VkMemoryRequirements memoryRequirements;
7319     imageHelper->getImage().getMemoryRequirements(getDevice(), &memoryRequirements);
7320     bool allocateDedicatedMemory =
7321         mRenderer->getImageMemorySuballocator().needsDedicatedMemory(memoryRequirements.size);
7322 
7323     VkResult result = imageHelper->initMemory(this, memoryProperties, flags, oomExcludedFlags,
7324                                               &memoryRequirements, allocateDedicatedMemory,
7325                                               allocationType, &outputFlags, &outputSize);
7326     if (ANGLE_LIKELY(result == VK_SUCCESS))
7327     {
7328         if (mRenderer->getFeatures().allocateNonZeroMemory.enabled)
7329         {
7330             ANGLE_TRY(imageHelper->initializeNonZeroMemory(this, hasProtectedContent, outputFlags,
7331                                                            outputSize));
7332         }
7333 
7334         return angle::Result::Continue;
7335     }
7336 
7337     // If the error is not OOM, we should stop and handle the error. In case of OOM, we can try
7338     // other options.
7339     bool shouldTryFallback = (result == VK_ERROR_OUT_OF_DEVICE_MEMORY);
7340     ANGLE_VK_CHECK(this, shouldTryFallback, result);
7341 
7342     // If memory allocation fails, it is possible to retry the allocation after cleaning the garbage
7343     // and waiting for submitted commands to finish if necessary.
7344     bool anyGarbageCleaned  = false;
7345     bool someGarbageCleaned = false;
7346     do
7347     {
7348         ANGLE_TRY(mRenderer->cleanupSomeGarbage(this, &anyGarbageCleaned));
7349         if (anyGarbageCleaned)
7350         {
7351             someGarbageCleaned = true;
7352             result = imageHelper->initMemory(this, memoryProperties, flags, oomExcludedFlags,
7353                                              &memoryRequirements, allocateDedicatedMemory,
7354                                              allocationType, &outputFlags, &outputSize);
7355         }
7356     } while (result != VK_SUCCESS && anyGarbageCleaned);
7357 
7358     if (someGarbageCleaned)
7359     {
7360         INFO() << "Initial allocation failed. Cleaned some garbage | Allocation result: "
7361                << ((result == VK_SUCCESS) ? "SUCCESS" : "FAIL");
7362     }
7363 
7364     // If memory allocation fails, it is possible retry after flushing the context and cleaning all
7365     // the garbage.
7366     if (result != VK_SUCCESS)
7367     {
7368         ANGLE_TRY(finishImpl(RenderPassClosureReason::OutOfMemory));
7369         INFO() << "Context flushed due to out-of-memory error.";
7370         result = imageHelper->initMemory(this, memoryProperties, flags, oomExcludedFlags,
7371                                          &memoryRequirements, allocateDedicatedMemory,
7372                                          allocationType, &outputFlags, &outputSize);
7373     }
7374 
7375     // If no fallback has worked so far, we should record the failed allocation information in case
7376     // it needs to be logged.
7377     if (result != VK_SUCCESS)
7378     {
7379         uint32_t pendingMemoryTypeIndex;
7380         if (vma::FindMemoryTypeIndexForImageInfo(
7381                 mRenderer->getAllocator().getHandle(), &imageHelper->getVkImageCreateInfo(), flags,
7382                 flags, allocateDedicatedMemory, &pendingMemoryTypeIndex) == VK_SUCCESS)
7383         {
7384             mRenderer->getMemoryAllocationTracker()->setPendingMemoryAlloc(
7385                 allocationType, memoryRequirements.size, pendingMemoryTypeIndex);
7386         }
7387     }
7388 
7389     // If there is no space for the new allocation and other fallbacks have proved ineffective, the
7390     // allocation may still be made outside the device from all other memory types, although it will
7391     // result in performance penalty. This is a last resort.
7392     if (result != VK_SUCCESS)
7393     {
7394         oomExcludedFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
7395         result           = imageHelper->initMemory(this, memoryProperties, flags, oomExcludedFlags,
7396                                                    &memoryRequirements, allocateDedicatedMemory,
7397                                                    allocationType, &outputFlags, &outputSize);
7398         INFO()
7399             << "Allocation failed. Removed the DEVICE_LOCAL bit requirement | Allocation result: "
7400             << ((result == VK_SUCCESS) ? "SUCCESS" : "FAIL");
7401 
7402         if (result == VK_SUCCESS)
7403         {
7404             // For images allocated here, although allocation is preferred on the device, it is not
7405             // required.
7406             mRenderer->getMemoryAllocationTracker()->compareExpectedFlagsWithAllocatedFlags(
7407                 flags & ~oomExcludedFlags, flags, outputFlags,
7408                 reinterpret_cast<void *>(imageHelper->getAllocation().getHandle()));
7409 
7410             getPerfCounters().deviceMemoryImageAllocationFallbacks++;
7411         }
7412     }
7413 
7414     // If the allocation continues to fail despite all the fallback options, the error must be
7415     // returned.
7416     ANGLE_VK_CHECK(this, result == VK_SUCCESS, result);
7417 
7418     // Initialize with non-zero value if needed.
7419     if (mRenderer->getFeatures().allocateNonZeroMemory.enabled)
7420     {
7421         ANGLE_TRY(imageHelper->initializeNonZeroMemory(this, hasProtectedContent, outputFlags,
7422                                                        outputSize));
7423         imageHelper->getImage().getHandle();
7424     }
7425 
7426     return angle::Result::Continue;
7427 }
7428 
releaseBufferAllocation(vk::BufferHelper * bufferHelper)7429 angle::Result ContextVk::releaseBufferAllocation(vk::BufferHelper *bufferHelper)
7430 {
7431     bufferHelper->releaseBufferAndDescriptorSetCache(this);
7432 
7433     if (ANGLE_UNLIKELY(hasExcessPendingGarbage()))
7434     {
7435         ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr,
7436                                          RenderPassClosureReason::ExcessivePendingGarbage));
7437     }
7438     return angle::Result::Continue;
7439 }
7440 
initBufferForBufferCopy(vk::BufferHelper * bufferHelper,size_t size,vk::MemoryCoherency coherency)7441 angle::Result ContextVk::initBufferForBufferCopy(vk::BufferHelper *bufferHelper,
7442                                                  size_t size,
7443                                                  vk::MemoryCoherency coherency)
7444 {
7445     uint32_t memoryTypeIndex = mRenderer->getStagingBufferMemoryTypeIndex(coherency);
7446     size_t alignment         = mRenderer->getStagingBufferAlignment();
7447     return initBufferAllocation(bufferHelper, memoryTypeIndex, size, alignment,
7448                                 BufferUsageType::Dynamic);
7449 }
7450 
initBufferForImageCopy(vk::BufferHelper * bufferHelper,size_t size,vk::MemoryCoherency coherency,angle::FormatID formatId,VkDeviceSize * offset,uint8_t ** dataPtr)7451 angle::Result ContextVk::initBufferForImageCopy(vk::BufferHelper *bufferHelper,
7452                                                 size_t size,
7453                                                 vk::MemoryCoherency coherency,
7454                                                 angle::FormatID formatId,
7455                                                 VkDeviceSize *offset,
7456                                                 uint8_t **dataPtr)
7457 {
7458     // When a buffer is used in copyImage, the offset must be multiple of pixel bytes. This may
7459     // result in non-power of two alignment. VMA's virtual allocator can not handle non-power of two
7460     // alignment. We have to adjust offset manually.
7461     uint32_t memoryTypeIndex  = mRenderer->getStagingBufferMemoryTypeIndex(coherency);
7462     size_t imageCopyAlignment = vk::GetImageCopyBufferAlignment(formatId);
7463 
7464     // Add extra padding for potential offset alignment
7465     size_t allocationSize   = size + imageCopyAlignment;
7466     allocationSize          = roundUp(allocationSize, imageCopyAlignment);
7467     size_t stagingAlignment = static_cast<size_t>(mRenderer->getStagingBufferAlignment());
7468 
7469     ANGLE_TRY(initBufferAllocation(bufferHelper, memoryTypeIndex, allocationSize, stagingAlignment,
7470                                    BufferUsageType::Static));
7471 
7472     *offset  = roundUp(bufferHelper->getOffset(), static_cast<VkDeviceSize>(imageCopyAlignment));
7473     *dataPtr = bufferHelper->getMappedMemory() + (*offset) - bufferHelper->getOffset();
7474 
7475     return angle::Result::Continue;
7476 }
7477 
initBufferForVertexConversion(ConversionBuffer * conversionBuffer,size_t size,vk::MemoryHostVisibility hostVisibility)7478 angle::Result ContextVk::initBufferForVertexConversion(ConversionBuffer *conversionBuffer,
7479                                                        size_t size,
7480                                                        vk::MemoryHostVisibility hostVisibility)
7481 {
7482     vk::BufferHelper *bufferHelper = conversionBuffer->getBuffer();
7483     if (bufferHelper->valid())
7484     {
7485         // If size is big enough and it is idle, then just reuse the existing buffer. Or if current
7486         // render pass uses the buffer, try to allocate a new one to avoid breaking the render pass.
7487         if (size <= bufferHelper->getSize() &&
7488             (hostVisibility == vk::MemoryHostVisibility::Visible) ==
7489                 bufferHelper->isHostVisible() &&
7490             !isRenderPassStartedAndUsesBuffer(*bufferHelper))
7491         {
7492             if (mRenderer->hasResourceUseFinished(bufferHelper->getResourceUse()))
7493             {
7494                 bufferHelper->initializeBarrierTracker(this);
7495                 return angle::Result::Continue;
7496             }
7497             else if (hostVisibility == vk::MemoryHostVisibility::NonVisible)
7498             {
7499                 // For device local buffer, we can reuse the buffer even if it is still GPU busy.
7500                 // The memory barrier should take care of this.
7501                 return angle::Result::Continue;
7502             }
7503         }
7504 
7505         bufferHelper->release(this);
7506     }
7507 
7508     //  Mark entire buffer dirty if we have to reallocate the buffer.
7509     conversionBuffer->setEntireBufferDirty();
7510 
7511     uint32_t memoryTypeIndex = mRenderer->getVertexConversionBufferMemoryTypeIndex(hostVisibility);
7512     size_t alignment         = static_cast<size_t>(mRenderer->getVertexConversionBufferAlignment());
7513 
7514     // The size is retrieved and used in descriptor set. The descriptor set wants aligned size,
7515     // otherwise there are test failures. Note that the underlying VMA allocation is always
7516     // allocated with an aligned size anyway.
7517     size_t sizeToAllocate = roundUp(size, alignment);
7518 
7519     return initBufferAllocation(bufferHelper, memoryTypeIndex, sizeToAllocate, alignment,
7520                                 BufferUsageType::Static);
7521 }
7522 
updateActiveTextures(const gl::Context * context,gl::Command command)7523 angle::Result ContextVk::updateActiveTextures(const gl::Context *context, gl::Command command)
7524 {
7525     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
7526     ProgramExecutableVk *executableVk       = vk::GetImpl(executable);
7527 
7528     const gl::ActiveTexturesCache &textures        = mState.getActiveTexturesCache();
7529     const gl::ActiveTextureMask &activeTextures    = executable->getActiveSamplersMask();
7530     const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
7531 
7532     FillWithNullptr(&mActiveTextures);
7533 
7534     bool recreatePipelineLayout                                     = false;
7535     ImmutableSamplerIndexMap immutableSamplerIndexMap               = {};
7536     std::unordered_map<size_t, uint32_t> textureUnitSamplerIndexMap = {};
7537     for (size_t textureUnit : activeTextures)
7538     {
7539         gl::Texture *texture        = textures[textureUnit];
7540         gl::TextureType textureType = textureTypes[textureUnit];
7541         ASSERT(textureType != gl::TextureType::InvalidEnum);
7542 
7543         const bool isIncompleteTexture = texture == nullptr;
7544 
7545         // Null textures represent incomplete textures.
7546         if (isIncompleteTexture)
7547         {
7548             ANGLE_TRY(getIncompleteTexture(
7549                 context, textureType, executable->getSamplerFormatForTextureUnitIndex(textureUnit),
7550                 &texture));
7551         }
7552 
7553         TextureVk *textureVk = vk::GetImpl(texture);
7554         ASSERT(textureVk != nullptr);
7555 
7556         mActiveTextures[textureUnit] = textureVk;
7557 
7558         if (textureType == gl::TextureType::Buffer)
7559         {
7560             vk::BufferHelper *buffer = textureVk->getPossiblyEmulatedTextureBuffer(this);
7561 
7562             if (mCurrentTransformFeedbackQueueSerial.valid() &&
7563                 buffer->writtenByCommandBuffer(mCurrentTransformFeedbackQueueSerial))
7564             {
7565                 ANGLE_TRY(flushCommandsAndEndRenderPass(
7566                     RenderPassClosureReason::XfbWriteThenTextureBuffer));
7567             }
7568             continue;
7569         }
7570 
7571         if (!isIncompleteTexture && texture->isDepthOrStencil())
7572         {
7573             const bool isStencilTexture = IsStencilSamplerBinding(*executable, textureUnit);
7574             ANGLE_TRY(switchToReadOnlyDepthStencilMode(texture, command, getDrawFramebuffer(),
7575                                                        isStencilTexture));
7576         }
7577 
7578         gl::Sampler *sampler = mState.getSampler(static_cast<uint32_t>(textureUnit));
7579         const gl::SamplerState &samplerState =
7580             sampler ? sampler->getSamplerState() : texture->getSamplerState();
7581 
7582         // GL_EXT_texture_sRGB_decode
7583         //   The new parameter, TEXTURE_SRGB_DECODE_EXT controls whether the
7584         //   decoding happens at sample time. It only applies to textures with an
7585         //   internal format that is sRGB and is ignored for all other textures.
7586         ANGLE_TRY(textureVk->updateSrgbDecodeState(this, samplerState));
7587 
7588         const vk::ImageHelper &image = textureVk->getImage();
7589         if (image.hasInefficientlyEmulatedImageFormat())
7590         {
7591             ANGLE_VK_PERF_WARNING(
7592                 this, GL_DEBUG_SEVERITY_LOW,
7593                 "The Vulkan driver does not support texture format 0x%04X, emulating with 0x%04X",
7594                 image.getIntendedFormat().glInternalFormat,
7595                 image.getActualFormat().glInternalFormat);
7596         }
7597 
7598         if (image.hasImmutableSampler())
7599         {
7600             if (textureUnitSamplerIndexMap.empty())
7601             {
7602                 GenerateTextureUnitSamplerIndexMap(executable->getSamplerBoundTextureUnits(),
7603                                                    &textureUnitSamplerIndexMap);
7604             }
7605             immutableSamplerIndexMap[image.getYcbcrConversionDesc()] =
7606                 textureUnitSamplerIndexMap[textureUnit];
7607         }
7608 
7609         if (textureVk->getAndResetImmutableSamplerDirtyState())
7610         {
7611             recreatePipelineLayout = true;
7612         }
7613     }
7614 
7615     if (!executableVk->areImmutableSamplersCompatible(immutableSamplerIndexMap))
7616     {
7617         recreatePipelineLayout = true;
7618     }
7619 
7620     // Recreate the pipeline layout, if necessary.
7621     if (recreatePipelineLayout)
7622     {
7623         executableVk->resetLayout(this);
7624         ANGLE_TRY(executableVk->createPipelineLayout(
7625             this, &getPipelineLayoutCache(), &getDescriptorSetLayoutCache(), &mActiveTextures));
7626         ANGLE_TRY(executableVk->initializeDescriptorPools(this, &getDescriptorSetLayoutCache(),
7627                                                           &getMetaDescriptorPools()));
7628 
7629         // The default uniforms descriptor set was reset during createPipelineLayout(), so mark them
7630         // dirty to get everything reallocated/rebound before the next draw.
7631         if (executable->hasDefaultUniforms())
7632         {
7633             executableVk->setAllDefaultUniformsDirty();
7634         }
7635     }
7636 
7637     return angle::Result::Continue;
7638 }
7639 
7640 template <typename CommandBufferHelperT>
updateActiveImages(CommandBufferHelperT * commandBufferHelper)7641 angle::Result ContextVk::updateActiveImages(CommandBufferHelperT *commandBufferHelper)
7642 {
7643     const gl::State &glState                = mState;
7644     const gl::ProgramExecutable *executable = glState.getProgramExecutable();
7645     ASSERT(executable);
7646 
7647     // If there are memoryBarrier call being made that requires we insert barriers for images we
7648     // must do so.
7649     bool memoryBarrierRequired = false;
7650     if ((mDeferredMemoryBarriers & kWriteAfterAccessImageMemoryBarriers) != 0)
7651     {
7652         memoryBarrierRequired = true;
7653         mDeferredMemoryBarriers &= ~kWriteAfterAccessImageMemoryBarriers;
7654     }
7655 
7656     FillWithNullptr(&mActiveImages);
7657 
7658     const gl::ActiveTextureMask &activeImages = executable->getActiveImagesMask();
7659     const gl::ActiveTextureArray<gl::ShaderBitSet> &activeImageShaderBits =
7660         executable->getActiveImageShaderBits();
7661 
7662     // Note: currently, the image layout is transitioned entirely even if only one level or layer is
7663     // used.  This is an issue if one subresource of the image is used as framebuffer attachment and
7664     // the other as image.  This is a similar issue to http://anglebug.com/40096531.  Another issue
7665     // however is if multiple subresources of the same image are used at the same time.
7666     // Inefficiencies aside, setting write dependency on the same image multiple times is not
7667     // supported.  The following makes sure write dependencies are set only once per image.
7668     std::set<vk::ImageHelper *> alreadyProcessed;
7669 
7670     for (size_t imageUnitIndex : activeImages)
7671     {
7672         const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
7673         const gl::Texture *texture     = imageUnit.texture.get();
7674         if (texture == nullptr)
7675         {
7676             continue;
7677         }
7678 
7679         TextureVk *textureVk          = vk::GetImpl(texture);
7680         mActiveImages[imageUnitIndex] = textureVk;
7681 
7682         // The image should be flushed and ready to use at this point. There may still be
7683         // lingering staged updates in its staging buffer for unused texture mip levels or
7684         // layers. Therefore we can't verify it has no staged updates right here.
7685         gl::ShaderBitSet shaderStages = activeImageShaderBits[imageUnitIndex];
7686         ASSERT(shaderStages.any());
7687 
7688         // Special handling of texture buffers.  They have a buffer attached instead of an image.
7689         if (texture->getType() == gl::TextureType::Buffer)
7690         {
7691             BufferVk *bufferVk = vk::GetImpl(textureVk->getBuffer().get());
7692 
7693             OnImageBufferWrite(this, bufferVk, shaderStages, commandBufferHelper);
7694 
7695             textureVk->retainBufferViews(commandBufferHelper);
7696             continue;
7697         }
7698 
7699         vk::ImageHelper *image = &textureVk->getImage();
7700 
7701         if (alreadyProcessed.find(image) != alreadyProcessed.end())
7702         {
7703             continue;
7704         }
7705         alreadyProcessed.insert(image);
7706 
7707         gl::LevelIndex level;
7708         uint32_t layerStart               = 0;
7709         uint32_t layerCount               = 0;
7710         const vk::ImageLayout imageLayout = GetImageWriteLayoutAndSubresource(
7711             imageUnit, *image, shaderStages, &level, &layerStart, &layerCount);
7712 
7713         if (imageLayout == image->getCurrentImageLayout() && !memoryBarrierRequired)
7714         {
7715             // GL spec does not require implementation to do WAW barriers for shader image access.
7716             // If there is no layout change, we skip the barrier here unless there is prior
7717             // memoryBarrier call.
7718             commandBufferHelper->retainImageWithEvent(this, image);
7719         }
7720         else
7721         {
7722             commandBufferHelper->imageWrite(this, level, layerStart, layerCount,
7723                                             image->getAspectFlags(), imageLayout, image);
7724         }
7725     }
7726 
7727     return angle::Result::Continue;
7728 }
7729 
flushAndSubmitCommands(const vk::Semaphore * signalSemaphore,const vk::SharedExternalFence * externalFence,RenderPassClosureReason renderPassClosureReason)7730 angle::Result ContextVk::flushAndSubmitCommands(const vk::Semaphore *signalSemaphore,
7731                                                 const vk::SharedExternalFence *externalFence,
7732                                                 RenderPassClosureReason renderPassClosureReason)
7733 {
7734     // Even if render pass does not have any command, we may still need to submit it in case it has
7735     // CLEAR loadOp.
7736     bool someCommandsNeedFlush =
7737         !mOutsideRenderPassCommands->empty() || mRenderPassCommands->started();
7738     bool someCommandAlreadyFlushedNeedsSubmit =
7739         mLastFlushedQueueSerial != mLastSubmittedQueueSerial;
7740     bool someOtherReasonNeedsSubmit = signalSemaphore != nullptr || externalFence != nullptr ||
7741                                       mHasWaitSemaphoresPendingSubmission ||
7742                                       hasForeignImagesToTransition();
7743 
7744     if (!someCommandsNeedFlush && !someCommandAlreadyFlushedNeedsSubmit &&
7745         !someOtherReasonNeedsSubmit)
7746     {
7747         // We have nothing to submit.
7748         return angle::Result::Continue;
7749     }
7750 
7751     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::flushAndSubmitCommands");
7752     if (someCommandsNeedFlush)
7753     {
7754         // If any of secondary command buffer not empty, we need to do flush
7755         // Avoid calling vkQueueSubmit() twice, since submitCommands() below will do that.
7756         ANGLE_TRY(flushCommandsAndEndRenderPassWithoutSubmit(renderPassClosureReason));
7757     }
7758     else if (someCommandAlreadyFlushedNeedsSubmit)
7759     {
7760         // This is when someone already called flushCommandsAndEndRenderPassWithoutQueueSubmit.
7761         // Nothing to flush but we have some command to submit.
7762         ASSERT(mLastFlushedQueueSerial.valid());
7763         ASSERT(QueueSerialsHaveDifferentIndexOrSmaller(mLastSubmittedQueueSerial,
7764                                                        mLastFlushedQueueSerial));
7765     }
7766 
7767     const bool outsideRenderPassWritesToBuffer =
7768         mOutsideRenderPassCommands->getAndResetHasHostVisibleBufferWrite();
7769     const bool renderPassWritesToBuffer =
7770         mRenderPassCommands->getAndResetHasHostVisibleBufferWrite();
7771     if (mIsAnyHostVisibleBufferWritten || outsideRenderPassWritesToBuffer ||
7772         renderPassWritesToBuffer)
7773     {
7774         // Make sure all writes to host-visible buffers are flushed.  We have no way of knowing
7775         // whether any buffer will be mapped for readback in the future, and we can't afford to
7776         // flush and wait on a one-pipeline-barrier command buffer on every map().
7777         VkMemoryBarrier memoryBarrier = {};
7778         memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
7779         memoryBarrier.srcAccessMask   = VK_ACCESS_MEMORY_WRITE_BIT;
7780         memoryBarrier.dstAccessMask   = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_HOST_WRITE_BIT;
7781 
7782         mOutsideRenderPassCommands->getCommandBuffer().memoryBarrier(
7783             mRenderer->getSupportedBufferWritePipelineStageMask(), VK_PIPELINE_STAGE_HOST_BIT,
7784             memoryBarrier);
7785         mIsAnyHostVisibleBufferWritten = false;
7786     }
7787 
7788     if (mGpuEventsEnabled)
7789     {
7790         EventName eventName = GetTraceEventName("Primary", mPrimaryBufferEventCounter);
7791         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
7792                                 TRACE_EVENT_PHASE_END, eventName));
7793     }
7794 
7795     // This will handle any commands that might be recorded above as well as flush any wait
7796     // semaphores.
7797     ANGLE_TRY(flushOutsideRenderPassCommands());
7798 
7799     if (mLastFlushedQueueSerial == mLastSubmittedQueueSerial)
7800     {
7801         // We have to do empty submission...
7802         ASSERT(!someCommandsNeedFlush);
7803         mLastFlushedQueueSerial = mOutsideRenderPassCommands->getQueueSerial();
7804         generateOutsideRenderPassCommandsQueueSerial();
7805     }
7806 
7807     // We must add the per context dynamic buffers into resourceUseList before submission so that
7808     // they get retained properly until GPU completes. We do not add current buffer into
7809     // resourceUseList since they never get reused or freed until context gets destroyed, at which
7810     // time we always wait for GPU to finish before destroying the dynamic buffers.
7811     mDefaultUniformStorage.updateQueueSerialAndReleaseInFlightBuffers(this,
7812                                                                       mLastFlushedQueueSerial);
7813 
7814     if (mHasInFlightStreamedVertexBuffers.any())
7815     {
7816         for (size_t attribIndex : mHasInFlightStreamedVertexBuffers)
7817         {
7818             mStreamedVertexBuffers[attribIndex].updateQueueSerialAndReleaseInFlightBuffers(
7819                 this, mLastFlushedQueueSerial);
7820         }
7821         mHasInFlightStreamedVertexBuffers.reset();
7822     }
7823 
7824     ASSERT(mWaitSemaphores.empty());
7825     ASSERT(mWaitSemaphoreStageMasks.empty());
7826 
7827     ANGLE_TRY(submitCommands(signalSemaphore, externalFence, Submit::AllCommands));
7828     mCommandsPendingSubmissionCount = 0;
7829 
7830     ASSERT(mOutsideRenderPassCommands->getQueueSerial() > mLastSubmittedQueueSerial);
7831 
7832     mHasAnyCommandsPendingSubmission    = false;
7833     mHasWaitSemaphoresPendingSubmission = false;
7834     onRenderPassFinished(RenderPassClosureReason::AlreadySpecifiedElsewhere);
7835 
7836     if (mGpuEventsEnabled)
7837     {
7838         EventName eventName = GetTraceEventName("Primary", ++mPrimaryBufferEventCounter);
7839         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
7840                                 TRACE_EVENT_PHASE_BEGIN, eventName));
7841     }
7842 
7843     // Since we just flushed, deferred flush is no longer deferred.
7844     mHasDeferredFlush = false;
7845     return angle::Result::Continue;
7846 }
7847 
finishImpl(RenderPassClosureReason renderPassClosureReason)7848 angle::Result ContextVk::finishImpl(RenderPassClosureReason renderPassClosureReason)
7849 {
7850     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::finishImpl");
7851 
7852     ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr, renderPassClosureReason));
7853 
7854     // You must have to wait for all queue indices ever used to finish. Just wait for
7855     // mLastSubmittedQueueSerial (which only contains current index) to finish is not enough, if it
7856     // has ever became unCurrent and then Current again.
7857     ANGLE_TRY(mRenderer->finishResourceUse(this, mSubmittedResourceUse));
7858 
7859     clearAllGarbage();
7860 
7861     if (mGpuEventsEnabled)
7862     {
7863         // This loop should in practice execute once since the queue is already idle.
7864         while (mInFlightGpuEventQueries.size() > 0)
7865         {
7866             ANGLE_TRY(checkCompletedGpuEvents());
7867         }
7868         // Recalculate the CPU/GPU time difference to account for clock drifting.  Avoid
7869         // unnecessary synchronization if there is no event to be adjusted (happens when
7870         // finish() gets called multiple times towards the end of the application).
7871         if (mGpuEvents.size() > 0)
7872         {
7873             ANGLE_TRY(synchronizeCpuGpuTime());
7874         }
7875     }
7876 
7877     return angle::Result::Continue;
7878 }
7879 
addWaitSemaphore(VkSemaphore semaphore,VkPipelineStageFlags stageMask)7880 void ContextVk::addWaitSemaphore(VkSemaphore semaphore, VkPipelineStageFlags stageMask)
7881 {
7882     mWaitSemaphores.push_back(semaphore);
7883     mWaitSemaphoreStageMasks.push_back(stageMask);
7884     mHasWaitSemaphoresPendingSubmission = true;
7885 }
7886 
getCompatibleRenderPass(const vk::RenderPassDesc & desc,const vk::RenderPass ** renderPassOut)7887 angle::Result ContextVk::getCompatibleRenderPass(const vk::RenderPassDesc &desc,
7888                                                  const vk::RenderPass **renderPassOut)
7889 {
7890     if (getFeatures().preferDynamicRendering.enabled)
7891     {
7892         *renderPassOut = &mNullRenderPass;
7893         return angle::Result::Continue;
7894     }
7895 
7896     // Note: Each context has it's own RenderPassCache so no locking needed.
7897     return mRenderPassCache.getCompatibleRenderPass(this, desc, renderPassOut);
7898 }
7899 
getRenderPassWithOps(const vk::RenderPassDesc & desc,const vk::AttachmentOpsArray & ops,const vk::RenderPass ** renderPassOut)7900 angle::Result ContextVk::getRenderPassWithOps(const vk::RenderPassDesc &desc,
7901                                               const vk::AttachmentOpsArray &ops,
7902                                               const vk::RenderPass **renderPassOut)
7903 {
7904     if (getFeatures().preferDynamicRendering.enabled)
7905     {
7906         if (mState.isPerfMonitorActive())
7907         {
7908             mRenderPassCommands->updatePerfCountersForDynamicRenderingInstance(this,
7909                                                                                &mPerfCounters);
7910         }
7911         return angle::Result::Continue;
7912     }
7913 
7914     // Note: Each context has it's own RenderPassCache so no locking needed.
7915     return mRenderPassCache.getRenderPassWithOps(this, desc, ops, renderPassOut);
7916 }
7917 
getTimestamp(uint64_t * timestampOut)7918 angle::Result ContextVk::getTimestamp(uint64_t *timestampOut)
7919 {
7920     // The intent of this function is to query the timestamp without stalling the GPU.
7921     // Currently, that seems impossible, so instead, we are going to make a small submission
7922     // with just a timestamp query.  First, the disjoint timer query extension says:
7923     //
7924     // > This will return the GL time after all previous commands have reached the GL server but
7925     // have not yet necessarily executed.
7926     //
7927     // The previous commands may be deferred at the moment and not yet flushed. The wording allows
7928     // us to make a submission to get the timestamp without flushing.
7929     //
7930     // Second:
7931     //
7932     // > By using a combination of this synchronous get command and the asynchronous timestamp
7933     // query object target, applications can measure the latency between when commands reach the
7934     // GL server and when they are realized in the framebuffer.
7935     //
7936     // This fits with the above strategy as well, although inevitably we are possibly
7937     // introducing a GPU bubble.  This function directly generates a command buffer and submits
7938     // it instead of using the other member functions.  This is to avoid changing any state,
7939     // such as the queue serial.
7940 
7941     // Create a query used to receive the GPU timestamp
7942     VkDevice device = getDevice();
7943     vk::DeviceScoped<vk::DynamicQueryPool> timestampQueryPool(device);
7944     vk::QueryHelper timestampQuery;
7945     ANGLE_TRY(timestampQueryPool.get().init(this, VK_QUERY_TYPE_TIMESTAMP, 1));
7946     ANGLE_TRY(timestampQueryPool.get().allocateQuery(this, &timestampQuery, 1));
7947 
7948     // Record the command buffer
7949     vk::ScopedPrimaryCommandBuffer scopedCommandBuffer(device);
7950 
7951     ANGLE_TRY(mRenderer->getCommandBufferOneOff(this, getProtectionType(), &scopedCommandBuffer));
7952     vk::PrimaryCommandBuffer &commandBuffer = scopedCommandBuffer.get();
7953 
7954     timestampQuery.writeTimestampToPrimary(this, &commandBuffer);
7955     ANGLE_VK_TRY(this, commandBuffer.end());
7956 
7957     QueueSerial submitQueueSerial;
7958     ANGLE_TRY(mRenderer->queueSubmitOneOff(this, std::move(scopedCommandBuffer),
7959                                            getProtectionType(), mContextPriority, VK_NULL_HANDLE, 0,
7960                                            &submitQueueSerial));
7961     // Track it with the submitSerial.
7962     timestampQuery.setQueueSerial(submitQueueSerial);
7963 
7964     // Wait for the submission to finish.  Given no semaphores, there is hope that it would execute
7965     // in parallel with what's already running on the GPU.
7966     ANGLE_TRY(mRenderer->finishQueueSerial(this, submitQueueSerial));
7967 
7968     // Get the query results
7969     vk::QueryResult result(1);
7970     ANGLE_TRY(timestampQuery.getUint64Result(this, &result));
7971     *timestampOut = result.getResult(vk::QueryResult::kDefaultResultIndex);
7972     timestampQueryPool.get().freeQuery(this, &timestampQuery);
7973 
7974     // Convert results to nanoseconds.
7975     *timestampOut = static_cast<uint64_t>(
7976         *timestampOut *
7977         static_cast<double>(getRenderer()->getPhysicalDeviceProperties().limits.timestampPeriod));
7978 
7979     return angle::Result::Continue;
7980 }
7981 
invalidateDefaultAttribute(size_t attribIndex)7982 void ContextVk::invalidateDefaultAttribute(size_t attribIndex)
7983 {
7984     mDirtyDefaultAttribsMask.set(attribIndex);
7985     mGraphicsDirtyBits.set(DIRTY_BIT_DEFAULT_ATTRIBS);
7986 }
7987 
invalidateDefaultAttributes(const gl::AttributesMask & dirtyMask)7988 void ContextVk::invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask)
7989 {
7990     if (dirtyMask.any())
7991     {
7992         mDirtyDefaultAttribsMask |= dirtyMask;
7993         mGraphicsDirtyBits.set(DIRTY_BIT_DEFAULT_ATTRIBS);
7994         mGraphicsDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
7995     }
7996 }
7997 
onBufferReleaseToExternal(const vk::BufferHelper & buffer)7998 angle::Result ContextVk::onBufferReleaseToExternal(const vk::BufferHelper &buffer)
7999 {
8000     if (mRenderPassCommands->usesBuffer(buffer))
8001     {
8002         return flushCommandsAndEndRenderPass(
8003             RenderPassClosureReason::BufferUseThenReleaseToExternal);
8004     }
8005     return angle::Result::Continue;
8006 }
8007 
onImageReleaseToExternal(const vk::ImageHelper & image)8008 angle::Result ContextVk::onImageReleaseToExternal(const vk::ImageHelper &image)
8009 {
8010     if (isRenderPassStartedAndUsesImage(image))
8011     {
8012         return flushCommandsAndEndRenderPass(
8013             RenderPassClosureReason::ImageUseThenReleaseToExternal);
8014     }
8015     return angle::Result::Continue;
8016 }
8017 
finalizeImageLayout(vk::ImageHelper * image,UniqueSerial imageSiblingSerial)8018 void ContextVk::finalizeImageLayout(vk::ImageHelper *image, UniqueSerial imageSiblingSerial)
8019 {
8020     if (mRenderPassCommands->started())
8021     {
8022         mRenderPassCommands->finalizeImageLayout(this, image, imageSiblingSerial);
8023     }
8024 
8025     if (image->isForeignImage() && !image->isReleasedToForeign())
8026     {
8027         // Note: Foreign images may be shared between different textures.  If another texture starts
8028         // to use the image while the barrier-to-foreign is cached in the context, it will attempt
8029         // to acquire the image from foreign while the release is still cached.  A submission is
8030         // made to finalize the queue family ownership transfer back to foreign.
8031         (void)flushAndSubmitCommands(nullptr, nullptr,
8032                                      RenderPassClosureReason::ForeignImageRelease);
8033         ASSERT(!hasForeignImagesToTransition());
8034     }
8035 }
8036 
beginNewRenderPass(vk::RenderPassFramebuffer && framebuffer,const gl::Rectangle & renderArea,const vk::RenderPassDesc & renderPassDesc,const vk::AttachmentOpsArray & renderPassAttachmentOps,const vk::PackedAttachmentCount colorAttachmentCount,const vk::PackedAttachmentIndex depthStencilAttachmentIndex,const vk::PackedClearValuesArray & clearValues,vk::RenderPassCommandBuffer ** commandBufferOut)8037 angle::Result ContextVk::beginNewRenderPass(
8038     vk::RenderPassFramebuffer &&framebuffer,
8039     const gl::Rectangle &renderArea,
8040     const vk::RenderPassDesc &renderPassDesc,
8041     const vk::AttachmentOpsArray &renderPassAttachmentOps,
8042     const vk::PackedAttachmentCount colorAttachmentCount,
8043     const vk::PackedAttachmentIndex depthStencilAttachmentIndex,
8044     const vk::PackedClearValuesArray &clearValues,
8045     vk::RenderPassCommandBuffer **commandBufferOut)
8046 {
8047     // End any currently outstanding render pass. The render pass is normally closed before reaching
8048     // here for various reasons, except typically when UtilsVk needs to start one.
8049     ANGLE_TRY(flushCommandsAndEndRenderPass(RenderPassClosureReason::NewRenderPass));
8050 
8051     // Now generate queueSerial for the renderPass.
8052     QueueSerial renderPassQueueSerial;
8053     generateRenderPassCommandsQueueSerial(&renderPassQueueSerial);
8054 
8055     mPerfCounters.renderPasses++;
8056     ANGLE_TRY(mRenderPassCommands->beginRenderPass(
8057         this, std::move(framebuffer), renderArea, renderPassDesc, renderPassAttachmentOps,
8058         colorAttachmentCount, depthStencilAttachmentIndex, clearValues, renderPassQueueSerial,
8059         commandBufferOut));
8060 
8061     // By default all render pass should allow to be reactivated.
8062     mAllowRenderPassToReactivate = true;
8063 
8064     if (mCurrentGraphicsPipeline)
8065     {
8066         ASSERT(mCurrentGraphicsPipeline->valid());
8067         mCurrentGraphicsPipeline->retainInRenderPass(mRenderPassCommands);
8068     }
8069     return angle::Result::Continue;
8070 }
8071 
startRenderPass(gl::Rectangle renderArea,vk::RenderPassCommandBuffer ** commandBufferOut,bool * renderPassDescChangedOut)8072 angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea,
8073                                          vk::RenderPassCommandBuffer **commandBufferOut,
8074                                          bool *renderPassDescChangedOut)
8075 {
8076     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
8077     ASSERT(drawFramebufferVk == vk::GetImpl(mState.getDrawFramebuffer()));
8078 
8079     ANGLE_TRY(drawFramebufferVk->startNewRenderPass(this, renderArea, &mRenderPassCommandBuffer,
8080                                                     renderPassDescChangedOut));
8081 
8082     // For dynamic rendering, the FramebufferVk's render pass desc does not track whether
8083     // framebuffer fetch is in use.  In that case, ContextVk updates the command buffer's (and
8084     // graphics pipeline's) render pass desc only:
8085     //
8086     // - When the render pass starts
8087     // - When the program binding changes (see |invalidateProgramExecutableHelper|)
8088     if (getFeatures().preferDynamicRendering.enabled)
8089     {
8090         vk::FramebufferFetchMode framebufferFetchMode =
8091             vk::GetProgramFramebufferFetchMode(mState.getProgramExecutable());
8092         if (framebufferFetchMode != vk::FramebufferFetchMode::None)
8093         {
8094             // Note: this function sets a dirty bit through onColorAccessChange() not through
8095             // |dirtyBitsIterator|, but that dirty bit is always set on new render passes, so it
8096             // won't be missed.
8097             onFramebufferFetchUse(framebufferFetchMode);
8098         }
8099         else
8100         {
8101             // Reset framebuffer fetch mode.  Note that |onFramebufferFetchUse| _accumulates_
8102             // framebuffer fetch mode.
8103             mRenderPassCommands->setFramebufferFetchMode(vk::FramebufferFetchMode::None);
8104         }
8105     }
8106 
8107     // Make sure the render pass is not restarted if it is started by UtilsVk (as opposed to
8108     // setupDraw(), which clears this bit automatically).
8109     mGraphicsDirtyBits.reset(DIRTY_BIT_RENDER_PASS);
8110 
8111     ANGLE_TRY(resumeRenderPassQueriesIfActive());
8112 
8113     if (commandBufferOut)
8114     {
8115         *commandBufferOut = mRenderPassCommandBuffer;
8116     }
8117 
8118     return angle::Result::Continue;
8119 }
8120 
startNextSubpass()8121 angle::Result ContextVk::startNextSubpass()
8122 {
8123     ASSERT(hasActiveRenderPass());
8124 
8125     // The graphics pipelines are bound to a subpass, so update the subpass as well.
8126     mGraphicsPipelineDesc->nextSubpass(&mGraphicsPipelineTransition);
8127 
8128     return mRenderPassCommands->nextSubpass(this, &mRenderPassCommandBuffer);
8129 }
8130 
getCurrentSubpassIndex() const8131 uint32_t ContextVk::getCurrentSubpassIndex() const
8132 {
8133     return mGraphicsPipelineDesc->getSubpass();
8134 }
8135 
getCurrentViewCount() const8136 uint32_t ContextVk::getCurrentViewCount() const
8137 {
8138     FramebufferVk *drawFBO = vk::GetImpl(mState.getDrawFramebuffer());
8139     return drawFBO->getRenderPassDesc().viewCount();
8140 }
8141 
flushCommandsAndEndRenderPassWithoutSubmit(RenderPassClosureReason reason)8142 angle::Result ContextVk::flushCommandsAndEndRenderPassWithoutSubmit(RenderPassClosureReason reason)
8143 {
8144     // Ensure we flush the RenderPass *after* the prior commands.
8145     ANGLE_TRY(flushOutsideRenderPassCommands());
8146     ASSERT(mOutsideRenderPassCommands->empty());
8147 
8148     if (!mRenderPassCommands->started())
8149     {
8150         onRenderPassFinished(RenderPassClosureReason::AlreadySpecifiedElsewhere);
8151         return angle::Result::Continue;
8152     }
8153 
8154     // Set dirty bits if render pass was open (and thus will be closed).
8155     mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
8156 
8157     mCurrentTransformFeedbackQueueSerial = QueueSerial();
8158 
8159     onRenderPassFinished(reason);
8160 
8161     if (mGpuEventsEnabled)
8162     {
8163         EventName eventName = GetTraceEventName("RP", mPerfCounters.renderPasses);
8164         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
8165                                 TRACE_EVENT_PHASE_BEGIN, eventName));
8166         ANGLE_TRY(flushOutsideRenderPassCommands());
8167     }
8168 
8169     addOverlayUsedBuffersCount(mRenderPassCommands);
8170 
8171     pauseTransformFeedbackIfActiveUnpaused();
8172 
8173     ANGLE_TRY(mRenderPassCommands->endRenderPass(this));
8174 
8175     if (kEnableCommandStreamDiagnostics)
8176     {
8177         addCommandBufferDiagnostics(mRenderPassCommands->getCommandDiagnostics());
8178     }
8179 
8180     flushDescriptorSetUpdates();
8181     // Collect RefCountedEvent garbage before submitting to renderer
8182     mRenderPassCommands->collectRefCountedEventsGarbage(
8183         mRenderer, mShareGroupVk->getRefCountedEventsGarbageRecycler());
8184 
8185     // Save the queueSerial before calling flushRenderPassCommands, which may return a new
8186     // mRenderPassCommands
8187     ASSERT(QueueSerialsHaveDifferentIndexOrSmaller(mLastFlushedQueueSerial,
8188                                                    mRenderPassCommands->getQueueSerial()));
8189     mLastFlushedQueueSerial = mRenderPassCommands->getQueueSerial();
8190 
8191     const vk::RenderPass unusedRenderPass;
8192     const vk::RenderPass *renderPass  = &unusedRenderPass;
8193     VkFramebuffer framebufferOverride = VK_NULL_HANDLE;
8194 
8195     ANGLE_TRY(getRenderPassWithOps(mRenderPassCommands->getRenderPassDesc(),
8196                                    mRenderPassCommands->getAttachmentOps(), &renderPass));
8197 
8198     // If a new framebuffer is used to accommodate resolve attachments that have been added
8199     // after the fact, create a temp one now and add it to garbage list.
8200     if (!getFeatures().preferDynamicRendering.enabled &&
8201         mRenderPassCommands->getFramebuffer().needsNewFramebufferWithResolveAttachments())
8202     {
8203         vk::Framebuffer tempFramebuffer;
8204         ANGLE_TRY(mRenderPassCommands->getFramebuffer().packResolveViewsAndCreateFramebuffer(
8205             this, *renderPass, &tempFramebuffer));
8206 
8207         framebufferOverride = tempFramebuffer.getHandle();
8208         addGarbage(&tempFramebuffer);
8209     }
8210 
8211     if (mRenderPassCommands->getAndResetHasHostVisibleBufferWrite())
8212     {
8213         mIsAnyHostVisibleBufferWritten = true;
8214     }
8215 
8216     // The counter for pending submission count is used for possible submission at FBO boundary and
8217     // flush.
8218     mCommandsPendingSubmissionCount +=
8219         mRenderPassCommands->getCommandBuffer().getRenderPassWriteCommandCount();
8220 
8221     ANGLE_TRY(mRenderer->flushRenderPassCommands(this, getProtectionType(), mContextPriority,
8222                                                  *renderPass, framebufferOverride,
8223                                                  &mRenderPassCommands));
8224 
8225     // We just flushed outSideRenderPassCommands above, and any future use of
8226     // outsideRenderPassCommands must have a queueSerial bigger than renderPassCommands. To ensure
8227     // this ordering, we generate a new queueSerial for outsideRenderPassCommands here.
8228     mOutsideRenderPassSerialFactory.reset();
8229 
8230     // Generate a new serial for outside commands.
8231     generateOutsideRenderPassCommandsQueueSerial();
8232 
8233     if (mGpuEventsEnabled)
8234     {
8235         EventName eventName = GetTraceEventName("RP", mPerfCounters.renderPasses);
8236         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
8237                                 TRACE_EVENT_PHASE_END, eventName));
8238         ANGLE_TRY(flushOutsideRenderPassCommands());
8239     }
8240 
8241     mHasAnyCommandsPendingSubmission = true;
8242     return angle::Result::Continue;
8243 }
8244 
flushCommandsAndEndRenderPass(RenderPassClosureReason reason)8245 angle::Result ContextVk::flushCommandsAndEndRenderPass(RenderPassClosureReason reason)
8246 {
8247     // The main reason we have mHasDeferredFlush is not to break render pass just because we want
8248     // to issue a flush. So there must be a started RP if it is true. Otherwise we should just
8249     // issue a flushAndSubmitCommands immediately instead of set mHasDeferredFlush to true.
8250     ASSERT(!mHasDeferredFlush || mRenderPassCommands->started());
8251 
8252     ANGLE_TRY(flushCommandsAndEndRenderPassWithoutSubmit(reason));
8253 
8254     if (mHasDeferredFlush || hasExcessPendingGarbage())
8255     {
8256         // If we have deferred glFlush call in the middle of render pass, or if there is too much
8257         // pending garbage, perform a flush now.
8258         RenderPassClosureReason flushImplReason =
8259             (hasExcessPendingGarbage()) ? RenderPassClosureReason::ExcessivePendingGarbage
8260                                         : RenderPassClosureReason::AlreadySpecifiedElsewhere;
8261         ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr, flushImplReason));
8262     }
8263     return angle::Result::Continue;
8264 }
8265 
flushDirtyGraphicsRenderPass(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask,RenderPassClosureReason reason)8266 angle::Result ContextVk::flushDirtyGraphicsRenderPass(DirtyBits::Iterator *dirtyBitsIterator,
8267                                                       DirtyBits dirtyBitMask,
8268                                                       RenderPassClosureReason reason)
8269 {
8270     ASSERT(mRenderPassCommands->started());
8271 
8272     ANGLE_TRY(flushCommandsAndEndRenderPass(reason));
8273 
8274     // Set dirty bits that need processing on new render pass on the dirty bits iterator that's
8275     // being processed right now.
8276     dirtyBitsIterator->setLaterBits(mNewGraphicsCommandBufferDirtyBits & dirtyBitMask);
8277 
8278     // Additionally, make sure any dirty bits not included in the mask are left for future
8279     // processing.  Note that |dirtyBitMask| is removed from |mNewGraphicsCommandBufferDirtyBits|
8280     // after dirty bits are iterated, so there's no need to mask them out.
8281     mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
8282 
8283     ASSERT(mGraphicsPipelineDesc->getSubpass() == 0);
8284 
8285     return angle::Result::Continue;
8286 }
8287 
syncExternalMemory()8288 angle::Result ContextVk::syncExternalMemory()
8289 {
8290     VkMemoryBarrier memoryBarrier = {};
8291     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
8292     memoryBarrier.srcAccessMask   = VK_ACCESS_MEMORY_WRITE_BIT;
8293     memoryBarrier.dstAccessMask   = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
8294 
8295     mOutsideRenderPassCommands->getCommandBuffer().memoryBarrier(
8296         VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, memoryBarrier);
8297     return angle::Result::Continue;
8298 }
8299 
onSyncObjectInit(vk::SyncHelper * syncHelper,SyncFenceScope scope)8300 angle::Result ContextVk::onSyncObjectInit(vk::SyncHelper *syncHelper, SyncFenceScope scope)
8301 {
8302     // Submit the commands:
8303     //
8304     // - This breaks the current render pass to ensure the proper ordering of the sync object in the
8305     //   commands,
8306     // - The sync object has a valid serial when it's waited on later,
8307     // - After waiting on the sync object, every resource that's used so far (and is being synced)
8308     //   will also be aware that it's finished (based on the serial) and won't incur a further wait
8309     //   (for example when a buffer is mapped).
8310     //
8311     // The submission is done immediately for EGL sync objects, and when no render pass is open.  If
8312     // a render pass is open, the submission is deferred.  This is done to be able to optimize
8313     // scenarios such as sync object init followed by eglSwapBuffers() (that would otherwise incur
8314     // another submission, as well as not being able to optimize the render-to-swapchain render
8315     // pass).
8316     if (scope != SyncFenceScope::CurrentContextToShareGroup || !mRenderPassCommands->started())
8317     {
8318         ANGLE_TRY(
8319             flushAndSubmitCommands(nullptr, nullptr, RenderPassClosureReason::SyncObjectInit));
8320         // Even if no commands is generated, and flushAndSubmitCommands bails out, queueSerial is
8321         // valid since Context initialization. It will always test finished/signaled.
8322         ASSERT(mLastSubmittedQueueSerial.valid());
8323 
8324         // If src synchronization scope is all contexts (an ANGLE extension), set the syncHelper
8325         // serial to the last serial of all contexts, instead of just the current context.
8326         if (scope == SyncFenceScope::AllContextsToAllContexts)
8327         {
8328             const size_t maxIndex = mRenderer->getLargestQueueSerialIndexEverAllocated();
8329             for (SerialIndex index = 0; index <= maxIndex; ++index)
8330             {
8331                 syncHelper->setSerial(index, mRenderer->getLastSubmittedSerial(index));
8332             }
8333         }
8334         else
8335         {
8336             syncHelper->setQueueSerial(mLastSubmittedQueueSerial);
8337         }
8338 
8339         return angle::Result::Continue;
8340     }
8341 
8342     // Otherwise we must have a started render pass. The sync object will track the completion of
8343     // this render pass.
8344     mRenderPassCommands->retainResource(syncHelper);
8345 
8346     onRenderPassFinished(RenderPassClosureReason::SyncObjectInit);
8347 
8348     // Mark the context as having a deferred flush.  This is later used to close the render pass and
8349     // cause a submission in this context if another context wants to wait on the fence while the
8350     // original context never issued a submission naturally.  Note that this also takes care of
8351     // contexts that think they issued a submission (through glFlush) but that the submission got
8352     // deferred.
8353     mHasDeferredFlush = true;
8354 
8355     return angle::Result::Continue;
8356 }
8357 
flushCommandsAndEndRenderPassIfDeferredSyncInit(RenderPassClosureReason reason)8358 angle::Result ContextVk::flushCommandsAndEndRenderPassIfDeferredSyncInit(
8359     RenderPassClosureReason reason)
8360 {
8361     if (!mHasDeferredFlush)
8362     {
8363         return angle::Result::Continue;
8364     }
8365 
8366     // If we have deferred glFlush call in the middle of render pass, flush them now.
8367     return flushCommandsAndEndRenderPass(reason);
8368 }
8369 
addCommandBufferDiagnostics(const std::string & commandBufferDiagnostics)8370 void ContextVk::addCommandBufferDiagnostics(const std::string &commandBufferDiagnostics)
8371 {
8372     mCommandBufferDiagnostics.push_back(commandBufferDiagnostics);
8373 }
8374 
dumpCommandStreamDiagnostics()8375 void ContextVk::dumpCommandStreamDiagnostics()
8376 {
8377     std::ostream &out = std::cout;
8378 
8379     if (mCommandBufferDiagnostics.empty())
8380         return;
8381 
8382     out << "digraph {\n" << "  node [shape=plaintext fontname=\"Consolas\"]\n";
8383 
8384     for (size_t index = 0; index < mCommandBufferDiagnostics.size(); ++index)
8385     {
8386         const std::string &payload = mCommandBufferDiagnostics[index];
8387         out << "  cb" << index << " [label =\"" << payload << "\"];\n";
8388     }
8389 
8390     for (size_t index = 0; index < mCommandBufferDiagnostics.size() - 1; ++index)
8391     {
8392         out << "  cb" << index << " -> cb" << index + 1 << "\n";
8393     }
8394 
8395     mCommandBufferDiagnostics.clear();
8396 
8397     out << "}\n";
8398 }
8399 
initIndexTypeMap()8400 void ContextVk::initIndexTypeMap()
8401 {
8402     // Init gles-vulkan index type map
8403     mIndexTypeMap[gl::DrawElementsType::UnsignedByte] =
8404         mRenderer->getFeatures().supportsIndexTypeUint8.enabled ? VK_INDEX_TYPE_UINT8_EXT
8405                                                                 : VK_INDEX_TYPE_UINT16;
8406     mIndexTypeMap[gl::DrawElementsType::UnsignedShort] = VK_INDEX_TYPE_UINT16;
8407     mIndexTypeMap[gl::DrawElementsType::UnsignedInt]   = VK_INDEX_TYPE_UINT32;
8408 }
8409 
getVkIndexType(gl::DrawElementsType glIndexType) const8410 VkIndexType ContextVk::getVkIndexType(gl::DrawElementsType glIndexType) const
8411 {
8412     return mIndexTypeMap[glIndexType];
8413 }
8414 
getVkIndexTypeSize(gl::DrawElementsType glIndexType) const8415 size_t ContextVk::getVkIndexTypeSize(gl::DrawElementsType glIndexType) const
8416 {
8417     gl::DrawElementsType elementsType = shouldConvertUint8VkIndexType(glIndexType)
8418                                             ? gl::DrawElementsType::UnsignedShort
8419                                             : glIndexType;
8420     ASSERT(elementsType < gl::DrawElementsType::EnumCount);
8421 
8422     // Use GetDrawElementsTypeSize() to get the size
8423     return static_cast<size_t>(gl::GetDrawElementsTypeSize(elementsType));
8424 }
8425 
shouldConvertUint8VkIndexType(gl::DrawElementsType glIndexType) const8426 bool ContextVk::shouldConvertUint8VkIndexType(gl::DrawElementsType glIndexType) const
8427 {
8428     return (glIndexType == gl::DrawElementsType::UnsignedByte &&
8429             !mRenderer->getFeatures().supportsIndexTypeUint8.enabled);
8430 }
8431 
GetDriverUniformSize(vk::ErrorContext * context,PipelineType pipelineType)8432 uint32_t GetDriverUniformSize(vk::ErrorContext *context, PipelineType pipelineType)
8433 {
8434     if (pipelineType == PipelineType::Compute)
8435     {
8436         return sizeof(ComputeDriverUniforms);
8437     }
8438 
8439     ASSERT(pipelineType == PipelineType::Graphics);
8440     if (ShouldUseGraphicsDriverUniformsExtended(context))
8441     {
8442         return sizeof(GraphicsDriverUniformsExtended);
8443     }
8444     else
8445     {
8446         return sizeof(GraphicsDriverUniforms);
8447     }
8448 }
8449 
flushAndSubmitOutsideRenderPassCommands()8450 angle::Result ContextVk::flushAndSubmitOutsideRenderPassCommands()
8451 {
8452     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::flushAndSubmitOutsideRenderPassCommands");
8453     ANGLE_TRY(flushOutsideRenderPassCommands());
8454     return submitCommands(nullptr, nullptr, Submit::OutsideRenderPassCommandsOnly);
8455 }
8456 
flushOutsideRenderPassCommands()8457 angle::Result ContextVk::flushOutsideRenderPassCommands()
8458 {
8459     if (!mWaitSemaphores.empty())
8460     {
8461         ASSERT(mHasWaitSemaphoresPendingSubmission);
8462         ANGLE_TRY(mRenderer->flushWaitSemaphores(getProtectionType(), mContextPriority,
8463                                                  std::move(mWaitSemaphores),
8464                                                  std::move(mWaitSemaphoreStageMasks)));
8465     }
8466     ASSERT(mWaitSemaphores.empty());
8467     ASSERT(mWaitSemaphoreStageMasks.empty());
8468 
8469     if (mOutsideRenderPassCommands->empty())
8470     {
8471         return angle::Result::Continue;
8472     }
8473     ASSERT(mOutsideRenderPassCommands->getQueueSerial().valid());
8474 
8475     addOverlayUsedBuffersCount(mOutsideRenderPassCommands);
8476 
8477     if (kEnableCommandStreamDiagnostics)
8478     {
8479         addCommandBufferDiagnostics(mOutsideRenderPassCommands->getCommandDiagnostics());
8480     }
8481 
8482     flushDescriptorSetUpdates();
8483 
8484     // Track completion of this command buffer.
8485     mOutsideRenderPassCommands->flushSetEvents(this);
8486     mOutsideRenderPassCommands->collectRefCountedEventsGarbage(
8487         mShareGroupVk->getRefCountedEventsGarbageRecycler());
8488 
8489     // Save the queueSerial before calling flushOutsideRPCommands, which may return a new
8490     // mOutsideRenderPassCommands
8491     ASSERT(QueueSerialsHaveDifferentIndexOrSmaller(mLastFlushedQueueSerial,
8492                                                    mOutsideRenderPassCommands->getQueueSerial()));
8493     mLastFlushedQueueSerial = mOutsideRenderPassCommands->getQueueSerial();
8494 
8495     if (mOutsideRenderPassCommands->getAndResetHasHostVisibleBufferWrite())
8496     {
8497         mIsAnyHostVisibleBufferWritten = true;
8498     }
8499     ANGLE_TRY(mRenderer->flushOutsideRPCommands(this, getProtectionType(), mContextPriority,
8500                                                 &mOutsideRenderPassCommands));
8501 
8502     // Make sure appropriate dirty bits are set, in case another thread makes a submission before
8503     // the next dispatch call.
8504     mComputeDirtyBits |= mNewComputeCommandBufferDirtyBits;
8505     mHasAnyCommandsPendingSubmission = true;
8506     mPerfCounters.flushedOutsideRenderPassCommandBuffers++;
8507 
8508     if (mRenderPassCommands->started() && mOutsideRenderPassSerialFactory.empty())
8509     {
8510         ANGLE_PERF_WARNING(
8511             getDebug(), GL_DEBUG_SEVERITY_HIGH,
8512             "Running out of reserved outsideRenderPass queueSerial. ending renderPass now.");
8513         // flushCommandsAndEndRenderPass will end up call back into this function again. We must
8514         // ensure mOutsideRenderPassCommands is empty so that it can early out.
8515         ASSERT(mOutsideRenderPassCommands->empty());
8516         // We used up all reserved serials. In order to maintain serial order (outsideRenderPass
8517         // must be smaller than render pass), we also endRenderPass here as well. This is not
8518         // expected to happen often in real world usage.
8519         return flushCommandsAndEndRenderPass(
8520             RenderPassClosureReason::OutOfReservedQueueSerialForOutsideCommands);
8521     }
8522     else
8523     {
8524         // Since queueSerial is used to decide if a resource is being used or not, we have to
8525         // generate a new queueSerial for outsideCommandBuffer since we just flushed
8526         // outsideRenderPassCommands.
8527         generateOutsideRenderPassCommandsQueueSerial();
8528     }
8529 
8530     return angle::Result::Continue;
8531 }
8532 
beginRenderPassQuery(QueryVk * queryVk)8533 angle::Result ContextVk::beginRenderPassQuery(QueryVk *queryVk)
8534 {
8535     gl::QueryType type = queryVk->getType();
8536 
8537     // Emit debug-util markers before calling the query command.
8538     ANGLE_TRY(handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd));
8539 
8540     // To avoid complexity, we always start and end these queries inside the render pass.  If the
8541     // render pass has not yet started, the query is deferred until it does.
8542     if (mRenderPassCommandBuffer)
8543     {
8544         ANGLE_TRY(queryVk->getQueryHelper()->beginRenderPassQuery(this));
8545         // Remove the dirty bit since next draw call will have active query enabled
8546         if (getFeatures().preferSubmitOnAnySamplesPassedQueryEnd.enabled && IsAnySamplesQuery(type))
8547         {
8548             mGraphicsDirtyBits.reset(DIRTY_BIT_ANY_SAMPLE_PASSED_QUERY_END);
8549         }
8550     }
8551 
8552     // Update rasterizer discard emulation with primitives generated query if necessary.
8553     if (type == gl::QueryType::PrimitivesGenerated)
8554     {
8555         updateRasterizerDiscardEnabled(true);
8556     }
8557 
8558     ASSERT(mActiveRenderPassQueries[type] == nullptr);
8559     mActiveRenderPassQueries[type] = queryVk;
8560 
8561     return angle::Result::Continue;
8562 }
8563 
endRenderPassQuery(QueryVk * queryVk)8564 angle::Result ContextVk::endRenderPassQuery(QueryVk *queryVk)
8565 {
8566     gl::QueryType type = queryVk->getType();
8567 
8568     // Emit debug-util markers before calling the query command.
8569     ANGLE_TRY(handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd));
8570 
8571     // End the query inside the render pass.  In some situations, the query may not have actually
8572     // been issued, so there is nothing to do there.  That is the case for transform feedback
8573     // queries which are deferred until a draw call with transform feedback active is issued, which
8574     // may have never happened.
8575     ASSERT(mRenderPassCommandBuffer == nullptr ||
8576            type == gl::QueryType::TransformFeedbackPrimitivesWritten || queryVk->hasQueryBegun());
8577     if (mRenderPassCommandBuffer && queryVk->hasQueryBegun())
8578     {
8579         queryVk->getQueryHelper()->endRenderPassQuery(this);
8580         // Set dirty bit so that we can detect and do something when a draw without active query is
8581         // issued.
8582         if (getFeatures().preferSubmitOnAnySamplesPassedQueryEnd.enabled && IsAnySamplesQuery(type))
8583         {
8584             mGraphicsDirtyBits.set(DIRTY_BIT_ANY_SAMPLE_PASSED_QUERY_END);
8585         }
8586     }
8587 
8588     // Update rasterizer discard emulation with primitives generated query if necessary.
8589     if (type == gl::QueryType::PrimitivesGenerated)
8590     {
8591         updateRasterizerDiscardEnabled(false);
8592     }
8593 
8594     ASSERT(mActiveRenderPassQueries[type] == queryVk);
8595     mActiveRenderPassQueries[type] = nullptr;
8596 
8597     return angle::Result::Continue;
8598 }
8599 
pauseRenderPassQueriesIfActive()8600 void ContextVk::pauseRenderPassQueriesIfActive()
8601 {
8602     for (QueryVk *activeQuery : mActiveRenderPassQueries)
8603     {
8604         if (activeQuery)
8605         {
8606             activeQuery->onRenderPassEnd(this);
8607             // No need to update rasterizer discard emulation with primitives generated query.  The
8608             // state will be updated when the next render pass starts.
8609         }
8610     }
8611 }
8612 
resumeRenderPassQueriesIfActive()8613 angle::Result ContextVk::resumeRenderPassQueriesIfActive()
8614 {
8615     // Note: these queries should be processed in order.  See comment in QueryVk::onRenderPassStart.
8616     for (QueryVk *activeQuery : mActiveRenderPassQueries)
8617     {
8618         if (activeQuery)
8619         {
8620             // Transform feedback queries are handled separately.
8621             if (activeQuery->getType() == gl::QueryType::TransformFeedbackPrimitivesWritten)
8622             {
8623                 continue;
8624             }
8625 
8626             ANGLE_TRY(activeQuery->onRenderPassStart(this));
8627 
8628             // Update rasterizer discard emulation with primitives generated query if necessary.
8629             if (activeQuery->getType() == gl::QueryType::PrimitivesGenerated)
8630             {
8631                 updateRasterizerDiscardEnabled(true);
8632             }
8633         }
8634     }
8635 
8636     return angle::Result::Continue;
8637 }
8638 
resumeXfbRenderPassQueriesIfActive()8639 angle::Result ContextVk::resumeXfbRenderPassQueriesIfActive()
8640 {
8641     // All other queries are handled separately.
8642     QueryVk *xfbQuery = mActiveRenderPassQueries[gl::QueryType::TransformFeedbackPrimitivesWritten];
8643     if (xfbQuery && mState.isTransformFeedbackActiveUnpaused())
8644     {
8645         ANGLE_TRY(xfbQuery->onRenderPassStart(this));
8646     }
8647 
8648     return angle::Result::Continue;
8649 }
8650 
doesPrimitivesGeneratedQuerySupportRasterizerDiscard() const8651 bool ContextVk::doesPrimitivesGeneratedQuerySupportRasterizerDiscard() const
8652 {
8653     // If primitives generated is implemented with VK_EXT_primitives_generated_query, check the
8654     // corresponding feature bit.
8655     if (getFeatures().supportsPrimitivesGeneratedQuery.enabled)
8656     {
8657         return mRenderer->getPhysicalDevicePrimitivesGeneratedQueryFeatures()
8658                    .primitivesGeneratedQueryWithRasterizerDiscard == VK_TRUE;
8659     }
8660 
8661     // If primitives generated is emulated with pipeline statistics query, it's unknown on which
8662     // hardware rasterizer discard is supported.  Assume it's supported on none.
8663     if (getFeatures().supportsPipelineStatisticsQuery.enabled)
8664     {
8665         return false;
8666     }
8667 
8668     return true;
8669 }
8670 
isEmulatingRasterizerDiscardDuringPrimitivesGeneratedQuery(bool isPrimitivesGeneratedQueryActive) const8671 bool ContextVk::isEmulatingRasterizerDiscardDuringPrimitivesGeneratedQuery(
8672     bool isPrimitivesGeneratedQueryActive) const
8673 {
8674     return isPrimitivesGeneratedQueryActive && mState.isRasterizerDiscardEnabled() &&
8675            !doesPrimitivesGeneratedQuerySupportRasterizerDiscard();
8676 }
8677 
getActiveRenderPassQuery(gl::QueryType queryType) const8678 QueryVk *ContextVk::getActiveRenderPassQuery(gl::QueryType queryType) const
8679 {
8680     return mActiveRenderPassQueries[queryType];
8681 }
8682 
isRobustResourceInitEnabled() const8683 bool ContextVk::isRobustResourceInitEnabled() const
8684 {
8685     return mState.isRobustResourceInitEnabled();
8686 }
8687 
setDefaultUniformBlocksMinSizeForTesting(size_t minSize)8688 void ContextVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize)
8689 {
8690     mDefaultUniformStorage.setMinimumSizeForTesting(minSize);
8691 }
8692 
initializeMultisampleTextureToBlack(const gl::Context * context,gl::Texture * glTexture)8693 angle::Result ContextVk::initializeMultisampleTextureToBlack(const gl::Context *context,
8694                                                              gl::Texture *glTexture)
8695 {
8696     ASSERT(glTexture->getType() == gl::TextureType::_2DMultisample);
8697     TextureVk *textureVk = vk::GetImpl(glTexture);
8698 
8699     return textureVk->initializeContentsWithBlack(context, GL_NONE,
8700                                                   gl::ImageIndex::Make2DMultisample());
8701 }
8702 
onProgramExecutableReset(ProgramExecutableVk * executableVk)8703 void ContextVk::onProgramExecutableReset(ProgramExecutableVk *executableVk)
8704 {
8705     // We can not check if executableVk deleted is what we was bound to, since by the time we get
8706     // here, the program executable in the context's state has already been updated.
8707     // Reset ContextVk::mCurrentGraphicsPipeline, since programInfo.release() freed the
8708     // PipelineHelper that it's currently pointing to.
8709     // TODO(http://anglebug.com/42264159): rework updateActiveTextures(), createPipelineLayout(),
8710     // handleDirtyGraphicsPipeline(), and ProgramPipelineVk::link().
8711     resetCurrentGraphicsPipeline();
8712     invalidateCurrentComputePipeline();
8713     invalidateCurrentGraphicsPipeline();
8714 }
8715 
switchToReadOnlyDepthStencilMode(gl::Texture * texture,gl::Command command,FramebufferVk * drawFramebuffer,bool isStencilTexture)8716 angle::Result ContextVk::switchToReadOnlyDepthStencilMode(gl::Texture *texture,
8717                                                           gl::Command command,
8718                                                           FramebufferVk *drawFramebuffer,
8719                                                           bool isStencilTexture)
8720 {
8721     ASSERT(texture->isDepthOrStencil());
8722 
8723     // When running compute we don't have a draw FBO.
8724     if (command == gl::Command::Dispatch)
8725     {
8726         return angle::Result::Continue;
8727     }
8728 
8729     // The readOnlyDepth/StencilMode flag enables read-only depth-stencil feedback loops.  We only
8730     // switch to read-only mode when there's a loop.  The render pass tracks the depth and stencil
8731     // access modes, which indicates whether it's possible to retroactively go back and change the
8732     // attachment layouts to read-only.
8733     //
8734     // If there are any writes, the render pass needs to break, so that one using the read-only
8735     // layouts can start.
8736     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
8737     if (!texture->isBoundToFramebuffer(drawFramebufferVk->getState().getFramebufferSerial()))
8738     {
8739         return angle::Result::Continue;
8740     }
8741 
8742     if (isStencilTexture)
8743     {
8744         if (mState.isStencilWriteEnabled(mState.getDrawFramebuffer()->getStencilBitCount()))
8745         {
8746             // This looks like a feedback loop, but we don't issue a warning because the application
8747             // may have correctly used BASE and MAX levels to avoid it.  ANGLE doesn't track that.
8748             mDepthStencilAttachmentFlags.set(vk::RenderPassUsage::StencilFeedbackLoop);
8749         }
8750         else if (!mDepthStencilAttachmentFlags[vk::RenderPassUsage::StencilFeedbackLoop])
8751         {
8752             // If we are not in the actual feedback loop mode, switch to read-only stencil mode
8753             mDepthStencilAttachmentFlags.set(vk::RenderPassUsage::StencilReadOnlyAttachment);
8754         }
8755     }
8756 
8757     // Switch to read-only depth feedback loop if not already
8758     if (mState.isDepthWriteEnabled())
8759     {
8760         // This looks like a feedback loop, but we don't issue a warning because the application
8761         // may have correctly used BASE and MAX levels to avoid it.  ANGLE doesn't track that.
8762         mDepthStencilAttachmentFlags.set(vk::RenderPassUsage::DepthFeedbackLoop);
8763     }
8764     else if (!mDepthStencilAttachmentFlags[vk::RenderPassUsage::DepthFeedbackLoop])
8765     {
8766         // If we are not in the actual feedback loop mode, switch to read-only depth mode
8767         mDepthStencilAttachmentFlags.set(vk::RenderPassUsage::DepthReadOnlyAttachment);
8768     }
8769 
8770     if ((mDepthStencilAttachmentFlags & vk::kDepthStencilReadOnlyBits).none())
8771     {
8772         return angle::Result::Continue;
8773     }
8774 
8775     // If the aspect that's switching to read-only has a pending clear, it can't be done in the same
8776     // render pass (as the clear is a write operation).  In that case, flush the deferred clears for
8777     // the aspect that is turning read-only first.  The other deferred clears (such as color) can
8778     // stay deferred.
8779     if ((!isStencilTexture && drawFramebuffer->hasDeferredDepthClear()) ||
8780         (isStencilTexture && drawFramebuffer->hasDeferredStencilClear()))
8781     {
8782         ANGLE_TRY(drawFramebuffer->flushDepthStencilDeferredClear(
8783             this, isStencilTexture ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT));
8784     }
8785 
8786     // If the render pass needs closing, mark it as such.  Note that a write to depth/stencil may be
8787     // pending through a deferred clear.
8788     if (hasActiveRenderPass())
8789     {
8790         const vk::RenderPassUsage readOnlyAttachmentUsage =
8791             isStencilTexture ? vk::RenderPassUsage::StencilReadOnlyAttachment
8792                              : vk::RenderPassUsage::DepthReadOnlyAttachment;
8793         TextureVk *textureVk = vk::GetImpl(texture);
8794 
8795         if (!textureVk->getImage().hasRenderPassUsageFlag(readOnlyAttachmentUsage))
8796         {
8797             // If the render pass has written to this aspect, it needs to be closed.
8798             if ((!isStencilTexture && getStartedRenderPassCommands().hasDepthWriteOrClear()) ||
8799                 (isStencilTexture && getStartedRenderPassCommands().hasStencilWriteOrClear()))
8800             {
8801                 onRenderPassFinished(RenderPassClosureReason::DepthStencilUseInFeedbackLoop);
8802 
8803                 // Don't let the render pass reactivate.
8804                 mAllowRenderPassToReactivate = false;
8805             }
8806         }
8807 
8808         // Make sure to update the current render pass's tracking of read-only depth/stencil mode.
8809         mGraphicsDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_ACCESS);
8810     }
8811 
8812     return angle::Result::Continue;
8813 }
8814 
onResourceAccess(const vk::CommandBufferAccess & access)8815 angle::Result ContextVk::onResourceAccess(const vk::CommandBufferAccess &access)
8816 {
8817     ANGLE_TRY(flushCommandBuffersIfNecessary(access));
8818 
8819     for (const vk::CommandBufferImageAccess &imageAccess : access.getReadImages())
8820     {
8821         vk::ImageHelper *image = imageAccess.image;
8822         ASSERT(!isRenderPassStartedAndUsesImage(*image));
8823 
8824         imageAccess.image->recordReadBarrier(this, imageAccess.aspectFlags, imageAccess.imageLayout,
8825                                              mOutsideRenderPassCommands);
8826         mOutsideRenderPassCommands->retainImage(image);
8827     }
8828 
8829     for (const vk::CommandBufferImageSubresourceAccess &imageReadAccess :
8830          access.getReadImageSubresources())
8831     {
8832         vk::ImageHelper *image = imageReadAccess.access.image;
8833         ASSERT(!isRenderPassStartedAndUsesImage(*image));
8834 
8835         image->recordReadSubresourceBarrier(
8836             this, imageReadAccess.access.aspectFlags, imageReadAccess.access.imageLayout,
8837             imageReadAccess.levelStart, imageReadAccess.levelCount, imageReadAccess.layerStart,
8838             imageReadAccess.layerCount, mOutsideRenderPassCommands);
8839         mOutsideRenderPassCommands->retainImage(image);
8840     }
8841 
8842     for (const vk::CommandBufferImageSubresourceAccess &imageWrite : access.getWriteImages())
8843     {
8844         vk::ImageHelper *image = imageWrite.access.image;
8845         ASSERT(!isRenderPassStartedAndUsesImage(*image));
8846 
8847         image->recordWriteBarrier(this, imageWrite.access.aspectFlags,
8848                                   imageWrite.access.imageLayout, imageWrite.levelStart,
8849                                   imageWrite.levelCount, imageWrite.layerStart,
8850                                   imageWrite.layerCount, mOutsideRenderPassCommands);
8851         mOutsideRenderPassCommands->retainImage(image);
8852         image->onWrite(imageWrite.levelStart, imageWrite.levelCount, imageWrite.layerStart,
8853                        imageWrite.layerCount, imageWrite.access.aspectFlags);
8854     }
8855 
8856     for (const vk::CommandBufferBufferAccess &bufferAccess : access.getReadBuffers())
8857     {
8858         ASSERT(!isRenderPassStartedAndUsesBufferForWrite(*bufferAccess.buffer));
8859         ASSERT(!mOutsideRenderPassCommands->usesBufferForWrite(*bufferAccess.buffer));
8860 
8861         mOutsideRenderPassCommands->bufferRead(this, bufferAccess.accessType, bufferAccess.stage,
8862                                                bufferAccess.buffer);
8863     }
8864 
8865     for (const vk::CommandBufferBufferAccess &bufferAccess : access.getWriteBuffers())
8866     {
8867         ASSERT(!isRenderPassStartedAndUsesBuffer(*bufferAccess.buffer));
8868         ASSERT(!mOutsideRenderPassCommands->usesBuffer(*bufferAccess.buffer));
8869 
8870         mOutsideRenderPassCommands->bufferWrite(this, bufferAccess.accessType, bufferAccess.stage,
8871                                                 bufferAccess.buffer);
8872     }
8873 
8874     for (const vk::CommandBufferBufferExternalAcquireRelease &bufferAcquireRelease :
8875          access.getExternalAcquireReleaseBuffers())
8876     {
8877         mOutsideRenderPassCommands->retainResourceForWrite(bufferAcquireRelease.buffer);
8878     }
8879 
8880     for (const vk::CommandBufferResourceAccess &resourceAccess : access.getAccessResources())
8881     {
8882         mOutsideRenderPassCommands->retainResource(resourceAccess.resource);
8883     }
8884 
8885     return angle::Result::Continue;
8886 }
8887 
flushCommandBuffersIfNecessary(const vk::CommandBufferAccess & access)8888 angle::Result ContextVk::flushCommandBuffersIfNecessary(const vk::CommandBufferAccess &access)
8889 {
8890     // Go over resources and decide whether the render pass needs to close, whether the outside
8891     // render pass commands need to be flushed, or neither.  Note that closing the render pass
8892     // implies flushing the outside render pass as well, so if that needs to be done, we can close
8893     // the render pass and immediately return from this function.  Otherwise, this function keeps
8894     // track of whether the outside render pass commands need to be closed, and if so, it will do
8895     // that once at the end.
8896 
8897     // Read images only need to close the render pass if they need a layout transition.
8898     for (const vk::CommandBufferImageAccess &imageAccess : access.getReadImages())
8899     {
8900         // Note that different read methods are not compatible. A shader read uses a different
8901         // layout than a transfer read. So we cannot support simultaneous read usage as easily as
8902         // for Buffers.  TODO: Don't close the render pass if the image was only used read-only in
8903         // the render pass.  http://anglebug.com/42263557
8904         if (isRenderPassStartedAndUsesImage(*imageAccess.image))
8905         {
8906             return flushCommandsAndEndRenderPass(RenderPassClosureReason::ImageUseThenOutOfRPRead);
8907         }
8908     }
8909 
8910     // In cases where the image has both read and write permissions, the render pass should be
8911     // closed if there is a read from a previously written subresource (in a specific level/layer),
8912     // or a write to a previously read one.
8913     for (const vk::CommandBufferImageSubresourceAccess &imageSubresourceAccess :
8914          access.getReadImageSubresources())
8915     {
8916         if (isRenderPassStartedAndUsesImage(*imageSubresourceAccess.access.image))
8917         {
8918             return flushCommandsAndEndRenderPass(RenderPassClosureReason::ImageUseThenOutOfRPRead);
8919         }
8920     }
8921 
8922     // Write images only need to close the render pass if they need a layout transition.
8923     for (const vk::CommandBufferImageSubresourceAccess &imageWrite : access.getWriteImages())
8924     {
8925         if (isRenderPassStartedAndUsesImage(*imageWrite.access.image))
8926         {
8927             return flushCommandsAndEndRenderPass(RenderPassClosureReason::ImageUseThenOutOfRPWrite);
8928         }
8929     }
8930 
8931     bool shouldCloseOutsideRenderPassCommands = false;
8932 
8933     // Read buffers only need a new command buffer if previously used for write.
8934     for (const vk::CommandBufferBufferAccess &bufferAccess : access.getReadBuffers())
8935     {
8936         if (isRenderPassStartedAndUsesBufferForWrite(*bufferAccess.buffer))
8937         {
8938             return flushCommandsAndEndRenderPass(
8939                 RenderPassClosureReason::BufferWriteThenOutOfRPRead);
8940         }
8941         else if (mOutsideRenderPassCommands->usesBufferForWrite(*bufferAccess.buffer))
8942         {
8943             shouldCloseOutsideRenderPassCommands = true;
8944         }
8945     }
8946 
8947     // Write buffers always need a new command buffer if previously used.
8948     for (const vk::CommandBufferBufferAccess &bufferAccess : access.getWriteBuffers())
8949     {
8950         if (isRenderPassStartedAndUsesBuffer(*bufferAccess.buffer))
8951         {
8952             return flushCommandsAndEndRenderPass(
8953                 RenderPassClosureReason::BufferUseThenOutOfRPWrite);
8954         }
8955         else if (mOutsideRenderPassCommands->usesBuffer(*bufferAccess.buffer))
8956         {
8957             shouldCloseOutsideRenderPassCommands = true;
8958         }
8959     }
8960 
8961     if (shouldCloseOutsideRenderPassCommands)
8962     {
8963         return flushOutsideRenderPassCommands();
8964     }
8965 
8966     return angle::Result::Continue;
8967 }
8968 
endRenderPassIfComputeReadAfterTransformFeedbackWrite()8969 angle::Result ContextVk::endRenderPassIfComputeReadAfterTransformFeedbackWrite()
8970 {
8971     // Similar to flushCommandBuffersIfNecessary(), but using uniform buffers currently bound and
8972     // used by the current (compute) program.  This is to handle read-after-write hazards where the
8973     // write originates from transform feedback.
8974     if (!mCurrentTransformFeedbackQueueSerial.valid())
8975     {
8976         return angle::Result::Continue;
8977     }
8978 
8979     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
8980     ASSERT(executable && executable->hasLinkedShaderStage(gl::ShaderType::Compute));
8981 
8982     // Uniform buffers:
8983     const std::vector<gl::InterfaceBlock> &blocks = executable->getUniformBlocks();
8984 
8985     for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
8986     {
8987         const GLuint binding = executable->getUniformBlockBinding(bufferIndex);
8988         const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
8989             mState.getIndexedUniformBuffer(binding);
8990 
8991         if (bufferBinding.get() == nullptr)
8992         {
8993             continue;
8994         }
8995 
8996         vk::BufferHelper &buffer = vk::GetImpl(bufferBinding.get())->getBuffer();
8997         if (buffer.writtenByCommandBuffer(mCurrentTransformFeedbackQueueSerial))
8998         {
8999             return flushCommandsAndEndRenderPass(RenderPassClosureReason::XfbWriteThenComputeRead);
9000         }
9001     }
9002 
9003     return angle::Result::Continue;
9004 }
9005 
9006 // When textures/images bound/used by current compute program and have been accessed
9007 // as sampled texture in current render pass, need to take care the implicit layout
9008 // transition of these textures/images in the render pass.
endRenderPassIfComputeAccessAfterGraphicsImageAccess()9009 angle::Result ContextVk::endRenderPassIfComputeAccessAfterGraphicsImageAccess()
9010 {
9011     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
9012     ASSERT(executable && executable->hasLinkedShaderStage(gl::ShaderType::Compute));
9013 
9014     for (size_t imageUnitIndex : executable->getActiveImagesMask())
9015     {
9016         const gl::Texture *texture = mState.getImageUnit(imageUnitIndex).texture.get();
9017         if (texture == nullptr)
9018         {
9019             continue;
9020         }
9021 
9022         TextureVk *textureVk = vk::GetImpl(texture);
9023 
9024         if (texture->getType() == gl::TextureType::Buffer)
9025         {
9026             continue;
9027         }
9028         else
9029         {
9030             vk::ImageHelper &image = textureVk->getImage();
9031 
9032             // This is to handle the implicit layout transition in render pass of this image,
9033             // while it currently be bound and used by current compute program.
9034             if (mRenderPassCommands->startedAndUsesImageWithBarrier(image))
9035             {
9036                 return flushCommandsAndEndRenderPass(
9037                     RenderPassClosureReason::GraphicsTextureImageAccessThenComputeAccess);
9038             }
9039         }
9040     }
9041 
9042     const gl::ActiveTexturesCache &textures        = mState.getActiveTexturesCache();
9043     const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
9044 
9045     for (size_t textureUnit : executable->getActiveSamplersMask())
9046     {
9047         gl::Texture *texture        = textures[textureUnit];
9048         gl::TextureType textureType = textureTypes[textureUnit];
9049 
9050         if (texture == nullptr || textureType == gl::TextureType::Buffer)
9051         {
9052             continue;
9053         }
9054 
9055         TextureVk *textureVk = vk::GetImpl(texture);
9056         ASSERT(textureVk != nullptr);
9057         vk::ImageHelper &image = textureVk->getImage();
9058 
9059         // Similar to flushCommandBuffersIfNecessary(), but using textures currently bound and used
9060         // by the current (compute) program.  This is to handle read-after-write hazards where the
9061         // write originates from a framebuffer attachment.
9062         if (image.hasRenderPassUsageFlag(vk::RenderPassUsage::RenderTargetAttachment) &&
9063             isRenderPassStartedAndUsesImage(image))
9064         {
9065             return flushCommandsAndEndRenderPass(
9066                 RenderPassClosureReason::ImageAttachmentThenComputeRead);
9067         }
9068 
9069         // Take care of the read image layout transition require implicit synchronization.
9070         if (mRenderPassCommands->startedAndUsesImageWithBarrier(image))
9071         {
9072             return flushCommandsAndEndRenderPass(
9073                 RenderPassClosureReason::GraphicsTextureImageAccessThenComputeAccess);
9074         }
9075     }
9076 
9077     return angle::Result::Continue;
9078 }
9079 
getPerfMonitorCounters()9080 const angle::PerfMonitorCounterGroups &ContextVk::getPerfMonitorCounters()
9081 {
9082     syncObjectPerfCounters(mRenderer->getCommandQueuePerfCounters());
9083 
9084     angle::PerfMonitorCounters &counters =
9085         angle::GetPerfMonitorCounterGroup(mPerfMonitorCounters, "vulkan").counters;
9086 
9087 #define ANGLE_UPDATE_PERF_MAP(COUNTER) \
9088     angle::GetPerfMonitorCounter(counters, #COUNTER).value = mPerfCounters.COUNTER;
9089 
9090     ANGLE_VK_PERF_COUNTERS_X(ANGLE_UPDATE_PERF_MAP)
9091 
9092 #undef ANGLE_UPDATE_PERF_MAP
9093 
9094     return mPerfMonitorCounters;
9095 }
9096 
switchToColorFramebufferFetchMode(bool hasColorFramebufferFetch)9097 angle::Result ContextVk::switchToColorFramebufferFetchMode(bool hasColorFramebufferFetch)
9098 {
9099     ASSERT(!getFeatures().preferDynamicRendering.enabled);
9100 
9101     // If framebuffer fetch is permanent, make sure we never switch out of it.
9102     if (getFeatures().permanentlySwitchToFramebufferFetchMode.enabled &&
9103         mIsInColorFramebufferFetchMode)
9104     {
9105         return angle::Result::Continue;
9106     }
9107 
9108     ASSERT(mIsInColorFramebufferFetchMode != hasColorFramebufferFetch);
9109     mIsInColorFramebufferFetchMode = hasColorFramebufferFetch;
9110 
9111     // If a render pass is already open, close it.
9112     if (mRenderPassCommands->started())
9113     {
9114         ANGLE_TRY(
9115             flushCommandsAndEndRenderPass(RenderPassClosureReason::FramebufferFetchEmulation));
9116     }
9117 
9118     // If there's a draw buffer bound, switch it to framebuffer fetch mode.  Every other framebuffer
9119     // will switch when bound.
9120     if (mState.getDrawFramebuffer() != nullptr)
9121     {
9122         getDrawFramebuffer()->switchToColorFramebufferFetchMode(this,
9123                                                                 mIsInColorFramebufferFetchMode);
9124     }
9125 
9126     // Clear the render pass cache; all render passes will be incompatible from now on with the
9127     // old ones.
9128     if (getFeatures().permanentlySwitchToFramebufferFetchMode.enabled)
9129     {
9130         mRenderPassCache.clear(this);
9131     }
9132 
9133     mRenderer->onColorFramebufferFetchUse();
9134 
9135     return angle::Result::Continue;
9136 }
9137 
onFramebufferFetchUse(vk::FramebufferFetchMode framebufferFetchMode)9138 void ContextVk::onFramebufferFetchUse(vk::FramebufferFetchMode framebufferFetchMode)
9139 {
9140     ASSERT(getFeatures().preferDynamicRendering.enabled);
9141 
9142     if (mRenderPassCommands->started())
9143     {
9144         // Accumulate framebuffer fetch mode to allow multiple draw calls in the same render pass
9145         // where some use color framebuffer fetch and some depth/stencil
9146         const vk::FramebufferFetchMode mergedMode = vk::FramebufferFetchModeMerge(
9147             mRenderPassCommands->getRenderPassDesc().framebufferFetchMode(), framebufferFetchMode);
9148 
9149         mRenderPassCommands->setFramebufferFetchMode(mergedMode);
9150 
9151         // When framebuffer fetch is enabled, attachments can be read from even if output is
9152         // masked, so update their access.
9153         if (FramebufferFetchModeHasColor(framebufferFetchMode))
9154         {
9155             onColorAccessChange();
9156         }
9157         if (FramebufferFetchModeHasDepthStencil(framebufferFetchMode))
9158         {
9159             onDepthStencilAccessChange();
9160         }
9161     }
9162 
9163     if (FramebufferFetchModeHasColor(framebufferFetchMode))
9164     {
9165         mRenderer->onColorFramebufferFetchUse();
9166     }
9167 }
9168 
allocateQueueSerialIndex()9169 ANGLE_INLINE angle::Result ContextVk::allocateQueueSerialIndex()
9170 {
9171     ASSERT(mCurrentQueueSerialIndex == kInvalidQueueSerialIndex);
9172     // Make everything appears to be flushed and submitted
9173     ANGLE_TRY(mRenderer->allocateQueueSerialIndex(&mCurrentQueueSerialIndex));
9174     // Note queueSerial for render pass is deferred until begin time.
9175     generateOutsideRenderPassCommandsQueueSerial();
9176     return angle::Result::Continue;
9177 }
9178 
releaseQueueSerialIndex()9179 ANGLE_INLINE void ContextVk::releaseQueueSerialIndex()
9180 {
9181     ASSERT(mCurrentQueueSerialIndex != kInvalidQueueSerialIndex);
9182     mRenderer->releaseQueueSerialIndex(mCurrentQueueSerialIndex);
9183     mCurrentQueueSerialIndex = kInvalidQueueSerialIndex;
9184 }
9185 
generateOutsideRenderPassCommandsQueueSerial()9186 ANGLE_INLINE void ContextVk::generateOutsideRenderPassCommandsQueueSerial()
9187 {
9188     ASSERT(mCurrentQueueSerialIndex != kInvalidQueueSerialIndex);
9189 
9190     // If there is reserved serial number, use that. Otherwise generate a new one.
9191     Serial serial;
9192     if (mOutsideRenderPassSerialFactory.generate(&serial))
9193     {
9194         ASSERT(mRenderPassCommands->getQueueSerial().valid());
9195         ASSERT(mRenderPassCommands->getQueueSerial().getSerial() > serial);
9196         mOutsideRenderPassCommands->setQueueSerial(mCurrentQueueSerialIndex, serial);
9197         return;
9198     }
9199 
9200     serial = mRenderer->generateQueueSerial(mCurrentQueueSerialIndex);
9201     mOutsideRenderPassCommands->setQueueSerial(mCurrentQueueSerialIndex, serial);
9202 }
9203 
generateRenderPassCommandsQueueSerial(QueueSerial * queueSerialOut)9204 ANGLE_INLINE void ContextVk::generateRenderPassCommandsQueueSerial(QueueSerial *queueSerialOut)
9205 {
9206     ASSERT(mCurrentQueueSerialIndex != kInvalidQueueSerialIndex);
9207 
9208     // We reserve some serial number for outsideRenderPassCommands in case we have to flush.
9209     ASSERT(mOutsideRenderPassCommands->getQueueSerial().valid());
9210     mRenderer->reserveQueueSerials(mCurrentQueueSerialIndex,
9211                                    kMaxReservedOutsideRenderPassQueueSerials,
9212                                    &mOutsideRenderPassSerialFactory);
9213 
9214     Serial serial   = mRenderer->generateQueueSerial(mCurrentQueueSerialIndex);
9215     *queueSerialOut = QueueSerial(mCurrentQueueSerialIndex, serial);
9216 }
9217 
resetPerFramePerfCounters()9218 void ContextVk::resetPerFramePerfCounters()
9219 {
9220     mPerfCounters.renderPasses                           = 0;
9221     mPerfCounters.writeDescriptorSets                    = 0;
9222     mPerfCounters.flushedOutsideRenderPassCommandBuffers = 0;
9223     mPerfCounters.resolveImageCommands                   = 0;
9224     mPerfCounters.descriptorSetAllocations               = 0;
9225 
9226     mRenderer->resetCommandQueuePerFrameCounters();
9227 
9228     mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::UniformsAndXfb]
9229         .resetDescriptorCacheStats();
9230     mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::Texture]
9231         .resetDescriptorCacheStats();
9232     mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::ShaderResource]
9233         .resetDescriptorCacheStats();
9234 }
9235 
ensureInterfacePipelineCache()9236 angle::Result ContextVk::ensureInterfacePipelineCache()
9237 {
9238     if (!mInterfacePipelinesCache.valid())
9239     {
9240         VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {};
9241         pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
9242 
9243         ANGLE_VK_TRY(this, mInterfacePipelinesCache.init(getDevice(), pipelineCacheCreateInfo));
9244     }
9245 
9246     return angle::Result::Continue;
9247 }
9248 }  // namespace rx
9249