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