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