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