• 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 "libANGLE/Context.h"
16 #include "libANGLE/Display.h"
17 #include "libANGLE/Program.h"
18 #include "libANGLE/Semaphore.h"
19 #include "libANGLE/Surface.h"
20 #include "libANGLE/angletypes.h"
21 #include "libANGLE/renderer/renderer_utils.h"
22 #include "libANGLE/renderer/vulkan/BufferVk.h"
23 #include "libANGLE/renderer/vulkan/CompilerVk.h"
24 #include "libANGLE/renderer/vulkan/DisplayVk.h"
25 #include "libANGLE/renderer/vulkan/FenceNVVk.h"
26 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
27 #include "libANGLE/renderer/vulkan/MemoryObjectVk.h"
28 #include "libANGLE/renderer/vulkan/OverlayVk.h"
29 #include "libANGLE/renderer/vulkan/ProgramPipelineVk.h"
30 #include "libANGLE/renderer/vulkan/ProgramVk.h"
31 #include "libANGLE/renderer/vulkan/QueryVk.h"
32 #include "libANGLE/renderer/vulkan/RenderbufferVk.h"
33 #include "libANGLE/renderer/vulkan/RendererVk.h"
34 #include "libANGLE/renderer/vulkan/SamplerVk.h"
35 #include "libANGLE/renderer/vulkan/SemaphoreVk.h"
36 #include "libANGLE/renderer/vulkan/ShaderVk.h"
37 #include "libANGLE/renderer/vulkan/SurfaceVk.h"
38 #include "libANGLE/renderer/vulkan/SyncVk.h"
39 #include "libANGLE/renderer/vulkan/TextureVk.h"
40 #include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
41 #include "libANGLE/renderer/vulkan/VertexArrayVk.h"
42 
43 #include "libANGLE/trace.h"
44 
45 #include <iostream>
46 
47 namespace rx
48 {
49 
50 namespace
51 {
52 // For DesciptorSetUpdates
53 constexpr size_t kDescriptorBufferInfosInitialSize = 8;
54 constexpr size_t kDescriptorImageInfosInitialSize  = 4;
55 constexpr size_t kDescriptorWriteInfosInitialSize =
56     kDescriptorBufferInfosInitialSize + kDescriptorImageInfosInitialSize;
57 
58 // For shader uniforms such as gl_DepthRange and the viewport size.
59 struct GraphicsDriverUniforms
60 {
61     std::array<float, 4> viewport;
62 
63     // 32 bits for 32 clip planes
64     uint32_t enabledClipPlanes;
65 
66     uint32_t advancedBlendEquation;
67     int32_t xfbVerticesPerInstance;
68 
69     // Used to replace gl_NumSamples. Because gl_NumSamples cannot be recognized in SPIR-V.
70     int32_t numSamples;
71 
72     std::array<int32_t, 4> xfbBufferOffsets;
73 
74     // .xy contain packed 8-bit values for atomic counter buffer offsets.  These offsets are
75     // within Vulkan's minStorageBufferOffsetAlignment limit and are used to support unaligned
76     // offsets allowed in GL.
77     //
78     // .zw are unused.
79     std::array<uint32_t, 4> acbBufferOffsets;
80 
81     // We'll use x, y, z for near / far / diff respectively.
82     std::array<float, 4> depthRange;
83 };
84 static_assert(sizeof(GraphicsDriverUniforms) % (sizeof(uint32_t) * 4) == 0,
85               "GraphicsDriverUniforms should 16bytes aligned");
86 
87 // TODO: http://issuetracker.google.com/173636783 Once the bug is fixed, we should remove this.
88 struct GraphicsDriverUniformsExtended
89 {
90     GraphicsDriverUniforms common;
91 
92     // Used to flip gl_FragCoord (both .xy for Android pre-rotation; only .y for desktop)
93     std::array<float, 2> halfRenderArea;
94     std::array<float, 2> flipXY;
95     std::array<float, 2> negFlipXY;
96     uint32_t dither;
97     uint32_t padding;
98 
99     // Used to pre-rotate gl_FragCoord for swapchain images on Android (a mat2, which is padded to
100     // the size of two vec4's).
101     std::array<float, 8> fragRotation;
102 };
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 
DefaultGLErrorCode(VkResult result)110 GLenum DefaultGLErrorCode(VkResult result)
111 {
112     switch (result)
113     {
114         case VK_ERROR_OUT_OF_HOST_MEMORY:
115         case VK_ERROR_OUT_OF_DEVICE_MEMORY:
116         case VK_ERROR_TOO_MANY_OBJECTS:
117             return GL_OUT_OF_MEMORY;
118         default:
119             return GL_INVALID_OPERATION;
120     }
121 }
122 
123 constexpr gl::ShaderMap<vk::ImageLayout> kShaderReadOnlyImageLayouts = {
124     {gl::ShaderType::Vertex, vk::ImageLayout::VertexShaderReadOnly},
125     {gl::ShaderType::TessControl, vk::ImageLayout::PreFragmentShadersReadOnly},
126     {gl::ShaderType::TessEvaluation, vk::ImageLayout::PreFragmentShadersReadOnly},
127     {gl::ShaderType::Geometry, vk::ImageLayout::PreFragmentShadersReadOnly},
128     {gl::ShaderType::Fragment, vk::ImageLayout::FragmentShaderReadOnly},
129     {gl::ShaderType::Compute, vk::ImageLayout::ComputeShaderReadOnly}};
130 
131 constexpr gl::ShaderMap<vk::ImageLayout> kShaderWriteImageLayouts = {
132     {gl::ShaderType::Vertex, vk::ImageLayout::VertexShaderWrite},
133     {gl::ShaderType::TessControl, vk::ImageLayout::PreFragmentShadersWrite},
134     {gl::ShaderType::TessEvaluation, vk::ImageLayout::PreFragmentShadersWrite},
135     {gl::ShaderType::Geometry, vk::ImageLayout::PreFragmentShadersWrite},
136     {gl::ShaderType::Fragment, vk::ImageLayout::FragmentShaderWrite},
137     {gl::ShaderType::Compute, vk::ImageLayout::ComputeShaderWrite}};
138 
139 constexpr VkBufferUsageFlags kVertexBufferUsage   = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
140 constexpr size_t kDynamicVertexDataSize           = 16 * 1024;
141 constexpr size_t kDriverUniformsAllocatorPageSize = 4 * 1024;
142 
CanMultiDrawIndirectUseCmd(ContextVk * contextVk,VertexArrayVk * vertexArray,gl::PrimitiveMode mode,GLsizei drawcount,GLsizei stride)143 bool CanMultiDrawIndirectUseCmd(ContextVk *contextVk,
144                                 VertexArrayVk *vertexArray,
145                                 gl::PrimitiveMode mode,
146                                 GLsizei drawcount,
147                                 GLsizei stride)
148 {
149     // Use the generic implementation if multiDrawIndirect is disabled, if line loop is being used
150     // for multiDraw, if drawcount is greater than maxDrawIndirectCount, or if there are streaming
151     // vertex attributes.
152     ASSERT(drawcount > 1);
153     const bool supportsMultiDrawIndirect =
154         contextVk->getFeatures().supportsMultiDrawIndirect.enabled;
155     const bool isMultiDrawLineLoop = (mode == gl::PrimitiveMode::LineLoop);
156     const bool isDrawCountBeyondLimit =
157         (static_cast<uint32_t>(drawcount) >
158          contextVk->getRenderer()->getPhysicalDeviceProperties().limits.maxDrawIndirectCount);
159     const bool isMultiDrawWithStreamingAttribs = vertexArray->getStreamingVertexAttribsMask().any();
160 
161     const bool canMultiDrawIndirectUseCmd = supportsMultiDrawIndirect && !isMultiDrawLineLoop &&
162                                             !isDrawCountBeyondLimit &&
163                                             !isMultiDrawWithStreamingAttribs;
164     return canMultiDrawIndirectUseCmd;
165 }
166 
GetCoverageSampleCount(const gl::State & glState,FramebufferVk * drawFramebuffer)167 uint32_t GetCoverageSampleCount(const gl::State &glState, FramebufferVk *drawFramebuffer)
168 {
169     if (!glState.isSampleCoverageEnabled())
170     {
171         return 0;
172     }
173 
174     // Get a fraction of the samples based on the coverage parameters.
175     // There are multiple ways to obtain an integer value from a float -
176     //     truncation, ceil and round
177     //
178     // round() provides a more even distribution of values but doesn't seem to play well
179     // with all vendors (AMD). A way to work around this is to increase the comparison threshold
180     // of deqp tests. Though this takes care of deqp tests other apps would still have issues.
181     //
182     // Truncation provides an uneven distribution near the edges of the interval but seems to
183     // play well with all vendors.
184     //
185     // We are going with truncation for expediency.
186     return static_cast<uint32_t>(glState.getSampleCoverageValue() * drawFramebuffer->getSamples());
187 }
188 
ApplySampleCoverage(const gl::State & glState,uint32_t coverageSampleCount,uint32_t maskNumber,uint32_t * maskOut)189 void ApplySampleCoverage(const gl::State &glState,
190                          uint32_t coverageSampleCount,
191                          uint32_t maskNumber,
192                          uint32_t *maskOut)
193 {
194     if (!glState.isSampleCoverageEnabled())
195     {
196         return;
197     }
198 
199     uint32_t maskBitOffset = maskNumber * 32;
200     uint32_t coverageMask  = coverageSampleCount >= (maskBitOffset + 32)
201                                 ? std::numeric_limits<uint32_t>::max()
202                                 : (1u << (coverageSampleCount - maskBitOffset)) - 1;
203 
204     if (glState.getSampleCoverageInvert())
205     {
206         coverageMask = ~coverageMask;
207     }
208 
209     *maskOut &= coverageMask;
210 }
211 
IsRenderPassStartedAndUsesImage(const vk::RenderPassCommandBufferHelper & renderPassCommands,const vk::ImageHelper & image)212 bool IsRenderPassStartedAndUsesImage(const vk::RenderPassCommandBufferHelper &renderPassCommands,
213                                      const vk::ImageHelper &image)
214 {
215     return renderPassCommands.started() && renderPassCommands.usesImage(image);
216 }
217 
218 // When an Android surface is rotated differently than the device's native orientation, ANGLE must
219 // rotate gl_Position in the last pre-rasterization shader and gl_FragCoord in the fragment shader.
220 // Rotation of gl_Position is done in SPIR-V.  The following are the rotation matrices for the
221 // fragment shader.
222 //
223 // Note: these are mat2's that are appropriately padded (4 floats per row).
224 using PreRotationMatrixValues = std::array<float, 8>;
225 constexpr angle::PackedEnumMap<rx::SurfaceRotation, PreRotationMatrixValues> kFragRotationMatrices =
226     {{{SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
227       {SurfaceRotation::Rotated90Degrees, {{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
228       {SurfaceRotation::Rotated180Degrees, {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
229       {SurfaceRotation::Rotated270Degrees, {{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
230       {SurfaceRotation::FlippedIdentity, {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
231       {SurfaceRotation::FlippedRotated90Degrees,
232        {{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
233       {SurfaceRotation::FlippedRotated180Degrees,
234        {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
235       {SurfaceRotation::FlippedRotated270Degrees,
236        {{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}}}};
237 
IsRotatedAspectRatio(SurfaceRotation rotation)238 bool IsRotatedAspectRatio(SurfaceRotation rotation)
239 {
240     return ((rotation == SurfaceRotation::Rotated90Degrees) ||
241             (rotation == SurfaceRotation::Rotated270Degrees) ||
242             (rotation == SurfaceRotation::FlippedRotated90Degrees) ||
243             (rotation == SurfaceRotation::FlippedRotated270Degrees));
244 }
245 
DetermineSurfaceRotation(gl::Framebuffer * framebuffer,WindowSurfaceVk * windowSurface)246 SurfaceRotation DetermineSurfaceRotation(gl::Framebuffer *framebuffer,
247                                          WindowSurfaceVk *windowSurface)
248 {
249     if (windowSurface && framebuffer->isDefault())
250     {
251         switch (windowSurface->getPreTransform())
252         {
253             case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
254                 // Do not rotate gl_Position (surface matches the device's orientation):
255                 return SurfaceRotation::Identity;
256             case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
257                 // Rotate gl_Position 90 degrees:
258                 return SurfaceRotation::Rotated90Degrees;
259             case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
260                 // Rotate gl_Position 180 degrees:
261                 return SurfaceRotation::Rotated180Degrees;
262             case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
263                 // Rotate gl_Position 270 degrees:
264                 return SurfaceRotation::Rotated270Degrees;
265             default:
266                 UNREACHABLE();
267                 return SurfaceRotation::Identity;
268         }
269     }
270     else
271     {
272         // Do not rotate gl_Position (offscreen framebuffer):
273         return SurfaceRotation::Identity;
274     }
275 }
276 
277 // Should not generate a copy with modern C++.
GetTraceEventName(const char * title,uint32_t counter)278 EventName GetTraceEventName(const char *title, uint32_t counter)
279 {
280     EventName buf;
281     snprintf(buf.data(), kMaxGpuEventNameLen - 1, "%s %u", title, counter);
282     return buf;
283 }
284 
GetColorAccess(const gl::State & state,const gl::FramebufferState & framebufferState,const gl::DrawBufferMask & emulatedAlphaMask,bool hasFramebufferFetch,size_t colorIndexGL)285 vk::ResourceAccess GetColorAccess(const gl::State &state,
286                                   const gl::FramebufferState &framebufferState,
287                                   const gl::DrawBufferMask &emulatedAlphaMask,
288                                   bool hasFramebufferFetch,
289                                   size_t colorIndexGL)
290 {
291     // No access if draw buffer is disabled altogether
292     // Without framebuffer fetch:
293     //   No access if color output is masked, or rasterizer discard is enabled
294     // With framebuffer fetch:
295     //   Read access if color output is masked, or rasterizer discard is enabled
296 
297     if (!framebufferState.getEnabledDrawBuffers().test(colorIndexGL))
298     {
299         return vk::ResourceAccess::Unused;
300     }
301 
302     const gl::BlendStateExt &blendStateExt = state.getBlendStateExt();
303     uint8_t colorMask                      = gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(
304         colorIndexGL, blendStateExt.mColorMask);
305     if (emulatedAlphaMask[colorIndexGL])
306     {
307         colorMask &= ~VK_COLOR_COMPONENT_A_BIT;
308     }
309     const bool isOutputMasked = colorMask == 0 || state.isRasterizerDiscardEnabled();
310 
311     if (isOutputMasked)
312     {
313         return hasFramebufferFetch ? vk::ResourceAccess::ReadOnly : vk::ResourceAccess::Unused;
314     }
315 
316     return vk::ResourceAccess::Write;
317 }
318 
GetDepthAccess(const gl::DepthStencilState & dsState,UpdateDepthFeedbackLoopReason reason)319 vk::ResourceAccess GetDepthAccess(const gl::DepthStencilState &dsState,
320                                   UpdateDepthFeedbackLoopReason reason)
321 {
322     // Skip if depth/stencil not actually accessed.
323     if (reason == UpdateDepthFeedbackLoopReason::None)
324     {
325         return vk::ResourceAccess::Unused;
326     }
327 
328     // Note that clear commands don't respect depth test enable, only the mask
329     // Note Other state can be stated here too in the future, such as rasterizer discard.
330     if (!dsState.depthTest && reason != UpdateDepthFeedbackLoopReason::Clear)
331     {
332         return vk::ResourceAccess::Unused;
333     }
334     return dsState.isDepthMaskedOut() ? vk::ResourceAccess::ReadOnly : vk::ResourceAccess::Write;
335 }
336 
GetStencilAccess(const gl::DepthStencilState & dsState,UpdateDepthFeedbackLoopReason reason)337 vk::ResourceAccess GetStencilAccess(const gl::DepthStencilState &dsState,
338                                     UpdateDepthFeedbackLoopReason reason)
339 {
340     // Skip if depth/stencil not actually accessed.
341     if (reason == UpdateDepthFeedbackLoopReason::None)
342     {
343         return vk::ResourceAccess::Unused;
344     }
345 
346     // Note that clear commands don't respect stencil test enable, only the mask
347     // Note Other state can be stated here too in the future, such as rasterizer discard.
348     if (!dsState.stencilTest && reason != UpdateDepthFeedbackLoopReason::Clear)
349     {
350         return vk::ResourceAccess::Unused;
351     }
352 
353     return dsState.isStencilNoOp() && dsState.isStencilBackNoOp() ? vk::ResourceAccess::ReadOnly
354                                                                   : vk::ResourceAccess::Write;
355 }
356 
GetContextPriority(const gl::State & state)357 egl::ContextPriority GetContextPriority(const gl::State &state)
358 {
359     return egl::FromEGLenum<egl::ContextPriority>(state.getContextPriority());
360 }
361 
362 template <typename MaskT>
AppendBufferVectorToDesc(vk::DescriptorSetDesc * desc,const gl::BufferVector & buffers,const MaskT & buffersMask,bool isDynamicDescriptor,bool appendOffset)363 void AppendBufferVectorToDesc(vk::DescriptorSetDesc *desc,
364                               const gl::BufferVector &buffers,
365                               const MaskT &buffersMask,
366                               bool isDynamicDescriptor,
367                               bool appendOffset)
368 {
369     if (buffersMask.any())
370     {
371         typename MaskT::param_type lastBufferIndex = buffersMask.last();
372         for (typename MaskT::param_type bufferIndex = 0; bufferIndex <= lastBufferIndex;
373              ++bufferIndex)
374         {
375             const gl::OffsetBindingPointer<gl::Buffer> &binding = buffers[bufferIndex];
376             const gl::Buffer *bufferGL                          = binding.get();
377 
378             if (!bufferGL)
379             {
380                 desc->append32BitValue(0);
381                 continue;
382             }
383 
384             BufferVk *bufferVk = vk::GetImpl(bufferGL);
385             if (!bufferVk->isBufferValid())
386             {
387                 desc->append32BitValue(0);
388                 continue;
389             }
390 
391             const vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
392 
393             // If this is sub-allocated, we always use the buffer block's serial to increase the
394             // cache hit rate.
395             vk::BufferSerial bufferSerial = bufferHelper.getBlockSerial();
396             desc->appendBufferSerial(bufferSerial);
397 
398             ASSERT(static_cast<uint64_t>(binding.getSize()) <=
399                    static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()));
400             // binding's size could be 0 if it is bound by glBindBufferBase call. In this case, the
401             // spec says we should use the actual buffer size at the time buffer is been referenced.
402             GLint64 size = binding.getSize() == 0 ? bufferGL->getSize() : binding.getSize();
403             desc->append32BitValue(static_cast<uint32_t>(size));
404 
405             if (appendOffset)
406             {
407                 ASSERT(static_cast<uint64_t>(binding.getOffset()) <
408                        static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()));
409                 VkDeviceSize bufferOffset = bufferHelper.getOffset();
410                 desc->append32BitValue(static_cast<uint32_t>(bufferOffset + binding.getOffset()));
411             }
412         }
413     }
414 
415     desc->append32BitValue(std::numeric_limits<uint32_t>::max());
416 }
417 
GetImageReadLayout(TextureVk * textureVk,const gl::ProgramExecutable * executable,size_t textureUnit,PipelineType pipelineType)418 vk::ImageLayout GetImageReadLayout(TextureVk *textureVk,
419                                    const gl::ProgramExecutable *executable,
420                                    size_t textureUnit,
421                                    PipelineType pipelineType)
422 {
423     vk::ImageHelper &image = textureVk->getImage();
424 
425     if (textureVk->hasBeenBoundAsImage())
426     {
427         return pipelineType == PipelineType::Compute ? vk::ImageLayout::ComputeShaderWrite
428                                                      : vk::ImageLayout::AllGraphicsShadersWrite;
429     }
430 
431     gl::ShaderBitSet remainingShaderBits =
432         executable->getSamplerShaderBitsForTextureUnitIndex(textureUnit);
433     ASSERT(remainingShaderBits.any());
434     gl::ShaderType firstShader = remainingShaderBits.first();
435     gl::ShaderType lastShader  = remainingShaderBits.last();
436     remainingShaderBits.reset(firstShader);
437     remainingShaderBits.reset(lastShader);
438 
439     if (image.hasRenderPassUsageFlag(vk::RenderPassUsage::RenderTargetAttachment))
440     {
441         // Right now we set this flag only when RenderTargetAttachment is set since we do
442         // not track all textures in the renderpass.
443         image.setRenderPassUsageFlag(vk::RenderPassUsage::TextureSampler);
444 
445         if (image.isDepthOrStencil())
446         {
447             if (image.hasRenderPassUsageFlag(vk::RenderPassUsage::ReadOnlyAttachment))
448             {
449                 if (firstShader == gl::ShaderType::Fragment)
450                 {
451                     ASSERT(remainingShaderBits.none() && lastShader == firstShader);
452                     return vk::ImageLayout::DSAttachmentReadAndFragmentShaderRead;
453                 }
454                 return vk::ImageLayout::DSAttachmentReadAndAllShadersRead;
455             }
456 
457             return firstShader == gl::ShaderType::Fragment
458                        ? vk::ImageLayout::DSAttachmentWriteAndFragmentShaderRead
459                        : vk::ImageLayout::DSAttachmentWriteAndAllShadersRead;
460         }
461 
462         return firstShader == gl::ShaderType::Fragment
463                    ? vk::ImageLayout::ColorAttachmentAndFragmentShaderRead
464                    : vk::ImageLayout::ColorAttachmentAndAllShadersRead;
465     }
466 
467     if (image.isDepthOrStencil())
468     {
469         // We always use a depth-stencil read-only layout for any depth Textures to simplify
470         // our implementation's handling of depth-stencil read-only mode. We don't have to
471         // split a RenderPass to transition a depth texture from shader-read to read-only.
472         // This improves performance in Manhattan. Future optimizations are likely possible
473         // here including using specialized barriers without breaking the RenderPass.
474         if (firstShader == gl::ShaderType::Fragment)
475         {
476             ASSERT(remainingShaderBits.none() && lastShader == firstShader);
477             return vk::ImageLayout::DSAttachmentReadAndFragmentShaderRead;
478         }
479         return vk::ImageLayout::DSAttachmentReadAndAllShadersRead;
480     }
481 
482     // We barrier against either:
483     // - Vertex only
484     // - Fragment only
485     // - Pre-fragment only (vertex, geometry and tessellation together)
486     if (remainingShaderBits.any() || firstShader != lastShader)
487     {
488         return lastShader == gl::ShaderType::Fragment ? vk::ImageLayout::AllGraphicsShadersReadOnly
489                                                       : vk::ImageLayout::PreFragmentShadersReadOnly;
490     }
491 
492     return kShaderReadOnlyImageLayouts[firstShader];
493 }
494 
GetImageWriteLayoutAndSubresource(const gl::ImageUnit & imageUnit,vk::ImageHelper & image,gl::ShaderBitSet shaderStages,gl::LevelIndex * levelOut,uint32_t * layerStartOut,uint32_t * layerCountOut)495 vk::ImageLayout GetImageWriteLayoutAndSubresource(const gl::ImageUnit &imageUnit,
496                                                   vk::ImageHelper &image,
497                                                   gl::ShaderBitSet shaderStages,
498                                                   gl::LevelIndex *levelOut,
499                                                   uint32_t *layerStartOut,
500                                                   uint32_t *layerCountOut)
501 {
502     *levelOut = gl::LevelIndex(static_cast<uint32_t>(imageUnit.level));
503 
504     *layerStartOut = 0;
505     *layerCountOut = image.getLayerCount();
506     if (imageUnit.layered)
507     {
508         *layerStartOut = imageUnit.layered;
509         *layerCountOut = 1;
510     }
511 
512     gl::ShaderType firstShader = shaderStages.first();
513     gl::ShaderType lastShader  = shaderStages.last();
514     shaderStages.reset(firstShader);
515     shaderStages.reset(lastShader);
516     // We barrier against either:
517     // - Vertex only
518     // - Fragment only
519     // - Pre-fragment only (vertex, geometry and tessellation together)
520     if (shaderStages.any() || firstShader != lastShader)
521     {
522         return lastShader == gl::ShaderType::Fragment ? vk::ImageLayout::AllGraphicsShadersWrite
523                                                       : vk::ImageLayout::PreFragmentShadersWrite;
524     }
525 
526     return kShaderWriteImageLayouts[firstShader];
527 }
528 
OnTextureBufferRead(ContextVk * contextVk,BufferVk * bufferVk,gl::ShaderBitSet stages,vk::CommandBufferHelperCommon * commandBufferHelper)529 void OnTextureBufferRead(ContextVk *contextVk,
530                          BufferVk *bufferVk,
531                          gl::ShaderBitSet stages,
532                          vk::CommandBufferHelperCommon *commandBufferHelper)
533 {
534     vk::BufferHelper &buffer = bufferVk->getBuffer();
535 
536     ASSERT(stages.any());
537 
538     // TODO: accept multiple stages in bufferRead.  http://anglebug.com/3573
539     for (gl::ShaderType stage : stages)
540     {
541         // Note: if another range of the same buffer is simultaneously used for storage,
542         // such as for transform feedback output, or SSBO, unnecessary barriers can be
543         // generated.
544         commandBufferHelper->bufferRead(contextVk, VK_ACCESS_SHADER_READ_BIT,
545                                         vk::GetPipelineStage(stage), &buffer);
546     }
547 }
548 
OnImageBufferWrite(ContextVk * contextVk,BufferVk * bufferVk,gl::ShaderBitSet stages,vk::CommandBufferHelperCommon * commandBufferHelper)549 void OnImageBufferWrite(ContextVk *contextVk,
550                         BufferVk *bufferVk,
551                         gl::ShaderBitSet stages,
552                         vk::CommandBufferHelperCommon *commandBufferHelper)
553 {
554     vk::BufferHelper &buffer = bufferVk->getBuffer();
555 
556     // TODO: accept multiple stages in bufferWrite.  http://anglebug.com/3573
557     for (gl::ShaderType stage : stages)
558     {
559         commandBufferHelper->bufferWrite(
560             contextVk, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
561             vk::GetPipelineStage(stage), vk::AliasingMode::Disallowed, &buffer);
562     }
563 }
564 
565 constexpr angle::PackedEnumMap<RenderPassClosureReason, const char *> kRenderPassClosureReason = {{
566     {RenderPassClosureReason::AlreadySpecifiedElsewhere, nullptr},
567     {RenderPassClosureReason::ContextDestruction, "Render pass closed due to context destruction"},
568     {RenderPassClosureReason::ContextChange, "Render pass closed due to context change"},
569     {RenderPassClosureReason::GLFlush, "Render pass closed due to glFlush()"},
570     {RenderPassClosureReason::GLFinish, "Render pass closed due to glFinish()"},
571     {RenderPassClosureReason::EGLSwapBuffers, "Render pass closed due to eglSwapBuffers()"},
572     {RenderPassClosureReason::EGLWaitClient, "Render pass closed due to eglWaitClient()"},
573     {RenderPassClosureReason::FramebufferBindingChange,
574      "Render pass closed due to framebuffer binding change"},
575     {RenderPassClosureReason::FramebufferChange, "Render pass closed due to framebuffer change"},
576     {RenderPassClosureReason::NewRenderPass,
577      "Render pass closed due to starting a new render pass"},
578     {RenderPassClosureReason::BufferUseThenXfbWrite,
579      "Render pass closed due to buffer use as transform feedback output after prior use in render "
580      "pass"},
581     {RenderPassClosureReason::XfbWriteThenVertexIndexBuffer,
582      "Render pass closed due to transform feedback buffer use as vertex/index input"},
583     {RenderPassClosureReason::XfbWriteThenIndirectDrawBuffer,
584      "Render pass closed due to indirect draw buffer previously used as transform feedback output "
585      "in render pass"},
586     {RenderPassClosureReason::XfbResumeAfterDrawBasedClear,
587      "Render pass closed due to transform feedback resume after clear through draw"},
588     {RenderPassClosureReason::DepthStencilUseInFeedbackLoop,
589      "Render pass closed due to depth/stencil attachment use under feedback loop"},
590     {RenderPassClosureReason::DepthStencilWriteAfterFeedbackLoop,
591      "Render pass closed due to depth/stencil attachment write after feedback loop"},
592     {RenderPassClosureReason::PipelineBindWhileXfbActive,
593      "Render pass closed due to graphics pipeline change while transform feedback is active"},
594     {RenderPassClosureReason::BufferWriteThenMap,
595      "Render pass closed due to mapping buffer being written to by said render pass"},
596     {RenderPassClosureReason::BufferUseThenOutOfRPRead,
597      "Render pass closed due to non-render-pass read of buffer that was written to in render pass"},
598     {RenderPassClosureReason::BufferUseThenOutOfRPWrite,
599      "Render pass closed due to non-render-pass write of buffer that was used in render pass"},
600     {RenderPassClosureReason::ImageUseThenOutOfRPRead,
601      "Render pass closed due to non-render-pass read of image that was used in render pass"},
602     {RenderPassClosureReason::ImageUseThenOutOfRPWrite,
603      "Render pass closed due to non-render-pass write of image that was used in render pass"},
604     {RenderPassClosureReason::XfbWriteThenComputeRead,
605      "Render pass closed due to compute read of buffer previously used as transform feedback "
606      "output in render pass"},
607     {RenderPassClosureReason::XfbWriteThenIndirectDispatchBuffer,
608      "Render pass closed due to indirect dispatch buffer previously used as transform feedback "
609      "output in render pass"},
610     {RenderPassClosureReason::ImageAttachmentThenComputeRead,
611      "Render pass closed due to compute read of image previously used as framebuffer attachment in "
612      "render pass"},
613     {RenderPassClosureReason::GetQueryResult, "Render pass closed due to getting query result"},
614     {RenderPassClosureReason::BeginNonRenderPassQuery,
615      "Render pass closed due to non-render-pass query begin"},
616     {RenderPassClosureReason::EndNonRenderPassQuery,
617      "Render pass closed due to non-render-pass query end"},
618     {RenderPassClosureReason::TimestampQuery, "Render pass closed due to timestamp query"},
619     {RenderPassClosureReason::GLReadPixels, "Render pass closed due to glReadPixels()"},
620     {RenderPassClosureReason::BufferUseThenReleaseToExternal,
621      "Render pass closed due to buffer (used by render pass) release to external"},
622     {RenderPassClosureReason::ImageUseThenReleaseToExternal,
623      "Render pass closed due to image (used by render pass) release to external"},
624     {RenderPassClosureReason::BufferInUseWhenSynchronizedMap,
625      "Render pass closed due to mapping buffer in use by GPU without GL_MAP_UNSYNCHRONIZED_BIT"},
626     {RenderPassClosureReason::ImageOrphan, "Render pass closed due to EGL image being orphaned"},
627     {RenderPassClosureReason::GLMemoryBarrierThenStorageResource,
628      "Render pass closed due to glMemoryBarrier before storage output in render pass"},
629     {RenderPassClosureReason::StorageResourceUseThenGLMemoryBarrier,
630      "Render pass closed due to glMemoryBarrier after storage output in render pass"},
631     {RenderPassClosureReason::ExternalSemaphoreSignal,
632      "Render pass closed due to external semaphore signal"},
633     {RenderPassClosureReason::SyncObjectInit, "Render pass closed due to sync object insertion"},
634     {RenderPassClosureReason::SyncObjectWithFdInit,
635      "Render pass closed due to sync object with fd insertion"},
636     {RenderPassClosureReason::SyncObjectClientWait,
637      "Render pass closed due to sync object client wait"},
638     {RenderPassClosureReason::SyncObjectServerWait,
639      "Render pass closed due to sync object server wait"},
640     {RenderPassClosureReason::XfbPause, "Render pass closed due to transform feedback pause"},
641     {RenderPassClosureReason::FramebufferFetchEmulation,
642      "Render pass closed due to framebuffer fetch emulation"},
643     {RenderPassClosureReason::ColorBufferInvalidate,
644      "Render pass closed due to glInvalidateFramebuffer() on a color buffer"},
645     {RenderPassClosureReason::GenerateMipmapOnCPU,
646      "Render pass closed due to fallback to CPU when generating mipmaps"},
647     {RenderPassClosureReason::CopyTextureOnCPU,
648      "Render pass closed due to fallback to CPU when copying texture"},
649     {RenderPassClosureReason::TextureReformatToRenderable,
650      "Render pass closed due to reformatting texture to a renderable fallback"},
651     {RenderPassClosureReason::DeviceLocalBufferMap,
652      "Render pass closed due to mapping device local buffer"},
653     {RenderPassClosureReason::PrepareForBlit, "Render pass closed prior to draw-based blit"},
654     {RenderPassClosureReason::PrepareForImageCopy,
655      "Render pass closed prior to draw-based image copy"},
656     {RenderPassClosureReason::TemporaryForImageClear,
657      "Temporary render pass used for image clear closed"},
658     {RenderPassClosureReason::TemporaryForImageCopy,
659      "Temporary render pass used for image copy closed"},
660     {RenderPassClosureReason::TemporaryForOverlayDraw,
661      "Temporary render pass used for overlay draw closed"},
662 }};
663 
GetLocalDependencyFlags(ContextVk * contextVk)664 VkDependencyFlags GetLocalDependencyFlags(ContextVk *contextVk)
665 {
666     VkDependencyFlags dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
667     if (contextVk->getCurrentViewCount() > 0)
668     {
669         dependencyFlags |= VK_DEPENDENCY_VIEW_LOCAL_BIT;
670     }
671     return dependencyFlags;
672 }
673 }  // anonymous namespace
674 
675 // Not necessary once upgraded to C++17.
676 constexpr ContextVk::DirtyBits ContextVk::kIndexAndVertexDirtyBits;
677 constexpr ContextVk::DirtyBits ContextVk::kPipelineDescAndBindingDirtyBits;
678 constexpr ContextVk::DirtyBits ContextVk::kTexturesAndDescSetDirtyBits;
679 constexpr ContextVk::DirtyBits ContextVk::kResourcesAndDescSetDirtyBits;
680 constexpr ContextVk::DirtyBits ContextVk::kXfbBuffersAndDescSetDirtyBits;
681 constexpr ContextVk::DirtyBits ContextVk::kDriverUniformsAndBindingDirtyBits;
682 
flushDescriptorSetUpdates()683 void ContextVk::flushDescriptorSetUpdates()
684 {
685     mPerfCounters.writeDescriptorSets +=
686         mUpdateDescriptorSetsBuilder.flushDescriptorSetUpdates(getDevice());
687 }
688 
onRenderPassFinished(RenderPassClosureReason reason)689 ANGLE_INLINE void ContextVk::onRenderPassFinished(RenderPassClosureReason reason)
690 {
691     pauseRenderPassQueriesIfActive();
692 
693     if (mRenderPassCommandBuffer != nullptr)
694     {
695         // If reason is specified, add it to the command buffer right before ending the render pass,
696         // so it will show up in GPU debuggers.
697         const char *reasonText = kRenderPassClosureReason[reason];
698         if (reasonText)
699         {
700             insertEventMarkerImpl(GL_DEBUG_SOURCE_API, reasonText);
701         }
702     }
703 
704     mRenderPassCommandBuffer = nullptr;
705     mGraphicsDirtyBits.set(DIRTY_BIT_RENDER_PASS);
706 }
707 
DriverUniformsDescriptorSet()708 ContextVk::DriverUniformsDescriptorSet::DriverUniformsDescriptorSet()
709     : descriptorSet(VK_NULL_HANDLE), currentBuffer(nullptr)
710 {}
711 
712 ContextVk::DriverUniformsDescriptorSet::~DriverUniformsDescriptorSet() = default;
713 
init(RendererVk * rendererVk)714 void ContextVk::DriverUniformsDescriptorSet::init(RendererVk *rendererVk)
715 {
716     size_t minAlignment = static_cast<size_t>(
717         rendererVk->getPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment);
718     dynamicBuffer.init(rendererVk, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, minAlignment,
719                        kDriverUniformsAllocatorPageSize, true);
720     descriptorSetCache.clear();
721 }
722 
destroy(RendererVk * renderer)723 void ContextVk::DriverUniformsDescriptorSet::destroy(RendererVk *renderer)
724 {
725     descriptorSetLayout.reset();
726     descriptorPoolBinding.reset();
727     dynamicBuffer.destroy(renderer);
728     descriptorSetCache.clear();
729     descriptorSetCache.destroy(renderer);
730 }
731 
732 // ContextVk implementation.
ContextVk(const gl::State & state,gl::ErrorSet * errorSet,RendererVk * renderer)733 ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk *renderer)
734     : ContextImpl(state, errorSet),
735       vk::Context(renderer),
736       mGraphicsDirtyBitHandlers{},
737       mComputeDirtyBitHandlers{},
738       mRenderPassCommandBuffer(nullptr),
739       mCurrentGraphicsPipeline(nullptr),
740       mCurrentComputePipeline(nullptr),
741       mCurrentDrawMode(gl::PrimitiveMode::InvalidEnum),
742       mCurrentWindowSurface(nullptr),
743       mCurrentRotationDrawFramebuffer(SurfaceRotation::Identity),
744       mCurrentRotationReadFramebuffer(SurfaceRotation::Identity),
745       mActiveRenderPassQueries{},
746       mLastIndexBufferOffset(nullptr),
747       mCurrentIndexBufferOffset(0),
748       mCurrentDrawElementsType(gl::DrawElementsType::InvalidEnum),
749       mXfbBaseVertex(0),
750       mXfbVertexCountPerInstance(0),
751       mClearColorValue{},
752       mClearDepthStencilValue{},
753       mClearColorMasks(0),
754       mFlipYForCurrentSurface(false),
755       mFlipViewportForDrawFramebuffer(false),
756       mFlipViewportForReadFramebuffer(false),
757       mIsAnyHostVisibleBufferWritten(false),
758       mEmulateSeamfulCubeMapSampling(false),
759       mOutsideRenderPassCommands(nullptr),
760       mRenderPassCommands(nullptr),
761       mQueryEventType(GraphicsEventCmdBuf::NotInQueryCmd),
762       mGpuEventsEnabled(false),
763       mHasDeferredFlush(false),
764       mGpuClockSync{std::numeric_limits<double>::max(), std::numeric_limits<double>::max()},
765       mGpuEventTimestampOrigin(0),
766       mContextPriority(renderer->getDriverPriority(GetContextPriority(state))),
767       mShareGroupVk(vk::GetImpl(state.getShareGroup()))
768 {
769     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::ContextVk");
770     memset(&mClearColorValue, 0, sizeof(mClearColorValue));
771     memset(&mClearDepthStencilValue, 0, sizeof(mClearDepthStencilValue));
772     memset(&mViewport, 0, sizeof(mViewport));
773     memset(&mScissor, 0, sizeof(mScissor));
774 
775     // Ensure viewport is within Vulkan requirements
776     vk::ClampViewport(&mViewport);
777 
778     mNonIndexedDirtyBitsMask.set();
779     mNonIndexedDirtyBitsMask.reset(DIRTY_BIT_INDEX_BUFFER);
780 
781     mIndexedDirtyBitsMask.set();
782 
783     // Once a command buffer is ended, all bindings (through |vkCmdBind*| calls) are lost per Vulkan
784     // spec.  Once a new command buffer is allocated, we must make sure every previously bound
785     // resource is bound again.
786     //
787     // Note that currently these dirty bits are set every time a new render pass command buffer is
788     // begun.  However, using ANGLE's SecondaryCommandBuffer, the Vulkan command buffer (which is
789     // the primary command buffer) is not ended, so technically we don't need to rebind these.
790     mNewGraphicsCommandBufferDirtyBits = DirtyBits{DIRTY_BIT_RENDER_PASS,
791                                                    DIRTY_BIT_COLOR_ACCESS,
792                                                    DIRTY_BIT_DEPTH_STENCIL_ACCESS,
793                                                    DIRTY_BIT_PIPELINE_BINDING,
794                                                    DIRTY_BIT_TEXTURES,
795                                                    DIRTY_BIT_VERTEX_BUFFERS,
796                                                    DIRTY_BIT_INDEX_BUFFER,
797                                                    DIRTY_BIT_SHADER_RESOURCES,
798                                                    DIRTY_BIT_DESCRIPTOR_SETS,
799                                                    DIRTY_BIT_DRIVER_UNIFORMS_BINDING,
800                                                    DIRTY_BIT_VIEWPORT,
801                                                    DIRTY_BIT_SCISSOR};
802     if (getFeatures().supportsTransformFeedbackExtension.enabled)
803     {
804         mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS);
805     }
806 
807     mNewComputeCommandBufferDirtyBits =
808         DirtyBits{DIRTY_BIT_PIPELINE_BINDING, DIRTY_BIT_TEXTURES, DIRTY_BIT_SHADER_RESOURCES,
809                   DIRTY_BIT_DESCRIPTOR_SETS, DIRTY_BIT_DRIVER_UNIFORMS_BINDING};
810 
811     mGraphicsDirtyBitHandlers[DIRTY_BIT_MEMORY_BARRIER] =
812         &ContextVk::handleDirtyGraphicsMemoryBarrier;
813     mGraphicsDirtyBitHandlers[DIRTY_BIT_DEFAULT_ATTRIBS] =
814         &ContextVk::handleDirtyGraphicsDefaultAttribs;
815     mGraphicsDirtyBitHandlers[DIRTY_BIT_PIPELINE_DESC] =
816         &ContextVk::handleDirtyGraphicsPipelineDesc;
817     mGraphicsDirtyBitHandlers[DIRTY_BIT_READ_ONLY_DEPTH_FEEDBACK_LOOP_MODE] =
818         &ContextVk::handleDirtyGraphicsReadOnlyDepthFeedbackLoopMode;
819     mGraphicsDirtyBitHandlers[DIRTY_BIT_RENDER_PASS]  = &ContextVk::handleDirtyGraphicsRenderPass;
820     mGraphicsDirtyBitHandlers[DIRTY_BIT_EVENT_LOG]    = &ContextVk::handleDirtyGraphicsEventLog;
821     mGraphicsDirtyBitHandlers[DIRTY_BIT_COLOR_ACCESS] = &ContextVk::handleDirtyGraphicsColorAccess;
822     mGraphicsDirtyBitHandlers[DIRTY_BIT_DEPTH_STENCIL_ACCESS] =
823         &ContextVk::handleDirtyGraphicsDepthStencilAccess;
824     mGraphicsDirtyBitHandlers[DIRTY_BIT_PIPELINE_BINDING] =
825         &ContextVk::handleDirtyGraphicsPipelineBinding;
826     mGraphicsDirtyBitHandlers[DIRTY_BIT_TEXTURES] = &ContextVk::handleDirtyGraphicsTextures;
827     mGraphicsDirtyBitHandlers[DIRTY_BIT_VERTEX_BUFFERS] =
828         &ContextVk::handleDirtyGraphicsVertexBuffers;
829     mGraphicsDirtyBitHandlers[DIRTY_BIT_INDEX_BUFFER] = &ContextVk::handleDirtyGraphicsIndexBuffer;
830     mGraphicsDirtyBitHandlers[DIRTY_BIT_UNIFORMS]     = &ContextVk::handleDirtyGraphicsUniforms;
831     mGraphicsDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS] =
832         &ContextVk::handleDirtyGraphicsDriverUniforms;
833     mGraphicsDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS_BINDING] =
834         &ContextVk::handleDirtyGraphicsDriverUniformsBinding;
835     mGraphicsDirtyBitHandlers[DIRTY_BIT_SHADER_RESOURCES] =
836         &ContextVk::handleDirtyGraphicsShaderResources;
837     mGraphicsDirtyBitHandlers[DIRTY_BIT_FRAMEBUFFER_FETCH_BARRIER] =
838         &ContextVk::handleDirtyGraphicsFramebufferFetchBarrier;
839     mGraphicsDirtyBitHandlers[DIRTY_BIT_BLEND_BARRIER] =
840         &ContextVk::handleDirtyGraphicsBlendBarrier;
841     if (getFeatures().supportsTransformFeedbackExtension.enabled)
842     {
843         mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS] =
844             &ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension;
845         mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME] =
846             &ContextVk::handleDirtyGraphicsTransformFeedbackResume;
847     }
848     else if (getFeatures().emulateTransformFeedback.enabled)
849     {
850         mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS] =
851             &ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation;
852     }
853 
854     mGraphicsDirtyBitHandlers[DIRTY_BIT_DESCRIPTOR_SETS] =
855         &ContextVk::handleDirtyGraphicsDescriptorSets;
856 
857     mGraphicsDirtyBitHandlers[DIRTY_BIT_VIEWPORT] = &ContextVk::handleDirtyGraphicsViewport;
858     mGraphicsDirtyBitHandlers[DIRTY_BIT_SCISSOR]  = &ContextVk::handleDirtyGraphicsScissor;
859 
860     mComputeDirtyBitHandlers[DIRTY_BIT_MEMORY_BARRIER] =
861         &ContextVk::handleDirtyComputeMemoryBarrier;
862     mComputeDirtyBitHandlers[DIRTY_BIT_EVENT_LOG]     = &ContextVk::handleDirtyComputeEventLog;
863     mComputeDirtyBitHandlers[DIRTY_BIT_PIPELINE_DESC] = &ContextVk::handleDirtyComputePipelineDesc;
864     mComputeDirtyBitHandlers[DIRTY_BIT_PIPELINE_BINDING] =
865         &ContextVk::handleDirtyComputePipelineBinding;
866     mComputeDirtyBitHandlers[DIRTY_BIT_TEXTURES] = &ContextVk::handleDirtyComputeTextures;
867     mComputeDirtyBitHandlers[DIRTY_BIT_UNIFORMS] = &ContextVk::handleDirtyComputeUniforms;
868     mComputeDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS] =
869         &ContextVk::handleDirtyComputeDriverUniforms;
870     mComputeDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS_BINDING] =
871         &ContextVk::handleDirtyComputeDriverUniformsBinding;
872     mComputeDirtyBitHandlers[DIRTY_BIT_SHADER_RESOURCES] =
873         &ContextVk::handleDirtyComputeShaderResources;
874     mComputeDirtyBitHandlers[DIRTY_BIT_DESCRIPTOR_SETS] =
875         &ContextVk::handleDirtyComputeDescriptorSets;
876 
877     mGraphicsDirtyBits = mNewGraphicsCommandBufferDirtyBits;
878     mComputeDirtyBits  = mNewComputeCommandBufferDirtyBits;
879 
880     mActiveTextures.fill({nullptr, nullptr, true});
881     mActiveImages.fill(nullptr);
882 
883     // The following dirty bits don't affect the program pipeline:
884     //
885     // - READ_FRAMEBUFFER_BINDING only affects operations that read from said framebuffer,
886     // - CLEAR_* only affect following clear calls,
887     // - PACK/UNPACK_STATE only affect texture data upload/download,
888     // - *_BINDING only affect descriptor sets.
889     //
890     mPipelineDirtyBitsMask.set();
891     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
892     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_CLEAR_COLOR);
893     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_CLEAR_DEPTH);
894     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_CLEAR_STENCIL);
895     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_UNPACK_STATE);
896     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_UNPACK_BUFFER_BINDING);
897     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_PACK_STATE);
898     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_PACK_BUFFER_BINDING);
899     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_RENDERBUFFER_BINDING);
900     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING);
901     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING);
902     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_SAMPLER_BINDINGS);
903     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
904     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_IMAGE_BINDINGS);
905     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING);
906     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
907     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
908     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
909 
910     angle::PerfMonitorCounterGroup vulkanGroup;
911     vulkanGroup.name = "vulkan";
912 
913 #define ANGLE_ADD_PERF_MONITOR_COUNTER_GROUP(COUNTER) \
914     {                                                 \
915         angle::PerfMonitorCounter counter;            \
916         counter.name  = #COUNTER;                     \
917         counter.value = 0;                            \
918         vulkanGroup.counters.push_back(counter);      \
919     }
920 
921     ANGLE_VK_PERF_COUNTERS_X(ANGLE_ADD_PERF_MONITOR_COUNTER_GROUP)
922 
923 #undef ANGLE_ADD_PERF_MONITOR_COUNTER_GROUP
924 
925     mPerfMonitorCounters.push_back(vulkanGroup);
926 }
927 
928 ContextVk::~ContextVk() = default;
929 
onDestroy(const gl::Context * context)930 void ContextVk::onDestroy(const gl::Context *context)
931 {
932     // Remove context from the share group
933     mShareGroupVk->removeContext(this);
934 
935     // This will not destroy any resources. It will release them to be collected after finish.
936     mIncompleteTextures.onDestroy(context);
937 
938     // Flush and complete current outstanding work before destruction.
939     (void)finishImpl(RenderPassClosureReason::ContextDestruction);
940 
941     VkDevice device = getDevice();
942 
943     for (DriverUniformsDescriptorSet &driverUniforms : mDriverUniforms)
944     {
945         driverUniforms.destroy(mRenderer);
946     }
947 
948     for (vk::DynamicDescriptorPool &dynamicDescriptorPool : mDriverUniformsDescriptorPools)
949     {
950         dynamicDescriptorPool.destroy(device);
951     }
952 
953     mDefaultUniformStorage.release(mRenderer);
954     mEmptyBuffer.release(mRenderer);
955 
956     for (vk::DynamicBuffer &defaultBuffer : mStreamedVertexBuffers)
957     {
958         defaultBuffer.destroy(mRenderer);
959     }
960 
961     for (vk::DynamicQueryPool &queryPool : mQueryPools)
962     {
963         queryPool.destroy(device);
964     }
965 
966     // Recycle current commands buffers.
967     mRenderer->recycleOutsideRenderPassCommandBufferHelper(device, &mOutsideRenderPassCommands);
968     mRenderer->recycleRenderPassCommandBufferHelper(device, &mRenderPassCommands);
969 
970     mRenderer->releaseSharedResources(&mResourceUseList);
971 
972     mUtils.destroy(mRenderer);
973 
974     mRenderPassCache.destroy(mRenderer);
975     mShaderLibrary.destroy(device);
976     mGpuEventQueryPool.destroy(device);
977     mCommandPools.outsideRenderPassPool.destroy(device);
978     mCommandPools.renderPassPool.destroy(device);
979 
980     ASSERT(mCurrentGarbage.empty());
981     ASSERT(mResourceUseList.empty());
982 }
983 
getVertexArray() const984 VertexArrayVk *ContextVk::getVertexArray() const
985 {
986     return vk::GetImpl(mState.getVertexArray());
987 }
988 
getDrawFramebuffer() const989 FramebufferVk *ContextVk::getDrawFramebuffer() const
990 {
991     return vk::GetImpl(mState.getDrawFramebuffer());
992 }
993 
getProgram() const994 ProgramVk *ContextVk::getProgram() const
995 {
996     return vk::SafeGetImpl(mState.getProgram());
997 }
998 
getProgramPipeline() const999 ProgramPipelineVk *ContextVk::getProgramPipeline() const
1000 {
1001     return vk::SafeGetImpl(mState.getProgramPipeline());
1002 }
1003 
getIncompleteTexture(const gl::Context * context,gl::TextureType type,gl::SamplerFormat format,gl::Texture ** textureOut)1004 angle::Result ContextVk::getIncompleteTexture(const gl::Context *context,
1005                                               gl::TextureType type,
1006                                               gl::SamplerFormat format,
1007                                               gl::Texture **textureOut)
1008 {
1009     return mIncompleteTextures.getIncompleteTexture(context, type, format, this, textureOut);
1010 }
1011 
initialize()1012 angle::Result ContextVk::initialize()
1013 {
1014     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::initialize");
1015 
1016     ANGLE_TRY(mQueryPools[gl::QueryType::AnySamples].init(this, VK_QUERY_TYPE_OCCLUSION,
1017                                                           vk::kDefaultOcclusionQueryPoolSize));
1018     ANGLE_TRY(mQueryPools[gl::QueryType::AnySamplesConservative].init(
1019         this, VK_QUERY_TYPE_OCCLUSION, vk::kDefaultOcclusionQueryPoolSize));
1020 
1021     // Only initialize the timestamp query pools if the extension is available.
1022     if (mRenderer->getQueueFamilyProperties().timestampValidBits > 0)
1023     {
1024         ANGLE_TRY(mQueryPools[gl::QueryType::Timestamp].init(this, VK_QUERY_TYPE_TIMESTAMP,
1025                                                              vk::kDefaultTimestampQueryPoolSize));
1026         ANGLE_TRY(mQueryPools[gl::QueryType::TimeElapsed].init(this, VK_QUERY_TYPE_TIMESTAMP,
1027                                                                vk::kDefaultTimestampQueryPoolSize));
1028     }
1029 
1030     if (getFeatures().supportsTransformFeedbackExtension.enabled)
1031     {
1032         ANGLE_TRY(mQueryPools[gl::QueryType::TransformFeedbackPrimitivesWritten].init(
1033             this, VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT,
1034             vk::kDefaultTransformFeedbackQueryPoolSize));
1035     }
1036 
1037     // The primitives generated query is provided through the Vulkan pipeline statistics query if
1038     // supported.  TODO: If VK_EXT_primitives_generated_query is supported, use that instead.
1039     // http://anglebug.com/5430
1040     if (getFeatures().supportsPipelineStatisticsQuery.enabled)
1041     {
1042         ANGLE_TRY(mQueryPools[gl::QueryType::PrimitivesGenerated].init(
1043             this, VK_QUERY_TYPE_PIPELINE_STATISTICS, vk::kDefaultPrimitivesGeneratedQueryPoolSize));
1044     }
1045 
1046     // Init GLES to Vulkan index type map.
1047     initIndexTypeMap();
1048 
1049     // Init driver uniforms and get the descriptor set layouts.
1050     for (PipelineType pipeline : angle::AllEnums<PipelineType>())
1051     {
1052         mDriverUniforms[pipeline].init(mRenderer);
1053 
1054         vk::DescriptorSetLayoutDesc desc = getDriverUniformsDescriptorSetDesc();
1055         ANGLE_TRY(getDescriptorSetLayoutCache().getDescriptorSetLayout(
1056             this, desc, &mDriverUniforms[pipeline].descriptorSetLayout));
1057 
1058         vk::DescriptorSetLayoutBindingVector bindingVector;
1059         std::vector<VkSampler> immutableSamplers;
1060         desc.unpackBindings(&bindingVector, &immutableSamplers);
1061         std::vector<VkDescriptorPoolSize> descriptorPoolSizes;
1062 
1063         for (const VkDescriptorSetLayoutBinding &binding : bindingVector)
1064         {
1065             if (binding.descriptorCount > 0)
1066             {
1067                 VkDescriptorPoolSize poolSize = {};
1068 
1069                 poolSize.type            = binding.descriptorType;
1070                 poolSize.descriptorCount = binding.descriptorCount;
1071                 descriptorPoolSizes.emplace_back(poolSize);
1072             }
1073         }
1074         if (!descriptorPoolSizes.empty())
1075         {
1076             ANGLE_TRY(mDriverUniformsDescriptorPools[pipeline].init(
1077                 this, descriptorPoolSizes.data(), descriptorPoolSizes.size(),
1078                 mDriverUniforms[pipeline].descriptorSetLayout.get().getHandle()));
1079         }
1080     }
1081 
1082     mGraphicsPipelineDesc.reset(new vk::GraphicsPipelineDesc());
1083     mGraphicsPipelineDesc->initDefaults(this);
1084 
1085     // Initialize current value/default attribute buffers.
1086     for (vk::DynamicBuffer &buffer : mStreamedVertexBuffers)
1087     {
1088         buffer.init(mRenderer, kVertexBufferUsage, 1, kDynamicVertexDataSize, true);
1089     }
1090 
1091 #if ANGLE_ENABLE_VULKAN_GPU_TRACE_EVENTS
1092     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
1093     ASSERT(platform);
1094 
1095     // GPU tracing workaround for anglebug.com/2927.  The renderer should not emit gpu events
1096     // during platform discovery.
1097     const unsigned char *gpuEventsEnabled =
1098         platform->getTraceCategoryEnabledFlag(platform, "gpu.angle.gpu");
1099     mGpuEventsEnabled = gpuEventsEnabled && *gpuEventsEnabled;
1100 #endif
1101 
1102     mEmulateSeamfulCubeMapSampling = shouldEmulateSeamfulCubeMapSampling();
1103 
1104     // Assign initial command buffers from queue
1105     ANGLE_TRY(vk::OutsideRenderPassCommandBuffer::InitializeCommandPool(
1106         this, &mCommandPools.outsideRenderPassPool, mRenderer->getDeviceQueueIndex(),
1107         hasProtectedContent()));
1108     ANGLE_TRY(vk::RenderPassCommandBuffer::InitializeCommandPool(
1109         this, &mCommandPools.renderPassPool, mRenderer->getDeviceQueueIndex(),
1110         hasProtectedContent()));
1111     ANGLE_TRY(mRenderer->getOutsideRenderPassCommandBufferHelper(
1112         this, &mCommandPools.outsideRenderPassPool, &mOutsideRenderPassCommands));
1113     ANGLE_TRY(mRenderer->getRenderPassCommandBufferHelper(this, &mCommandPools.renderPassPool,
1114                                                           &mRenderPassCommands));
1115 
1116     if (mGpuEventsEnabled)
1117     {
1118         // GPU events should only be available if timestamp queries are available.
1119         ASSERT(mRenderer->getQueueFamilyProperties().timestampValidBits > 0);
1120         // Calculate the difference between CPU and GPU clocks for GPU event reporting.
1121         ANGLE_TRY(mGpuEventQueryPool.init(this, VK_QUERY_TYPE_TIMESTAMP,
1122                                           vk::kDefaultTimestampQueryPoolSize));
1123         ANGLE_TRY(synchronizeCpuGpuTime());
1124 
1125         mPerfCounters.primaryBuffers++;
1126 
1127         EventName eventName = GetTraceEventName("Primary", mPerfCounters.primaryBuffers);
1128         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
1129                                 TRACE_EVENT_PHASE_BEGIN, eventName));
1130     }
1131 
1132     size_t minAlignment = static_cast<size_t>(
1133         mRenderer->getPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment);
1134     mDefaultUniformStorage.init(mRenderer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, minAlignment,
1135                                 mRenderer->getDefaultUniformBufferSize(), true);
1136 
1137     // Initialize an "empty" buffer for use with default uniform blocks where there are no uniforms,
1138     // or atomic counter buffer array indices that are unused.
1139     constexpr VkBufferUsageFlags kEmptyBufferUsage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
1140                                                      VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
1141                                                      VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
1142     VkBufferCreateInfo emptyBufferInfo          = {};
1143     emptyBufferInfo.sType                       = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1144     emptyBufferInfo.flags                       = 0;
1145     emptyBufferInfo.size                        = 16;
1146     emptyBufferInfo.usage                       = kEmptyBufferUsage;
1147     emptyBufferInfo.sharingMode                 = VK_SHARING_MODE_EXCLUSIVE;
1148     emptyBufferInfo.queueFamilyIndexCount       = 0;
1149     emptyBufferInfo.pQueueFamilyIndices         = nullptr;
1150     constexpr VkMemoryPropertyFlags kMemoryType = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
1151     ANGLE_TRY(mEmptyBuffer.init(this, emptyBufferInfo, kMemoryType));
1152 
1153     // Add context into the share group
1154     mShareGroupVk->addContext(this);
1155 
1156     return angle::Result::Continue;
1157 }
1158 
flush(const gl::Context * context)1159 angle::Result ContextVk::flush(const gl::Context *context)
1160 {
1161     const bool isSingleBuffer =
1162         (mCurrentWindowSurface != nullptr) && mCurrentWindowSurface->isSharedPresentMode();
1163 
1164     // Don't defer flushes in single-buffer mode.  In this mode, the application is not required to
1165     // call eglSwapBuffers(), and glFlush() is expected to ensure that work is submitted.
1166     if (mRenderer->getFeatures().deferFlushUntilEndRenderPass.enabled && hasStartedRenderPass() &&
1167         !isSingleBuffer)
1168     {
1169         mHasDeferredFlush = true;
1170         return angle::Result::Continue;
1171     }
1172 
1173     if (mRenderer->getFeatures().swapbuffersOnFlushOrFinishWithSingleBuffer.enabled &&
1174         isSingleBuffer)
1175     {
1176         return mCurrentWindowSurface->onSharedPresentContextFlush(context);
1177     }
1178 
1179     return flushImpl(nullptr, RenderPassClosureReason::GLFlush);
1180 }
1181 
finish(const gl::Context * context)1182 angle::Result ContextVk::finish(const gl::Context *context)
1183 {
1184     if (mRenderer->getFeatures().swapbuffersOnFlushOrFinishWithSingleBuffer.enabled &&
1185         (mCurrentWindowSurface != nullptr) && mCurrentWindowSurface->isSharedPresentMode())
1186     {
1187         return mCurrentWindowSurface->onSharedPresentContextFlush(context);
1188     }
1189 
1190     return finishImpl(RenderPassClosureReason::GLFinish);
1191 }
1192 
setupDraw(const gl::Context * context,gl::PrimitiveMode mode,GLint firstVertexOrInvalid,GLsizei vertexOrIndexCount,GLsizei instanceCount,gl::DrawElementsType indexTypeOrInvalid,const void * indices,DirtyBits dirtyBitMask)1193 angle::Result ContextVk::setupDraw(const gl::Context *context,
1194                                    gl::PrimitiveMode mode,
1195                                    GLint firstVertexOrInvalid,
1196                                    GLsizei vertexOrIndexCount,
1197                                    GLsizei instanceCount,
1198                                    gl::DrawElementsType indexTypeOrInvalid,
1199                                    const void *indices,
1200                                    DirtyBits dirtyBitMask)
1201 {
1202     // Set any dirty bits that depend on draw call parameters or other objects.
1203     if (mode != mCurrentDrawMode)
1204     {
1205         invalidateCurrentGraphicsPipeline();
1206         mCurrentDrawMode = mode;
1207         mGraphicsPipelineDesc->updateTopology(&mGraphicsPipelineTransition, mCurrentDrawMode);
1208     }
1209 
1210     // Must be called before the command buffer is started. Can call finish.
1211     VertexArrayVk *vertexArrayVk = getVertexArray();
1212     if (vertexArrayVk->getStreamingVertexAttribsMask().any())
1213     {
1214         // All client attribs & any emulated buffered attribs will be updated
1215         ANGLE_TRY(vertexArrayVk->updateStreamedAttribs(context, firstVertexOrInvalid,
1216                                                        vertexOrIndexCount, instanceCount,
1217                                                        indexTypeOrInvalid, indices));
1218 
1219         mGraphicsDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
1220     }
1221 
1222     ProgramExecutableVk *programExecutableVk = getExecutable();
1223     if (programExecutableVk->hasDirtyUniforms())
1224     {
1225         mGraphicsDirtyBits.set(DIRTY_BIT_UNIFORMS);
1226     }
1227 
1228     // Update transform feedback offsets on every draw call when emulating transform feedback.  This
1229     // relies on the fact that no geometry/tessellation, indirect or indexed calls are supported in
1230     // ES3.1 (and emulation is not done for ES3.2).
1231     if (getFeatures().emulateTransformFeedback.enabled &&
1232         mState.isTransformFeedbackActiveUnpaused())
1233     {
1234         ASSERT(firstVertexOrInvalid != -1);
1235         mXfbBaseVertex             = firstVertexOrInvalid;
1236         mXfbVertexCountPerInstance = vertexOrIndexCount;
1237         invalidateGraphicsDriverUniforms();
1238     }
1239 
1240     DirtyBits dirtyBits = mGraphicsDirtyBits & dirtyBitMask;
1241 
1242     if (dirtyBits.none())
1243     {
1244         ASSERT(mRenderPassCommandBuffer);
1245         return angle::Result::Continue;
1246     }
1247 
1248     // Flush any relevant dirty bits.
1249     for (DirtyBits::Iterator dirtyBitIter = dirtyBits.begin(); dirtyBitIter != dirtyBits.end();
1250          ++dirtyBitIter)
1251     {
1252         ASSERT(mGraphicsDirtyBitHandlers[*dirtyBitIter]);
1253         ANGLE_TRY((this->*mGraphicsDirtyBitHandlers[*dirtyBitIter])(&dirtyBitIter, dirtyBitMask));
1254     }
1255 
1256     mGraphicsDirtyBits &= ~dirtyBitMask;
1257 
1258     // Render pass must be always available at this point.
1259     ASSERT(mRenderPassCommandBuffer);
1260 
1261     return angle::Result::Continue;
1262 }
1263 
setupIndexedDraw(const gl::Context * context,gl::PrimitiveMode mode,GLsizei indexCount,GLsizei instanceCount,gl::DrawElementsType indexType,const void * indices)1264 angle::Result ContextVk::setupIndexedDraw(const gl::Context *context,
1265                                           gl::PrimitiveMode mode,
1266                                           GLsizei indexCount,
1267                                           GLsizei instanceCount,
1268                                           gl::DrawElementsType indexType,
1269                                           const void *indices)
1270 {
1271     ASSERT(mode != gl::PrimitiveMode::LineLoop);
1272 
1273     if (indexType != mCurrentDrawElementsType)
1274     {
1275         mCurrentDrawElementsType = indexType;
1276         ANGLE_TRY(onIndexBufferChange(nullptr));
1277     }
1278 
1279     VertexArrayVk *vertexArrayVk         = getVertexArray();
1280     const gl::Buffer *elementArrayBuffer = vertexArrayVk->getState().getElementArrayBuffer();
1281     if (!elementArrayBuffer)
1282     {
1283         BufferBindingDirty bindingDirty;
1284         ANGLE_TRY(vertexArrayVk->convertIndexBufferCPU(this, indexType, indexCount, indices,
1285                                                        &bindingDirty));
1286 
1287         // We only set dirty bit when the bound buffer actually changed.
1288         if (bindingDirty == BufferBindingDirty::Yes)
1289         {
1290             mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
1291             mCurrentIndexBufferOffset = 0;
1292         }
1293     }
1294     else
1295     {
1296         mCurrentIndexBufferOffset = reinterpret_cast<VkDeviceSize>(indices);
1297 
1298         if (indices != mLastIndexBufferOffset)
1299         {
1300             mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
1301             mLastIndexBufferOffset = indices;
1302         }
1303 
1304         // When you draw with LineLoop mode or GL_UNSIGNED_BYTE type, we may allocate its own
1305         // element buffer and modify mCurrentElementArrayBuffer. When we switch out of that draw
1306         // mode, we must reset mCurrentElementArrayBuffer back to the vertexArray's element buffer.
1307         // Since in either case we set DIRTY_BIT_INDEX_BUFFER dirty bit, we use this bit to re-sync
1308         // mCurrentElementArrayBuffer.
1309         if (mGraphicsDirtyBits[DIRTY_BIT_INDEX_BUFFER])
1310         {
1311             vertexArrayVk->updateCurrentElementArrayBuffer();
1312         }
1313 
1314         if (shouldConvertUint8VkIndexType(indexType) && mGraphicsDirtyBits[DIRTY_BIT_INDEX_BUFFER])
1315         {
1316             ANGLE_VK_PERF_WARNING(this, GL_DEBUG_SEVERITY_LOW,
1317                                   "Potential inefficiency emulating uint8 vertex attributes due to "
1318                                   "lack of hardware support");
1319 
1320             BufferVk *bufferVk             = vk::GetImpl(elementArrayBuffer);
1321             vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
1322 
1323             if (bufferHelper.isHostVisible() &&
1324                 !bufferHelper.isCurrentlyInUse(getLastCompletedQueueSerial()))
1325             {
1326                 uint8_t *src = nullptr;
1327                 ANGLE_TRY(
1328                     bufferVk->mapImpl(this, GL_MAP_READ_BIT, reinterpret_cast<void **>(&src)));
1329                 // Note: bufferOffset is not added here because mapImpl already adds it.
1330                 src += reinterpret_cast<uintptr_t>(indices);
1331                 const size_t byteCount = static_cast<size_t>(elementArrayBuffer->getSize()) -
1332                                          reinterpret_cast<uintptr_t>(indices);
1333                 BufferBindingDirty bindingDirty;
1334                 ANGLE_TRY(vertexArrayVk->convertIndexBufferCPU(this, indexType, byteCount, src,
1335                                                                &bindingDirty));
1336                 ANGLE_TRY(bufferVk->unmapImpl(this));
1337             }
1338             else
1339             {
1340                 ANGLE_TRY(vertexArrayVk->convertIndexBufferGPU(this, bufferVk, indices));
1341             }
1342 
1343             mCurrentIndexBufferOffset = 0;
1344         }
1345     }
1346 
1347     return setupDraw(context, mode, 0, indexCount, instanceCount, indexType, indices,
1348                      mIndexedDirtyBitsMask);
1349 }
1350 
setupIndirectDraw(const gl::Context * context,gl::PrimitiveMode mode,DirtyBits dirtyBitMask,vk::BufferHelper * indirectBuffer)1351 angle::Result ContextVk::setupIndirectDraw(const gl::Context *context,
1352                                            gl::PrimitiveMode mode,
1353                                            DirtyBits dirtyBitMask,
1354                                            vk::BufferHelper *indirectBuffer)
1355 {
1356     GLint firstVertex     = -1;
1357     GLsizei vertexCount   = 0;
1358     GLsizei instanceCount = 1;
1359 
1360     // Break the render pass if the indirect buffer was previously used as the output from transform
1361     // feedback.
1362     if (mCurrentTransformFeedbackBuffers.contains(indirectBuffer))
1363     {
1364         ANGLE_TRY(
1365             flushCommandsAndEndRenderPass(RenderPassClosureReason::XfbWriteThenIndirectDrawBuffer));
1366     }
1367 
1368     ANGLE_TRY(setupDraw(context, mode, firstVertex, vertexCount, instanceCount,
1369                         gl::DrawElementsType::InvalidEnum, nullptr, dirtyBitMask));
1370 
1371     // Process indirect buffer after render pass has started.
1372     mRenderPassCommands->bufferRead(this, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
1373                                     vk::PipelineStage::DrawIndirect, indirectBuffer);
1374 
1375     return angle::Result::Continue;
1376 }
1377 
setupIndexedIndirectDraw(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType indexType,vk::BufferHelper * indirectBuffer)1378 angle::Result ContextVk::setupIndexedIndirectDraw(const gl::Context *context,
1379                                                   gl::PrimitiveMode mode,
1380                                                   gl::DrawElementsType indexType,
1381                                                   vk::BufferHelper *indirectBuffer)
1382 {
1383     ASSERT(mode != gl::PrimitiveMode::LineLoop);
1384 
1385     if (indexType != mCurrentDrawElementsType)
1386     {
1387         mCurrentDrawElementsType = indexType;
1388         ANGLE_TRY(onIndexBufferChange(nullptr));
1389     }
1390 
1391     return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, indirectBuffer);
1392 }
1393 
setupLineLoopIndexedIndirectDraw(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType indexType,vk::BufferHelper * srcIndirectBuf,VkDeviceSize indirectBufferOffset,vk::BufferHelper ** indirectBufferOut)1394 angle::Result ContextVk::setupLineLoopIndexedIndirectDraw(const gl::Context *context,
1395                                                           gl::PrimitiveMode mode,
1396                                                           gl::DrawElementsType indexType,
1397                                                           vk::BufferHelper *srcIndirectBuf,
1398                                                           VkDeviceSize indirectBufferOffset,
1399                                                           vk::BufferHelper **indirectBufferOut)
1400 {
1401     ASSERT(mode == gl::PrimitiveMode::LineLoop);
1402 
1403     vk::BufferHelper *dstIndirectBuf = nullptr;
1404 
1405     VertexArrayVk *vertexArrayVk = getVertexArray();
1406     ANGLE_TRY(vertexArrayVk->handleLineLoopIndexIndirect(this, indexType, srcIndirectBuf,
1407                                                          indirectBufferOffset, &dstIndirectBuf));
1408 
1409     *indirectBufferOut = dstIndirectBuf;
1410 
1411     if (indexType != mCurrentDrawElementsType)
1412     {
1413         mCurrentDrawElementsType = indexType;
1414         ANGLE_TRY(onIndexBufferChange(nullptr));
1415     }
1416 
1417     return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, dstIndirectBuf);
1418 }
1419 
setupLineLoopIndirectDraw(const gl::Context * context,gl::PrimitiveMode mode,vk::BufferHelper * indirectBuffer,VkDeviceSize indirectBufferOffset,vk::BufferHelper ** indirectBufferOut)1420 angle::Result ContextVk::setupLineLoopIndirectDraw(const gl::Context *context,
1421                                                    gl::PrimitiveMode mode,
1422                                                    vk::BufferHelper *indirectBuffer,
1423                                                    VkDeviceSize indirectBufferOffset,
1424                                                    vk::BufferHelper **indirectBufferOut)
1425 {
1426     ASSERT(mode == gl::PrimitiveMode::LineLoop);
1427 
1428     vk::BufferHelper *indirectBufferHelperOut = nullptr;
1429 
1430     VertexArrayVk *vertexArrayVk = getVertexArray();
1431     ANGLE_TRY(vertexArrayVk->handleLineLoopIndirectDraw(
1432         context, indirectBuffer, indirectBufferOffset, &indirectBufferHelperOut));
1433 
1434     *indirectBufferOut = indirectBufferHelperOut;
1435 
1436     if (gl::DrawElementsType::UnsignedInt != mCurrentDrawElementsType)
1437     {
1438         mCurrentDrawElementsType = gl::DrawElementsType::UnsignedInt;
1439         ANGLE_TRY(onIndexBufferChange(nullptr));
1440     }
1441 
1442     return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, indirectBufferHelperOut);
1443 }
1444 
setupLineLoopDraw(const gl::Context * context,gl::PrimitiveMode mode,GLint firstVertex,GLsizei vertexOrIndexCount,gl::DrawElementsType indexTypeOrInvalid,const void * indices,uint32_t * numIndicesOut)1445 angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
1446                                            gl::PrimitiveMode mode,
1447                                            GLint firstVertex,
1448                                            GLsizei vertexOrIndexCount,
1449                                            gl::DrawElementsType indexTypeOrInvalid,
1450                                            const void *indices,
1451                                            uint32_t *numIndicesOut)
1452 {
1453     mCurrentIndexBufferOffset    = 0;
1454     VertexArrayVk *vertexArrayVk = getVertexArray();
1455     ANGLE_TRY(vertexArrayVk->handleLineLoop(this, firstVertex, vertexOrIndexCount,
1456                                             indexTypeOrInvalid, indices, numIndicesOut));
1457     ANGLE_TRY(onIndexBufferChange(nullptr));
1458     mCurrentDrawElementsType = indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum
1459                                    ? indexTypeOrInvalid
1460                                    : gl::DrawElementsType::UnsignedInt;
1461     return setupDraw(context, mode, firstVertex, vertexOrIndexCount, 1, indexTypeOrInvalid, indices,
1462                      mIndexedDirtyBitsMask);
1463 }
1464 
setupDispatch(const gl::Context * context)1465 angle::Result ContextVk::setupDispatch(const gl::Context *context)
1466 {
1467     // Note: numerous tests miss a glMemoryBarrier call between the initial texture data upload and
1468     // the dispatch call.  Flush the outside render pass command buffer as a workaround.
1469     // TODO: Remove this and fix tests.  http://anglebug.com/5070
1470     ANGLE_TRY(flushOutsideRenderPassCommands());
1471 
1472     ProgramExecutableVk *programExecutableVk = getExecutable();
1473     if (programExecutableVk->hasDirtyUniforms())
1474     {
1475         mComputeDirtyBits.set(DIRTY_BIT_UNIFORMS);
1476         mComputeDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
1477     }
1478 
1479     DirtyBits dirtyBits = mComputeDirtyBits;
1480 
1481     // Flush any relevant dirty bits.
1482     for (size_t dirtyBit : dirtyBits)
1483     {
1484         ASSERT(mComputeDirtyBitHandlers[dirtyBit]);
1485         ANGLE_TRY((this->*mComputeDirtyBitHandlers[dirtyBit])());
1486     }
1487 
1488     mComputeDirtyBits.reset();
1489 
1490     return angle::Result::Continue;
1491 }
1492 
handleDirtyGraphicsMemoryBarrier(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)1493 angle::Result ContextVk::handleDirtyGraphicsMemoryBarrier(DirtyBits::Iterator *dirtyBitsIterator,
1494                                                           DirtyBits dirtyBitMask)
1495 {
1496     return handleDirtyMemoryBarrierImpl(dirtyBitsIterator, dirtyBitMask);
1497 }
1498 
handleDirtyComputeMemoryBarrier()1499 angle::Result ContextVk::handleDirtyComputeMemoryBarrier()
1500 {
1501     return handleDirtyMemoryBarrierImpl(nullptr, {});
1502 }
1503 
renderPassUsesStorageResources() const1504 bool ContextVk::renderPassUsesStorageResources() const
1505 {
1506     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
1507     ASSERT(executable);
1508 
1509     // Storage images:
1510     for (size_t imageUnitIndex : executable->getActiveImagesMask())
1511     {
1512         const gl::Texture *texture = mState.getImageUnit(imageUnitIndex).texture.get();
1513         if (texture == nullptr)
1514         {
1515             continue;
1516         }
1517 
1518         TextureVk *textureVk = vk::GetImpl(texture);
1519 
1520         if (texture->getType() == gl::TextureType::Buffer)
1521         {
1522             vk::BufferHelper &buffer = vk::GetImpl(textureVk->getBuffer().get())->getBuffer();
1523             if (mRenderPassCommands->usesBuffer(buffer))
1524             {
1525                 return true;
1526             }
1527         }
1528         else
1529         {
1530             vk::ImageHelper &image = textureVk->getImage();
1531             // Images only need to close the render pass if they need a layout transition.  Outside
1532             // render pass command buffer doesn't need closing as the layout transition barriers are
1533             // recorded in sequence with the rest of the commands.
1534             if (IsRenderPassStartedAndUsesImage(*mRenderPassCommands, image))
1535             {
1536                 return true;
1537             }
1538         }
1539     }
1540 
1541     // Storage buffers:
1542     const std::vector<gl::InterfaceBlock> &blocks = executable->getShaderStorageBlocks();
1543     for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
1544     {
1545         uint32_t binding = blocks[bufferIndex].binding;
1546         const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
1547             mState.getIndexedShaderStorageBuffer(binding);
1548 
1549         if (bufferBinding.get() == nullptr)
1550         {
1551             continue;
1552         }
1553 
1554         vk::BufferHelper &buffer = vk::GetImpl(bufferBinding.get())->getBuffer();
1555         if (mRenderPassCommands->usesBuffer(buffer))
1556         {
1557             return true;
1558         }
1559     }
1560 
1561     // Atomic counters:
1562     const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers =
1563         executable->getAtomicCounterBuffers();
1564     for (uint32_t bufferIndex = 0; bufferIndex < atomicCounterBuffers.size(); ++bufferIndex)
1565     {
1566         uint32_t binding = atomicCounterBuffers[bufferIndex].binding;
1567         const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
1568             mState.getIndexedAtomicCounterBuffer(binding);
1569 
1570         if (bufferBinding.get() == nullptr)
1571         {
1572             continue;
1573         }
1574 
1575         vk::BufferHelper &buffer = vk::GetImpl(bufferBinding.get())->getBuffer();
1576         if (mRenderPassCommands->usesBuffer(buffer))
1577         {
1578             return true;
1579         }
1580     }
1581 
1582     return false;
1583 }
1584 
handleDirtyMemoryBarrierImpl(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)1585 angle::Result ContextVk::handleDirtyMemoryBarrierImpl(DirtyBits::Iterator *dirtyBitsIterator,
1586                                                       DirtyBits dirtyBitMask)
1587 {
1588     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
1589     ASSERT(executable);
1590 
1591     const bool hasImages         = executable->hasImages();
1592     const bool hasStorageBuffers = executable->hasStorageBuffers();
1593     const bool hasAtomicCounters = executable->hasAtomicCounterBuffers();
1594 
1595     if (!hasImages && !hasStorageBuffers && !hasAtomicCounters)
1596     {
1597         return angle::Result::Continue;
1598     }
1599 
1600     // Break the render pass if necessary.  This is only needed for write-after-read situations, and
1601     // is done by checking whether current storage buffers and images are used in the render pass.
1602     if (renderPassUsesStorageResources())
1603     {
1604         // Either set later bits (if called during handling of graphics dirty bits), or set the
1605         // dirty bits directly (if called during handling of compute dirty bits).
1606         if (dirtyBitsIterator)
1607         {
1608             return flushDirtyGraphicsRenderPass(
1609                 dirtyBitsIterator, dirtyBitMask,
1610                 RenderPassClosureReason::GLMemoryBarrierThenStorageResource);
1611         }
1612         else
1613         {
1614             return flushCommandsAndEndRenderPass(
1615                 RenderPassClosureReason::GLMemoryBarrierThenStorageResource);
1616         }
1617     }
1618 
1619     // Flushing outside render pass commands is cheap.  If a memory barrier has been issued in its
1620     // life time, just flush it instead of wasting time trying to figure out if it's necessary.
1621     if (mOutsideRenderPassCommands->hasGLMemoryBarrierIssued())
1622     {
1623         ANGLE_TRY(flushOutsideRenderPassCommands());
1624     }
1625 
1626     return angle::Result::Continue;
1627 }
1628 
handleDirtyGraphicsEventLog(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)1629 angle::Result ContextVk::handleDirtyGraphicsEventLog(DirtyBits::Iterator *dirtyBitsIterator,
1630                                                      DirtyBits dirtyBitMask)
1631 {
1632     return handleDirtyEventLogImpl(mRenderPassCommandBuffer);
1633 }
1634 
handleDirtyComputeEventLog()1635 angle::Result ContextVk::handleDirtyComputeEventLog()
1636 {
1637     return handleDirtyEventLogImpl(&mOutsideRenderPassCommands->getCommandBuffer());
1638 }
1639 
1640 template <typename CommandBufferT>
handleDirtyEventLogImpl(CommandBufferT * commandBuffer)1641 angle::Result ContextVk::handleDirtyEventLogImpl(CommandBufferT *commandBuffer)
1642 {
1643     // This method is called when a draw or dispatch command is being processed.  It's purpose is
1644     // to call the vkCmd*DebugUtilsLabelEXT functions in order to communicate to debuggers
1645     // (e.g. AGI) the OpenGL ES commands that the application uses.
1646 
1647     // Exit early if no OpenGL ES commands have been logged, or if no command buffer (for a no-op
1648     // draw), or if calling the vkCmd*DebugUtilsLabelEXT functions is not enabled.
1649     if (mEventLog.empty() || commandBuffer == nullptr || !mRenderer->angleDebuggerMode())
1650     {
1651         return angle::Result::Continue;
1652     }
1653 
1654     // Insert OpenGL ES commands into debug label.  We create a 3-level cascade here for
1655     // OpenGL-ES-first debugging in AGI.  Here's the general outline of commands:
1656     // -glDrawCommand
1657     // --vkCmdBeginDebugUtilsLabelEXT() #1 for "glDrawCommand"
1658     // --OpenGL ES Commands
1659     // ---vkCmdBeginDebugUtilsLabelEXT() #2 for "OpenGL ES Commands"
1660     // ---Individual OpenGL ES Commands leading up to glDrawCommand
1661     // ----vkCmdBeginDebugUtilsLabelEXT() #3 for each individual OpenGL ES Command
1662     // ----vkCmdEndDebugUtilsLabelEXT() #3 for each individual OpenGL ES Command
1663     // ----...More Individual OGL Commands...
1664     // ----Final Individual OGL command will be the same glDrawCommand shown in #1 above
1665     // ---vkCmdEndDebugUtilsLabelEXT() #2 for "OpenGL ES Commands"
1666     // --VK SetupDraw & Draw-related commands will be embedded here under glDraw #1
1667     // --vkCmdEndDebugUtilsLabelEXT() #1 is called after each vkDraw* or vkDispatch* call
1668 
1669     // AGI desires no parameters on the top-level of the hierarchy.
1670     std::string topLevelCommand = mEventLog.back();
1671     size_t startOfParameters    = topLevelCommand.find("(");
1672     if (startOfParameters != std::string::npos)
1673     {
1674         topLevelCommand = topLevelCommand.substr(0, startOfParameters);
1675     }
1676     VkDebugUtilsLabelEXT label = {VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
1677                                   nullptr,
1678                                   topLevelCommand.c_str(),
1679                                   {0.0f, 0.0f, 0.0f, 0.0f}};
1680     // This is #1 from comment above
1681     commandBuffer->beginDebugUtilsLabelEXT(label);
1682     std::string oglCmds = "OpenGL ES Commands";
1683     label.pLabelName    = oglCmds.c_str();
1684     // This is #2 from comment above
1685     commandBuffer->beginDebugUtilsLabelEXT(label);
1686     for (uint32_t i = 0; i < mEventLog.size(); ++i)
1687     {
1688         label.pLabelName = mEventLog[i].c_str();
1689         // NOTE: We have to use a begin/end pair here because AGI does not promote the
1690         // pLabelName from an insertDebugUtilsLabelEXT() call to the Commands panel.
1691         // Internal bug b/169243237 is tracking this and once the insert* call shows the
1692         // pLabelName similar to begin* call, we can switch these to insert* calls instead.
1693         // This is #3 from comment above.
1694         commandBuffer->beginDebugUtilsLabelEXT(label);
1695         commandBuffer->endDebugUtilsLabelEXT();
1696     }
1697     commandBuffer->endDebugUtilsLabelEXT();
1698     // The final end* call for #1 above is made in the ContextVk::draw* or
1699     //  ContextVk::dispatch* function calls.
1700 
1701     mEventLog.clear();
1702     return angle::Result::Continue;
1703 }
1704 
handleDirtyGraphicsDefaultAttribs(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)1705 angle::Result ContextVk::handleDirtyGraphicsDefaultAttribs(DirtyBits::Iterator *dirtyBitsIterator,
1706                                                            DirtyBits dirtyBitMask)
1707 {
1708     ASSERT(mDirtyDefaultAttribsMask.any());
1709 
1710     VertexArrayVk *vertexArrayVk = getVertexArray();
1711     for (size_t attribIndex : mDirtyDefaultAttribsMask)
1712     {
1713         ANGLE_TRY(vertexArrayVk->updateDefaultAttrib(this, attribIndex));
1714     }
1715 
1716     mDirtyDefaultAttribsMask.reset();
1717     return angle::Result::Continue;
1718 }
1719 
handleDirtyGraphicsPipelineDesc(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)1720 angle::Result ContextVk::handleDirtyGraphicsPipelineDesc(DirtyBits::Iterator *dirtyBitsIterator,
1721                                                          DirtyBits dirtyBitMask)
1722 {
1723     const VkPipeline previousPipeline = mCurrentGraphicsPipeline
1724                                             ? mCurrentGraphicsPipeline->getPipeline().getHandle()
1725                                             : VK_NULL_HANDLE;
1726 
1727     ASSERT(mState.getProgramExecutable() != nullptr);
1728     const gl::ProgramExecutable &glExecutable = *mState.getProgramExecutable();
1729     ProgramExecutableVk *executableVk         = getExecutable();
1730     ASSERT(executableVk);
1731 
1732     if (!mCurrentGraphicsPipeline)
1733     {
1734         const vk::GraphicsPipelineDesc *descPtr;
1735 
1736         // The desc's specialization constant depends on program's
1737         // specConstUsageBits. We need to update it if program has changed.
1738         SpecConstUsageBits usageBits = getCurrentProgramSpecConstUsageBits();
1739         updateGraphicsPipelineDescWithSpecConstUsageBits(usageBits);
1740 
1741         // Draw call shader patching, shader compilation, and pipeline cache query.
1742         ANGLE_TRY(executableVk->getGraphicsPipeline(this, mCurrentDrawMode, *mGraphicsPipelineDesc,
1743                                                     glExecutable, &descPtr,
1744                                                     &mCurrentGraphicsPipeline));
1745         mGraphicsPipelineTransition.reset();
1746     }
1747     else if (mGraphicsPipelineTransition.any())
1748     {
1749         ASSERT(mCurrentGraphicsPipeline->valid());
1750         if (!mCurrentGraphicsPipeline->findTransition(
1751                 mGraphicsPipelineTransition, *mGraphicsPipelineDesc, &mCurrentGraphicsPipeline))
1752         {
1753             vk::PipelineHelper *oldPipeline = mCurrentGraphicsPipeline;
1754             const vk::GraphicsPipelineDesc *descPtr;
1755 
1756             ANGLE_TRY(executableVk->getGraphicsPipeline(this, mCurrentDrawMode,
1757                                                         *mGraphicsPipelineDesc, glExecutable,
1758                                                         &descPtr, &mCurrentGraphicsPipeline));
1759 
1760             oldPipeline->addTransition(mGraphicsPipelineTransition, descPtr,
1761                                        mCurrentGraphicsPipeline);
1762         }
1763 
1764         mGraphicsPipelineTransition.reset();
1765     }
1766     // Update the queue serial for the pipeline object.
1767     ASSERT(mCurrentGraphicsPipeline && mCurrentGraphicsPipeline->valid());
1768 
1769     mCurrentGraphicsPipeline->retain(&mResourceUseList);
1770 
1771     const VkPipeline newPipeline = mCurrentGraphicsPipeline->getPipeline().getHandle();
1772 
1773     // If there's no change in pipeline, avoid rebinding it later.  If the rebind is due to a new
1774     // command buffer or UtilsVk, it will happen anyway with DIRTY_BIT_PIPELINE_BINDING.
1775     if (newPipeline == previousPipeline)
1776     {
1777         return angle::Result::Continue;
1778     }
1779 
1780     // VK_EXT_transform_feedback disallows binding pipelines while transform feedback is active.
1781     // If a new pipeline needs to be bound, the render pass should necessarily be broken (which
1782     // implicitly pauses transform feedback), as resuming requires a barrier on the transform
1783     // feedback counter buffer.
1784     if (mRenderPassCommands->started() && mRenderPassCommands->isTransformFeedbackActiveUnpaused())
1785     {
1786         ANGLE_TRY(flushDirtyGraphicsRenderPass(
1787             dirtyBitsIterator, dirtyBitMask, RenderPassClosureReason::PipelineBindWhileXfbActive));
1788 
1789         dirtyBitsIterator->setLaterBit(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
1790     }
1791 
1792     // The pipeline needs to rebind because it's changed.
1793     dirtyBitsIterator->setLaterBit(DIRTY_BIT_PIPELINE_BINDING);
1794 
1795     return angle::Result::Continue;
1796 }
1797 
updateRenderPassDepthFeedbackLoopMode(UpdateDepthFeedbackLoopReason depthReason,UpdateDepthFeedbackLoopReason stencilReason)1798 angle::Result ContextVk::updateRenderPassDepthFeedbackLoopMode(
1799     UpdateDepthFeedbackLoopReason depthReason,
1800     UpdateDepthFeedbackLoopReason stencilReason)
1801 {
1802     return updateRenderPassDepthFeedbackLoopModeImpl(nullptr, {}, depthReason, stencilReason);
1803 }
1804 
updateRenderPassDepthFeedbackLoopModeImpl(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask,UpdateDepthFeedbackLoopReason depthReason,UpdateDepthFeedbackLoopReason stencilReason)1805 angle::Result ContextVk::updateRenderPassDepthFeedbackLoopModeImpl(
1806     DirtyBits::Iterator *dirtyBitsIterator,
1807     DirtyBits dirtyBitMask,
1808     UpdateDepthFeedbackLoopReason depthReason,
1809     UpdateDepthFeedbackLoopReason stencilReason)
1810 {
1811     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
1812     if (!hasStartedRenderPass() || drawFramebufferVk->getDepthStencilRenderTarget() == nullptr)
1813     {
1814         return angle::Result::Continue;
1815     }
1816 
1817     const gl::DepthStencilState &dsState = mState.getDepthStencilState();
1818     vk::ResourceAccess depthAccess       = GetDepthAccess(dsState, depthReason);
1819     vk::ResourceAccess stencilAccess     = GetStencilAccess(dsState, stencilReason);
1820 
1821     if ((depthAccess == vk::ResourceAccess::Write || stencilAccess == vk::ResourceAccess::Write) &&
1822         drawFramebufferVk->isReadOnlyDepthFeedbackLoopMode())
1823     {
1824         // If we are switching out of read only mode and we are in feedback loop, we must end
1825         // renderpass here. Otherwise, updating it to writeable layout will produce a writable
1826         // feedback loop that is illegal in vulkan and will trigger validation errors that depth
1827         // texture is using the writable layout.
1828         if (dirtyBitsIterator)
1829         {
1830             ANGLE_TRY(flushDirtyGraphicsRenderPass(
1831                 dirtyBitsIterator, dirtyBitMask,
1832                 RenderPassClosureReason::DepthStencilWriteAfterFeedbackLoop));
1833         }
1834         else
1835         {
1836             ANGLE_TRY(flushCommandsAndEndRenderPass(
1837                 RenderPassClosureReason::DepthStencilWriteAfterFeedbackLoop));
1838         }
1839         // Clear read-only depth feedback mode.
1840         drawFramebufferVk->setReadOnlyDepthFeedbackLoopMode(false);
1841     }
1842 
1843     return angle::Result::Continue;
1844 }
1845 
handleDirtyGraphicsReadOnlyDepthFeedbackLoopMode(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)1846 angle::Result ContextVk::handleDirtyGraphicsReadOnlyDepthFeedbackLoopMode(
1847     DirtyBits::Iterator *dirtyBitsIterator,
1848     DirtyBits dirtyBitMask)
1849 {
1850     return updateRenderPassDepthFeedbackLoopModeImpl(dirtyBitsIterator, dirtyBitMask,
1851                                                      UpdateDepthFeedbackLoopReason::Draw,
1852                                                      UpdateDepthFeedbackLoopReason::Draw);
1853 }
1854 
handleDirtyGraphicsRenderPass(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)1855 angle::Result ContextVk::handleDirtyGraphicsRenderPass(DirtyBits::Iterator *dirtyBitsIterator,
1856                                                        DirtyBits dirtyBitMask)
1857 {
1858     // If the render pass needs to be recreated, close it using the special mid-dirty-bit-handling
1859     // function, so later dirty bits can be set.
1860     if (mRenderPassCommands->started())
1861     {
1862         ANGLE_TRY(flushDirtyGraphicsRenderPass(dirtyBitsIterator,
1863                                                dirtyBitMask & ~DirtyBits{DIRTY_BIT_RENDER_PASS},
1864                                                RenderPassClosureReason::AlreadySpecifiedElsewhere));
1865     }
1866 
1867     FramebufferVk *drawFramebufferVk  = getDrawFramebuffer();
1868     gl::Rectangle scissoredRenderArea = drawFramebufferVk->getRotatedScissoredRenderArea(this);
1869     bool renderPassDescChanged        = false;
1870 
1871     ANGLE_TRY(startRenderPass(scissoredRenderArea, nullptr, &renderPassDescChanged));
1872 
1873     // The render pass desc can change when starting the render pass, for example due to
1874     // multisampled-render-to-texture needs based on loadOps.  In that case, recreate the graphics
1875     // pipeline.
1876     if (renderPassDescChanged)
1877     {
1878         ANGLE_TRY(handleDirtyGraphicsPipelineDesc(dirtyBitsIterator, dirtyBitMask));
1879     }
1880 
1881     return angle::Result::Continue;
1882 }
1883 
handleDirtyGraphicsColorAccess(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)1884 angle::Result ContextVk::handleDirtyGraphicsColorAccess(DirtyBits::Iterator *dirtyBitsIterator,
1885                                                         DirtyBits dirtyBitMask)
1886 {
1887     FramebufferVk *drawFramebufferVk             = getDrawFramebuffer();
1888     const gl::FramebufferState &framebufferState = drawFramebufferVk->getState();
1889 
1890     // Update color attachment accesses
1891     vk::PackedAttachmentIndex colorIndexVk(0);
1892     for (size_t colorIndexGL : framebufferState.getColorAttachmentsMask())
1893     {
1894         if (framebufferState.getEnabledDrawBuffers().test(colorIndexGL))
1895         {
1896             vk::ResourceAccess colorAccess = GetColorAccess(
1897                 mState, framebufferState, drawFramebufferVk->getEmulatedAlphaAttachmentMask(),
1898                 drawFramebufferVk->hasFramebufferFetch(), colorIndexGL);
1899             mRenderPassCommands->onColorAccess(colorIndexVk, colorAccess);
1900         }
1901         ++colorIndexVk;
1902     }
1903 
1904     return angle::Result::Continue;
1905 }
1906 
handleDirtyGraphicsDepthStencilAccess(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)1907 angle::Result ContextVk::handleDirtyGraphicsDepthStencilAccess(
1908     DirtyBits::Iterator *dirtyBitsIterator,
1909     DirtyBits dirtyBitMask)
1910 {
1911     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
1912     if (drawFramebufferVk->getDepthStencilRenderTarget() == nullptr)
1913     {
1914         return angle::Result::Continue;
1915     }
1916 
1917     // Update depth/stencil attachment accesses
1918     const gl::DepthStencilState &dsState = mState.getDepthStencilState();
1919     vk::ResourceAccess depthAccess = GetDepthAccess(dsState, UpdateDepthFeedbackLoopReason::Draw);
1920     vk::ResourceAccess stencilAccess =
1921         GetStencilAccess(dsState, UpdateDepthFeedbackLoopReason::Draw);
1922     mRenderPassCommands->onDepthAccess(depthAccess);
1923     mRenderPassCommands->onStencilAccess(stencilAccess);
1924 
1925     drawFramebufferVk->updateRenderPassReadOnlyDepthMode(this, mRenderPassCommands);
1926 
1927     return angle::Result::Continue;
1928 }
1929 
handleDirtyGraphicsPipelineBinding(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)1930 angle::Result ContextVk::handleDirtyGraphicsPipelineBinding(DirtyBits::Iterator *dirtyBitsIterator,
1931                                                             DirtyBits dirtyBitMask)
1932 {
1933     ASSERT(mCurrentGraphicsPipeline);
1934 
1935     mRenderPassCommandBuffer->bindGraphicsPipeline(mCurrentGraphicsPipeline->getPipeline());
1936 
1937     return angle::Result::Continue;
1938 }
1939 
handleDirtyComputePipelineDesc()1940 angle::Result ContextVk::handleDirtyComputePipelineDesc()
1941 {
1942     if (!mCurrentComputePipeline)
1943     {
1944         ProgramExecutableVk *executableVk = getExecutable();
1945         ASSERT(executableVk);
1946         ANGLE_TRY(executableVk->getComputePipeline(this, &mCurrentComputePipeline));
1947     }
1948 
1949     ASSERT(mComputeDirtyBits.test(DIRTY_BIT_PIPELINE_BINDING));
1950 
1951     return angle::Result::Continue;
1952 }
1953 
handleDirtyComputePipelineBinding()1954 angle::Result ContextVk::handleDirtyComputePipelineBinding()
1955 {
1956     ASSERT(mCurrentComputePipeline);
1957 
1958     mOutsideRenderPassCommands->getCommandBuffer().bindComputePipeline(
1959         mCurrentComputePipeline->getPipeline());
1960     mCurrentComputePipeline->retain(&mResourceUseList);
1961 
1962     return angle::Result::Continue;
1963 }
1964 
1965 template <typename CommandBufferHelperT>
handleDirtyTexturesImpl(CommandBufferHelperT * commandBufferHelper,PipelineType pipelineType)1966 ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
1967     CommandBufferHelperT *commandBufferHelper,
1968     PipelineType pipelineType)
1969 {
1970     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
1971     ASSERT(executable);
1972     const gl::ActiveTextureMask &activeTextures = executable->getActiveSamplersMask();
1973 
1974     for (size_t textureUnit : activeTextures)
1975     {
1976         const vk::TextureUnit &unit = mActiveTextures[textureUnit];
1977         TextureVk *textureVk        = unit.texture;
1978 
1979         // If it's a texture buffer, get the attached buffer.
1980         if (textureVk->getBuffer().get() != nullptr)
1981         {
1982             BufferVk *bufferVk = vk::GetImpl(textureVk->getBuffer().get());
1983             const gl::ShaderBitSet stages =
1984                 executable->getSamplerShaderBitsForTextureUnitIndex(textureUnit);
1985 
1986             OnTextureBufferRead(this, bufferVk, stages, commandBufferHelper);
1987 
1988             textureVk->retainBufferViews(&mResourceUseList);
1989             continue;
1990         }
1991 
1992         // The image should be flushed and ready to use at this point. There may still be
1993         // lingering staged updates in its staging buffer for unused texture mip levels or
1994         // layers. Therefore we can't verify it has no staged updates right here.
1995         vk::ImageHelper &image = textureVk->getImage();
1996 
1997         // Select the appropriate vk::ImageLayout depending on whether the texture is also bound as
1998         // a GL image, and whether the program is a compute or graphics shader.
1999         const vk::ImageLayout imageLayout =
2000             GetImageReadLayout(textureVk, executable, textureUnit, pipelineType);
2001 
2002         // Ensure the image is in the desired layout
2003         commandBufferHelper->imageRead(this, image.getAspectFlags(), imageLayout, &image);
2004     }
2005 
2006     if (executable->hasTextures())
2007     {
2008         ProgramExecutableVk *executableVk = getExecutable();
2009         ANGLE_TRY(executableVk->updateTexturesDescriptorSet(
2010             this, &mUpdateDescriptorSetsBuilder, &mResourceUseList, *executable, mActiveTextures,
2011             mActiveTexturesDesc, mEmulateSeamfulCubeMapSampling));
2012     }
2013 
2014     return angle::Result::Continue;
2015 }
2016 
handleDirtyGraphicsTextures(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2017 angle::Result ContextVk::handleDirtyGraphicsTextures(DirtyBits::Iterator *dirtyBitsIterator,
2018                                                      DirtyBits dirtyBitMask)
2019 {
2020     return handleDirtyTexturesImpl(mRenderPassCommands, PipelineType::Graphics);
2021 }
2022 
handleDirtyComputeTextures()2023 angle::Result ContextVk::handleDirtyComputeTextures()
2024 {
2025     return handleDirtyTexturesImpl(mOutsideRenderPassCommands, PipelineType::Compute);
2026 }
2027 
handleDirtyGraphicsVertexBuffers(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2028 angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(DirtyBits::Iterator *dirtyBitsIterator,
2029                                                           DirtyBits dirtyBitMask)
2030 {
2031     VertexArrayVk *vertexArrayVk = getVertexArray();
2032     uint32_t maxAttrib           = mState.getProgramExecutable()->getMaxActiveAttribLocation();
2033     const gl::AttribArray<VkBuffer> &bufferHandles = vertexArrayVk->getCurrentArrayBufferHandles();
2034     const gl::AttribArray<VkDeviceSize> &bufferOffsets =
2035         vertexArrayVk->getCurrentArrayBufferOffsets();
2036 
2037     mRenderPassCommandBuffer->bindVertexBuffers(0, maxAttrib, bufferHandles.data(),
2038                                                 bufferOffsets.data());
2039 
2040     const gl::AttribArray<vk::BufferHelper *> &arrayBufferResources =
2041         vertexArrayVk->getCurrentArrayBuffers();
2042 
2043     // Mark all active vertex buffers as accessed.
2044     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2045     gl::AttributesMask attribsMask          = executable->getActiveAttribLocationsMask();
2046     for (size_t attribIndex : attribsMask)
2047     {
2048         vk::BufferHelper *arrayBuffer = arrayBufferResources[attribIndex];
2049         if (arrayBuffer)
2050         {
2051             mRenderPassCommands->bufferRead(this, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
2052                                             vk::PipelineStage::VertexInput, arrayBuffer);
2053         }
2054     }
2055 
2056     return angle::Result::Continue;
2057 }
2058 
handleDirtyGraphicsIndexBuffer(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2059 angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(DirtyBits::Iterator *dirtyBitsIterator,
2060                                                         DirtyBits dirtyBitMask)
2061 {
2062     VertexArrayVk *vertexArrayVk         = getVertexArray();
2063     vk::BufferHelper *elementArrayBuffer = vertexArrayVk->getCurrentElementArrayBuffer();
2064     ASSERT(elementArrayBuffer != nullptr);
2065 
2066     VkDeviceSize bufferOffset;
2067     const vk::Buffer &buffer = elementArrayBuffer->getBufferForVertexArray(
2068         this, elementArrayBuffer->getSize(), &bufferOffset);
2069 
2070     mRenderPassCommandBuffer->bindIndexBuffer(buffer, bufferOffset + mCurrentIndexBufferOffset,
2071                                               getVkIndexType(mCurrentDrawElementsType));
2072 
2073     mRenderPassCommands->bufferRead(this, VK_ACCESS_INDEX_READ_BIT, vk::PipelineStage::VertexInput,
2074                                     elementArrayBuffer);
2075 
2076     return angle::Result::Continue;
2077 }
2078 
handleDirtyGraphicsFramebufferFetchBarrier(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2079 angle::Result ContextVk::handleDirtyGraphicsFramebufferFetchBarrier(
2080     DirtyBits::Iterator *dirtyBitsIterator,
2081     DirtyBits dirtyBitMask)
2082 {
2083     VkMemoryBarrier memoryBarrier = {};
2084     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2085     memoryBarrier.srcAccessMask   = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
2086     memoryBarrier.dstAccessMask   = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
2087 
2088     mRenderPassCommandBuffer->pipelineBarrier(
2089         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
2090         GetLocalDependencyFlags(this), 1, &memoryBarrier, 0, nullptr, 0, nullptr);
2091 
2092     return angle::Result::Continue;
2093 }
2094 
handleDirtyGraphicsBlendBarrier(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2095 angle::Result ContextVk::handleDirtyGraphicsBlendBarrier(DirtyBits::Iterator *dirtyBitsIterator,
2096                                                          DirtyBits dirtyBitMask)
2097 {
2098     VkMemoryBarrier memoryBarrier = {};
2099     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2100     memoryBarrier.srcAccessMask   = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
2101     memoryBarrier.dstAccessMask   = VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT;
2102 
2103     mRenderPassCommandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2104                                               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2105                                               GetLocalDependencyFlags(this), 1, &memoryBarrier, 0,
2106                                               nullptr, 0, nullptr);
2107 
2108     return angle::Result::Continue;
2109 }
2110 
2111 template <typename CommandBufferHelperT>
handleDirtyShaderResourcesImpl(CommandBufferHelperT * commandBufferHelper,PipelineType pipelineType)2112 angle::Result ContextVk::handleDirtyShaderResourcesImpl(CommandBufferHelperT *commandBufferHelper,
2113                                                         PipelineType pipelineType)
2114 {
2115     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2116     ASSERT(executable);
2117 
2118     const bool hasImages = executable->hasImages();
2119     const bool hasStorageBuffers =
2120         executable->hasStorageBuffers() || executable->hasAtomicCounterBuffers();
2121     const bool hasUniformBuffers = executable->hasUniformBuffers();
2122 
2123     if (!hasUniformBuffers && !hasStorageBuffers && !hasImages &&
2124         !executable->usesFramebufferFetch())
2125     {
2126         return angle::Result::Continue;
2127     }
2128 
2129     if (hasImages)
2130     {
2131         ANGLE_TRY(updateActiveImages(commandBufferHelper));
2132     }
2133 
2134     handleDirtyShaderBufferResourcesImpl(commandBufferHelper);
2135 
2136     updateShaderResourcesDescriptorDesc(pipelineType);
2137 
2138     ProgramExecutableVk *executableVk = getExecutable();
2139     FramebufferVk *drawFramebufferVk  = getDrawFramebuffer();
2140     ANGLE_TRY(executableVk->updateShaderResourcesDescriptorSet(
2141         this, executable, &mUpdateDescriptorSetsBuilder, &mEmptyBuffer, &mResourceUseList,
2142         drawFramebufferVk, mShaderBuffersDescriptorDesc));
2143 
2144     // Record usage of storage buffers and images in the command buffer to aid handling of
2145     // glMemoryBarrier.
2146     if (hasImages || hasStorageBuffers)
2147     {
2148         commandBufferHelper->setHasShaderStorageOutput();
2149     }
2150 
2151     return angle::Result::Continue;
2152 }
2153 
handleDirtyShaderBufferResourcesImpl(vk::CommandBufferHelperCommon * commandBufferHelper)2154 void ContextVk::handleDirtyShaderBufferResourcesImpl(
2155     vk::CommandBufferHelperCommon *commandBufferHelper)
2156 {
2157     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2158     ASSERT(executable);
2159 
2160     // Process buffer barriers.
2161     for (const gl::ShaderType shaderType : executable->getLinkedShaderStages())
2162     {
2163         const std::vector<gl::InterfaceBlock> &ubos = executable->getUniformBlocks();
2164 
2165         for (const gl::InterfaceBlock &ubo : ubos)
2166         {
2167             const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
2168                 mState.getIndexedUniformBuffer(ubo.binding);
2169 
2170             if (!ubo.isActive(shaderType))
2171             {
2172                 continue;
2173             }
2174 
2175             if (bufferBinding.get() == nullptr)
2176             {
2177                 continue;
2178             }
2179 
2180             BufferVk *bufferVk             = vk::GetImpl(bufferBinding.get());
2181             vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
2182 
2183             commandBufferHelper->bufferRead(this, VK_ACCESS_UNIFORM_READ_BIT,
2184                                             vk::GetPipelineStage(shaderType), &bufferHelper);
2185         }
2186 
2187         const std::vector<gl::InterfaceBlock> &ssbos = executable->getShaderStorageBlocks();
2188         for (const gl::InterfaceBlock &ssbo : ssbos)
2189         {
2190             const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
2191                 mState.getIndexedShaderStorageBuffer(ssbo.binding);
2192 
2193             if (!ssbo.isActive(shaderType))
2194             {
2195                 continue;
2196             }
2197 
2198             if (bufferBinding.get() == nullptr)
2199             {
2200                 continue;
2201             }
2202 
2203             BufferVk *bufferVk             = vk::GetImpl(bufferBinding.get());
2204             vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
2205 
2206             // We set the SHADER_READ_BIT to be conservative.
2207             VkAccessFlags accessFlags = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
2208             commandBufferHelper->bufferWrite(this, accessFlags, vk::GetPipelineStage(shaderType),
2209                                              vk::AliasingMode::Allowed, &bufferHelper);
2210         }
2211 
2212         const std::vector<gl::AtomicCounterBuffer> &acbs = executable->getAtomicCounterBuffers();
2213         for (const gl::AtomicCounterBuffer &atomicCounterBuffer : acbs)
2214         {
2215             uint32_t binding = atomicCounterBuffer.binding;
2216             const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
2217                 mState.getIndexedAtomicCounterBuffer(binding);
2218 
2219             if (bufferBinding.get() == nullptr)
2220             {
2221                 continue;
2222             }
2223 
2224             BufferVk *bufferVk             = vk::GetImpl(bufferBinding.get());
2225             vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
2226 
2227             // We set SHADER_READ_BIT to be conservative.
2228             commandBufferHelper->bufferWrite(
2229                 this, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
2230                 vk::GetPipelineStage(shaderType), vk::AliasingMode::Allowed, &bufferHelper);
2231         }
2232     }
2233 }
2234 
handleDirtyGraphicsShaderResources(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2235 angle::Result ContextVk::handleDirtyGraphicsShaderResources(DirtyBits::Iterator *dirtyBitsIterator,
2236                                                             DirtyBits dirtyBitMask)
2237 {
2238     return handleDirtyShaderResourcesImpl(mRenderPassCommands, PipelineType::Graphics);
2239 }
2240 
handleDirtyComputeShaderResources()2241 angle::Result ContextVk::handleDirtyComputeShaderResources()
2242 {
2243     return handleDirtyShaderResourcesImpl(mOutsideRenderPassCommands, PipelineType::Compute);
2244 }
2245 
handleDirtyGraphicsTransformFeedbackBuffersEmulation(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2246 angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation(
2247     DirtyBits::Iterator *dirtyBitsIterator,
2248     DirtyBits dirtyBitMask)
2249 {
2250     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2251     ASSERT(executable);
2252 
2253     if (!executable->hasTransformFeedbackOutput())
2254     {
2255         return angle::Result::Continue;
2256     }
2257 
2258     TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(mState.getCurrentTransformFeedback());
2259 
2260     if (mState.isTransformFeedbackActiveUnpaused())
2261     {
2262         size_t bufferCount = executable->getTransformFeedbackBufferCount();
2263         const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &bufferHelpers =
2264             transformFeedbackVk->getBufferHelpers();
2265 
2266         for (size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
2267         {
2268             vk::BufferHelper *bufferHelper = bufferHelpers[bufferIndex];
2269             ASSERT(bufferHelper);
2270             mRenderPassCommands->bufferWrite(this, VK_ACCESS_SHADER_WRITE_BIT,
2271                                              vk::PipelineStage::VertexShader,
2272                                              vk::AliasingMode::Disallowed, bufferHelper);
2273         }
2274     }
2275 
2276     // TODO(http://anglebug.com/3570): Need to update to handle Program Pipelines
2277     vk::BufferHelper *uniformBuffer     = mDefaultUniformStorage.getCurrentBuffer();
2278     vk::DescriptorSetDesc xfbBufferDesc = transformFeedbackVk->getTransformFeedbackDesc();
2279     xfbBufferDesc.updateDefaultUniformBuffer(uniformBuffer ? uniformBuffer->getBufferSerial()
2280                                                            : vk::kInvalidBufferSerial);
2281 
2282     ProgramVk *programVk = getProgram();
2283     return programVk->getExecutable().updateUniformsAndXfbDescriptorSet(
2284         this, &mUpdateDescriptorSetsBuilder, &mResourceUseList, &mEmptyBuffer, *executable,
2285         uniformBuffer, xfbBufferDesc, mState.isTransformFeedbackActiveUnpaused(),
2286         transformFeedbackVk);
2287 }
2288 
handleDirtyGraphicsTransformFeedbackBuffersExtension(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2289 angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension(
2290     DirtyBits::Iterator *dirtyBitsIterator,
2291     DirtyBits dirtyBitMask)
2292 {
2293     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2294     ASSERT(executable);
2295 
2296     if (!executable->hasTransformFeedbackOutput() || !mState.isTransformFeedbackActive())
2297     {
2298         return angle::Result::Continue;
2299     }
2300 
2301     TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(mState.getCurrentTransformFeedback());
2302     size_t bufferCount                       = executable->getTransformFeedbackBufferCount();
2303 
2304     const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &buffers =
2305         transformFeedbackVk->getBufferHelpers();
2306     gl::TransformFeedbackBuffersArray<vk::BufferHelper> &counterBuffers =
2307         transformFeedbackVk->getCounterBufferHelpers();
2308 
2309     // Issue necessary barriers for the transform feedback buffers.
2310     for (size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
2311     {
2312         vk::BufferHelper *bufferHelper = buffers[bufferIndex];
2313         ASSERT(bufferHelper);
2314         mRenderPassCommands->bufferWrite(this, VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT,
2315                                          vk::PipelineStage::TransformFeedback,
2316                                          vk::AliasingMode::Disallowed, bufferHelper);
2317     }
2318 
2319     // Issue necessary barriers for the transform feedback counter buffer.  Note that the barrier is
2320     // issued only on the first buffer (which uses a global memory barrier), as all the counter
2321     // buffers of the transform feedback object are used together.  The rest of the buffers are
2322     // simply retained so they don't get deleted too early.
2323     ASSERT(counterBuffers[0].valid());
2324     mRenderPassCommands->bufferWrite(this,
2325                                      VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT |
2326                                          VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT,
2327                                      vk::PipelineStage::TransformFeedback,
2328                                      vk::AliasingMode::Disallowed, &counterBuffers[0]);
2329     for (size_t bufferIndex = 1; bufferIndex < bufferCount; ++bufferIndex)
2330     {
2331         counterBuffers[bufferIndex].retainReadWrite(&getResourceUseList());
2332     }
2333 
2334     const gl::TransformFeedbackBuffersArray<VkBuffer> &bufferHandles =
2335         transformFeedbackVk->getBufferHandles();
2336     const gl::TransformFeedbackBuffersArray<VkDeviceSize> &bufferOffsets =
2337         transformFeedbackVk->getBufferOffsets();
2338     const gl::TransformFeedbackBuffersArray<VkDeviceSize> &bufferSizes =
2339         transformFeedbackVk->getBufferSizes();
2340 
2341     mRenderPassCommandBuffer->bindTransformFeedbackBuffers(
2342         0, static_cast<uint32_t>(bufferCount), bufferHandles.data(), bufferOffsets.data(),
2343         bufferSizes.data());
2344 
2345     if (!mState.isTransformFeedbackActiveUnpaused())
2346     {
2347         return angle::Result::Continue;
2348     }
2349 
2350     // We should have same number of counter buffers as xfb buffers have
2351     const gl::TransformFeedbackBuffersArray<VkBuffer> &counterBufferHandles =
2352         transformFeedbackVk->getCounterBufferHandles();
2353     const gl::TransformFeedbackBuffersArray<VkDeviceSize> &counterBufferOffsets =
2354         transformFeedbackVk->getCounterBufferOffsets();
2355 
2356     bool rebindBuffers = transformFeedbackVk->getAndResetBufferRebindState();
2357 
2358     mRenderPassCommands->beginTransformFeedback(bufferCount, counterBufferHandles.data(),
2359                                                 counterBufferOffsets.data(), rebindBuffers);
2360 
2361     return angle::Result::Continue;
2362 }
2363 
handleDirtyGraphicsTransformFeedbackResume(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2364 angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackResume(
2365     DirtyBits::Iterator *dirtyBitsIterator,
2366     DirtyBits dirtyBitMask)
2367 {
2368     if (mRenderPassCommands->isTransformFeedbackStarted())
2369     {
2370         mRenderPassCommands->resumeTransformFeedback();
2371     }
2372 
2373     ANGLE_TRY(resumeXfbRenderPassQueriesIfActive());
2374 
2375     return angle::Result::Continue;
2376 }
2377 
handleDirtyGraphicsDescriptorSets(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2378 angle::Result ContextVk::handleDirtyGraphicsDescriptorSets(DirtyBits::Iterator *dirtyBitsIterator,
2379                                                            DirtyBits dirtyBitMask)
2380 {
2381     return handleDirtyDescriptorSetsImpl(mRenderPassCommandBuffer, PipelineType::Graphics);
2382 }
2383 
handleDirtyGraphicsUniforms(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2384 angle::Result ContextVk::handleDirtyGraphicsUniforms(DirtyBits::Iterator *dirtyBitsIterator,
2385                                                      DirtyBits dirtyBitMask)
2386 {
2387     dirtyBitsIterator->setLaterBit(DIRTY_BIT_DESCRIPTOR_SETS);
2388     return handleDirtyUniformsImpl();
2389 }
2390 
handleDirtyComputeUniforms()2391 angle::Result ContextVk::handleDirtyComputeUniforms()
2392 {
2393     return handleDirtyUniformsImpl();
2394 }
2395 
handleDirtyUniformsImpl()2396 angle::Result ContextVk::handleDirtyUniformsImpl()
2397 {
2398     ProgramExecutableVk *programExecutableVk = getExecutable();
2399     TransformFeedbackVk *transformFeedbackVk =
2400         vk::SafeGetImpl(mState.getCurrentTransformFeedback());
2401     ANGLE_TRY(programExecutableVk->updateUniforms(
2402         this, &mUpdateDescriptorSetsBuilder, &mResourceUseList, &mEmptyBuffer,
2403         *mState.getProgramExecutable(), &mDefaultUniformStorage,
2404         mState.isTransformFeedbackActiveUnpaused(), transformFeedbackVk));
2405 
2406     return angle::Result::Continue;
2407 }
2408 
handleDirtyGraphicsViewport(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2409 angle::Result ContextVk::handleDirtyGraphicsViewport(DirtyBits::Iterator *dirtyBitsIterator,
2410                                                      DirtyBits dirtyBitMask)
2411 {
2412     mRenderPassCommandBuffer->setViewport(0, 1, &mViewport);
2413     return angle::Result::Continue;
2414 }
2415 
handleDirtyGraphicsScissor(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2416 angle::Result ContextVk::handleDirtyGraphicsScissor(DirtyBits::Iterator *dirtyBitsIterator,
2417                                                     DirtyBits dirtyBitMask)
2418 {
2419     handleDirtyGraphicsScissorImpl(mState.isQueryActive(gl::QueryType::PrimitivesGenerated));
2420     return angle::Result::Continue;
2421 }
2422 
handleDirtyGraphicsScissorImpl(bool isPrimitivesGeneratedQueryActive)2423 void ContextVk::handleDirtyGraphicsScissorImpl(bool isPrimitivesGeneratedQueryActive)
2424 {
2425     // If primitives generated query and rasterizer discard are both active, but the Vulkan
2426     // implementation of the query does not support rasterizer discard, use an empty scissor to
2427     // emulate it.
2428     if (isEmulatingRasterizerDiscardDuringPrimitivesGeneratedQuery(
2429             isPrimitivesGeneratedQueryActive))
2430     {
2431         VkRect2D emptyScissor = {};
2432         mRenderPassCommandBuffer->setScissor(0, 1, &emptyScissor);
2433     }
2434     else
2435     {
2436         mRenderPassCommandBuffer->setScissor(0, 1, &mScissor);
2437     }
2438 }
2439 
handleDirtyComputeDescriptorSets()2440 angle::Result ContextVk::handleDirtyComputeDescriptorSets()
2441 {
2442     return handleDirtyDescriptorSetsImpl(&mOutsideRenderPassCommands->getCommandBuffer(),
2443                                          PipelineType::Compute);
2444 }
2445 
2446 template <typename CommandBufferT>
handleDirtyDescriptorSetsImpl(CommandBufferT * commandBuffer,PipelineType pipelineType)2447 angle::Result ContextVk::handleDirtyDescriptorSetsImpl(CommandBufferT *commandBuffer,
2448                                                        PipelineType pipelineType)
2449 {
2450     // When using Vulkan secondary command buffers, the descriptor sets need to be updated before
2451     // they are bound.
2452     if (!CommandBufferT::ExecutesInline())
2453     {
2454         flushDescriptorSetUpdates();
2455     }
2456 
2457     ProgramExecutableVk *executableVk = getExecutable();
2458     return executableVk->updateDescriptorSets(this, &mResourceUseList, commandBuffer, pipelineType);
2459 }
2460 
syncObjectPerfCounters()2461 void ContextVk::syncObjectPerfCounters()
2462 {
2463     mPerfCounters.descriptorSetCacheTotalSize                = 0;
2464     mPerfCounters.descriptorSetCacheKeySizeBytes             = 0;
2465     mPerfCounters.uniformsAndXfbDescriptorSetCacheHits       = 0;
2466     mPerfCounters.uniformsAndXfbDescriptorSetCacheMisses     = 0;
2467     mPerfCounters.uniformsAndXfbDescriptorSetCacheTotalSize  = 0;
2468     mPerfCounters.textureDescriptorSetCacheHits              = 0;
2469     mPerfCounters.textureDescriptorSetCacheMisses            = 0;
2470     mPerfCounters.textureDescriptorSetCacheTotalSize         = 0;
2471     mPerfCounters.shaderResourcesDescriptorSetCacheHits      = 0;
2472     mPerfCounters.shaderResourcesDescriptorSetCacheMisses    = 0;
2473     mPerfCounters.shaderResourcesDescriptorSetCacheTotalSize = 0;
2474     mPerfCounters.dynamicBufferAllocations                   = 0;
2475 
2476     // ProgramExecutableVk's descriptor set allocations
2477     const gl::ShaderProgramManager &shadersAndPrograms = mState.getShaderProgramManagerForCapture();
2478     const gl::ResourceMap<gl::Program, gl::ShaderProgramID> &programs =
2479         shadersAndPrograms.getProgramsForCaptureAndPerf();
2480     for (const std::pair<GLuint, gl::Program *> &resource : programs)
2481     {
2482         gl::Program *program = resource.second;
2483         if (program->hasLinkingState())
2484         {
2485             continue;
2486         }
2487         ProgramVk *programVk = vk::GetImpl(resource.second);
2488         ProgramExecutablePerfCounters progPerfCounters =
2489             programVk->getExecutable().getDescriptorSetPerfCounters();
2490 
2491         mPerfCounters.uniformsAndXfbDescriptorSetCacheHits +=
2492             progPerfCounters.cacheStats[DescriptorSetIndex::UniformsAndXfb].getHitCount();
2493         mPerfCounters.uniformsAndXfbDescriptorSetCacheMisses +=
2494             progPerfCounters.cacheStats[DescriptorSetIndex::UniformsAndXfb].getMissCount();
2495         mPerfCounters.uniformsAndXfbDescriptorSetCacheTotalSize +=
2496             progPerfCounters.cacheStats[DescriptorSetIndex::UniformsAndXfb].getSize();
2497         mPerfCounters.textureDescriptorSetCacheHits +=
2498             progPerfCounters.cacheStats[DescriptorSetIndex::Texture].getHitCount();
2499         mPerfCounters.textureDescriptorSetCacheMisses +=
2500             progPerfCounters.cacheStats[DescriptorSetIndex::Texture].getMissCount();
2501         mPerfCounters.textureDescriptorSetCacheTotalSize +=
2502             progPerfCounters.cacheStats[DescriptorSetIndex::Texture].getSize();
2503         mPerfCounters.shaderResourcesDescriptorSetCacheHits +=
2504             progPerfCounters.cacheStats[DescriptorSetIndex::ShaderResource].getHitCount();
2505         mPerfCounters.shaderResourcesDescriptorSetCacheMisses +=
2506             progPerfCounters.cacheStats[DescriptorSetIndex::ShaderResource].getMissCount();
2507         mPerfCounters.shaderResourcesDescriptorSetCacheTotalSize +=
2508             progPerfCounters.cacheStats[DescriptorSetIndex::ShaderResource].getSize();
2509 
2510         for (uint32_t keySizeBytes : progPerfCounters.descriptorSetCacheKeySizesBytes)
2511         {
2512             mPerfCounters.descriptorSetCacheKeySizeBytes += keySizeBytes;
2513         }
2514     }
2515 
2516     mPerfCounters.descriptorSetCacheTotalSize +=
2517         mPerfCounters.uniformsAndXfbDescriptorSetCacheTotalSize;
2518     mPerfCounters.descriptorSetCacheTotalSize += mPerfCounters.textureDescriptorSetCacheTotalSize;
2519     mPerfCounters.descriptorSetCacheTotalSize +=
2520         mPerfCounters.shaderResourcesDescriptorSetCacheTotalSize;
2521 
2522     for (const DriverUniformsDescriptorSet &driverSet : mDriverUniforms)
2523     {
2524         mPerfCounters.descriptorSetCacheTotalSize += driverSet.descriptorSetCache.getSize();
2525     }
2526 }
2527 
updateOverlayOnPresent()2528 void ContextVk::updateOverlayOnPresent()
2529 {
2530     const gl::OverlayType *overlay = mState.getOverlay();
2531     ASSERT(overlay->isEnabled());
2532 
2533     syncObjectPerfCounters();
2534 
2535     // Update overlay if active.
2536     {
2537         gl::RunningGraphWidget *renderPassCount =
2538             overlay->getRunningGraphWidget(gl::WidgetId::VulkanRenderPassCount);
2539         renderPassCount->add(mRenderPassCommands->getAndResetCounter());
2540         renderPassCount->next();
2541     }
2542 
2543     {
2544         gl::RunningGraphWidget *writeDescriptorSetCount =
2545             overlay->getRunningGraphWidget(gl::WidgetId::VulkanWriteDescriptorSetCount);
2546         writeDescriptorSetCount->add(mPerfCounters.writeDescriptorSets);
2547         writeDescriptorSetCount->next();
2548     }
2549 
2550     {
2551         gl::RunningGraphWidget *descriptorSetAllocationCount =
2552             overlay->getRunningGraphWidget(gl::WidgetId::VulkanDescriptorSetAllocations);
2553         descriptorSetAllocationCount->add(mPerfCounters.descriptorSetAllocations);
2554         descriptorSetAllocationCount->next();
2555     }
2556 
2557     {
2558         gl::RunningGraphWidget *shaderResourceHitRate =
2559             overlay->getRunningGraphWidget(gl::WidgetId::VulkanShaderResourceDSHitRate);
2560         size_t numCacheAccesses = mPerfCounters.shaderResourcesDescriptorSetCacheHits +
2561                                   mPerfCounters.shaderResourcesDescriptorSetCacheMisses;
2562         if (numCacheAccesses > 0)
2563         {
2564             float hitRateFloat =
2565                 static_cast<float>(mPerfCounters.shaderResourcesDescriptorSetCacheHits) /
2566                 static_cast<float>(numCacheAccesses);
2567             size_t hitRate = static_cast<size_t>(hitRateFloat * 100.0f);
2568             shaderResourceHitRate->add(hitRate);
2569             shaderResourceHitRate->next();
2570         }
2571     }
2572 
2573     {
2574         gl::RunningGraphWidget *dynamicBufferAllocations =
2575             overlay->getRunningGraphWidget(gl::WidgetId::VulkanDynamicBufferAllocations);
2576         dynamicBufferAllocations->next();
2577     }
2578 
2579     {
2580         gl::CountWidget *cacheKeySize =
2581             overlay->getCountWidget(gl::WidgetId::VulkanDescriptorCacheKeySize);
2582         cacheKeySize->reset();
2583         cacheKeySize->add(mPerfCounters.descriptorSetCacheKeySizeBytes);
2584     }
2585 
2586     {
2587         gl::RunningGraphWidget *dynamicBufferAllocations =
2588             overlay->getRunningGraphWidget(gl::WidgetId::VulkanDynamicBufferAllocations);
2589         dynamicBufferAllocations->add(mPerfCounters.dynamicBufferAllocations);
2590     }
2591 }
2592 
addOverlayUsedBuffersCount(vk::CommandBufferHelperCommon * commandBuffer)2593 void ContextVk::addOverlayUsedBuffersCount(vk::CommandBufferHelperCommon *commandBuffer)
2594 {
2595     const gl::OverlayType *overlay = mState.getOverlay();
2596     if (!overlay->isEnabled())
2597     {
2598         return;
2599     }
2600 
2601     gl::RunningHistogramWidget *widget =
2602         overlay->getRunningHistogramWidget(gl::WidgetId::VulkanRenderPassBufferCount);
2603     size_t buffersCount = commandBuffer->getUsedBuffersCount();
2604     if (buffersCount > 0)
2605     {
2606         widget->add(buffersCount);
2607         widget->next();
2608     }
2609 
2610     {
2611         gl::RunningGraphWidget *textureDescriptorCacheSize =
2612             overlay->getRunningGraphWidget(gl::WidgetId::VulkanTextureDescriptorCacheSize);
2613         textureDescriptorCacheSize->add(mPerfCounters.textureDescriptorSetCacheTotalSize);
2614         textureDescriptorCacheSize->next();
2615     }
2616 
2617     {
2618         gl::RunningGraphWidget *uniformDescriptorCacheSize =
2619             overlay->getRunningGraphWidget(gl::WidgetId::VulkanUniformDescriptorCacheSize);
2620         uniformDescriptorCacheSize->add(mPerfCounters.uniformsAndXfbDescriptorSetCacheTotalSize);
2621         uniformDescriptorCacheSize->next();
2622     }
2623 
2624     {
2625         gl::RunningGraphWidget *descriptorCacheSize =
2626             overlay->getRunningGraphWidget(gl::WidgetId::VulkanDescriptorCacheSize);
2627         descriptorCacheSize->add(mPerfCounters.descriptorSetCacheTotalSize);
2628         descriptorCacheSize->next();
2629     }
2630 }
2631 
submitFrame(const vk::Semaphore * signalSemaphore,Serial * submitSerialOut)2632 angle::Result ContextVk::submitFrame(const vk::Semaphore *signalSemaphore, Serial *submitSerialOut)
2633 {
2634     getShareGroupVk()->acquireResourceUseList(
2635         std::move(mOutsideRenderPassCommands->getResourceUseList()));
2636     getShareGroupVk()->acquireResourceUseList(std::move(mResourceUseList));
2637     getShareGroupVk()->acquireResourceUseList(std::move(mRenderPassCommands->getResourceUseList()));
2638 
2639     ANGLE_TRY(submitCommands(signalSemaphore, submitSerialOut));
2640 
2641     onRenderPassFinished(RenderPassClosureReason::AlreadySpecifiedElsewhere);
2642     return angle::Result::Continue;
2643 }
2644 
submitFrameOutsideCommandBufferOnly(Serial * submitSerialOut)2645 angle::Result ContextVk::submitFrameOutsideCommandBufferOnly(Serial *submitSerialOut)
2646 {
2647     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::submitFrameOutsideCommandBufferOnly");
2648     getShareGroupVk()->acquireResourceUseList(
2649         std::move(mOutsideRenderPassCommands->getResourceUseList()));
2650 
2651     return submitCommands(nullptr, submitSerialOut);
2652 }
2653 
submitCommands(const vk::Semaphore * signalSemaphore,Serial * submitSerialOut)2654 angle::Result ContextVk::submitCommands(const vk::Semaphore *signalSemaphore,
2655                                         Serial *submitSerialOut)
2656 {
2657     if (mCurrentWindowSurface)
2658     {
2659         const vk::Semaphore *waitSemaphore =
2660             mCurrentWindowSurface->getAndResetAcquireImageSemaphore();
2661         if (waitSemaphore != nullptr)
2662         {
2663             addWaitSemaphore(waitSemaphore->getHandle(),
2664                              VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
2665         }
2666     }
2667 
2668     if (vk::CommandBufferHelperCommon::kEnableCommandStreamDiagnostics)
2669     {
2670         dumpCommandStreamDiagnostics();
2671     }
2672 
2673     ANGLE_TRY(mRenderer->submitFrame(this, hasProtectedContent(), mContextPriority,
2674                                      std::move(mWaitSemaphores),
2675                                      std::move(mWaitSemaphoreStageMasks), signalSemaphore,
2676                                      std::move(mCurrentGarbage), &mCommandPools, submitSerialOut));
2677 
2678     getShareGroupVk()->releaseResourceUseLists(*submitSerialOut);
2679     // Now that we have processed resourceUseList, some of pending garbage may no longer pending
2680     // and should be moved to garbage list.
2681     mRenderer->cleanupPendingSubmissionGarbage();
2682 
2683     mComputeDirtyBits |= mNewComputeCommandBufferDirtyBits;
2684 
2685     if (mGpuEventsEnabled)
2686     {
2687         ANGLE_TRY(checkCompletedGpuEvents());
2688     }
2689 
2690     mPerfCounters.submittedCommands++;
2691     resetTotalBufferToImageCopySize();
2692 
2693     return angle::Result::Continue;
2694 }
2695 
onCopyUpdate(VkDeviceSize size)2696 angle::Result ContextVk::onCopyUpdate(VkDeviceSize size)
2697 {
2698     mTotalBufferToImageCopySize += size;
2699     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::onCopyUpdate");
2700     // If the copy size exceeds the specified threshold, submit the outside command buffer.
2701     VkDeviceSize copySize = getTotalBufferToImageCopySize();
2702     if (copySize >= kMaxBufferToImageCopySize)
2703     {
2704         ANGLE_TRY(submitOutsideRenderPassCommandsImpl());
2705     }
2706     return angle::Result::Continue;
2707 }
2708 
synchronizeCpuGpuTime()2709 angle::Result ContextVk::synchronizeCpuGpuTime()
2710 {
2711     ASSERT(mGpuEventsEnabled);
2712 
2713     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
2714     ASSERT(platform);
2715 
2716     // To synchronize CPU and GPU times, we need to get the CPU timestamp as close as possible
2717     // to the GPU timestamp.  The process of getting the GPU timestamp is as follows:
2718     //
2719     //             CPU                            GPU
2720     //
2721     //     Record command buffer
2722     //     with timestamp query
2723     //
2724     //     Submit command buffer
2725     //
2726     //     Post-submission work             Begin execution
2727     //
2728     //            ????                    Write timestamp Tgpu
2729     //
2730     //            ????                       End execution
2731     //
2732     //            ????                    Return query results
2733     //
2734     //            ????
2735     //
2736     //       Get query results
2737     //
2738     // The areas of unknown work (????) on the CPU indicate that the CPU may or may not have
2739     // finished post-submission work while the GPU is executing in parallel. With no further
2740     // work, querying CPU timestamps before submission and after getting query results give the
2741     // bounds to Tgpu, which could be quite large.
2742     //
2743     // Using VkEvents, the GPU can be made to wait for the CPU and vice versa, in an effort to
2744     // reduce this range. This function implements the following procedure:
2745     //
2746     //             CPU                            GPU
2747     //
2748     //     Record command buffer
2749     //     with timestamp query
2750     //
2751     //     Submit command buffer
2752     //
2753     //     Post-submission work             Begin execution
2754     //
2755     //            ????                    Set Event GPUReady
2756     //
2757     //    Wait on Event GPUReady         Wait on Event CPUReady
2758     //
2759     //       Get CPU Time Ts             Wait on Event CPUReady
2760     //
2761     //      Set Event CPUReady           Wait on Event CPUReady
2762     //
2763     //      Get CPU Time Tcpu              Get GPU Time Tgpu
2764     //
2765     //    Wait on Event GPUDone            Set Event GPUDone
2766     //
2767     //       Get CPU Time Te                 End Execution
2768     //
2769     //            Idle                    Return query results
2770     //
2771     //      Get query results
2772     //
2773     // If Te-Ts > epsilon, a GPU or CPU interruption can be assumed and the operation can be
2774     // retried.  Once Te-Ts < epsilon, Tcpu can be taken to presumably match Tgpu.  Finding an
2775     // epsilon that's valid for all devices may be difficult, so the loop can be performed only
2776     // a limited number of times and the Tcpu,Tgpu pair corresponding to smallest Te-Ts used for
2777     // calibration.
2778     //
2779     // Note: Once VK_EXT_calibrated_timestamps is ubiquitous, this should be redone.
2780 
2781     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::synchronizeCpuGpuTime");
2782 
2783     // Create a query used to receive the GPU timestamp
2784     vk::QueryHelper timestampQuery;
2785     ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, &timestampQuery, 1));
2786 
2787     // Create the three events
2788     VkEventCreateInfo eventCreateInfo = {};
2789     eventCreateInfo.sType             = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
2790     eventCreateInfo.flags             = 0;
2791 
2792     VkDevice device = getDevice();
2793     vk::DeviceScoped<vk::Event> cpuReady(device), gpuReady(device), gpuDone(device);
2794     ANGLE_VK_TRY(this, cpuReady.get().init(device, eventCreateInfo));
2795     ANGLE_VK_TRY(this, gpuReady.get().init(device, eventCreateInfo));
2796     ANGLE_VK_TRY(this, gpuDone.get().init(device, eventCreateInfo));
2797 
2798     constexpr uint32_t kRetries = 10;
2799 
2800     // Time suffixes used are S for seconds and Cycles for cycles
2801     double tightestRangeS = 1e6f;
2802     double TcpuS          = 0;
2803     uint64_t TgpuCycles   = 0;
2804     for (uint32_t i = 0; i < kRetries; ++i)
2805     {
2806         // Reset the events
2807         ANGLE_VK_TRY(this, cpuReady.get().reset(device));
2808         ANGLE_VK_TRY(this, gpuReady.get().reset(device));
2809         ANGLE_VK_TRY(this, gpuDone.get().reset(device));
2810 
2811         // Record the command buffer
2812         vk::DeviceScoped<vk::PrimaryCommandBuffer> commandBatch(device);
2813         vk::PrimaryCommandBuffer &commandBuffer = commandBatch.get();
2814 
2815         vk::ResourceUseList scratchResourceUseList;
2816 
2817         ANGLE_TRY(mRenderer->getCommandBufferOneOff(this, hasProtectedContent(), &commandBuffer));
2818 
2819         commandBuffer.setEvent(gpuReady.get().getHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
2820         commandBuffer.waitEvents(1, cpuReady.get().ptr(), VK_PIPELINE_STAGE_HOST_BIT,
2821                                  VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, nullptr, 0, nullptr, 0,
2822                                  nullptr);
2823         timestampQuery.writeTimestampToPrimary(this, &commandBuffer);
2824         timestampQuery.retain(&scratchResourceUseList);
2825 
2826         commandBuffer.setEvent(gpuDone.get().getHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
2827 
2828         ANGLE_VK_TRY(this, commandBuffer.end());
2829 
2830         Serial submitSerial;
2831         // vkEvent's are externally synchronized, therefore need work to be submitted before calling
2832         // vkGetEventStatus
2833         ANGLE_TRY(mRenderer->queueSubmitOneOff(
2834             this, std::move(commandBuffer), hasProtectedContent(), mContextPriority, nullptr, 0,
2835             nullptr, vk::SubmitPolicy::EnsureSubmitted, &submitSerial));
2836         scratchResourceUseList.releaseResourceUsesAndUpdateSerials(submitSerial);
2837 
2838         // Wait for GPU to be ready.  This is a short busy wait.
2839         VkResult result = VK_EVENT_RESET;
2840         do
2841         {
2842             result = gpuReady.get().getStatus(device);
2843             if (result != VK_EVENT_SET && result != VK_EVENT_RESET)
2844             {
2845                 ANGLE_VK_TRY(this, result);
2846             }
2847         } while (result == VK_EVENT_RESET);
2848 
2849         double TsS = platform->monotonicallyIncreasingTime(platform);
2850 
2851         // Tell the GPU to go ahead with the timestamp query.
2852         ANGLE_VK_TRY(this, cpuReady.get().set(device));
2853         double cpuTimestampS = platform->monotonicallyIncreasingTime(platform);
2854 
2855         // Wait for GPU to be done.  Another short busy wait.
2856         do
2857         {
2858             result = gpuDone.get().getStatus(device);
2859             if (result != VK_EVENT_SET && result != VK_EVENT_RESET)
2860             {
2861                 ANGLE_VK_TRY(this, result);
2862             }
2863         } while (result == VK_EVENT_RESET);
2864 
2865         double TeS = platform->monotonicallyIncreasingTime(platform);
2866 
2867         // Get the query results
2868         ANGLE_TRY(finishToSerial(submitSerial));
2869 
2870         vk::QueryResult gpuTimestampCycles(1);
2871         ANGLE_TRY(timestampQuery.getUint64Result(this, &gpuTimestampCycles));
2872 
2873         // Use the first timestamp queried as origin.
2874         if (mGpuEventTimestampOrigin == 0)
2875         {
2876             mGpuEventTimestampOrigin =
2877                 gpuTimestampCycles.getResult(vk::QueryResult::kDefaultResultIndex);
2878         }
2879 
2880         // Take these CPU and GPU timestamps if there is better confidence.
2881         double confidenceRangeS = TeS - TsS;
2882         if (confidenceRangeS < tightestRangeS)
2883         {
2884             tightestRangeS = confidenceRangeS;
2885             TcpuS          = cpuTimestampS;
2886             TgpuCycles     = gpuTimestampCycles.getResult(vk::QueryResult::kDefaultResultIndex);
2887         }
2888     }
2889 
2890     mGpuEventQueryPool.freeQuery(this, &timestampQuery);
2891 
2892     // timestampPeriod gives nanoseconds/cycle.
2893     double TgpuS =
2894         (TgpuCycles - mGpuEventTimestampOrigin) *
2895         static_cast<double>(getRenderer()->getPhysicalDeviceProperties().limits.timestampPeriod) /
2896         1'000'000'000.0;
2897 
2898     flushGpuEvents(TgpuS, TcpuS);
2899 
2900     mGpuClockSync.gpuTimestampS = TgpuS;
2901     mGpuClockSync.cpuTimestampS = TcpuS;
2902 
2903     return angle::Result::Continue;
2904 }
2905 
traceGpuEventImpl(vk::OutsideRenderPassCommandBuffer * commandBuffer,char phase,const EventName & name)2906 angle::Result ContextVk::traceGpuEventImpl(vk::OutsideRenderPassCommandBuffer *commandBuffer,
2907                                            char phase,
2908                                            const EventName &name)
2909 {
2910     ASSERT(mGpuEventsEnabled);
2911 
2912     GpuEventQuery gpuEvent;
2913     gpuEvent.name  = name;
2914     gpuEvent.phase = phase;
2915     ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, &gpuEvent.queryHelper, 1));
2916 
2917     gpuEvent.queryHelper.writeTimestamp(this, commandBuffer);
2918 
2919     mInFlightGpuEventQueries.push_back(std::move(gpuEvent));
2920     return angle::Result::Continue;
2921 }
2922 
checkCompletedGpuEvents()2923 angle::Result ContextVk::checkCompletedGpuEvents()
2924 {
2925     ASSERT(mGpuEventsEnabled);
2926 
2927     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
2928     ASSERT(platform);
2929 
2930     int finishedCount = 0;
2931 
2932     Serial lastCompletedSerial = getLastCompletedQueueSerial();
2933 
2934     for (GpuEventQuery &eventQuery : mInFlightGpuEventQueries)
2935     {
2936         // Only check the timestamp query if the submission has finished.
2937         if (eventQuery.queryHelper.usedInRunningCommands(lastCompletedSerial))
2938         {
2939             break;
2940         }
2941 
2942         // See if the results are available.
2943         vk::QueryResult gpuTimestampCycles(1);
2944         bool available = false;
2945         ANGLE_TRY(eventQuery.queryHelper.getUint64ResultNonBlocking(this, &gpuTimestampCycles,
2946                                                                     &available));
2947         if (!available)
2948         {
2949             break;
2950         }
2951 
2952         mGpuEventQueryPool.freeQuery(this, &eventQuery.queryHelper);
2953 
2954         GpuEvent gpuEvent;
2955         gpuEvent.gpuTimestampCycles =
2956             gpuTimestampCycles.getResult(vk::QueryResult::kDefaultResultIndex);
2957         gpuEvent.name  = eventQuery.name;
2958         gpuEvent.phase = eventQuery.phase;
2959 
2960         mGpuEvents.emplace_back(gpuEvent);
2961 
2962         ++finishedCount;
2963     }
2964 
2965     mInFlightGpuEventQueries.erase(mInFlightGpuEventQueries.begin(),
2966                                    mInFlightGpuEventQueries.begin() + finishedCount);
2967 
2968     return angle::Result::Continue;
2969 }
2970 
flushGpuEvents(double nextSyncGpuTimestampS,double nextSyncCpuTimestampS)2971 void ContextVk::flushGpuEvents(double nextSyncGpuTimestampS, double nextSyncCpuTimestampS)
2972 {
2973     if (mGpuEvents.empty())
2974     {
2975         return;
2976     }
2977 
2978     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
2979     ASSERT(platform);
2980 
2981     // Find the slope of the clock drift for adjustment
2982     double lastGpuSyncTimeS  = mGpuClockSync.gpuTimestampS;
2983     double lastGpuSyncDiffS  = mGpuClockSync.cpuTimestampS - mGpuClockSync.gpuTimestampS;
2984     double gpuSyncDriftSlope = 0;
2985 
2986     double nextGpuSyncTimeS = nextSyncGpuTimestampS;
2987     double nextGpuSyncDiffS = nextSyncCpuTimestampS - nextSyncGpuTimestampS;
2988 
2989     // No gpu trace events should have been generated before the clock sync, so if there is no
2990     // "previous" clock sync, there should be no gpu events (i.e. the function early-outs
2991     // above).
2992     ASSERT(mGpuClockSync.gpuTimestampS != std::numeric_limits<double>::max() &&
2993            mGpuClockSync.cpuTimestampS != std::numeric_limits<double>::max());
2994 
2995     gpuSyncDriftSlope =
2996         (nextGpuSyncDiffS - lastGpuSyncDiffS) / (nextGpuSyncTimeS - lastGpuSyncTimeS);
2997 
2998     for (const GpuEvent &gpuEvent : mGpuEvents)
2999     {
3000         double gpuTimestampS =
3001             (gpuEvent.gpuTimestampCycles - mGpuEventTimestampOrigin) *
3002             static_cast<double>(
3003                 getRenderer()->getPhysicalDeviceProperties().limits.timestampPeriod) *
3004             1e-9;
3005 
3006         // Account for clock drift.
3007         gpuTimestampS += lastGpuSyncDiffS + gpuSyncDriftSlope * (gpuTimestampS - lastGpuSyncTimeS);
3008 
3009         // Generate the trace now that the GPU timestamp is available and clock drifts are
3010         // accounted for.
3011         static long long eventId = 1;
3012         static const unsigned char *categoryEnabled =
3013             TRACE_EVENT_API_GET_CATEGORY_ENABLED(platform, "gpu.angle.gpu");
3014         platform->addTraceEvent(platform, gpuEvent.phase, categoryEnabled, gpuEvent.name.data(),
3015                                 eventId++, gpuTimestampS, 0, nullptr, nullptr, nullptr,
3016                                 TRACE_EVENT_FLAG_NONE);
3017     }
3018 
3019     mGpuEvents.clear();
3020 }
3021 
clearAllGarbage()3022 void ContextVk::clearAllGarbage()
3023 {
3024     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::clearAllGarbage");
3025 
3026     // The VMA virtual allocator code has assertion to ensure all sub-ranges are freed before
3027     // virtual block gets freed. We need to ensure all completed garbage objects are actually freed
3028     // to avoid hitting that assertion.
3029     mRenderer->cleanupCompletedCommandsGarbage();
3030 
3031     for (vk::GarbageObject &garbage : mCurrentGarbage)
3032     {
3033         garbage.destroy(mRenderer);
3034     }
3035     mCurrentGarbage.clear();
3036 }
3037 
handleDeviceLost()3038 void ContextVk::handleDeviceLost()
3039 {
3040     (void)mOutsideRenderPassCommands->reset(this);
3041     (void)mRenderPassCommands->reset(this);
3042     mRenderer->handleDeviceLost();
3043     clearAllGarbage();
3044 
3045     mRenderer->notifyDeviceLost();
3046 }
3047 
drawArrays(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count)3048 angle::Result ContextVk::drawArrays(const gl::Context *context,
3049                                     gl::PrimitiveMode mode,
3050                                     GLint first,
3051                                     GLsizei count)
3052 {
3053     uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
3054 
3055     if (mode == gl::PrimitiveMode::LineLoop)
3056     {
3057         uint32_t numIndices;
3058         ANGLE_TRY(setupLineLoopDraw(context, mode, first, count, gl::DrawElementsType::InvalidEnum,
3059                                     nullptr, &numIndices));
3060         vk::LineLoopHelper::Draw(numIndices, 0, mRenderPassCommandBuffer);
3061     }
3062     else
3063     {
3064         ANGLE_TRY(setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum,
3065                             nullptr, mNonIndexedDirtyBitsMask));
3066         mRenderPassCommandBuffer->draw(clampedVertexCount, first);
3067     }
3068 
3069     return angle::Result::Continue;
3070 }
3071 
drawArraysInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instances)3072 angle::Result ContextVk::drawArraysInstanced(const gl::Context *context,
3073                                              gl::PrimitiveMode mode,
3074                                              GLint first,
3075                                              GLsizei count,
3076                                              GLsizei instances)
3077 {
3078     if (mode == gl::PrimitiveMode::LineLoop)
3079     {
3080         uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
3081         uint32_t numIndices;
3082         ANGLE_TRY(setupLineLoopDraw(context, mode, first, clampedVertexCount,
3083                                     gl::DrawElementsType::InvalidEnum, nullptr, &numIndices));
3084         mRenderPassCommandBuffer->drawIndexedInstanced(numIndices, instances);
3085         return angle::Result::Continue;
3086     }
3087 
3088     ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
3089                         nullptr, mNonIndexedDirtyBitsMask));
3090     mRenderPassCommandBuffer->drawInstanced(gl::GetClampedVertexCount<uint32_t>(count), instances,
3091                                             first);
3092     return angle::Result::Continue;
3093 }
3094 
drawArraysInstancedBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instances,GLuint baseInstance)3095 angle::Result ContextVk::drawArraysInstancedBaseInstance(const gl::Context *context,
3096                                                          gl::PrimitiveMode mode,
3097                                                          GLint first,
3098                                                          GLsizei count,
3099                                                          GLsizei instances,
3100                                                          GLuint baseInstance)
3101 {
3102     if (mode == gl::PrimitiveMode::LineLoop)
3103     {
3104         uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
3105         uint32_t numIndices;
3106         ANGLE_TRY(setupLineLoopDraw(context, mode, first, clampedVertexCount,
3107                                     gl::DrawElementsType::InvalidEnum, nullptr, &numIndices));
3108         mRenderPassCommandBuffer->drawIndexedInstancedBaseVertexBaseInstance(numIndices, instances,
3109                                                                              0, 0, baseInstance);
3110         return angle::Result::Continue;
3111     }
3112 
3113     ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
3114                         nullptr, mNonIndexedDirtyBitsMask));
3115     mRenderPassCommandBuffer->drawInstancedBaseInstance(gl::GetClampedVertexCount<uint32_t>(count),
3116                                                         instances, first, baseInstance);
3117     return angle::Result::Continue;
3118 }
3119 
drawElements(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices)3120 angle::Result ContextVk::drawElements(const gl::Context *context,
3121                                       gl::PrimitiveMode mode,
3122                                       GLsizei count,
3123                                       gl::DrawElementsType type,
3124                                       const void *indices)
3125 {
3126     if (mode == gl::PrimitiveMode::LineLoop)
3127     {
3128         uint32_t indexCount;
3129         ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
3130         vk::LineLoopHelper::Draw(indexCount, 0, mRenderPassCommandBuffer);
3131     }
3132     else
3133     {
3134         ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices));
3135         mRenderPassCommandBuffer->drawIndexed(count);
3136     }
3137 
3138     return angle::Result::Continue;
3139 }
3140 
drawElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)3141 angle::Result ContextVk::drawElementsBaseVertex(const gl::Context *context,
3142                                                 gl::PrimitiveMode mode,
3143                                                 GLsizei count,
3144                                                 gl::DrawElementsType type,
3145                                                 const void *indices,
3146                                                 GLint baseVertex)
3147 {
3148     if (mode == gl::PrimitiveMode::LineLoop)
3149     {
3150         uint32_t indexCount;
3151         ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
3152         vk::LineLoopHelper::Draw(indexCount, baseVertex, mRenderPassCommandBuffer);
3153     }
3154     else
3155     {
3156         ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices));
3157         mRenderPassCommandBuffer->drawIndexedBaseVertex(count, baseVertex);
3158     }
3159 
3160     return angle::Result::Continue;
3161 }
3162 
drawElementsInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances)3163 angle::Result ContextVk::drawElementsInstanced(const gl::Context *context,
3164                                                gl::PrimitiveMode mode,
3165                                                GLsizei count,
3166                                                gl::DrawElementsType type,
3167                                                const void *indices,
3168                                                GLsizei instances)
3169 {
3170     if (mode == gl::PrimitiveMode::LineLoop)
3171     {
3172         uint32_t indexCount;
3173         ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
3174         count = indexCount;
3175     }
3176     else
3177     {
3178         ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices));
3179     }
3180 
3181     mRenderPassCommandBuffer->drawIndexedInstanced(count, instances);
3182     return angle::Result::Continue;
3183 }
3184 
drawElementsInstancedBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex)3185 angle::Result ContextVk::drawElementsInstancedBaseVertex(const gl::Context *context,
3186                                                          gl::PrimitiveMode mode,
3187                                                          GLsizei count,
3188                                                          gl::DrawElementsType type,
3189                                                          const void *indices,
3190                                                          GLsizei instances,
3191                                                          GLint baseVertex)
3192 {
3193     if (mode == gl::PrimitiveMode::LineLoop)
3194     {
3195         uint32_t indexCount;
3196         ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
3197         count = indexCount;
3198     }
3199     else
3200     {
3201         ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices));
3202     }
3203 
3204     mRenderPassCommandBuffer->drawIndexedInstancedBaseVertex(count, instances, baseVertex);
3205     return angle::Result::Continue;
3206 }
3207 
drawElementsInstancedBaseVertexBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex,GLuint baseInstance)3208 angle::Result ContextVk::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
3209                                                                      gl::PrimitiveMode mode,
3210                                                                      GLsizei count,
3211                                                                      gl::DrawElementsType type,
3212                                                                      const void *indices,
3213                                                                      GLsizei instances,
3214                                                                      GLint baseVertex,
3215                                                                      GLuint baseInstance)
3216 {
3217     if (mode == gl::PrimitiveMode::LineLoop)
3218     {
3219         uint32_t indexCount;
3220         ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
3221         mRenderPassCommandBuffer->drawIndexedInstancedBaseVertexBaseInstance(
3222             indexCount, instances, 0, baseVertex, baseInstance);
3223         return angle::Result::Continue;
3224     }
3225 
3226     ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices));
3227     mRenderPassCommandBuffer->drawIndexedInstancedBaseVertexBaseInstance(count, instances, 0,
3228                                                                          baseVertex, baseInstance);
3229     return angle::Result::Continue;
3230 }
3231 
drawRangeElements(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices)3232 angle::Result ContextVk::drawRangeElements(const gl::Context *context,
3233                                            gl::PrimitiveMode mode,
3234                                            GLuint start,
3235                                            GLuint end,
3236                                            GLsizei count,
3237                                            gl::DrawElementsType type,
3238                                            const void *indices)
3239 {
3240     return drawElements(context, mode, count, type, indices);
3241 }
3242 
drawRangeElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)3243 angle::Result ContextVk::drawRangeElementsBaseVertex(const gl::Context *context,
3244                                                      gl::PrimitiveMode mode,
3245                                                      GLuint start,
3246                                                      GLuint end,
3247                                                      GLsizei count,
3248                                                      gl::DrawElementsType type,
3249                                                      const void *indices,
3250                                                      GLint baseVertex)
3251 {
3252     return drawElementsBaseVertex(context, mode, count, type, indices, baseVertex);
3253 }
3254 
getDevice() const3255 VkDevice ContextVk::getDevice() const
3256 {
3257     return mRenderer->getDevice();
3258 }
3259 
drawArraysIndirect(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect)3260 angle::Result ContextVk::drawArraysIndirect(const gl::Context *context,
3261                                             gl::PrimitiveMode mode,
3262                                             const void *indirect)
3263 {
3264     return multiDrawArraysIndirectHelper(context, mode, indirect, 1, 0);
3265 }
3266 
drawElementsIndirect(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect)3267 angle::Result ContextVk::drawElementsIndirect(const gl::Context *context,
3268                                               gl::PrimitiveMode mode,
3269                                               gl::DrawElementsType type,
3270                                               const void *indirect)
3271 {
3272     return multiDrawElementsIndirectHelper(context, mode, type, indirect, 1, 0);
3273 }
3274 
multiDrawArrays(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,GLsizei drawcount)3275 angle::Result ContextVk::multiDrawArrays(const gl::Context *context,
3276                                          gl::PrimitiveMode mode,
3277                                          const GLint *firsts,
3278                                          const GLsizei *counts,
3279                                          GLsizei drawcount)
3280 {
3281     return rx::MultiDrawArraysGeneral(this, context, mode, firsts, counts, drawcount);
3282 }
3283 
multiDrawArraysInstanced(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,GLsizei drawcount)3284 angle::Result ContextVk::multiDrawArraysInstanced(const gl::Context *context,
3285                                                   gl::PrimitiveMode mode,
3286                                                   const GLint *firsts,
3287                                                   const GLsizei *counts,
3288                                                   const GLsizei *instanceCounts,
3289                                                   GLsizei drawcount)
3290 {
3291     return rx::MultiDrawArraysInstancedGeneral(this, context, mode, firsts, counts, instanceCounts,
3292                                                drawcount);
3293 }
3294 
multiDrawArraysIndirect(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect,GLsizei drawcount,GLsizei stride)3295 angle::Result ContextVk::multiDrawArraysIndirect(const gl::Context *context,
3296                                                  gl::PrimitiveMode mode,
3297                                                  const void *indirect,
3298                                                  GLsizei drawcount,
3299                                                  GLsizei stride)
3300 {
3301     return multiDrawArraysIndirectHelper(context, mode, indirect, drawcount, stride);
3302 }
3303 
multiDrawArraysIndirectHelper(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect,GLsizei drawcount,GLsizei stride)3304 angle::Result ContextVk::multiDrawArraysIndirectHelper(const gl::Context *context,
3305                                                        gl::PrimitiveMode mode,
3306                                                        const void *indirect,
3307                                                        GLsizei drawcount,
3308                                                        GLsizei stride)
3309 {
3310     VertexArrayVk *vertexArrayVk = getVertexArray();
3311     if (drawcount > 1 && !CanMultiDrawIndirectUseCmd(this, vertexArrayVk, mode, drawcount, stride))
3312     {
3313         return rx::MultiDrawArraysIndirectGeneral(this, context, mode, indirect, drawcount, stride);
3314     }
3315 
3316     // Stride must be a multiple of the size of VkDrawIndirectCommand (stride = 0 is invalid when
3317     // drawcount > 1).
3318     uint32_t vkStride = (stride == 0 && drawcount > 1) ? sizeof(VkDrawIndirectCommand) : stride;
3319 
3320     gl::Buffer *indirectBuffer            = mState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
3321     vk::BufferHelper *currentIndirectBuf  = &vk::GetImpl(indirectBuffer)->getBuffer();
3322     VkDeviceSize currentIndirectBufOffset = reinterpret_cast<VkDeviceSize>(indirect);
3323 
3324     if (vertexArrayVk->getStreamingVertexAttribsMask().any())
3325     {
3326         // Handling instanced vertex attributes is not covered for drawcount > 1.
3327         ASSERT(drawcount <= 1);
3328 
3329         // We have instanced vertex attributes that need to be emulated for Vulkan.
3330         // invalidate any cache and map the buffer so that we can read the indirect data.
3331         // Mapping the buffer will cause a flush.
3332         ANGLE_TRY(currentIndirectBuf->invalidate(mRenderer, 0, sizeof(VkDrawIndirectCommand)));
3333         uint8_t *buffPtr;
3334         ANGLE_TRY(currentIndirectBuf->map(this, &buffPtr));
3335         const VkDrawIndirectCommand *indirectData =
3336             reinterpret_cast<VkDrawIndirectCommand *>(buffPtr + currentIndirectBufOffset);
3337 
3338         ANGLE_TRY(drawArraysInstanced(context, mode, indirectData->firstVertex,
3339                                       indirectData->vertexCount, indirectData->instanceCount));
3340 
3341         currentIndirectBuf->unmap(mRenderer);
3342         return angle::Result::Continue;
3343     }
3344 
3345     if (mode == gl::PrimitiveMode::LineLoop)
3346     {
3347         // Line loop only supports handling at most one indirect parameter.
3348         ASSERT(drawcount <= 1);
3349 
3350         ASSERT(indirectBuffer);
3351         vk::BufferHelper *dstIndirectBuf = nullptr;
3352 
3353         ANGLE_TRY(setupLineLoopIndirectDraw(context, mode, currentIndirectBuf,
3354                                             currentIndirectBufOffset, &dstIndirectBuf));
3355 
3356         mRenderPassCommandBuffer->drawIndexedIndirect(
3357             dstIndirectBuf->getBuffer(), dstIndirectBuf->getOffset(), drawcount, vkStride);
3358         return angle::Result::Continue;
3359     }
3360 
3361     ANGLE_TRY(setupIndirectDraw(context, mode, mNonIndexedDirtyBitsMask, currentIndirectBuf));
3362 
3363     mRenderPassCommandBuffer->drawIndirect(
3364         currentIndirectBuf->getBuffer(), currentIndirectBuf->getOffset() + currentIndirectBufOffset,
3365         drawcount, vkStride);
3366 
3367     return angle::Result::Continue;
3368 }
3369 
multiDrawElements(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,GLsizei drawcount)3370 angle::Result ContextVk::multiDrawElements(const gl::Context *context,
3371                                            gl::PrimitiveMode mode,
3372                                            const GLsizei *counts,
3373                                            gl::DrawElementsType type,
3374                                            const GLvoid *const *indices,
3375                                            GLsizei drawcount)
3376 {
3377     return rx::MultiDrawElementsGeneral(this, context, mode, counts, type, indices, drawcount);
3378 }
3379 
multiDrawElementsInstanced(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,GLsizei drawcount)3380 angle::Result ContextVk::multiDrawElementsInstanced(const gl::Context *context,
3381                                                     gl::PrimitiveMode mode,
3382                                                     const GLsizei *counts,
3383                                                     gl::DrawElementsType type,
3384                                                     const GLvoid *const *indices,
3385                                                     const GLsizei *instanceCounts,
3386                                                     GLsizei drawcount)
3387 {
3388     return rx::MultiDrawElementsInstancedGeneral(this, context, mode, counts, type, indices,
3389                                                  instanceCounts, drawcount);
3390 }
3391 
multiDrawElementsIndirect(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect,GLsizei drawcount,GLsizei stride)3392 angle::Result ContextVk::multiDrawElementsIndirect(const gl::Context *context,
3393                                                    gl::PrimitiveMode mode,
3394                                                    gl::DrawElementsType type,
3395                                                    const void *indirect,
3396                                                    GLsizei drawcount,
3397                                                    GLsizei stride)
3398 {
3399     return multiDrawElementsIndirectHelper(context, mode, type, indirect, drawcount, stride);
3400 }
3401 
multiDrawElementsIndirectHelper(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect,GLsizei drawcount,GLsizei stride)3402 angle::Result ContextVk::multiDrawElementsIndirectHelper(const gl::Context *context,
3403                                                          gl::PrimitiveMode mode,
3404                                                          gl::DrawElementsType type,
3405                                                          const void *indirect,
3406                                                          GLsizei drawcount,
3407                                                          GLsizei stride)
3408 {
3409     VertexArrayVk *vertexArrayVk = getVertexArray();
3410     if (drawcount > 1 && !CanMultiDrawIndirectUseCmd(this, vertexArrayVk, mode, drawcount, stride))
3411     {
3412         return rx::MultiDrawElementsIndirectGeneral(this, context, mode, type, indirect, drawcount,
3413                                                     stride);
3414     }
3415 
3416     // Stride must be a multiple of the size of VkDrawIndexedIndirectCommand (stride = 0 is invalid
3417     // when drawcount > 1).
3418     uint32_t vkStride =
3419         (stride == 0 && drawcount > 1) ? sizeof(VkDrawIndexedIndirectCommand) : stride;
3420 
3421     gl::Buffer *indirectBuffer = mState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
3422     ASSERT(indirectBuffer);
3423     vk::BufferHelper *currentIndirectBuf  = &vk::GetImpl(indirectBuffer)->getBuffer();
3424     VkDeviceSize currentIndirectBufOffset = reinterpret_cast<VkDeviceSize>(indirect);
3425 
3426     // Reset the index buffer offset
3427     mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
3428     mCurrentIndexBufferOffset = 0;
3429 
3430     if (vertexArrayVk->getStreamingVertexAttribsMask().any())
3431     {
3432         // Handling instanced vertex attributes is not covered for drawcount > 1.
3433         ASSERT(drawcount <= 1);
3434 
3435         // We have instanced vertex attributes that need to be emulated for Vulkan.
3436         // invalidate any cache and map the buffer so that we can read the indirect data.
3437         // Mapping the buffer will cause a flush.
3438         ANGLE_TRY(
3439             currentIndirectBuf->invalidate(mRenderer, 0, sizeof(VkDrawIndexedIndirectCommand)));
3440         uint8_t *buffPtr;
3441         ANGLE_TRY(currentIndirectBuf->map(this, &buffPtr));
3442         const VkDrawIndexedIndirectCommand *indirectData =
3443             reinterpret_cast<VkDrawIndexedIndirectCommand *>(buffPtr + currentIndirectBufOffset);
3444 
3445         ANGLE_TRY(drawElementsInstanced(context, mode, indirectData->indexCount, type, nullptr,
3446                                         indirectData->instanceCount));
3447 
3448         currentIndirectBuf->unmap(mRenderer);
3449         return angle::Result::Continue;
3450     }
3451 
3452     if (shouldConvertUint8VkIndexType(type) && mGraphicsDirtyBits[DIRTY_BIT_INDEX_BUFFER])
3453     {
3454         ANGLE_VK_PERF_WARNING(
3455             this, GL_DEBUG_SEVERITY_LOW,
3456             "Potential inefficiency emulating uint8 vertex attributes due to lack "
3457             "of hardware support");
3458 
3459         vk::BufferHelper *dstIndirectBuf;
3460 
3461         ANGLE_TRY(vertexArrayVk->convertIndexBufferIndirectGPU(
3462             this, currentIndirectBuf, currentIndirectBufOffset, &dstIndirectBuf));
3463 
3464         currentIndirectBuf       = dstIndirectBuf;
3465         currentIndirectBufOffset = 0;
3466     }
3467 
3468     if (mode == gl::PrimitiveMode::LineLoop)
3469     {
3470         // Line loop only supports handling at most one indirect parameter.
3471         ASSERT(drawcount <= 1);
3472 
3473         vk::BufferHelper *dstIndirectBuf;
3474 
3475         ANGLE_TRY(setupLineLoopIndexedIndirectDraw(context, mode, type, currentIndirectBuf,
3476                                                    currentIndirectBufOffset, &dstIndirectBuf));
3477 
3478         currentIndirectBuf       = dstIndirectBuf;
3479         currentIndirectBufOffset = 0;
3480     }
3481     else
3482     {
3483         ANGLE_TRY(setupIndexedIndirectDraw(context, mode, type, currentIndirectBuf));
3484     }
3485 
3486     mRenderPassCommandBuffer->drawIndexedIndirect(
3487         currentIndirectBuf->getBuffer(), currentIndirectBuf->getOffset() + currentIndirectBufOffset,
3488         drawcount, vkStride);
3489 
3490     return angle::Result::Continue;
3491 }
3492 
multiDrawArraysInstancedBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,const GLuint * baseInstances,GLsizei drawcount)3493 angle::Result ContextVk::multiDrawArraysInstancedBaseInstance(const gl::Context *context,
3494                                                               gl::PrimitiveMode mode,
3495                                                               const GLint *firsts,
3496                                                               const GLsizei *counts,
3497                                                               const GLsizei *instanceCounts,
3498                                                               const GLuint *baseInstances,
3499                                                               GLsizei drawcount)
3500 {
3501     return rx::MultiDrawArraysInstancedBaseInstanceGeneral(
3502         this, context, mode, firsts, counts, instanceCounts, baseInstances, drawcount);
3503 }
3504 
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)3505 angle::Result ContextVk::multiDrawElementsInstancedBaseVertexBaseInstance(
3506     const gl::Context *context,
3507     gl::PrimitiveMode mode,
3508     const GLsizei *counts,
3509     gl::DrawElementsType type,
3510     const GLvoid *const *indices,
3511     const GLsizei *instanceCounts,
3512     const GLint *baseVertices,
3513     const GLuint *baseInstances,
3514     GLsizei drawcount)
3515 {
3516     return rx::MultiDrawElementsInstancedBaseVertexBaseInstanceGeneral(
3517         this, context, mode, counts, type, indices, instanceCounts, baseVertices, baseInstances,
3518         drawcount);
3519 }
3520 
optimizeRenderPassForPresent(VkFramebuffer framebufferHandle,vk::ImageViewHelper * colorImageView,vk::ImageHelper * colorImage,vk::ImageHelper * colorImageMS,VkPresentModeKHR presentMode,bool * imageResolved)3521 angle::Result ContextVk::optimizeRenderPassForPresent(VkFramebuffer framebufferHandle,
3522                                                       vk::ImageViewHelper *colorImageView,
3523                                                       vk::ImageHelper *colorImage,
3524                                                       vk::ImageHelper *colorImageMS,
3525                                                       VkPresentModeKHR presentMode,
3526                                                       bool *imageResolved)
3527 {
3528     if (!mRenderPassCommands->started())
3529     {
3530         return angle::Result::Continue;
3531     }
3532 
3533     if (framebufferHandle != mRenderPassCommands->getFramebufferHandle())
3534     {
3535         return angle::Result::Continue;
3536     }
3537 
3538     // EGL1.5 spec: The contents of ancillary buffers are always undefined after calling
3539     // eglSwapBuffers
3540     FramebufferVk *drawFramebufferVk         = getDrawFramebuffer();
3541     RenderTargetVk *depthStencilRenderTarget = drawFramebufferVk->getDepthStencilRenderTarget();
3542     if (depthStencilRenderTarget != nullptr)
3543     {
3544         // Change depth/stencil attachment storeOp to DONT_CARE
3545         const gl::DepthStencilState &dsState = mState.getDepthStencilState();
3546         mRenderPassCommands->invalidateRenderPassDepthAttachment(
3547             dsState, mRenderPassCommands->getRenderArea());
3548         mRenderPassCommands->invalidateRenderPassStencilAttachment(
3549             dsState, mRenderPassCommands->getRenderArea());
3550     }
3551 
3552     // Resolve the multisample image
3553     if (colorImageMS->valid())
3554     {
3555         vk::ImageOrBufferViewSubresourceSerial resolveImageViewSerial =
3556             colorImageView->getSubresourceSerial(gl::LevelIndex(0), 1, 0, vk::LayerMode::All,
3557                                                  vk::SrgbDecodeMode::SkipDecode,
3558                                                  gl::SrgbOverride::Default);
3559         ASSERT(resolveImageViewSerial.viewSerial.valid());
3560         drawFramebufferVk->updateColorResolveAttachment(0, resolveImageViewSerial);
3561 
3562         const vk::ImageView *resolveImageView = nullptr;
3563         ANGLE_TRY(colorImageView->getLevelLayerDrawImageView(this, *colorImage, vk::LevelIndex(0),
3564                                                              0, gl::SrgbWriteControlMode::Default,
3565                                                              &resolveImageView));
3566         vk::Framebuffer *newFramebuffer                      = nullptr;
3567         constexpr SwapchainResolveMode kSwapchainResolveMode = SwapchainResolveMode::Enabled;
3568         ANGLE_TRY(drawFramebufferVk->getFramebuffer(this, &newFramebuffer, resolveImageView,
3569                                                     kSwapchainResolveMode));
3570 
3571         vk::RenderPassCommandBufferHelper &commandBufferHelper = getStartedRenderPassCommands();
3572         commandBufferHelper.updateRenderPassForResolve(this, newFramebuffer,
3573                                                        drawFramebufferVk->getRenderPassDesc());
3574 
3575         onImageRenderPassWrite(gl::LevelIndex(0), 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
3576                                vk::ImageLayout::ColorAttachment, colorImage);
3577 
3578         // Invalidate the surface.  See comment in WindowSurfaceVk::doDeferredAcquireNextImage on
3579         // why this is not done when in DEMAND_REFRESH mode.
3580         if (presentMode != VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR)
3581         {
3582             const gl::Rectangle invalidateArea(0, 0, colorImageMS->getExtents().width,
3583                                                colorImageMS->getExtents().height);
3584             commandBufferHelper.invalidateRenderPassColorAttachment(
3585                 mState, 0, vk::PackedAttachmentIndex(0), invalidateArea);
3586         }
3587 
3588         ANGLE_TRY(
3589             flushCommandsAndEndRenderPass(RenderPassClosureReason::AlreadySpecifiedElsewhere));
3590 
3591         // Remove the resolve attachment from the draw framebuffer.
3592         drawFramebufferVk->removeColorResolveAttachment(0);
3593 
3594         *imageResolved = true;
3595 
3596         mPerfCounters.swapchainResolveInSubpass++;
3597     }
3598 
3599     // Use finalLayout instead of extra barrier for layout change to present
3600     if (colorImage != nullptr)
3601     {
3602         mRenderPassCommands->setImageOptimizeForPresent(colorImage);
3603     }
3604     return angle::Result::Continue;
3605 }
3606 
getResetStatus()3607 gl::GraphicsResetStatus ContextVk::getResetStatus()
3608 {
3609     if (mRenderer->isDeviceLost())
3610     {
3611         // TODO(geofflang): It may be possible to track which context caused the device lost and
3612         // return either GL_GUILTY_CONTEXT_RESET or GL_INNOCENT_CONTEXT_RESET.
3613         // http://anglebug.com/2787
3614         return gl::GraphicsResetStatus::UnknownContextReset;
3615     }
3616 
3617     return gl::GraphicsResetStatus::NoError;
3618 }
3619 
insertEventMarker(GLsizei length,const char * marker)3620 angle::Result ContextVk::insertEventMarker(GLsizei length, const char *marker)
3621 {
3622     insertEventMarkerImpl(GL_DEBUG_SOURCE_APPLICATION, marker);
3623     return angle::Result::Continue;
3624 }
3625 
insertEventMarkerImpl(GLenum source,const char * marker)3626 void ContextVk::insertEventMarkerImpl(GLenum source, const char *marker)
3627 {
3628     if (!mRenderer->enableDebugUtils() && !mRenderer->angleDebuggerMode())
3629     {
3630         return;
3631     }
3632 
3633     VkDebugUtilsLabelEXT label;
3634     vk::MakeDebugUtilsLabel(source, marker, &label);
3635 
3636     if (hasStartedRenderPass())
3637     {
3638         mRenderPassCommandBuffer->insertDebugUtilsLabelEXT(label);
3639     }
3640     else
3641     {
3642         mOutsideRenderPassCommands->getCommandBuffer().insertDebugUtilsLabelEXT(label);
3643     }
3644 }
3645 
pushGroupMarker(GLsizei length,const char * marker)3646 angle::Result ContextVk::pushGroupMarker(GLsizei length, const char *marker)
3647 {
3648     return pushDebugGroupImpl(GL_DEBUG_SOURCE_APPLICATION, 0, marker);
3649 }
3650 
popGroupMarker()3651 angle::Result ContextVk::popGroupMarker()
3652 {
3653     return popDebugGroupImpl();
3654 }
3655 
pushDebugGroup(const gl::Context * context,GLenum source,GLuint id,const std::string & message)3656 angle::Result ContextVk::pushDebugGroup(const gl::Context *context,
3657                                         GLenum source,
3658                                         GLuint id,
3659                                         const std::string &message)
3660 {
3661     return pushDebugGroupImpl(source, id, message.c_str());
3662 }
3663 
popDebugGroup(const gl::Context * context)3664 angle::Result ContextVk::popDebugGroup(const gl::Context *context)
3665 {
3666     return popDebugGroupImpl();
3667 }
3668 
pushDebugGroupImpl(GLenum source,GLuint id,const char * message)3669 angle::Result ContextVk::pushDebugGroupImpl(GLenum source, GLuint id, const char *message)
3670 {
3671     if (!mRenderer->enableDebugUtils() && !mRenderer->angleDebuggerMode())
3672     {
3673         return angle::Result::Continue;
3674     }
3675 
3676     VkDebugUtilsLabelEXT label;
3677     vk::MakeDebugUtilsLabel(source, message, &label);
3678 
3679     if (hasStartedRenderPass())
3680     {
3681         mRenderPassCommandBuffer->beginDebugUtilsLabelEXT(label);
3682     }
3683     else
3684     {
3685         mOutsideRenderPassCommands->getCommandBuffer().beginDebugUtilsLabelEXT(label);
3686     }
3687 
3688     return angle::Result::Continue;
3689 }
3690 
popDebugGroupImpl()3691 angle::Result ContextVk::popDebugGroupImpl()
3692 {
3693     if (!mRenderer->enableDebugUtils() && !mRenderer->angleDebuggerMode())
3694     {
3695         return angle::Result::Continue;
3696     }
3697 
3698     if (hasStartedRenderPass())
3699     {
3700         mRenderPassCommandBuffer->endDebugUtilsLabelEXT();
3701     }
3702     else
3703     {
3704         mOutsideRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
3705     }
3706 
3707     return angle::Result::Continue;
3708 }
3709 
logEvent(const char * eventString)3710 void ContextVk::logEvent(const char *eventString)
3711 {
3712     if (!mRenderer->angleDebuggerMode())
3713     {
3714         return;
3715     }
3716 
3717     // Save this event (about an OpenGL ES command being called).
3718     mEventLog.push_back(eventString);
3719 
3720     // Set a dirty bit in order to stay off the "hot path" for when not logging.
3721     mGraphicsDirtyBits.set(DIRTY_BIT_EVENT_LOG);
3722     mComputeDirtyBits.set(DIRTY_BIT_EVENT_LOG);
3723 }
3724 
endEventLog(angle::EntryPoint entryPoint,PipelineType pipelineType)3725 void ContextVk::endEventLog(angle::EntryPoint entryPoint, PipelineType pipelineType)
3726 {
3727     if (!mRenderer->angleDebuggerMode())
3728     {
3729         return;
3730     }
3731 
3732     if (pipelineType == PipelineType::Graphics)
3733     {
3734         ASSERT(mRenderPassCommands);
3735         mRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
3736     }
3737     else
3738     {
3739         ASSERT(pipelineType == PipelineType::Compute);
3740         ASSERT(mOutsideRenderPassCommands);
3741         mOutsideRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
3742     }
3743 }
endEventLogForClearOrQuery()3744 void ContextVk::endEventLogForClearOrQuery()
3745 {
3746     if (!mRenderer->angleDebuggerMode())
3747     {
3748         return;
3749     }
3750 
3751     switch (mQueryEventType)
3752     {
3753         case GraphicsEventCmdBuf::InOutsideCmdBufQueryCmd:
3754             ASSERT(mOutsideRenderPassCommands);
3755             mOutsideRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
3756             break;
3757         case GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd:
3758             ASSERT(mRenderPassCommands);
3759             mRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
3760             break;
3761         case GraphicsEventCmdBuf::NotInQueryCmd:
3762             // The glClear* or gl*Query* command was noop'd or otherwise ended early.  We could
3763             // call handleDirtyEventLogImpl() to start the hierarchy, but it isn't clear which (if
3764             // any) command buffer to use.  We'll just skip processing this command (other than to
3765             // let it stay queued for the next time handleDirtyEventLogImpl() is called.
3766             return;
3767         default:
3768             UNREACHABLE();
3769     }
3770 
3771     mQueryEventType = GraphicsEventCmdBuf::NotInQueryCmd;
3772 }
3773 
handleNoopDrawEvent()3774 angle::Result ContextVk::handleNoopDrawEvent()
3775 {
3776     // Even though this draw call is being no-op'd, we still must handle the dirty event log
3777     return handleDirtyEventLogImpl(mRenderPassCommandBuffer);
3778 }
3779 
handleGraphicsEventLog(GraphicsEventCmdBuf queryEventType)3780 angle::Result ContextVk::handleGraphicsEventLog(GraphicsEventCmdBuf queryEventType)
3781 {
3782     ASSERT(mQueryEventType == GraphicsEventCmdBuf::NotInQueryCmd || mEventLog.empty());
3783     if (!mRenderer->angleDebuggerMode())
3784     {
3785         return angle::Result::Continue;
3786     }
3787 
3788     mQueryEventType = queryEventType;
3789 
3790     switch (mQueryEventType)
3791     {
3792         case GraphicsEventCmdBuf::InOutsideCmdBufQueryCmd:
3793             ASSERT(mOutsideRenderPassCommands);
3794             return handleDirtyEventLogImpl(&mOutsideRenderPassCommands->getCommandBuffer());
3795         case GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd:
3796             ASSERT(mRenderPassCommands);
3797             return handleDirtyEventLogImpl(&mRenderPassCommands->getCommandBuffer());
3798         default:
3799             UNREACHABLE();
3800             return angle::Result::Stop;
3801     }
3802 }
3803 
isViewportFlipEnabledForDrawFBO() const3804 bool ContextVk::isViewportFlipEnabledForDrawFBO() const
3805 {
3806     return mFlipViewportForDrawFramebuffer && mFlipYForCurrentSurface;
3807 }
3808 
isViewportFlipEnabledForReadFBO() const3809 bool ContextVk::isViewportFlipEnabledForReadFBO() const
3810 {
3811     return mFlipViewportForReadFramebuffer;
3812 }
3813 
isRotatedAspectRatioForDrawFBO() const3814 bool ContextVk::isRotatedAspectRatioForDrawFBO() const
3815 {
3816     return IsRotatedAspectRatio(mCurrentRotationDrawFramebuffer);
3817 }
3818 
isRotatedAspectRatioForReadFBO() const3819 bool ContextVk::isRotatedAspectRatioForReadFBO() const
3820 {
3821     return IsRotatedAspectRatio(mCurrentRotationReadFramebuffer);
3822 }
3823 
getRotationDrawFramebuffer() const3824 SurfaceRotation ContextVk::getRotationDrawFramebuffer() const
3825 {
3826     return mCurrentRotationDrawFramebuffer;
3827 }
3828 
getRotationReadFramebuffer() const3829 SurfaceRotation ContextVk::getRotationReadFramebuffer() const
3830 {
3831     return mCurrentRotationReadFramebuffer;
3832 }
3833 
updateColorMasks()3834 void ContextVk::updateColorMasks()
3835 {
3836     const gl::BlendStateExt &blendStateExt = mState.getBlendStateExt();
3837 
3838     mClearColorMasks = blendStateExt.mColorMask;
3839 
3840     FramebufferVk *framebufferVk = vk::GetImpl(mState.getDrawFramebuffer());
3841     mGraphicsPipelineDesc->updateColorWriteMasks(&mGraphicsPipelineTransition, mClearColorMasks,
3842                                                  framebufferVk->getEmulatedAlphaAttachmentMask(),
3843                                                  framebufferVk->getState().getEnabledDrawBuffers());
3844 
3845     onColorAccessChange();
3846 }
3847 
updateBlendFuncsAndEquations()3848 void ContextVk::updateBlendFuncsAndEquations()
3849 {
3850     const gl::BlendStateExt &blendStateExt = mState.getBlendStateExt();
3851 
3852     FramebufferVk *framebufferVk              = vk::GetImpl(mState.getDrawFramebuffer());
3853     mCachedDrawFramebufferColorAttachmentMask = framebufferVk->getState().getEnabledDrawBuffers();
3854 
3855     mGraphicsPipelineDesc->updateBlendFuncs(&mGraphicsPipelineTransition, blendStateExt,
3856                                             mCachedDrawFramebufferColorAttachmentMask);
3857 
3858     mGraphicsPipelineDesc->updateBlendEquations(&mGraphicsPipelineTransition, blendStateExt,
3859                                                 mCachedDrawFramebufferColorAttachmentMask);
3860 }
3861 
updateSampleMaskWithRasterizationSamples(const uint32_t rasterizationSamples)3862 void ContextVk::updateSampleMaskWithRasterizationSamples(const uint32_t rasterizationSamples)
3863 {
3864     // FramebufferVk::syncState could have been the origin for this call, at which point the
3865     // draw FBO may have changed, retrieve the latest draw FBO.
3866     FramebufferVk *drawFramebuffer = vk::GetImpl(mState.getDrawFramebuffer());
3867 
3868     // If sample coverage is enabled, emulate it by generating and applying a mask on top of the
3869     // sample mask.
3870     uint32_t coverageSampleCount = GetCoverageSampleCount(mState, drawFramebuffer);
3871 
3872     static_assert(sizeof(uint32_t) == sizeof(GLbitfield), "Vulkan assumes 32-bit sample masks");
3873     for (uint32_t maskNumber = 0; maskNumber < mState.getMaxSampleMaskWords(); ++maskNumber)
3874     {
3875         uint32_t mask = mState.isSampleMaskEnabled() && rasterizationSamples > 1
3876                             ? mState.getSampleMaskWord(maskNumber)
3877                             : std::numeric_limits<uint32_t>::max();
3878 
3879         ApplySampleCoverage(mState, coverageSampleCount, maskNumber, &mask);
3880 
3881         mGraphicsPipelineDesc->updateSampleMask(&mGraphicsPipelineTransition, maskNumber, mask);
3882     }
3883 }
3884 
getCorrectedViewport(const gl::Rectangle & viewport) const3885 gl::Rectangle ContextVk::getCorrectedViewport(const gl::Rectangle &viewport) const
3886 {
3887     const gl::Caps &caps                   = getCaps();
3888     const VkPhysicalDeviceLimits &limitsVk = mRenderer->getPhysicalDeviceProperties().limits;
3889     const int viewportBoundsRangeLow       = static_cast<int>(limitsVk.viewportBoundsRange[0]);
3890     const int viewportBoundsRangeHigh      = static_cast<int>(limitsVk.viewportBoundsRange[1]);
3891 
3892     // Clamp the viewport values to what Vulkan specifies
3893 
3894     // width must be greater than 0.0 and less than or equal to
3895     // VkPhysicalDeviceLimits::maxViewportDimensions[0]
3896     int correctedWidth = std::min<int>(viewport.width, caps.maxViewportWidth);
3897     correctedWidth     = std::max<int>(correctedWidth, 0);
3898     // height must be greater than 0.0 and less than or equal to
3899     // VkPhysicalDeviceLimits::maxViewportDimensions[1]
3900     int correctedHeight = std::min<int>(viewport.height, caps.maxViewportHeight);
3901     correctedHeight     = std::max<int>(correctedHeight, 0);
3902     // x and y must each be between viewportBoundsRange[0] and viewportBoundsRange[1], inclusive.
3903     // Viewport size cannot be 0 so ensure there is always size for a 1x1 viewport
3904     int correctedX = std::min<int>(viewport.x, viewportBoundsRangeHigh - 1);
3905     correctedX     = std::max<int>(correctedX, viewportBoundsRangeLow);
3906     int correctedY = std::min<int>(viewport.y, viewportBoundsRangeHigh - 1);
3907     correctedY     = std::max<int>(correctedY, viewportBoundsRangeLow);
3908     // x + width must be less than or equal to viewportBoundsRange[1]
3909     if ((correctedX + correctedWidth) > viewportBoundsRangeHigh)
3910     {
3911         correctedWidth = viewportBoundsRangeHigh - correctedX;
3912     }
3913     // y + height must be less than or equal to viewportBoundsRange[1]
3914     if ((correctedY + correctedHeight) > viewportBoundsRangeHigh)
3915     {
3916         correctedHeight = viewportBoundsRangeHigh - correctedY;
3917     }
3918 
3919     return gl::Rectangle(correctedX, correctedY, correctedWidth, correctedHeight);
3920 }
3921 
updateViewport(FramebufferVk * framebufferVk,const gl::Rectangle & viewport,float nearPlane,float farPlane)3922 void ContextVk::updateViewport(FramebufferVk *framebufferVk,
3923                                const gl::Rectangle &viewport,
3924                                float nearPlane,
3925                                float farPlane)
3926 {
3927 
3928     gl::Box fbDimensions        = framebufferVk->getState().getDimensions();
3929     gl::Rectangle correctedRect = getCorrectedViewport(viewport);
3930     gl::Rectangle rotatedRect;
3931     RotateRectangle(getRotationDrawFramebuffer(), false, fbDimensions.width, fbDimensions.height,
3932                     correctedRect, &rotatedRect);
3933 
3934     bool invertViewport =
3935         isViewportFlipEnabledForDrawFBO() && getFeatures().supportsNegativeViewport.enabled;
3936 
3937     gl_vk::GetViewport(
3938         rotatedRect, nearPlane, farPlane, invertViewport,
3939         // If clip space origin is upper left, viewport origin's y value will be offset by the
3940         // height of the viewport when clip space is mapped into screen space.
3941         mState.getClipSpaceOrigin() == gl::ClipSpaceOrigin::UpperLeft,
3942         // If the surface is rotated 90/270 degrees, use the framebuffer's width instead of the
3943         // height for calculating the final viewport.
3944         isRotatedAspectRatioForDrawFBO() ? fbDimensions.width : fbDimensions.height, &mViewport);
3945 
3946     // Ensure viewport is within Vulkan requirements
3947     vk::ClampViewport(&mViewport);
3948 
3949     invalidateGraphicsDriverUniforms();
3950     mGraphicsDirtyBits.set(DIRTY_BIT_VIEWPORT);
3951 }
3952 
updateDepthRange(float nearPlane,float farPlane)3953 void ContextVk::updateDepthRange(float nearPlane, float farPlane)
3954 {
3955     // GLES2.0 Section 2.12.1: Each of n and f are clamped to lie within [0, 1], as are all
3956     // arguments of type clampf.
3957     ASSERT(nearPlane >= 0.0f && nearPlane <= 1.0f);
3958     ASSERT(farPlane >= 0.0f && farPlane <= 1.0f);
3959     mViewport.minDepth = nearPlane;
3960     mViewport.maxDepth = farPlane;
3961 
3962     invalidateGraphicsDriverUniforms();
3963     mGraphicsDirtyBits.set(DIRTY_BIT_VIEWPORT);
3964 }
3965 
updateScissor(const gl::State & glState)3966 void ContextVk::updateScissor(const gl::State &glState)
3967 {
3968     FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer());
3969     gl::Rectangle renderArea     = framebufferVk->getNonRotatedCompleteRenderArea();
3970 
3971     // Clip the render area to the viewport.
3972     gl::Rectangle viewportClippedRenderArea;
3973     if (!gl::ClipRectangle(renderArea, getCorrectedViewport(glState.getViewport()),
3974                            &viewportClippedRenderArea))
3975     {
3976         viewportClippedRenderArea = gl::Rectangle();
3977     }
3978 
3979     gl::Rectangle scissoredArea = ClipRectToScissor(getState(), viewportClippedRenderArea, false);
3980     gl::Rectangle rotatedScissoredArea;
3981     RotateRectangle(getRotationDrawFramebuffer(), isViewportFlipEnabledForDrawFBO(),
3982                     renderArea.width, renderArea.height, scissoredArea, &rotatedScissoredArea);
3983     mScissor = gl_vk::GetRect(rotatedScissoredArea);
3984     mGraphicsDirtyBits.set(DIRTY_BIT_SCISSOR);
3985 
3986     // If the scissor has grown beyond the previous scissoredRenderArea, grow the render pass render
3987     // area.  The only undesirable effect this may have is that if the render area does not cover a
3988     // previously invalidated area, that invalidate will have to be discarded.
3989     if (mRenderPassCommandBuffer &&
3990         !mRenderPassCommands->getRenderArea().encloses(rotatedScissoredArea))
3991     {
3992         ASSERT(mRenderPassCommands->started());
3993         mRenderPassCommands->growRenderArea(this, rotatedScissoredArea);
3994     }
3995 }
3996 
updateDepthStencil(const gl::State & glState)3997 void ContextVk::updateDepthStencil(const gl::State &glState)
3998 {
3999     const gl::DepthStencilState depthStencilState = glState.getDepthStencilState();
4000 
4001     gl::Framebuffer *drawFramebuffer = mState.getDrawFramebuffer();
4002     mGraphicsPipelineDesc->updateDepthTestEnabled(&mGraphicsPipelineTransition, depthStencilState,
4003                                                   drawFramebuffer);
4004     mGraphicsPipelineDesc->updateDepthWriteEnabled(&mGraphicsPipelineTransition, depthStencilState,
4005                                                    drawFramebuffer);
4006     mGraphicsPipelineDesc->updateStencilTestEnabled(&mGraphicsPipelineTransition, depthStencilState,
4007                                                     drawFramebuffer);
4008     mGraphicsPipelineDesc->updateStencilFrontWriteMask(&mGraphicsPipelineTransition,
4009                                                        depthStencilState, drawFramebuffer);
4010     mGraphicsPipelineDesc->updateStencilBackWriteMask(&mGraphicsPipelineTransition,
4011                                                       depthStencilState, drawFramebuffer);
4012 }
4013 
4014 // If the target is a single-sampled target, sampleShading should be disabled, to use Bresenham line
4015 // rasterization feature.
updateSampleShadingWithRasterizationSamples(const uint32_t rasterizationSamples)4016 void ContextVk::updateSampleShadingWithRasterizationSamples(const uint32_t rasterizationSamples)
4017 {
4018     bool sampleShadingEnable =
4019         (rasterizationSamples <= 1 ? false : mState.isSampleShadingEnabled());
4020 
4021     mGraphicsPipelineDesc->updateSampleShading(&mGraphicsPipelineTransition, sampleShadingEnable,
4022                                                mState.getMinSampleShading());
4023 }
4024 
4025 // If the target is switched between a single-sampled and multisample, the dependency related to the
4026 // rasterization sample should be updated.
updateRasterizationSamples(const uint32_t rasterizationSamples)4027 void ContextVk::updateRasterizationSamples(const uint32_t rasterizationSamples)
4028 {
4029     mGraphicsPipelineDesc->updateRasterizationSamples(&mGraphicsPipelineTransition,
4030                                                       rasterizationSamples);
4031     updateSampleShadingWithRasterizationSamples(rasterizationSamples);
4032     updateSampleMaskWithRasterizationSamples(rasterizationSamples);
4033 }
4034 
updateRasterizerDiscardEnabled(bool isPrimitivesGeneratedQueryActive)4035 void ContextVk::updateRasterizerDiscardEnabled(bool isPrimitivesGeneratedQueryActive)
4036 {
4037     // On some devices, when rasterizerDiscardEnable is enabled, the
4038     // VK_EXT_primitives_generated_query as well as the pipeline statistics query used to emulate it
4039     // are non-functional.  For VK_EXT_primitives_generated_query there's a feature bit but not for
4040     // pipeline statistics query.  If the primitives generated query is active (and rasterizer
4041     // discard is not supported), rasterizerDiscardEnable is set to false and the functionality
4042     // is otherwise emulated (by using an empty scissor).
4043 
4044     // If the primitives generated query implementation supports rasterizer discard, just set
4045     // rasterizer discard as requested.  Otherwise disable it.
4046     bool isRasterizerDiscardEnabled   = mState.isRasterizerDiscardEnabled();
4047     bool isEmulatingRasterizerDiscard = isEmulatingRasterizerDiscardDuringPrimitivesGeneratedQuery(
4048         isPrimitivesGeneratedQueryActive);
4049 
4050     mGraphicsPipelineDesc->updateRasterizerDiscardEnabled(
4051         &mGraphicsPipelineTransition, isRasterizerDiscardEnabled && !isEmulatingRasterizerDiscard);
4052 
4053     invalidateCurrentGraphicsPipeline();
4054 
4055     if (!isEmulatingRasterizerDiscard)
4056     {
4057         return;
4058     }
4059 
4060     // If we are emulating rasterizer discard, update the scissor if in render pass.  If not in
4061     // render pass, DIRTY_BIT_SCISSOR will be set when the render pass next starts.
4062     if (hasStartedRenderPass())
4063     {
4064         handleDirtyGraphicsScissorImpl(isPrimitivesGeneratedQueryActive);
4065     }
4066 }
4067 
updateAdvancedBlendEquations(const gl::ProgramExecutable * executable)4068 void ContextVk::updateAdvancedBlendEquations(const gl::ProgramExecutable *executable)
4069 {
4070     if (!getFeatures().emulateAdvancedBlendEquations.enabled || executable == nullptr)
4071     {
4072         return;
4073     }
4074 
4075     // If advanced blend equations is emulated and the program uses advanced equations, update the
4076     // driver uniforms to pass the equation to the shader.
4077     if (executable->getAdvancedBlendEquations().any())
4078     {
4079         invalidateGraphicsDriverUniforms();
4080     }
4081 }
4082 
updateDither()4083 void ContextVk::updateDither()
4084 {
4085     if (!getFeatures().emulateDithering.enabled)
4086     {
4087         return;
4088     }
4089 
4090     FramebufferVk *framebufferVk = vk::GetImpl(mState.getDrawFramebuffer());
4091 
4092     // Dithering in OpenGL is vaguely defined, to the extent that no dithering is also a valid
4093     // dithering algorithm.  Dithering is enabled by default, but emulating it has a non-negligible
4094     // cost.  Similarly to some other GLES drivers, ANGLE enables dithering only on low-bit formats
4095     // where visual banding is particularly common; namely RGBA4444, RGBA5551 and RGB565.
4096     //
4097     // Dithering is emulated in the fragment shader and is controlled by a spec constant.  Every 2
4098     // bits of the spec constant correspond to one attachment, with the value indicating:
4099     //
4100     // - 00: No dithering
4101     // - 01: Dither for RGBA4444
4102     // - 10: Dither for RGBA5551
4103     // - 11: Dither for RGB565
4104     //
4105     uint16_t ditherControl = 0;
4106     if (mState.isDitherEnabled())
4107     {
4108         // As dithering is emulated in the fragment shader itself, there are a number of situations
4109         // that can lead to incorrect blending.  When blend is enabled, dither is not enabled to
4110         // avoid such situations.
4111         const gl::DrawBufferMask attachmentMask =
4112             framebufferVk->getState().getColorAttachmentsMask() &
4113             ~mState.getBlendEnabledDrawBufferMask();
4114         for (size_t colorIndex : attachmentMask)
4115         {
4116             RenderTargetVk *attachment   = framebufferVk->getColorDrawRenderTarget(colorIndex);
4117             const angle::FormatID format = attachment->getImageActualFormatID();
4118 
4119             uint16_t attachmentDitherControl = sh::vk::kDitherControlNoDither;
4120             switch (format)
4121             {
4122                 case angle::FormatID::R4G4B4A4_UNORM:
4123                 case angle::FormatID::B4G4R4A4_UNORM:
4124                     attachmentDitherControl = sh::vk::kDitherControlDither4444;
4125                     break;
4126                 case angle::FormatID::R5G5B5A1_UNORM:
4127                 case angle::FormatID::B5G5R5A1_UNORM:
4128                 case angle::FormatID::A1R5G5B5_UNORM:
4129                     attachmentDitherControl = sh::vk::kDitherControlDither5551;
4130                     break;
4131                 case angle::FormatID::R5G6B5_UNORM:
4132                 case angle::FormatID::B5G6R5_UNORM:
4133                     attachmentDitherControl = sh::vk::kDitherControlDither565;
4134                     break;
4135                 default:
4136                     break;
4137             }
4138 
4139             ditherControl |= static_cast<uint16_t>(attachmentDitherControl << 2 * colorIndex);
4140         }
4141     }
4142 
4143     if (ditherControl != mGraphicsPipelineDesc->getEmulatedDitherControl())
4144     {
4145         mGraphicsPipelineDesc->updateEmulatedDitherControl(&mGraphicsPipelineTransition,
4146                                                            ditherControl);
4147         invalidateCurrentGraphicsPipeline();
4148     }
4149 }
4150 
checkAndUpdateFramebufferFetchStatus(const gl::ProgramExecutable * executable)4151 angle::Result ContextVk::checkAndUpdateFramebufferFetchStatus(
4152     const gl::ProgramExecutable *executable)
4153 {
4154     if (!executable)
4155     {
4156         return angle::Result::Continue;
4157     }
4158 
4159     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
4160     ASSERT(drawFramebufferVk);
4161 
4162     if (drawFramebufferVk->getRenderPassDesc().getFramebufferFetchMode() !=
4163         executable->usesFramebufferFetch())
4164     {
4165         drawFramebufferVk->onSwitchProgramFramebufferFetch(this,
4166                                                            executable->usesFramebufferFetch());
4167         if (executable->usesFramebufferFetch())
4168         {
4169             mRenderer->onFramebufferFetchUsed();
4170 
4171             // When framebuffer fetch is enabled, attachments can be read from even if output is
4172             // masked, so update their access.
4173             onColorAccessChange();
4174         }
4175     }
4176 
4177     return angle::Result::Continue;
4178 }
4179 
invalidateProgramExecutableHelper(const gl::Context * context)4180 angle::Result ContextVk::invalidateProgramExecutableHelper(const gl::Context *context)
4181 {
4182     const gl::State &glState                = context->getState();
4183     const gl::ProgramExecutable *executable = glState.getProgramExecutable();
4184 
4185     if (executable->hasLinkedShaderStage(gl::ShaderType::Compute))
4186     {
4187         invalidateCurrentComputePipeline();
4188     }
4189 
4190     if (executable->hasLinkedShaderStage(gl::ShaderType::Vertex))
4191     {
4192         invalidateCurrentGraphicsPipeline();
4193         // No additional work is needed here. We will update the pipeline desc
4194         // later.
4195         invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask());
4196         invalidateVertexAndIndexBuffers();
4197         bool useVertexBuffer = (executable->getMaxActiveAttribLocation() > 0);
4198         mNonIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer);
4199         mIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer);
4200         mCurrentGraphicsPipeline = nullptr;
4201         mGraphicsPipelineTransition.reset();
4202 
4203         ProgramExecutableVk *executableVk = getExecutable();
4204         ASSERT(executableVk);
4205         executableVk->updateEarlyFragmentTestsOptimization(this, *executable);
4206 
4207         if (getDrawFramebuffer()->getRenderPassDesc().getFramebufferFetchMode() !=
4208             executable->usesFramebufferFetch())
4209         {
4210             ANGLE_TRY(
4211                 flushCommandsAndEndRenderPass(RenderPassClosureReason::FramebufferFetchEmulation));
4212 
4213             ANGLE_TRY(checkAndUpdateFramebufferFetchStatus(executable));
4214         }
4215     }
4216 
4217     return angle::Result::Continue;
4218 }
4219 
syncState(const gl::Context * context,const gl::State::DirtyBits & dirtyBits,const gl::State::DirtyBits & bitMask,gl::Command command)4220 angle::Result ContextVk::syncState(const gl::Context *context,
4221                                    const gl::State::DirtyBits &dirtyBits,
4222                                    const gl::State::DirtyBits &bitMask,
4223                                    gl::Command command)
4224 {
4225     const gl::State &glState                       = context->getState();
4226     const gl::ProgramExecutable *programExecutable = glState.getProgramExecutable();
4227 
4228     if ((dirtyBits & mPipelineDirtyBitsMask).any() &&
4229         (programExecutable == nullptr || command != gl::Command::Dispatch))
4230     {
4231         invalidateCurrentGraphicsPipeline();
4232     }
4233 
4234     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
4235     VertexArrayVk *vertexArrayVk     = getVertexArray();
4236 
4237     for (auto iter = dirtyBits.begin(), endIter = dirtyBits.end(); iter != endIter; ++iter)
4238     {
4239         size_t dirtyBit = *iter;
4240         switch (dirtyBit)
4241         {
4242             case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
4243             case gl::State::DIRTY_BIT_SCISSOR:
4244                 updateScissor(glState);
4245                 break;
4246             case gl::State::DIRTY_BIT_VIEWPORT:
4247             {
4248                 FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer());
4249                 updateViewport(framebufferVk, glState.getViewport(), glState.getNearPlane(),
4250                                glState.getFarPlane());
4251                 // Update the scissor, which will be constrained to the viewport
4252                 updateScissor(glState);
4253                 break;
4254             }
4255             case gl::State::DIRTY_BIT_DEPTH_RANGE:
4256                 updateDepthRange(glState.getNearPlane(), glState.getFarPlane());
4257                 break;
4258             case gl::State::DIRTY_BIT_BLEND_ENABLED:
4259                 mGraphicsPipelineDesc->updateBlendEnabled(&mGraphicsPipelineTransition,
4260                                                           glState.getBlendStateExt().mEnabledMask);
4261                 updateDither();
4262                 break;
4263             case gl::State::DIRTY_BIT_BLEND_COLOR:
4264                 mGraphicsPipelineDesc->updateBlendColor(&mGraphicsPipelineTransition,
4265                                                         glState.getBlendColor());
4266                 break;
4267             case gl::State::DIRTY_BIT_BLEND_FUNCS:
4268                 mGraphicsPipelineDesc->updateBlendFuncs(
4269                     &mGraphicsPipelineTransition, glState.getBlendStateExt(),
4270                     drawFramebufferVk->getState().getColorAttachmentsMask());
4271                 break;
4272             case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
4273                 mGraphicsPipelineDesc->updateBlendEquations(
4274                     &mGraphicsPipelineTransition, glState.getBlendStateExt(),
4275                     drawFramebufferVk->getState().getColorAttachmentsMask());
4276                 updateAdvancedBlendEquations(programExecutable);
4277                 break;
4278             case gl::State::DIRTY_BIT_COLOR_MASK:
4279                 updateColorMasks();
4280                 break;
4281             case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
4282                 mGraphicsPipelineDesc->updateAlphaToCoverageEnable(
4283                     &mGraphicsPipelineTransition, glState.isSampleAlphaToCoverageEnabled());
4284                 static_assert(gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE >
4285                                   gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED,
4286                               "Dirty bit order");
4287                 iter.setLaterBit(gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE);
4288                 break;
4289             case gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED:
4290                 updateSampleMaskWithRasterizationSamples(drawFramebufferVk->getSamples());
4291                 break;
4292             case gl::State::DIRTY_BIT_SAMPLE_COVERAGE:
4293                 updateSampleMaskWithRasterizationSamples(drawFramebufferVk->getSamples());
4294                 break;
4295             case gl::State::DIRTY_BIT_SAMPLE_MASK_ENABLED:
4296                 updateSampleMaskWithRasterizationSamples(drawFramebufferVk->getSamples());
4297                 break;
4298             case gl::State::DIRTY_BIT_SAMPLE_MASK:
4299                 updateSampleMaskWithRasterizationSamples(drawFramebufferVk->getSamples());
4300                 break;
4301             case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
4302             {
4303                 mGraphicsPipelineDesc->updateDepthTestEnabled(&mGraphicsPipelineTransition,
4304                                                               glState.getDepthStencilState(),
4305                                                               glState.getDrawFramebuffer());
4306                 iter.setLaterBit(gl::State::DIRTY_BIT_DEPTH_MASK);
4307                 break;
4308             }
4309             case gl::State::DIRTY_BIT_DEPTH_FUNC:
4310                 mGraphicsPipelineDesc->updateDepthFunc(&mGraphicsPipelineTransition,
4311                                                        glState.getDepthStencilState());
4312                 break;
4313             case gl::State::DIRTY_BIT_DEPTH_MASK:
4314             {
4315                 mGraphicsPipelineDesc->updateDepthWriteEnabled(&mGraphicsPipelineTransition,
4316                                                                glState.getDepthStencilState(),
4317                                                                glState.getDrawFramebuffer());
4318                 onDepthStencilAccessChange();
4319                 break;
4320             }
4321             case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
4322             {
4323                 mGraphicsPipelineDesc->updateStencilTestEnabled(&mGraphicsPipelineTransition,
4324                                                                 glState.getDepthStencilState(),
4325                                                                 glState.getDrawFramebuffer());
4326                 onDepthStencilAccessChange();
4327                 break;
4328             }
4329             case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
4330                 mGraphicsPipelineDesc->updateStencilFrontFuncs(&mGraphicsPipelineTransition,
4331                                                                glState.getStencilRef(),
4332                                                                glState.getDepthStencilState());
4333                 onDepthStencilAccessChange();
4334                 break;
4335             case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
4336                 mGraphicsPipelineDesc->updateStencilBackFuncs(&mGraphicsPipelineTransition,
4337                                                               glState.getStencilBackRef(),
4338                                                               glState.getDepthStencilState());
4339                 onDepthStencilAccessChange();
4340                 break;
4341             case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
4342                 mGraphicsPipelineDesc->updateStencilFrontOps(&mGraphicsPipelineTransition,
4343                                                              glState.getDepthStencilState());
4344                 onDepthStencilAccessChange();
4345                 break;
4346             case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
4347                 mGraphicsPipelineDesc->updateStencilBackOps(&mGraphicsPipelineTransition,
4348                                                             glState.getDepthStencilState());
4349                 onDepthStencilAccessChange();
4350                 break;
4351             case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
4352                 mGraphicsPipelineDesc->updateStencilFrontWriteMask(&mGraphicsPipelineTransition,
4353                                                                    glState.getDepthStencilState(),
4354                                                                    glState.getDrawFramebuffer());
4355                 onDepthStencilAccessChange();
4356                 break;
4357             case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
4358                 mGraphicsPipelineDesc->updateStencilBackWriteMask(&mGraphicsPipelineTransition,
4359                                                                   glState.getDepthStencilState(),
4360                                                                   glState.getDrawFramebuffer());
4361                 onDepthStencilAccessChange();
4362                 break;
4363             case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
4364             case gl::State::DIRTY_BIT_CULL_FACE:
4365                 mGraphicsPipelineDesc->updateCullMode(&mGraphicsPipelineTransition,
4366                                                       glState.getRasterizerState());
4367                 break;
4368             case gl::State::DIRTY_BIT_FRONT_FACE:
4369                 mGraphicsPipelineDesc->updateFrontFace(&mGraphicsPipelineTransition,
4370                                                        glState.getRasterizerState(),
4371                                                        isYFlipEnabledForDrawFBO());
4372                 break;
4373             case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
4374                 mGraphicsPipelineDesc->updatePolygonOffsetFillEnabled(
4375                     &mGraphicsPipelineTransition, glState.isPolygonOffsetFillEnabled());
4376                 break;
4377             case gl::State::DIRTY_BIT_POLYGON_OFFSET:
4378                 mGraphicsPipelineDesc->updatePolygonOffset(&mGraphicsPipelineTransition,
4379                                                            glState.getRasterizerState());
4380                 break;
4381             case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
4382                 updateRasterizerDiscardEnabled(
4383                     mState.isQueryActive(gl::QueryType::PrimitivesGenerated));
4384                 onColorAccessChange();
4385                 break;
4386             case gl::State::DIRTY_BIT_LINE_WIDTH:
4387                 mGraphicsPipelineDesc->updateLineWidth(&mGraphicsPipelineTransition,
4388                                                        glState.getLineWidth());
4389                 break;
4390             case gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED:
4391                 mGraphicsPipelineDesc->updatePrimitiveRestartEnabled(
4392                     &mGraphicsPipelineTransition, glState.isPrimitiveRestartEnabled());
4393                 break;
4394             case gl::State::DIRTY_BIT_CLEAR_COLOR:
4395                 mClearColorValue.color.float32[0] = glState.getColorClearValue().red;
4396                 mClearColorValue.color.float32[1] = glState.getColorClearValue().green;
4397                 mClearColorValue.color.float32[2] = glState.getColorClearValue().blue;
4398                 mClearColorValue.color.float32[3] = glState.getColorClearValue().alpha;
4399                 break;
4400             case gl::State::DIRTY_BIT_CLEAR_DEPTH:
4401                 mClearDepthStencilValue.depthStencil.depth = glState.getDepthClearValue();
4402                 break;
4403             case gl::State::DIRTY_BIT_CLEAR_STENCIL:
4404                 mClearDepthStencilValue.depthStencil.stencil =
4405                     static_cast<uint32_t>(glState.getStencilClearValue());
4406                 break;
4407             case gl::State::DIRTY_BIT_UNPACK_STATE:
4408                 // This is a no-op, it's only important to use the right unpack state when we do
4409                 // setImage or setSubImage in TextureVk, which is plumbed through the frontend
4410                 // call
4411                 break;
4412             case gl::State::DIRTY_BIT_UNPACK_BUFFER_BINDING:
4413                 break;
4414             case gl::State::DIRTY_BIT_PACK_STATE:
4415                 // This is a no-op, its only important to use the right pack state when we do
4416                 // call readPixels later on.
4417                 break;
4418             case gl::State::DIRTY_BIT_PACK_BUFFER_BINDING:
4419                 break;
4420             case gl::State::DIRTY_BIT_DITHER_ENABLED:
4421                 updateDither();
4422                 break;
4423             case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING:
4424                 updateFlipViewportReadFramebuffer(context->getState());
4425                 updateSurfaceRotationReadFramebuffer(glState);
4426                 break;
4427             case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
4428             {
4429                 // FramebufferVk::syncState signals that we should start a new command buffer.
4430                 // But changing the binding can skip FramebufferVk::syncState if the Framebuffer
4431                 // has no dirty bits. Thus we need to explicitly clear the current command
4432                 // buffer to ensure we start a new one. We don't actually close the render pass here
4433                 // as some optimizations in non-draw commands require the render pass to remain
4434                 // open, such as invalidate or blit. Note that we always start a new command buffer
4435                 // because we currently can only support one open RenderPass at a time.
4436                 onRenderPassFinished(RenderPassClosureReason::FramebufferBindingChange);
4437                 if (getFeatures().preferSubmitAtFBOBoundary.enabled)
4438                 {
4439                     // This will behave as if user called glFlush, but the actual flush will be
4440                     // triggered at endRenderPass time.
4441                     mHasDeferredFlush = true;
4442                 }
4443 
4444                 drawFramebufferVk->setReadOnlyDepthFeedbackLoopMode(false);
4445                 updateFlipViewportDrawFramebuffer(glState);
4446                 updateSurfaceRotationDrawFramebuffer(glState);
4447                 SpecConstUsageBits usageBits = getCurrentProgramSpecConstUsageBits();
4448                 updateGraphicsPipelineDescWithSpecConstUsageBits(usageBits);
4449                 updateViewport(drawFramebufferVk, glState.getViewport(), glState.getNearPlane(),
4450                                glState.getFarPlane());
4451                 updateColorMasks();
4452                 updateRasterizationSamples(drawFramebufferVk->getSamples());
4453                 updateRasterizerDiscardEnabled(
4454                     mState.isQueryActive(gl::QueryType::PrimitivesGenerated));
4455 
4456                 mGraphicsPipelineDesc->updateFrontFace(&mGraphicsPipelineTransition,
4457                                                        glState.getRasterizerState(),
4458                                                        isYFlipEnabledForDrawFBO());
4459                 updateScissor(glState);
4460                 updateDepthStencil(glState);
4461                 updateDither();
4462 
4463                 // Clear the blend funcs/equations for color attachment indices that no longer
4464                 // exist.
4465                 gl::DrawBufferMask newColorAttachmentMask =
4466                     drawFramebufferVk->getState().getColorAttachmentsMask();
4467                 mGraphicsPipelineDesc->resetBlendFuncsAndEquations(
4468                     &mGraphicsPipelineTransition, glState.getBlendStateExt(),
4469                     mCachedDrawFramebufferColorAttachmentMask, newColorAttachmentMask);
4470                 mCachedDrawFramebufferColorAttachmentMask = newColorAttachmentMask;
4471 
4472                 mGraphicsPipelineDesc->resetSubpass(&mGraphicsPipelineTransition);
4473                 onDrawFramebufferRenderPassDescChange(drawFramebufferVk, nullptr);
4474 
4475                 // We may need to update the framebuffer's use of fetch to match the in-use program
4476                 ANGLE_TRY(checkAndUpdateFramebufferFetchStatus(glState.getProgramExecutable()));
4477 
4478                 break;
4479             }
4480             case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
4481                 break;
4482             case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
4483             {
4484                 invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask());
4485                 ANGLE_TRY(vertexArrayVk->updateActiveAttribInfo(this));
4486                 ANGLE_TRY(onIndexBufferChange(vertexArrayVk->getCurrentElementArrayBuffer()));
4487                 break;
4488             }
4489             case gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
4490                 break;
4491             case gl::State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING:
4492                 break;
4493             case gl::State::DIRTY_BIT_PROGRAM_BINDING:
4494                 static_assert(
4495                     gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE > gl::State::DIRTY_BIT_PROGRAM_BINDING,
4496                     "Dirty bit order");
4497                 iter.setLaterBit(gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE);
4498                 break;
4499             case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
4500             {
4501                 ASSERT(programExecutable);
4502                 invalidateCurrentDefaultUniforms();
4503                 updateAdvancedBlendEquations(programExecutable);
4504                 getExecutable()->onProgramBind(*programExecutable);
4505                 static_assert(
4506                     gl::State::DIRTY_BIT_TEXTURE_BINDINGS > gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE,
4507                     "Dirty bit order");
4508                 iter.setLaterBit(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
4509                 static_assert(gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING >
4510                                   gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE,
4511                               "Dirty bit order");
4512                 iter.setLaterBit(gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
4513                 ANGLE_TRY(invalidateProgramExecutableHelper(context));
4514                 break;
4515             }
4516             case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
4517             {
4518                 static_assert(
4519                     gl::State::DIRTY_BIT_TEXTURE_BINDINGS > gl::State::DIRTY_BIT_SAMPLER_BINDINGS,
4520                     "Dirty bit order");
4521                 iter.setLaterBit(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
4522                 break;
4523             }
4524             case gl::State::DIRTY_BIT_TEXTURE_BINDINGS:
4525                 ANGLE_TRY(invalidateCurrentTextures(context, command));
4526                 break;
4527             case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
4528                 // Nothing to do.
4529                 break;
4530             case gl::State::DIRTY_BIT_IMAGE_BINDINGS:
4531                 static_assert(gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING >
4532                                   gl::State::DIRTY_BIT_IMAGE_BINDINGS,
4533                               "Dirty bit order");
4534                 iter.setLaterBit(gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
4535                 break;
4536             case gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
4537                 static_assert(gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING >
4538                                   gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING,
4539                               "Dirty bit order");
4540                 iter.setLaterBit(gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
4541                 break;
4542             case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
4543                 static_assert(gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING >
4544                                   gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS,
4545                               "Dirty bit order");
4546                 iter.setLaterBit(gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
4547                 break;
4548             case gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
4549                 ANGLE_TRY(invalidateCurrentShaderResources(command));
4550                 invalidateDriverUniforms();
4551                 break;
4552             case gl::State::DIRTY_BIT_MULTISAMPLING:
4553                 // TODO(syoussefi): this should configure the pipeline to render as if
4554                 // single-sampled, and write the results to all samples of a pixel regardless of
4555                 // coverage. See EXT_multisample_compatibility.  http://anglebug.com/3204
4556                 break;
4557             case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE:
4558                 // TODO(syoussefi): this is part of EXT_multisample_compatibility.  The
4559                 // alphaToOne Vulkan feature should be enabled to support this extension.
4560                 // http://anglebug.com/3204
4561                 mGraphicsPipelineDesc->updateAlphaToOneEnable(&mGraphicsPipelineTransition,
4562                                                               glState.isSampleAlphaToOneEnabled());
4563                 break;
4564             case gl::State::DIRTY_BIT_SAMPLE_SHADING:
4565                 updateSampleShadingWithRasterizationSamples(drawFramebufferVk->getSamples());
4566                 break;
4567             case gl::State::DIRTY_BIT_COVERAGE_MODULATION:
4568                 break;
4569             case gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE:
4570                 break;
4571             case gl::State::DIRTY_BIT_CURRENT_VALUES:
4572             {
4573                 invalidateDefaultAttributes(glState.getAndResetDirtyCurrentValues());
4574                 break;
4575             }
4576             case gl::State::DIRTY_BIT_PROVOKING_VERTEX:
4577                 break;
4578             case gl::State::DIRTY_BIT_EXTENDED:
4579             {
4580                 gl::State::ExtendedDirtyBits extendedDirtyBits =
4581                     glState.getAndResetExtendedDirtyBits();
4582                 for (size_t extendedDirtyBit : extendedDirtyBits)
4583                 {
4584                     switch (extendedDirtyBit)
4585                     {
4586                         case gl::State::ExtendedDirtyBitType::EXTENDED_DIRTY_BIT_CLIP_CONTROL:
4587                             updateViewport(vk::GetImpl(glState.getDrawFramebuffer()),
4588                                            glState.getViewport(), glState.getNearPlane(),
4589                                            glState.getFarPlane());
4590                             // Since we are flipping the y coordinate, update front face state
4591                             mGraphicsPipelineDesc->updateFrontFace(&mGraphicsPipelineTransition,
4592                                                                    glState.getRasterizerState(),
4593                                                                    isYFlipEnabledForDrawFBO());
4594                             updateScissor(glState);
4595 
4596                             // If VK_EXT_depth_clip_control is not enabled, there's nothing needed
4597                             // for depth correction for EXT_clip_control.
4598                             // glState will be used to toggle control path of depth correction code
4599                             // in SPIR-V tranform options.
4600                             if (getFeatures().supportsDepthClipControl.enabled)
4601                             {
4602                                 mGraphicsPipelineDesc->updateDepthClipControl(
4603                                     &mGraphicsPipelineTransition,
4604                                     !glState.isClipControlDepthZeroToOne());
4605                             }
4606                             break;
4607                         case gl::State::ExtendedDirtyBitType::EXTENDED_DIRTY_BIT_CLIP_DISTANCES:
4608                             invalidateGraphicsDriverUniforms();
4609                             break;
4610                         case gl::State::ExtendedDirtyBitType::
4611                             EXTENDED_DIRTY_BIT_MIPMAP_GENERATION_HINT:
4612                             break;
4613                         case gl::State::ExtendedDirtyBitType::
4614                             EXTENDED_DIRTY_BIT_SHADER_DERIVATIVE_HINT:
4615                             break;
4616                         default:
4617                             UNREACHABLE();
4618                     }
4619                 }
4620                 break;
4621             }
4622             case gl::State::DIRTY_BIT_PATCH_VERTICES:
4623                 mGraphicsPipelineDesc->updatePatchVertices(&mGraphicsPipelineTransition,
4624                                                            glState.getPatchVertices());
4625                 break;
4626             default:
4627                 UNREACHABLE();
4628                 break;
4629         }
4630     }
4631 
4632     return angle::Result::Continue;
4633 }
4634 
getGPUDisjoint()4635 GLint ContextVk::getGPUDisjoint()
4636 {
4637     // No extension seems to be available to query this information.
4638     return 0;
4639 }
4640 
getTimestamp()4641 GLint64 ContextVk::getTimestamp()
4642 {
4643     // This function should only be called if timestamp queries are available.
4644     ASSERT(mRenderer->getQueueFamilyProperties().timestampValidBits > 0);
4645 
4646     uint64_t timestamp = 0;
4647 
4648     (void)getTimestamp(&timestamp);
4649 
4650     return static_cast<GLint64>(timestamp);
4651 }
4652 
onMakeCurrent(const gl::Context * context)4653 angle::Result ContextVk::onMakeCurrent(const gl::Context *context)
4654 {
4655     mRenderer->reloadVolkIfNeeded();
4656 
4657     // Flip viewports if the user did not request that the surface is flipped.
4658     egl::Surface *drawSurface = context->getCurrentDrawSurface();
4659     mFlipYForCurrentSurface =
4660         drawSurface != nullptr &&
4661         !IsMaskFlagSet(drawSurface->getOrientation(), EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE);
4662 
4663     if (drawSurface && drawSurface->getType() == EGL_WINDOW_BIT)
4664     {
4665         mCurrentWindowSurface = GetImplAs<WindowSurfaceVk>(drawSurface);
4666     }
4667     else
4668     {
4669         mCurrentWindowSurface = nullptr;
4670     }
4671 
4672     const gl::State &glState = context->getState();
4673     updateFlipViewportDrawFramebuffer(glState);
4674     updateFlipViewportReadFramebuffer(glState);
4675     updateSurfaceRotationDrawFramebuffer(glState);
4676     updateSurfaceRotationReadFramebuffer(glState);
4677 
4678     if (getFeatures().forceDriverUniformOverSpecConst.enabled)
4679     {
4680         invalidateDriverUniforms();
4681     }
4682     else
4683     {
4684         // Force update mGraphicsPipelineDesc
4685         mCurrentGraphicsPipeline = nullptr;
4686         invalidateCurrentGraphicsPipeline();
4687     }
4688 
4689     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
4690     if (executable && executable->hasTransformFeedbackOutput() &&
4691         mState.isTransformFeedbackActive())
4692     {
4693         onTransformFeedbackStateChanged();
4694         if (getFeatures().supportsTransformFeedbackExtension.enabled)
4695         {
4696             mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
4697         }
4698     }
4699 
4700     return angle::Result::Continue;
4701 }
4702 
onUnMakeCurrent(const gl::Context * context)4703 angle::Result ContextVk::onUnMakeCurrent(const gl::Context *context)
4704 {
4705     ANGLE_TRY(flushImpl(nullptr, RenderPassClosureReason::ContextChange));
4706     mCurrentWindowSurface = nullptr;
4707     return angle::Result::Continue;
4708 }
4709 
updateFlipViewportDrawFramebuffer(const gl::State & glState)4710 void ContextVk::updateFlipViewportDrawFramebuffer(const gl::State &glState)
4711 {
4712     // The default framebuffer (originating from the swapchain) is rendered upside-down due to the
4713     // difference in the coordinate systems of Vulkan and GLES.  Rendering upside-down has the
4714     // effect that rendering is done the same way as OpenGL.  The KHR_MAINTENANCE_1 extension is
4715     // subsequently enabled to allow negative viewports.  We inverse rendering to the backbuffer by
4716     // reversing the height of the viewport and increasing Y by the height.  So if the viewport was
4717     // (0, 0, width, height), it becomes (0, height, width, -height).  Unfortunately, when we start
4718     // doing this, we also need to adjust a number of places since the rendering now happens
4719     // upside-down.  Affected places so far:
4720     //
4721     // - readPixels
4722     // - copyTexImage
4723     // - framebuffer blit
4724     // - generating mipmaps
4725     // - Point sprites tests
4726     // - texStorage
4727     gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
4728     mFlipViewportForDrawFramebuffer  = drawFramebuffer->isDefault();
4729 }
4730 
updateFlipViewportReadFramebuffer(const gl::State & glState)4731 void ContextVk::updateFlipViewportReadFramebuffer(const gl::State &glState)
4732 {
4733     gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
4734     mFlipViewportForReadFramebuffer  = readFramebuffer->isDefault();
4735 }
4736 
getCurrentProgramSpecConstUsageBits() const4737 SpecConstUsageBits ContextVk::getCurrentProgramSpecConstUsageBits() const
4738 {
4739     SpecConstUsageBits usageBits;
4740     if (mState.getProgram())
4741     {
4742         usageBits = mState.getProgram()->getState().getSpecConstUsageBits();
4743     }
4744     else if (mState.getProgramPipeline())
4745     {
4746         usageBits = mState.getProgramPipeline()->getState().getSpecConstUsageBits();
4747     }
4748     return usageBits;
4749 }
4750 
updateGraphicsPipelineDescWithSpecConstUsageBits(SpecConstUsageBits usageBits)4751 void ContextVk::updateGraphicsPipelineDescWithSpecConstUsageBits(SpecConstUsageBits usageBits)
4752 {
4753     SurfaceRotation rotationAndFlip = mCurrentRotationDrawFramebuffer;
4754     ASSERT(ToUnderlying(rotationAndFlip) < ToUnderlying(SurfaceRotation::FlippedIdentity));
4755     bool yFlipped =
4756         isViewportFlipEnabledForDrawFBO() && (usageBits.test(sh::vk::SpecConstUsage::YFlip) ||
4757                                               !getFeatures().supportsNegativeViewport.enabled);
4758 
4759     // usageBits are only set when specialization constants are used.  With gl_Position pre-rotation
4760     // handled by the SPIR-V transformer, we need to have this information even when the driver
4761     // uniform path is taken to pre-rotate everything else.
4762     const bool programUsesRotation = usageBits.test(sh::vk::SpecConstUsage::Rotation) ||
4763                                      getFeatures().forceDriverUniformOverSpecConst.enabled;
4764 
4765     // If program is not using rotation at all, we force it to use the Identity or FlippedIdentity
4766     // slot to improve the program cache hit rate
4767     if (!programUsesRotation)
4768     {
4769         rotationAndFlip = yFlipped ? SurfaceRotation::FlippedIdentity : SurfaceRotation::Identity;
4770     }
4771     else if (yFlipped)
4772     {
4773         // DetermineSurfaceRotation() does not encode yflip information. Shader code uses
4774         // SurfaceRotation specialization constant to determine yflip as well. We add yflip
4775         // information to the SurfaceRotation here so the shader does yflip properly.
4776         rotationAndFlip = static_cast<SurfaceRotation>(
4777             ToUnderlying(SurfaceRotation::FlippedIdentity) + ToUnderlying(rotationAndFlip));
4778     }
4779     else
4780     {
4781         // If program is not using yflip, then we just use the non-flipped slot to increase the
4782         // chance of pipeline program cache hit even if drawable is yflipped.
4783     }
4784 
4785     if (rotationAndFlip != mGraphicsPipelineDesc->getSurfaceRotation())
4786     {
4787         // surface rotation are specialization constants, which affects program compilation. When
4788         // rotation changes, we need to update GraphicsPipelineDesc so that the correct pipeline
4789         // program object will be retrieved.
4790         mGraphicsPipelineDesc->updateSurfaceRotation(&mGraphicsPipelineTransition, rotationAndFlip);
4791     }
4792 
4793     if (usageBits.test(sh::vk::SpecConstUsage::DrawableSize))
4794     {
4795         const gl::Box &dimensions = getState().getDrawFramebuffer()->getDimensions();
4796         mGraphicsPipelineDesc->updateDrawableSize(&mGraphicsPipelineTransition, dimensions.width,
4797                                                   dimensions.height);
4798     }
4799     else
4800     {
4801         // Always set specialization constant to 1x1 if it is not used so that pipeline program with
4802         // only drawable size difference will be able to be reused.
4803         mGraphicsPipelineDesc->updateDrawableSize(&mGraphicsPipelineTransition, 1, 1);
4804     }
4805 }
4806 
updateSurfaceRotationDrawFramebuffer(const gl::State & glState)4807 void ContextVk::updateSurfaceRotationDrawFramebuffer(const gl::State &glState)
4808 {
4809     gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
4810     mCurrentRotationDrawFramebuffer =
4811         DetermineSurfaceRotation(drawFramebuffer, mCurrentWindowSurface);
4812 }
4813 
updateSurfaceRotationReadFramebuffer(const gl::State & glState)4814 void ContextVk::updateSurfaceRotationReadFramebuffer(const gl::State &glState)
4815 {
4816     gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
4817     mCurrentRotationReadFramebuffer =
4818         DetermineSurfaceRotation(readFramebuffer, mCurrentWindowSurface);
4819 }
4820 
getNativeCaps() const4821 gl::Caps ContextVk::getNativeCaps() const
4822 {
4823     return mRenderer->getNativeCaps();
4824 }
4825 
getNativeTextureCaps() const4826 const gl::TextureCapsMap &ContextVk::getNativeTextureCaps() const
4827 {
4828     return mRenderer->getNativeTextureCaps();
4829 }
4830 
getNativeExtensions() const4831 const gl::Extensions &ContextVk::getNativeExtensions() const
4832 {
4833     return mRenderer->getNativeExtensions();
4834 }
4835 
getNativeLimitations() const4836 const gl::Limitations &ContextVk::getNativeLimitations() const
4837 {
4838     return mRenderer->getNativeLimitations();
4839 }
4840 
createCompiler()4841 CompilerImpl *ContextVk::createCompiler()
4842 {
4843     return new CompilerVk();
4844 }
4845 
createShader(const gl::ShaderState & state)4846 ShaderImpl *ContextVk::createShader(const gl::ShaderState &state)
4847 {
4848     return new ShaderVk(state);
4849 }
4850 
createProgram(const gl::ProgramState & state)4851 ProgramImpl *ContextVk::createProgram(const gl::ProgramState &state)
4852 {
4853     return new ProgramVk(state);
4854 }
4855 
createFramebuffer(const gl::FramebufferState & state)4856 FramebufferImpl *ContextVk::createFramebuffer(const gl::FramebufferState &state)
4857 {
4858     return FramebufferVk::CreateUserFBO(mRenderer, state);
4859 }
4860 
createTexture(const gl::TextureState & state)4861 TextureImpl *ContextVk::createTexture(const gl::TextureState &state)
4862 {
4863     return new TextureVk(state, mRenderer);
4864 }
4865 
createRenderbuffer(const gl::RenderbufferState & state)4866 RenderbufferImpl *ContextVk::createRenderbuffer(const gl::RenderbufferState &state)
4867 {
4868     return new RenderbufferVk(state);
4869 }
4870 
createBuffer(const gl::BufferState & state)4871 BufferImpl *ContextVk::createBuffer(const gl::BufferState &state)
4872 {
4873     return new BufferVk(state);
4874 }
4875 
createVertexArray(const gl::VertexArrayState & state)4876 VertexArrayImpl *ContextVk::createVertexArray(const gl::VertexArrayState &state)
4877 {
4878     return new VertexArrayVk(this, state);
4879 }
4880 
createQuery(gl::QueryType type)4881 QueryImpl *ContextVk::createQuery(gl::QueryType type)
4882 {
4883     return new QueryVk(type);
4884 }
4885 
createFenceNV()4886 FenceNVImpl *ContextVk::createFenceNV()
4887 {
4888     return new FenceNVVk();
4889 }
4890 
createSync()4891 SyncImpl *ContextVk::createSync()
4892 {
4893     return new SyncVk();
4894 }
4895 
createTransformFeedback(const gl::TransformFeedbackState & state)4896 TransformFeedbackImpl *ContextVk::createTransformFeedback(const gl::TransformFeedbackState &state)
4897 {
4898     return new TransformFeedbackVk(state);
4899 }
4900 
createSampler(const gl::SamplerState & state)4901 SamplerImpl *ContextVk::createSampler(const gl::SamplerState &state)
4902 {
4903     return new SamplerVk(state);
4904 }
4905 
createProgramPipeline(const gl::ProgramPipelineState & state)4906 ProgramPipelineImpl *ContextVk::createProgramPipeline(const gl::ProgramPipelineState &state)
4907 {
4908     return new ProgramPipelineVk(state);
4909 }
4910 
createMemoryObject()4911 MemoryObjectImpl *ContextVk::createMemoryObject()
4912 {
4913     return new MemoryObjectVk();
4914 }
4915 
createSemaphore()4916 SemaphoreImpl *ContextVk::createSemaphore()
4917 {
4918     return new SemaphoreVk();
4919 }
4920 
createOverlay(const gl::OverlayState & state)4921 OverlayImpl *ContextVk::createOverlay(const gl::OverlayState &state)
4922 {
4923     return new OverlayVk(state);
4924 }
4925 
invalidateCurrentDefaultUniforms()4926 void ContextVk::invalidateCurrentDefaultUniforms()
4927 {
4928     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
4929     ASSERT(executable);
4930 
4931     if (executable->hasDefaultUniforms())
4932     {
4933         mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
4934         mComputeDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
4935     }
4936 }
4937 
invalidateCurrentTextures(const gl::Context * context,gl::Command command)4938 angle::Result ContextVk::invalidateCurrentTextures(const gl::Context *context, gl::Command command)
4939 {
4940     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
4941     ASSERT(executable);
4942 
4943     if (executable->hasTextures())
4944     {
4945         mGraphicsDirtyBits |= kTexturesAndDescSetDirtyBits;
4946         mComputeDirtyBits |= kTexturesAndDescSetDirtyBits;
4947 
4948         ANGLE_TRY(updateActiveTextures(context, command));
4949 
4950         // Take care of read-after-write hazards that require implicit synchronization.
4951         if (command == gl::Command::Dispatch)
4952         {
4953             ANGLE_TRY(endRenderPassIfComputeReadAfterAttachmentWrite());
4954         }
4955     }
4956 
4957     return angle::Result::Continue;
4958 }
4959 
invalidateCurrentShaderResources(gl::Command command)4960 angle::Result ContextVk::invalidateCurrentShaderResources(gl::Command command)
4961 {
4962     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
4963     ASSERT(executable);
4964 
4965     const bool hasImages = executable->hasImages();
4966     const bool hasStorageBuffers =
4967         executable->hasStorageBuffers() || executable->hasAtomicCounterBuffers();
4968     const bool hasUniformBuffers = executable->hasUniformBuffers();
4969 
4970     if (hasUniformBuffers || hasStorageBuffers || hasImages || executable->usesFramebufferFetch())
4971     {
4972         mGraphicsDirtyBits |= kResourcesAndDescSetDirtyBits;
4973         mComputeDirtyBits |= kResourcesAndDescSetDirtyBits;
4974     }
4975 
4976     // Take care of read-after-write hazards that require implicit synchronization.
4977     if (hasUniformBuffers && command == gl::Command::Dispatch)
4978     {
4979         ANGLE_TRY(endRenderPassIfComputeReadAfterTransformFeedbackWrite());
4980     }
4981 
4982     // If memory barrier has been issued but the command buffers haven't been flushed, make sure
4983     // they get a chance to do so if necessary on program and storage buffer/image binding change.
4984     const bool hasGLMemoryBarrierIssuedInCommandBuffers =
4985         mOutsideRenderPassCommands->hasGLMemoryBarrierIssued() ||
4986         mRenderPassCommands->hasGLMemoryBarrierIssued();
4987 
4988     if ((hasStorageBuffers || hasImages) && hasGLMemoryBarrierIssuedInCommandBuffers)
4989     {
4990         mGraphicsDirtyBits.set(DIRTY_BIT_MEMORY_BARRIER);
4991         mComputeDirtyBits.set(DIRTY_BIT_MEMORY_BARRIER);
4992     }
4993 
4994     return angle::Result::Continue;
4995 }
4996 
updateShaderResourcesDescriptorDesc(PipelineType pipelineType)4997 void ContextVk::updateShaderResourcesDescriptorDesc(PipelineType pipelineType)
4998 {
4999     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
5000     ASSERT(executable);
5001 
5002     const bool hasStorageBuffers =
5003         executable->hasStorageBuffers() || executable->hasAtomicCounterBuffers();
5004     const bool hasUniformBuffers = executable->hasUniformBuffers();
5005 
5006     if (!hasUniformBuffers && !hasStorageBuffers)
5007     {
5008         return;
5009     }
5010 
5011     mShaderBuffersDescriptorDesc.reset();
5012 
5013     ProgramExecutableVk *executableVk = getExecutable();
5014 
5015     const gl::BufferVector &uniformBuffers = mState.getOffsetBindingPointerUniformBuffers();
5016     bool isDynamicDescriptor               = executableVk->usesDynamicUniformBufferDescriptors();
5017     bool appendOffset                      = !isDynamicDescriptor;
5018     AppendBufferVectorToDesc(&mShaderBuffersDescriptorDesc, uniformBuffers,
5019                              mState.getUniformBuffersMask(), isDynamicDescriptor, appendOffset);
5020 
5021     const gl::BufferVector &shaderStorageBuffers =
5022         mState.getOffsetBindingPointerShaderStorageBuffers();
5023     isDynamicDescriptor = executableVk->usesDynamicShaderStorageBufferDescriptors();
5024     appendOffset        = true;
5025     AppendBufferVectorToDesc(&mShaderBuffersDescriptorDesc, shaderStorageBuffers,
5026                              mState.getShaderStorageBuffersMask(), isDynamicDescriptor,
5027                              appendOffset);
5028 
5029     const gl::BufferVector &atomicCounterBuffers =
5030         mState.getOffsetBindingPointerAtomicCounterBuffers();
5031     isDynamicDescriptor = executableVk->usesDynamicAtomicCounterBufferDescriptors();
5032     appendOffset        = true;
5033     AppendBufferVectorToDesc(&mShaderBuffersDescriptorDesc, atomicCounterBuffers,
5034                              mState.getAtomicCounterBuffersMask(), isDynamicDescriptor,
5035                              appendOffset);
5036 }
5037 
invalidateGraphicsDriverUniforms()5038 void ContextVk::invalidateGraphicsDriverUniforms()
5039 {
5040     mGraphicsDirtyBits |= kDriverUniformsAndBindingDirtyBits;
5041 }
5042 
invalidateDriverUniforms()5043 void ContextVk::invalidateDriverUniforms()
5044 {
5045     mGraphicsDirtyBits |= kDriverUniformsAndBindingDirtyBits;
5046     mComputeDirtyBits |= kDriverUniformsAndBindingDirtyBits;
5047 }
5048 
onFramebufferChange(FramebufferVk * framebufferVk,gl::Command command)5049 angle::Result ContextVk::onFramebufferChange(FramebufferVk *framebufferVk, gl::Command command)
5050 {
5051     // This is called from FramebufferVk::syncState.  Skip these updates if the framebuffer being
5052     // synced is the read framebuffer (which is not equal the draw framebuffer).
5053     if (framebufferVk != vk::GetImpl(mState.getDrawFramebuffer()))
5054     {
5055         return angle::Result::Continue;
5056     }
5057 
5058     // Always consider the render pass finished.  FramebufferVk::syncState (caller of this function)
5059     // normally closes the render pass, except for blit to allow an optimization.  The following
5060     // code nevertheless must treat the render pass closed.
5061     onRenderPassFinished(RenderPassClosureReason::FramebufferChange);
5062 
5063     // Ensure that the pipeline description is updated.
5064     if (mGraphicsPipelineDesc->getRasterizationSamples() !=
5065         static_cast<uint32_t>(framebufferVk->getSamples()))
5066     {
5067         updateRasterizationSamples(framebufferVk->getSamples());
5068     }
5069 
5070     // Update scissor.
5071     updateScissor(mState);
5072 
5073     // Update depth and stencil.
5074     updateDepthStencil(mState);
5075 
5076     // Update dither based on attachment formats.
5077     updateDither();
5078 
5079     if (mState.getProgramExecutable())
5080     {
5081         ANGLE_TRY(invalidateCurrentShaderResources(command));
5082     }
5083 
5084     onDrawFramebufferRenderPassDescChange(framebufferVk, nullptr);
5085 
5086     return angle::Result::Continue;
5087 }
5088 
onDrawFramebufferRenderPassDescChange(FramebufferVk * framebufferVk,bool * renderPassDescChangedOut)5089 void ContextVk::onDrawFramebufferRenderPassDescChange(FramebufferVk *framebufferVk,
5090                                                       bool *renderPassDescChangedOut)
5091 {
5092     mGraphicsPipelineDesc->updateRenderPassDesc(&mGraphicsPipelineTransition,
5093                                                 framebufferVk->getRenderPassDesc());
5094     const gl::Box &dimensions = framebufferVk->getState().getDimensions();
5095     mGraphicsPipelineDesc->updateDrawableSize(&mGraphicsPipelineTransition, dimensions.width,
5096                                               dimensions.height);
5097 
5098     if (renderPassDescChangedOut)
5099     {
5100         // If render pass desc has changed while processing the dirty bits, notify the caller.
5101         *renderPassDescChangedOut = true;
5102     }
5103     else
5104     {
5105         // Otherwise mark the pipeline as dirty.
5106         invalidateCurrentGraphicsPipeline();
5107     }
5108 }
5109 
invalidateCurrentTransformFeedbackBuffers()5110 void ContextVk::invalidateCurrentTransformFeedbackBuffers()
5111 {
5112     if (getFeatures().supportsTransformFeedbackExtension.enabled)
5113     {
5114         mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS);
5115     }
5116     else if (getFeatures().emulateTransformFeedback.enabled)
5117     {
5118         mGraphicsDirtyBits |= kXfbBuffersAndDescSetDirtyBits;
5119     }
5120 }
5121 
onTransformFeedbackStateChanged()5122 void ContextVk::onTransformFeedbackStateChanged()
5123 {
5124     if (getFeatures().supportsTransformFeedbackExtension.enabled)
5125     {
5126         mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS);
5127     }
5128     else if (getFeatures().emulateTransformFeedback.enabled)
5129     {
5130         invalidateGraphicsDriverUniforms();
5131         invalidateCurrentTransformFeedbackBuffers();
5132 
5133         // Invalidate the graphics pipeline too.  On transform feedback state change, the current
5134         // program may be used again, and it should switch between outputting transform feedback and
5135         // not.
5136         invalidateCurrentGraphicsPipeline();
5137         resetCurrentGraphicsPipeline();
5138     }
5139 }
5140 
onBeginTransformFeedback(size_t bufferCount,const gl::TransformFeedbackBuffersArray<vk::BufferHelper * > & buffers,const gl::TransformFeedbackBuffersArray<vk::BufferHelper> & counterBuffers)5141 angle::Result ContextVk::onBeginTransformFeedback(
5142     size_t bufferCount,
5143     const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &buffers,
5144     const gl::TransformFeedbackBuffersArray<vk::BufferHelper> &counterBuffers)
5145 {
5146     onTransformFeedbackStateChanged();
5147 
5148     bool shouldEndRenderPass = false;
5149 
5150     // If any of the buffers were previously used in the render pass, break the render pass as a
5151     // barrier is needed.
5152     for (size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
5153     {
5154         const vk::BufferHelper *buffer = buffers[bufferIndex];
5155         if (mRenderPassCommands->usesBuffer(*buffer))
5156         {
5157             shouldEndRenderPass = true;
5158             break;
5159         }
5160     }
5161 
5162     if (getFeatures().supportsTransformFeedbackExtension.enabled)
5163     {
5164         // Break the render pass if the counter buffers are used too.  Note that Vulkan requires a
5165         // barrier on the counter buffer between pause and resume, so it cannot be resumed in the
5166         // same render pass.  Note additionally that we don't need to test all counters being used
5167         // in the render pass, as outside of the transform feedback object these buffers are
5168         // inaccessible and are therefore always used together.
5169         if (!shouldEndRenderPass && mRenderPassCommands->usesBuffer(counterBuffers[0]))
5170         {
5171             shouldEndRenderPass = true;
5172         }
5173 
5174         mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
5175     }
5176 
5177     if (shouldEndRenderPass)
5178     {
5179         ANGLE_TRY(flushCommandsAndEndRenderPass(RenderPassClosureReason::BufferUseThenXfbWrite));
5180     }
5181 
5182     populateTransformFeedbackBufferSet(bufferCount, buffers);
5183 
5184     return angle::Result::Continue;
5185 }
5186 
populateTransformFeedbackBufferSet(size_t bufferCount,const gl::TransformFeedbackBuffersArray<vk::BufferHelper * > & buffers)5187 void ContextVk::populateTransformFeedbackBufferSet(
5188     size_t bufferCount,
5189     const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &buffers)
5190 {
5191     for (size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
5192     {
5193         vk::BufferHelper *buffer = buffers[bufferIndex];
5194         if (!mCurrentTransformFeedbackBuffers.contains(buffer))
5195         {
5196             mCurrentTransformFeedbackBuffers.insert(buffer);
5197         }
5198     }
5199 }
5200 
onEndTransformFeedback()5201 void ContextVk::onEndTransformFeedback()
5202 {
5203     if (getFeatures().supportsTransformFeedbackExtension.enabled)
5204     {
5205         if (mRenderPassCommands->isTransformFeedbackStarted())
5206         {
5207             mRenderPassCommands->endTransformFeedback();
5208         }
5209     }
5210     else if (getFeatures().emulateTransformFeedback.enabled)
5211     {
5212         onTransformFeedbackStateChanged();
5213     }
5214 }
5215 
onPauseTransformFeedback()5216 angle::Result ContextVk::onPauseTransformFeedback()
5217 {
5218     if (getFeatures().supportsTransformFeedbackExtension.enabled)
5219     {
5220         // If transform feedback was already active on this render pass, break it.  This
5221         // is for simplicity to avoid tracking multiple simultaneously active transform feedback
5222         // settings in the render pass.
5223         if (mRenderPassCommands->isTransformFeedbackActiveUnpaused())
5224         {
5225             return flushCommandsAndEndRenderPass(RenderPassClosureReason::XfbPause);
5226         }
5227     }
5228     else if (getFeatures().emulateTransformFeedback.enabled)
5229     {
5230         invalidateCurrentTransformFeedbackBuffers();
5231     }
5232     return angle::Result::Continue;
5233 }
5234 
invalidateGraphicsPipelineBinding()5235 void ContextVk::invalidateGraphicsPipelineBinding()
5236 {
5237     mGraphicsDirtyBits.set(DIRTY_BIT_PIPELINE_BINDING);
5238 }
5239 
invalidateComputePipelineBinding()5240 void ContextVk::invalidateComputePipelineBinding()
5241 {
5242     mComputeDirtyBits.set(DIRTY_BIT_PIPELINE_BINDING);
5243 }
5244 
invalidateGraphicsDescriptorSet(DescriptorSetIndex usedDescriptorSet)5245 void ContextVk::invalidateGraphicsDescriptorSet(DescriptorSetIndex usedDescriptorSet)
5246 {
5247     // UtilsVk currently only uses set 0
5248     ASSERT(usedDescriptorSet == DescriptorSetIndex::Internal);
5249     if (mDriverUniforms[PipelineType::Graphics].descriptorSet != VK_NULL_HANDLE)
5250     {
5251         mGraphicsDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING);
5252     }
5253 }
5254 
invalidateComputeDescriptorSet(DescriptorSetIndex usedDescriptorSet)5255 void ContextVk::invalidateComputeDescriptorSet(DescriptorSetIndex usedDescriptorSet)
5256 {
5257     // UtilsVk currently only uses set 0
5258     ASSERT(usedDescriptorSet == DescriptorSetIndex::Internal);
5259     if (mDriverUniforms[PipelineType::Compute].descriptorSet != VK_NULL_HANDLE)
5260     {
5261         mComputeDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING);
5262     }
5263 }
5264 
invalidateViewportAndScissor()5265 void ContextVk::invalidateViewportAndScissor()
5266 {
5267     mGraphicsDirtyBits.set(DIRTY_BIT_VIEWPORT);
5268     mGraphicsDirtyBits.set(DIRTY_BIT_SCISSOR);
5269 }
5270 
dispatchCompute(const gl::Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)5271 angle::Result ContextVk::dispatchCompute(const gl::Context *context,
5272                                          GLuint numGroupsX,
5273                                          GLuint numGroupsY,
5274                                          GLuint numGroupsZ)
5275 {
5276     ANGLE_TRY(setupDispatch(context));
5277 
5278     mOutsideRenderPassCommands->getCommandBuffer().dispatch(numGroupsX, numGroupsY, numGroupsZ);
5279 
5280     return angle::Result::Continue;
5281 }
5282 
dispatchComputeIndirect(const gl::Context * context,GLintptr indirect)5283 angle::Result ContextVk::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
5284 {
5285     gl::Buffer *glBuffer     = getState().getTargetBuffer(gl::BufferBinding::DispatchIndirect);
5286     vk::BufferHelper &buffer = vk::GetImpl(glBuffer)->getBuffer();
5287 
5288     // Break the render pass if the indirect buffer was previously used as the output from transform
5289     // feedback.
5290     if (mCurrentTransformFeedbackBuffers.contains(&buffer))
5291     {
5292         ANGLE_TRY(flushCommandsAndEndRenderPass(
5293             RenderPassClosureReason::XfbWriteThenIndirectDispatchBuffer));
5294     }
5295 
5296     ANGLE_TRY(setupDispatch(context));
5297 
5298     // Process indirect buffer after command buffer has started.
5299     mOutsideRenderPassCommands->bufferRead(this, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
5300                                            vk::PipelineStage::DrawIndirect, &buffer);
5301 
5302     mOutsideRenderPassCommands->getCommandBuffer().dispatchIndirect(buffer.getBuffer(),
5303                                                                     buffer.getOffset() + indirect);
5304 
5305     return angle::Result::Continue;
5306 }
5307 
memoryBarrier(const gl::Context * context,GLbitfield barriers)5308 angle::Result ContextVk::memoryBarrier(const gl::Context *context, GLbitfield barriers)
5309 {
5310     // First, turn GL_ALL_BARRIER_BITS into a mask that has only the valid barriers set.
5311     constexpr GLbitfield kCoreBarrierBits =
5312         GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
5313         GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
5314         GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
5315         GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT |
5316         GL_ATOMIC_COUNTER_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT;
5317     constexpr GLbitfield kExtensionBarrierBits = GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT;
5318 
5319     barriers &= kCoreBarrierBits | kExtensionBarrierBits;
5320 
5321     // GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT specifies that a fence sync or glFinish must be used
5322     // after the barrier for the CPU to to see the shader writes.  Since host-visible buffer writes
5323     // always issue a barrier automatically for the sake of glMapBuffer() (see
5324     // comment on |mIsAnyHostVisibleBufferWritten|), there's nothing to do for
5325     // GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT.
5326     barriers &= ~GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT;
5327 
5328     // If no other barrier, early out.
5329     if (barriers == 0)
5330     {
5331         return angle::Result::Continue;
5332     }
5333 
5334     // glMemoryBarrier for barrier bit X_BARRIER_BIT implies:
5335     //
5336     // - An execution+memory barrier: shader writes are made visible to subsequent X accesses
5337     //
5338     // Additionally, SHADER_IMAGE_ACCESS_BARRIER_BIT and SHADER_STORAGE_BARRIER_BIT imply:
5339     //
5340     // - An execution+memory barrier: all accesses are finished before image/buffer writes
5341     //
5342     // For the first barrier, we can simplify the implementation by assuming that prior writes are
5343     // expected to be used right after this barrier, so we can close the render pass or flush the
5344     // outside render pass commands right away if they have had any writes.
5345     //
5346     // It's noteworthy that some barrier bits affect draw/dispatch calls only, while others affect
5347     // other commands.  For the latter, since storage buffer and images are not tracked in command
5348     // buffers, we can't rely on the command buffers being flushed in the usual way when recording
5349     // these commands (i.e. through |getOutsideRenderPassCommandBuffer()| and
5350     // |vk::CommandBufferAccess|).  Conservatively flushing command buffers with any storage output
5351     // simplifies this use case.  If this needs to be avoided in the future,
5352     // |getOutsideRenderPassCommandBuffer()| can be modified to flush the command buffers if they
5353     // have had any storage output.
5354     //
5355     // For the second barrier, we need to defer closing the render pass until there's a draw or
5356     // dispatch call that uses storage buffers or images that were previously used in the render
5357     // pass.  This allows the render pass to remain open in scenarios such as this:
5358     //
5359     // - Draw using resource X
5360     // - glMemoryBarrier
5361     // - Draw/dispatch with storage buffer/image Y
5362     //
5363     // To achieve this, a dirty bit is added that breaks the render pass if any storage
5364     // buffer/images are used in it.  Until the render pass breaks, changing the program or storage
5365     // buffer/image bindings should set this dirty bit again.
5366 
5367     if (mRenderPassCommands->hasShaderStorageOutput())
5368     {
5369         // Break the render pass if necessary as future non-draw commands can't know if they should.
5370         ANGLE_TRY(flushCommandsAndEndRenderPass(
5371             RenderPassClosureReason::StorageResourceUseThenGLMemoryBarrier));
5372     }
5373     else if (mOutsideRenderPassCommands->hasShaderStorageOutput())
5374     {
5375         // Otherwise flush the outside render pass commands if necessary.
5376         ANGLE_TRY(flushOutsideRenderPassCommands());
5377     }
5378 
5379     constexpr GLbitfield kWriteAfterAccessBarriers =
5380         GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT;
5381 
5382     if ((barriers & kWriteAfterAccessBarriers) == 0)
5383     {
5384         return angle::Result::Continue;
5385     }
5386 
5387     // Defer flushing the command buffers until a draw/dispatch with storage buffer/image is
5388     // encountered.
5389     mGraphicsDirtyBits.set(DIRTY_BIT_MEMORY_BARRIER);
5390     mComputeDirtyBits.set(DIRTY_BIT_MEMORY_BARRIER);
5391 
5392     // Make sure memory barrier is issued for future usages of storage buffers and images even if
5393     // there's no binding change.
5394     mGraphicsDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
5395     mComputeDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
5396 
5397     // Mark the command buffers as affected by glMemoryBarrier, so future program and storage
5398     // buffer/image binding changes can set DIRTY_BIT_MEMORY_BARRIER again.
5399     mOutsideRenderPassCommands->setGLMemoryBarrierIssued();
5400     mRenderPassCommands->setGLMemoryBarrierIssued();
5401 
5402     return angle::Result::Continue;
5403 }
5404 
memoryBarrierByRegion(const gl::Context * context,GLbitfield barriers)5405 angle::Result ContextVk::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers)
5406 {
5407     // Note: memoryBarrierByRegion is expected to affect only the fragment pipeline, but is
5408     // otherwise similar to memoryBarrier in function.
5409     //
5410     // TODO: Optimize memoryBarrierByRegion by issuing an in-subpass pipeline barrier instead of
5411     // breaking the render pass.  http://anglebug.com/5132
5412     return memoryBarrier(context, barriers);
5413 }
5414 
framebufferFetchBarrier()5415 void ContextVk::framebufferFetchBarrier()
5416 {
5417     mGraphicsDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_FETCH_BARRIER);
5418 }
5419 
blendBarrier()5420 void ContextVk::blendBarrier()
5421 {
5422     if (getFeatures().emulateAdvancedBlendEquations.enabled)
5423     {
5424         // When emulated, advanced blend is implemented through framebuffer fetch.
5425         framebufferFetchBarrier();
5426     }
5427     else
5428     {
5429         mGraphicsDirtyBits.set(DIRTY_BIT_BLEND_BARRIER);
5430     }
5431 }
5432 
acquireTextures(const gl::Context * context,const gl::TextureBarrierVector & textureBarriers)5433 angle::Result ContextVk::acquireTextures(const gl::Context *context,
5434                                          const gl::TextureBarrierVector &textureBarriers)
5435 {
5436     for (const gl::TextureAndLayout &textureBarrier : textureBarriers)
5437     {
5438         TextureVk *textureVk   = vk::GetImpl(textureBarrier.texture);
5439         vk::ImageHelper &image = textureVk->getImage();
5440         vk::ImageLayout layout = vk::GetImageLayoutFromGLImageLayout(textureBarrier.layout);
5441         // Image should not be accessed while unowned. Emulated formats may have staged updates
5442         // to clear the image after initialization.
5443         ASSERT(!image.hasStagedUpdatesInAllocatedLevels() || image.hasEmulatedImageChannels());
5444         image.setCurrentImageLayout(layout);
5445     }
5446     return angle::Result::Continue;
5447 }
5448 
releaseTextures(const gl::Context * context,gl::TextureBarrierVector * textureBarriers)5449 angle::Result ContextVk::releaseTextures(const gl::Context *context,
5450                                          gl::TextureBarrierVector *textureBarriers)
5451 {
5452     for (gl::TextureAndLayout &textureBarrier : *textureBarriers)
5453     {
5454 
5455         TextureVk *textureVk = vk::GetImpl(textureBarrier.texture);
5456 
5457         ANGLE_TRY(textureVk->ensureImageInitialized(this, ImageMipLevels::EnabledLevels));
5458 
5459         vk::ImageHelper &image = textureVk->getImage();
5460         ANGLE_TRY(onImageReleaseToExternal(image));
5461 
5462         textureBarrier.layout =
5463             vk::ConvertImageLayoutToGLImageLayout(image.getCurrentImageLayout());
5464     }
5465 
5466     ANGLE_TRY(flushImpl(nullptr, RenderPassClosureReason::ImageUseThenReleaseToExternal));
5467     return mRenderer->ensureNoPendingWork(this);
5468 }
5469 
getQueryPool(gl::QueryType queryType)5470 vk::DynamicQueryPool *ContextVk::getQueryPool(gl::QueryType queryType)
5471 {
5472     ASSERT(queryType == gl::QueryType::AnySamples ||
5473            queryType == gl::QueryType::AnySamplesConservative ||
5474            queryType == gl::QueryType::PrimitivesGenerated ||
5475            queryType == gl::QueryType::TransformFeedbackPrimitivesWritten ||
5476            queryType == gl::QueryType::Timestamp || queryType == gl::QueryType::TimeElapsed);
5477 
5478     // For PrimitivesGenerated queries:
5479     //
5480     // - If VK_EXT_primitives_generated_query is supported, use that.
5481     //   TODO: http://anglebug.com/5430
5482     // - Otherwise, if pipelineStatisticsQuery is supported, use that,
5483     // - Otherwise, use the same pool as TransformFeedbackPrimitivesWritten and share the query as
5484     //   the Vulkan transform feedback query produces both results.  This option is non-conformant
5485     //   as the primitives generated query will not be functional without transform feedback.
5486     //
5487     if (queryType == gl::QueryType::PrimitivesGenerated &&
5488         !getFeatures().supportsPipelineStatisticsQuery.enabled)
5489     {
5490         queryType = gl::QueryType::TransformFeedbackPrimitivesWritten;
5491     }
5492 
5493     // Assert that timestamp extension is available if needed.
5494     ASSERT(queryType != gl::QueryType::Timestamp && queryType != gl::QueryType::TimeElapsed ||
5495            mRenderer->getQueueFamilyProperties().timestampValidBits > 0);
5496     ASSERT(mQueryPools[queryType].isValid());
5497     return &mQueryPools[queryType];
5498 }
5499 
getClearColorValue() const5500 const VkClearValue &ContextVk::getClearColorValue() const
5501 {
5502     return mClearColorValue;
5503 }
5504 
getClearDepthStencilValue() const5505 const VkClearValue &ContextVk::getClearDepthStencilValue() const
5506 {
5507     return mClearDepthStencilValue;
5508 }
5509 
getClearColorMasks() const5510 gl::BlendStateExt::ColorMaskStorage::Type ContextVk::getClearColorMasks() const
5511 {
5512     return mClearColorMasks;
5513 }
5514 
writeAtomicCounterBufferDriverUniformOffsets(uint32_t * offsetsOut,size_t offsetsSize)5515 void ContextVk::writeAtomicCounterBufferDriverUniformOffsets(uint32_t *offsetsOut,
5516                                                              size_t offsetsSize)
5517 {
5518     const VkDeviceSize offsetAlignment =
5519         mRenderer->getPhysicalDeviceProperties().limits.minStorageBufferOffsetAlignment;
5520     size_t atomicCounterBufferCount = mState.getAtomicCounterBufferCount();
5521 
5522     ASSERT(atomicCounterBufferCount <= offsetsSize * 4);
5523 
5524     for (uint32_t bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
5525     {
5526         uint32_t offsetDiff = 0;
5527 
5528         const gl::OffsetBindingPointer<gl::Buffer> *atomicCounterBuffer =
5529             &mState.getIndexedAtomicCounterBuffer(bufferIndex);
5530         if (atomicCounterBuffer->get())
5531         {
5532             VkDeviceSize offset        = atomicCounterBuffer->getOffset();
5533             VkDeviceSize alignedOffset = (offset / offsetAlignment) * offsetAlignment;
5534 
5535             // GL requires the atomic counter buffer offset to be aligned with uint.
5536             ASSERT((offset - alignedOffset) % sizeof(uint32_t) == 0);
5537             offsetDiff = static_cast<uint32_t>((offset - alignedOffset) / sizeof(uint32_t));
5538 
5539             // We expect offsetDiff to fit in an 8-bit value.  The maximum difference is
5540             // minStorageBufferOffsetAlignment / 4, where minStorageBufferOffsetAlignment
5541             // currently has a maximum value of 256 on any device.
5542             ASSERT(offsetDiff < (1 << 8));
5543         }
5544 
5545         // The output array is already cleared prior to this call.
5546         ASSERT(bufferIndex % 4 != 0 || offsetsOut[bufferIndex / 4] == 0);
5547 
5548         offsetsOut[bufferIndex / 4] |= static_cast<uint8_t>(offsetDiff) << ((bufferIndex % 4) * 8);
5549     }
5550 }
5551 
pauseTransformFeedbackIfActiveUnpaused()5552 void ContextVk::pauseTransformFeedbackIfActiveUnpaused()
5553 {
5554     if (mRenderPassCommands->isTransformFeedbackActiveUnpaused())
5555     {
5556         ASSERT(getFeatures().supportsTransformFeedbackExtension.enabled);
5557         mRenderPassCommands->pauseTransformFeedback();
5558 
5559         // Note that this function is called when render pass break is imminent
5560         // (flushCommandsAndEndRenderPass(), or UtilsVk::clearFramebuffer which will close the
5561         // render pass after the clear).  This dirty bit allows transform feedback to resume
5562         // automatically on next render pass.
5563         mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
5564     }
5565 }
5566 
handleDirtyGraphicsDriverUniforms(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)5567 angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(DirtyBits::Iterator *dirtyBitsIterator,
5568                                                            DirtyBits dirtyBitMask)
5569 {
5570     // Allocate a new region in the dynamic buffer.
5571     bool useGraphicsDriverUniformsExtended = getFeatures().forceDriverUniformOverSpecConst.enabled;
5572     uint8_t *ptr;
5573     bool newBuffer;
5574     GraphicsDriverUniforms *driverUniforms;
5575     size_t driverUniformSize;
5576 
5577     if (useGraphicsDriverUniformsExtended)
5578     {
5579         driverUniformSize = sizeof(GraphicsDriverUniformsExtended);
5580     }
5581     else
5582     {
5583         driverUniformSize = sizeof(GraphicsDriverUniforms);
5584     }
5585 
5586     ANGLE_TRY(allocateDriverUniforms(driverUniformSize, &mDriverUniforms[PipelineType::Graphics],
5587                                      &ptr, &newBuffer));
5588 
5589     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
5590     if (useGraphicsDriverUniformsExtended)
5591     {
5592         float halfRenderAreaWidth =
5593             static_cast<float>(drawFramebufferVk->getState().getDimensions().width) * 0.5f;
5594         float halfRenderAreaHeight =
5595             static_cast<float>(drawFramebufferVk->getState().getDimensions().height) * 0.5f;
5596 
5597         float flipX = 1.0f;
5598         float flipY = -1.0f;
5599         // Y-axis flipping only comes into play with the default framebuffer (i.e. a swapchain
5600         // image). For 0-degree rotation, an FBO or pbuffer could be the draw framebuffer, and so we
5601         // must check whether flipY should be positive or negative.  All other rotations, will be to
5602         // the default framebuffer, and so the value of isViewportFlipEnabledForDrawFBO() is assumed
5603         // true; the appropriate flipY value is chosen such that gl_FragCoord is positioned at the
5604         // lower-left corner of the window.
5605         switch (mCurrentRotationDrawFramebuffer)
5606         {
5607             case SurfaceRotation::Identity:
5608                 flipX = 1.0f;
5609                 flipY = isViewportFlipEnabledForDrawFBO() ? -1.0f : 1.0f;
5610                 break;
5611             case SurfaceRotation::Rotated90Degrees:
5612                 ASSERT(isViewportFlipEnabledForDrawFBO());
5613                 flipX = 1.0f;
5614                 flipY = 1.0f;
5615                 break;
5616             case SurfaceRotation::Rotated180Degrees:
5617                 ASSERT(isViewportFlipEnabledForDrawFBO());
5618                 flipX = -1.0f;
5619                 flipY = 1.0f;
5620                 break;
5621             case SurfaceRotation::Rotated270Degrees:
5622                 ASSERT(isViewportFlipEnabledForDrawFBO());
5623                 flipX = -1.0f;
5624                 flipY = -1.0f;
5625                 break;
5626             default:
5627                 UNREACHABLE();
5628                 break;
5629         }
5630 
5631         GraphicsDriverUniformsExtended *driverUniformsExt =
5632             reinterpret_cast<GraphicsDriverUniformsExtended *>(ptr);
5633         driverUniformsExt->halfRenderArea = {halfRenderAreaWidth, halfRenderAreaHeight};
5634         driverUniformsExt->flipXY         = {flipX, flipY};
5635         driverUniformsExt->negFlipXY      = {flipX, -flipY};
5636         memcpy(&driverUniformsExt->fragRotation,
5637                &kFragRotationMatrices[mCurrentRotationDrawFramebuffer],
5638                sizeof(PreRotationMatrixValues));
5639         driverUniforms = &driverUniformsExt->common;
5640     }
5641     else
5642     {
5643         driverUniforms = reinterpret_cast<GraphicsDriverUniforms *>(ptr);
5644     }
5645 
5646     gl::Rectangle glViewport = mState.getViewport();
5647     if (isRotatedAspectRatioForDrawFBO())
5648     {
5649         // The surface is rotated 90/270 degrees.  This changes the aspect ratio of the surface.
5650         std::swap(glViewport.x, glViewport.y);
5651         std::swap(glViewport.width, glViewport.height);
5652     }
5653 
5654     float depthRangeNear = mState.getNearPlane();
5655     float depthRangeFar  = mState.getFarPlane();
5656     float depthRangeDiff = depthRangeFar - depthRangeNear;
5657     int32_t numSamples   = drawFramebufferVk->getSamples();
5658 
5659     uint32_t advancedBlendEquation = 0;
5660     if (getFeatures().emulateAdvancedBlendEquations.enabled)
5661     {
5662         // Pass the advanced blend equation to shader as-is.  If the equation is not one of the
5663         // advanced ones, 0 is expected.
5664         const gl::BlendStateExt &blendStateExt = mState.getBlendStateExt();
5665         if (blendStateExt.mUsesAdvancedBlendEquationMask.test(0))
5666         {
5667             advancedBlendEquation = static_cast<uint32_t>(gl::FromGLenum<gl::BlendEquationType>(
5668                 getState().getBlendStateExt().getEquationColorIndexed(0)));
5669         }
5670     }
5671 
5672     // Copy and flush to the device.
5673     *driverUniforms = {
5674         {static_cast<float>(glViewport.x), static_cast<float>(glViewport.y),
5675          static_cast<float>(glViewport.width), static_cast<float>(glViewport.height)},
5676         mState.getEnabledClipDistances().bits(),
5677         advancedBlendEquation,
5678         static_cast<int32_t>(mXfbVertexCountPerInstance),
5679         numSamples,
5680         {},
5681         {},
5682         {depthRangeNear, depthRangeFar, depthRangeDiff, 0.0f}};
5683 
5684     if (mState.isTransformFeedbackActiveUnpaused())
5685     {
5686         TransformFeedbackVk *transformFeedbackVk =
5687             vk::GetImpl(mState.getCurrentTransformFeedback());
5688         transformFeedbackVk->getBufferOffsets(this, mXfbBaseVertex,
5689                                               driverUniforms->xfbBufferOffsets.data(),
5690                                               driverUniforms->xfbBufferOffsets.size());
5691     }
5692 
5693     if (mState.hasValidAtomicCounterBuffer())
5694     {
5695         writeAtomicCounterBufferDriverUniformOffsets(driverUniforms->acbBufferOffsets.data(),
5696                                                      driverUniforms->acbBufferOffsets.size());
5697     }
5698 
5699     return updateDriverUniformsDescriptorSet(newBuffer, driverUniformSize, PipelineType::Graphics);
5700 }
5701 
handleDirtyComputeDriverUniforms()5702 angle::Result ContextVk::handleDirtyComputeDriverUniforms()
5703 {
5704     // Allocate a new region in the dynamic buffer.
5705     uint8_t *ptr;
5706     bool newBuffer;
5707     ANGLE_TRY(allocateDriverUniforms(sizeof(ComputeDriverUniforms),
5708                                      &mDriverUniforms[PipelineType::Compute], &ptr, &newBuffer));
5709 
5710     // Copy and flush to the device.
5711     ComputeDriverUniforms *driverUniforms = reinterpret_cast<ComputeDriverUniforms *>(ptr);
5712     *driverUniforms                       = {};
5713 
5714     if (mState.hasValidAtomicCounterBuffer())
5715     {
5716         writeAtomicCounterBufferDriverUniformOffsets(driverUniforms->acbBufferOffsets.data(),
5717                                                      driverUniforms->acbBufferOffsets.size());
5718     }
5719 
5720     return updateDriverUniformsDescriptorSet(newBuffer, sizeof(ComputeDriverUniforms),
5721                                              PipelineType::Compute);
5722 }
5723 
5724 template <typename CommandBufferT>
handleDirtyDriverUniformsBindingImpl(CommandBufferT * commandBuffer,VkPipelineBindPoint bindPoint,DriverUniformsDescriptorSet * driverUniforms)5725 void ContextVk::handleDirtyDriverUniformsBindingImpl(CommandBufferT *commandBuffer,
5726                                                      VkPipelineBindPoint bindPoint,
5727                                                      DriverUniformsDescriptorSet *driverUniforms)
5728 {
5729     // The descriptor pool that this descriptor set was allocated from needs to be retained when the
5730     // descriptor set is used in a new command. Since the descriptor pools are specific to each
5731     // ContextVk, we only need to retain them once to ensure the reference count and Serial are
5732     // updated correctly.
5733     if (!driverUniforms->descriptorPoolBinding.get().usedInRecordedCommands())
5734     {
5735         driverUniforms->descriptorPoolBinding.get().retain(&mResourceUseList);
5736     }
5737 
5738     ProgramExecutableVk *executableVk = getExecutable();
5739     const uint32_t dynamicOffset =
5740         static_cast<uint32_t>(driverUniforms->currentBuffer->getOffset());
5741     commandBuffer->bindDescriptorSets(executableVk->getPipelineLayout(), bindPoint,
5742                                       DescriptorSetIndex::Internal, 1,
5743                                       &driverUniforms->descriptorSet, 1, &dynamicOffset);
5744 }
5745 
handleDirtyGraphicsDriverUniformsBinding(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)5746 angle::Result ContextVk::handleDirtyGraphicsDriverUniformsBinding(
5747     DirtyBits::Iterator *dirtyBitsIterator,
5748     DirtyBits dirtyBitMask)
5749 {
5750     // Bind the driver descriptor set.
5751     handleDirtyDriverUniformsBindingImpl(mRenderPassCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
5752                                          &mDriverUniforms[PipelineType::Graphics]);
5753     return angle::Result::Continue;
5754 }
5755 
handleDirtyComputeDriverUniformsBinding()5756 angle::Result ContextVk::handleDirtyComputeDriverUniformsBinding()
5757 {
5758     // Bind the driver descriptor set.
5759     handleDirtyDriverUniformsBindingImpl(&mOutsideRenderPassCommands->getCommandBuffer(),
5760                                          VK_PIPELINE_BIND_POINT_COMPUTE,
5761                                          &mDriverUniforms[PipelineType::Compute]);
5762     return angle::Result::Continue;
5763 }
5764 
allocateDriverUniforms(size_t driverUniformsSize,DriverUniformsDescriptorSet * driverUniforms,uint8_t ** ptrOut,bool * newBufferOut)5765 angle::Result ContextVk::allocateDriverUniforms(size_t driverUniformsSize,
5766                                                 DriverUniformsDescriptorSet *driverUniforms,
5767                                                 uint8_t **ptrOut,
5768                                                 bool *newBufferOut)
5769 {
5770     // Allocate a new region in the dynamic buffer. The allocate call may put buffer into dynamic
5771     // buffer's mInflightBuffers. During command submission time, these in-flight buffers are added
5772     // into context's mResourceUseList which will ensure they get tagged with queue serial number
5773     // before moving them into the free list.
5774     ANGLE_TRY(driverUniforms->dynamicBuffer.allocate(this, driverUniformsSize,
5775                                                      &driverUniforms->currentBuffer, newBufferOut));
5776 
5777     *ptrOut = driverUniforms->currentBuffer->getMappedMemory();
5778 
5779     return angle::Result::Continue;
5780 }
5781 
updateDriverUniformsDescriptorSet(bool newBuffer,size_t driverUniformsSize,PipelineType pipelineType)5782 angle::Result ContextVk::updateDriverUniformsDescriptorSet(bool newBuffer,
5783                                                            size_t driverUniformsSize,
5784                                                            PipelineType pipelineType)
5785 {
5786     DriverUniformsDescriptorSet &driverUniforms = mDriverUniforms[pipelineType];
5787 
5788     ANGLE_TRY(driverUniforms.currentBuffer->flush(mRenderer));
5789 
5790     if (!newBuffer)
5791     {
5792         return angle::Result::Continue;
5793     }
5794 
5795     vk::BufferSerial bufferSerial = driverUniforms.currentBuffer->getBufferSerial();
5796     // Look up in the cache first
5797     if (driverUniforms.descriptorSetCache.get(bufferSerial.getValue(),
5798                                               &driverUniforms.descriptorSet))
5799     {
5800         // The descriptor pool that this descriptor set was allocated from needs to be retained each
5801         // time the descriptor set is used in a new command.
5802         driverUniforms.descriptorPoolBinding.get().retain(&mResourceUseList);
5803         return angle::Result::Continue;
5804     }
5805 
5806     // Allocate a new descriptor set.
5807     bool newPoolAllocated;
5808     ANGLE_TRY(mDriverUniformsDescriptorPools[pipelineType].allocateSetsAndGetInfo(
5809         this, &mResourceUseList, driverUniforms.descriptorSetLayout.get(), 1,
5810         &driverUniforms.descriptorPoolBinding, &driverUniforms.descriptorSet, &newPoolAllocated));
5811 
5812     // Clear descriptor set cache. It may no longer be valid.
5813     if (newPoolAllocated)
5814     {
5815         driverUniforms.descriptorSetCache.clear();
5816     }
5817 
5818     // Update the driver uniform descriptor set.
5819     VkDescriptorBufferInfo &bufferInfo = mUpdateDescriptorSetsBuilder.allocDescriptorBufferInfo();
5820     bufferInfo.buffer                  = driverUniforms.currentBuffer->getBuffer().getHandle();
5821     bufferInfo.offset                  = 0;
5822     bufferInfo.range                   = driverUniformsSize;
5823 
5824     VkWriteDescriptorSet &writeInfo = mUpdateDescriptorSetsBuilder.allocWriteDescriptorSet();
5825     writeInfo.sType                 = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
5826     writeInfo.dstSet                = driverUniforms.descriptorSet;
5827     writeInfo.dstBinding            = 0;
5828     writeInfo.dstArrayElement       = 0;
5829     writeInfo.descriptorCount       = 1;
5830     writeInfo.descriptorType        = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
5831     writeInfo.pImageInfo            = nullptr;
5832     writeInfo.pTexelBufferView      = nullptr;
5833     writeInfo.pBufferInfo           = &bufferInfo;
5834 
5835     // Add into descriptor set cache
5836     driverUniforms.descriptorSetCache.insert(bufferSerial.getValue(), driverUniforms.descriptorSet);
5837 
5838     return angle::Result::Continue;
5839 }
5840 
handleError(VkResult errorCode,const char * file,const char * function,unsigned int line)5841 void ContextVk::handleError(VkResult errorCode,
5842                             const char *file,
5843                             const char *function,
5844                             unsigned int line)
5845 {
5846     ASSERT(errorCode != VK_SUCCESS);
5847 
5848     GLenum glErrorCode = DefaultGLErrorCode(errorCode);
5849 
5850     std::stringstream errorStream;
5851     errorStream << "Internal Vulkan error (" << errorCode << "): " << VulkanResultString(errorCode)
5852                 << ".";
5853 
5854     if (errorCode == VK_ERROR_DEVICE_LOST)
5855     {
5856         WARN() << errorStream.str();
5857         handleDeviceLost();
5858     }
5859 
5860     mErrors->handleError(glErrorCode, errorStream.str().c_str(), file, function, line);
5861 }
5862 
updateActiveTextures(const gl::Context * context,gl::Command command)5863 angle::Result ContextVk::updateActiveTextures(const gl::Context *context, gl::Command command)
5864 {
5865     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
5866     ASSERT(executable);
5867 
5868     mActiveTexturesDesc.reset();
5869 
5870     const gl::ActiveTexturesCache &textures        = mState.getActiveTexturesCache();
5871     const gl::ActiveTextureMask &activeTextures    = executable->getActiveSamplersMask();
5872     const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
5873 
5874     bool recreatePipelineLayout                       = false;
5875     ImmutableSamplerIndexMap immutableSamplerIndexMap = {};
5876     for (size_t textureUnit : activeTextures)
5877     {
5878         gl::Texture *texture        = textures[textureUnit];
5879         gl::TextureType textureType = textureTypes[textureUnit];
5880         ASSERT(textureType != gl::TextureType::InvalidEnum);
5881 
5882         const bool isIncompleteTexture = texture == nullptr;
5883 
5884         // Null textures represent incomplete textures.
5885         if (isIncompleteTexture)
5886         {
5887             ANGLE_TRY(getIncompleteTexture(
5888                 context, textureType, executable->getSamplerFormatForTextureUnitIndex(textureUnit),
5889                 &texture));
5890         }
5891 
5892         TextureVk *textureVk = vk::GetImpl(texture);
5893         ASSERT(textureVk != nullptr);
5894 
5895         vk::TextureUnit &activeTexture = mActiveTextures[textureUnit];
5896 
5897         // Special handling of texture buffers.  They have a buffer attached instead of an image.
5898         if (textureType == gl::TextureType::Buffer)
5899         {
5900             activeTexture.texture = textureVk;
5901             mActiveTexturesDesc.updateTexture(textureUnit, textureVk->getBufferViewSerial(),
5902                                               vk::SamplerSerial());
5903 
5904             continue;
5905         }
5906 
5907         if (!isIncompleteTexture && texture->isDepthOrStencil() &&
5908             shouldSwitchToReadOnlyDepthFeedbackLoopMode(texture, command))
5909         {
5910             FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
5911             // Special handling for deferred clears.
5912             ANGLE_TRY(drawFramebufferVk->flushDeferredClears(this));
5913 
5914             if (hasStartedRenderPass())
5915             {
5916                 if (!textureVk->getImage().hasRenderPassUsageFlag(
5917                         vk::RenderPassUsage::ReadOnlyAttachment))
5918                 {
5919                     // To enter depth feedback loop, we must flush and start a new renderpass.
5920                     // Otherwise it will stick with writable layout and cause validation error.
5921                     ANGLE_TRY(flushCommandsAndEndRenderPass(
5922                         RenderPassClosureReason::DepthStencilUseInFeedbackLoop));
5923                 }
5924                 else
5925                 {
5926                     drawFramebufferVk->updateRenderPassReadOnlyDepthMode(this, mRenderPassCommands);
5927                 }
5928             }
5929 
5930             drawFramebufferVk->setReadOnlyDepthFeedbackLoopMode(true);
5931         }
5932 
5933         gl::Sampler *sampler       = mState.getSampler(static_cast<uint32_t>(textureUnit));
5934         const SamplerVk *samplerVk = sampler ? vk::GetImpl(sampler) : nullptr;
5935 
5936         const vk::SamplerHelper &samplerHelper =
5937             samplerVk ? samplerVk->getSampler() : textureVk->getSampler();
5938         const gl::SamplerState &samplerState =
5939             sampler ? sampler->getSamplerState() : texture->getSamplerState();
5940         activeTexture.texture    = textureVk;
5941         activeTexture.sampler    = &samplerHelper;
5942         activeTexture.srgbDecode = samplerState.getSRGBDecode();
5943 
5944         // GL_EXT_texture_sRGB_decode
5945         //   The new parameter, TEXTURE_SRGB_DECODE_EXT controls whether the
5946         //   decoding happens at sample time. It only applies to textures with an
5947         //   internal format that is sRGB and is ignored for all other textures.
5948         const vk::ImageHelper &image = textureVk->getImage();
5949         ASSERT(image.valid());
5950         if (image.getActualFormat().isSRGB && activeTexture.srgbDecode == GL_SKIP_DECODE_EXT)
5951         {
5952             // Make sure we use the MUTABLE bit for the storage. Because the "skip decode" is a
5953             // Sampler state we might not have caught this setting in TextureVk::syncState.
5954             ANGLE_TRY(textureVk->ensureMutable(this));
5955         }
5956 
5957         if (image.hasEmulatedImageFormat())
5958         {
5959             ANGLE_VK_PERF_WARNING(
5960                 this, GL_DEBUG_SEVERITY_LOW,
5961                 "The Vulkan driver does not support texture format 0x%04X, emulating with 0x%04X",
5962                 image.getIntendedFormat().glInternalFormat,
5963                 image.getActualFormat().glInternalFormat);
5964         }
5965 
5966         vk::ImageOrBufferViewSubresourceSerial imageViewSerial =
5967             textureVk->getImageViewSubresourceSerial(samplerState);
5968         mActiveTexturesDesc.updateTexture(textureUnit, imageViewSerial,
5969                                           samplerHelper.getSamplerSerial());
5970 
5971         if (image.hasImmutableSampler())
5972         {
5973             immutableSamplerIndexMap[image.getYcbcrConversionDesc()] =
5974                 static_cast<uint32_t>(textureUnit);
5975         }
5976 
5977         if (textureVk->getAndResetImmutableSamplerDirtyState())
5978         {
5979             recreatePipelineLayout = true;
5980         }
5981     }
5982 
5983     ProgramExecutableVk *executableVk = getExecutable();
5984     if (!executableVk->areImmutableSamplersCompatible(immutableSamplerIndexMap))
5985     {
5986         recreatePipelineLayout = true;
5987     }
5988 
5989     // Recreate the pipeline layout, if necessary.
5990     if (recreatePipelineLayout)
5991     {
5992         ANGLE_TRY(executableVk->createPipelineLayout(this, *executable, &mActiveTextures));
5993 
5994         // The default uniforms descriptor set was reset during createPipelineLayout(), so mark them
5995         // dirty to get everything reallocated/rebound before the next draw.
5996         if (executable->hasDefaultUniforms())
5997         {
5998             executableVk->setAllDefaultUniformsDirty(*executable);
5999         }
6000     }
6001 
6002     return angle::Result::Continue;
6003 }
6004 
6005 template <typename CommandBufferHelperT>
updateActiveImages(CommandBufferHelperT * commandBufferHelper)6006 angle::Result ContextVk::updateActiveImages(CommandBufferHelperT *commandBufferHelper)
6007 {
6008     const gl::State &glState                = mState;
6009     const gl::ProgramExecutable *executable = glState.getProgramExecutable();
6010     ASSERT(executable);
6011 
6012     mActiveImages.fill(nullptr);
6013 
6014     const gl::ActiveTextureMask &activeImages = executable->getActiveImagesMask();
6015     const gl::ActiveTextureArray<gl::ShaderBitSet> &activeImageShaderBits =
6016         executable->getActiveImageShaderBits();
6017 
6018     // Note: currently, the image layout is transitioned entirely even if only one level or layer is
6019     // used.  This is an issue if one subresource of the image is used as framebuffer attachment and
6020     // the other as image.  This is a similar issue to http://anglebug.com/2914.  Another issue
6021     // however is if multiple subresources of the same image are used at the same time.
6022     // Inefficiencies aside, setting write dependency on the same image multiple times is not
6023     // supported.  The following makes sure write dependencies are set only once per image.
6024     std::set<vk::ImageHelper *> alreadyProcessed;
6025 
6026     for (size_t imageUnitIndex : activeImages)
6027     {
6028         const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
6029         const gl::Texture *texture     = imageUnit.texture.get();
6030         if (texture == nullptr)
6031         {
6032             continue;
6033         }
6034 
6035         TextureVk *textureVk          = vk::GetImpl(texture);
6036         mActiveImages[imageUnitIndex] = textureVk;
6037 
6038         // The image should be flushed and ready to use at this point. There may still be
6039         // lingering staged updates in its staging buffer for unused texture mip levels or
6040         // layers. Therefore we can't verify it has no staged updates right here.
6041         gl::ShaderBitSet shaderStages = activeImageShaderBits[imageUnitIndex];
6042         ASSERT(shaderStages.any());
6043 
6044         // Special handling of texture buffers.  They have a buffer attached instead of an image.
6045         if (texture->getType() == gl::TextureType::Buffer)
6046         {
6047             BufferVk *bufferVk = vk::GetImpl(textureVk->getBuffer().get());
6048 
6049             OnImageBufferWrite(this, bufferVk, shaderStages, commandBufferHelper);
6050 
6051             textureVk->retainBufferViews(&mResourceUseList);
6052             continue;
6053         }
6054 
6055         vk::ImageHelper *image = &textureVk->getImage();
6056 
6057         if (alreadyProcessed.find(image) != alreadyProcessed.end())
6058         {
6059             continue;
6060         }
6061         alreadyProcessed.insert(image);
6062 
6063         gl::LevelIndex level;
6064         uint32_t layerStart               = 0;
6065         uint32_t layerCount               = 0;
6066         const vk::ImageLayout imageLayout = GetImageWriteLayoutAndSubresource(
6067             imageUnit, *image, shaderStages, &level, &layerStart, &layerCount);
6068 
6069         commandBufferHelper->imageWrite(this, level, layerStart, layerCount,
6070                                         image->getAspectFlags(), imageLayout,
6071                                         vk::AliasingMode::Allowed, image);
6072     }
6073 
6074     return angle::Result::Continue;
6075 }
6076 
flushImpl(const vk::Semaphore * signalSemaphore,RenderPassClosureReason renderPassClosureReason)6077 angle::Result ContextVk::flushImpl(const vk::Semaphore *signalSemaphore,
6078                                    RenderPassClosureReason renderPassClosureReason)
6079 {
6080     Serial unusedSerial;
6081     return flushAndGetSerial(signalSemaphore, &unusedSerial, renderPassClosureReason);
6082 }
6083 
flushAndGetSerial(const vk::Semaphore * signalSemaphore,Serial * submitSerialOut,RenderPassClosureReason renderPassClosureReason)6084 angle::Result ContextVk::flushAndGetSerial(const vk::Semaphore *signalSemaphore,
6085                                            Serial *submitSerialOut,
6086                                            RenderPassClosureReason renderPassClosureReason)
6087 {
6088     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::flushImpl");
6089 
6090     // We must set this to false before calling flushCommandsAndEndRenderPass to prevent it from
6091     // calling back to flushImpl.
6092     mHasDeferredFlush = false;
6093 
6094     // Avoid calling vkQueueSubmit() twice, since submitFrame() below will do that.
6095     ANGLE_TRY(flushCommandsAndEndRenderPassWithoutQueueSubmit(renderPassClosureReason));
6096 
6097     if (mIsAnyHostVisibleBufferWritten)
6098     {
6099         // Make sure all writes to host-visible buffers are flushed.  We have no way of knowing
6100         // whether any buffer will be mapped for readback in the future, and we can't afford to
6101         // flush and wait on a one-pipeline-barrier command buffer on every map().
6102         VkMemoryBarrier memoryBarrier = {};
6103         memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
6104         memoryBarrier.srcAccessMask   = VK_ACCESS_MEMORY_WRITE_BIT;
6105         memoryBarrier.dstAccessMask   = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_HOST_WRITE_BIT;
6106 
6107         const VkPipelineStageFlags supportedShaderStages =
6108             (VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
6109              VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
6110              VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
6111              VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
6112              VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT) &
6113             mRenderer->getSupportedVulkanPipelineStageMask();
6114         const VkPipelineStageFlags bufferWriteStages =
6115             VK_PIPELINE_STAGE_TRANSFER_BIT | supportedShaderStages |
6116             (getFeatures().supportsTransformFeedbackExtension.enabled
6117                  ? VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT
6118                  : 0);
6119 
6120         mOutsideRenderPassCommands->getCommandBuffer().memoryBarrier(
6121             bufferWriteStages, VK_PIPELINE_STAGE_HOST_BIT, &memoryBarrier);
6122         mIsAnyHostVisibleBufferWritten = false;
6123     }
6124 
6125     if (mGpuEventsEnabled)
6126     {
6127         EventName eventName = GetTraceEventName("Primary", mPerfCounters.primaryBuffers);
6128         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
6129                                 TRACE_EVENT_PHASE_END, eventName));
6130     }
6131     ANGLE_TRY(flushOutsideRenderPassCommands());
6132 
6133     // We must add the per context dynamic buffers into mResourceUseList before submission so that
6134     // they get retained properly until GPU completes. We do not add current buffer into
6135     // mResourceUseList since they never get reused or freed until context gets destroyed, at which
6136     // time we always wait for GPU to finish before destroying the dynamic buffers.
6137     for (DriverUniformsDescriptorSet &driverUniform : mDriverUniforms)
6138     {
6139         driverUniform.dynamicBuffer.releaseInFlightBuffersToResourceUseList(this);
6140     }
6141     mDefaultUniformStorage.releaseInFlightBuffersToResourceUseList(this);
6142 
6143     if (mHasInFlightStreamedVertexBuffers.any())
6144     {
6145         for (size_t attribIndex : mHasInFlightStreamedVertexBuffers)
6146         {
6147             mStreamedVertexBuffers[attribIndex].releaseInFlightBuffersToResourceUseList(this);
6148         }
6149         mHasInFlightStreamedVertexBuffers.reset();
6150     }
6151 
6152     ANGLE_TRY(submitFrame(signalSemaphore, submitSerialOut));
6153 
6154     ASSERT(mWaitSemaphores.empty());
6155     ASSERT(mWaitSemaphoreStageMasks.empty());
6156 
6157     mPerfCounters.primaryBuffers++;
6158 
6159     if (mGpuEventsEnabled)
6160     {
6161         EventName eventName = GetTraceEventName("Primary", mPerfCounters.primaryBuffers);
6162         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
6163                                 TRACE_EVENT_PHASE_BEGIN, eventName));
6164     }
6165 
6166     // Try to detect frame boundary for both on screen and offscreen usage by detecting
6167     // fush/finish/swap.
6168     if ((renderPassClosureReason == RenderPassClosureReason::GLFlush ||
6169          renderPassClosureReason == RenderPassClosureReason::GLFinish ||
6170          renderPassClosureReason == RenderPassClosureReason::EGLSwapBuffers) &&
6171         mShareGroupVk->isDueForBufferPoolPrune())
6172     {
6173         mShareGroupVk->pruneDefaultBufferPools(mRenderer);
6174     }
6175 
6176     return angle::Result::Continue;
6177 }
6178 
finishImpl(RenderPassClosureReason renderPassClosureReason)6179 angle::Result ContextVk::finishImpl(RenderPassClosureReason renderPassClosureReason)
6180 {
6181     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::finishImpl");
6182 
6183     ANGLE_TRY(flushImpl(nullptr, renderPassClosureReason));
6184     ANGLE_TRY(mRenderer->finish(this, hasProtectedContent()));
6185 
6186     clearAllGarbage();
6187 
6188     if (mGpuEventsEnabled)
6189     {
6190         // This loop should in practice execute once since the queue is already idle.
6191         while (mInFlightGpuEventQueries.size() > 0)
6192         {
6193             ANGLE_TRY(checkCompletedGpuEvents());
6194         }
6195         // Recalculate the CPU/GPU time difference to account for clock drifting.  Avoid
6196         // unnecessary synchronization if there is no event to be adjusted (happens when
6197         // finish() gets called multiple times towards the end of the application).
6198         if (mGpuEvents.size() > 0)
6199         {
6200             ANGLE_TRY(synchronizeCpuGpuTime());
6201         }
6202     }
6203 
6204     return angle::Result::Continue;
6205 }
6206 
addWaitSemaphore(VkSemaphore semaphore,VkPipelineStageFlags stageMask)6207 void ContextVk::addWaitSemaphore(VkSemaphore semaphore, VkPipelineStageFlags stageMask)
6208 {
6209     mWaitSemaphores.push_back(semaphore);
6210     mWaitSemaphoreStageMasks.push_back(stageMask);
6211 }
6212 
isSerialInUse(Serial serial) const6213 bool ContextVk::isSerialInUse(Serial serial) const
6214 {
6215     return serial > getLastCompletedQueueSerial();
6216 }
6217 
checkCompletedCommands()6218 angle::Result ContextVk::checkCompletedCommands()
6219 {
6220     return mRenderer->checkCompletedCommands(this);
6221 }
6222 
finishToSerial(Serial serial)6223 angle::Result ContextVk::finishToSerial(Serial serial)
6224 {
6225     return mRenderer->finishToSerial(this, serial);
6226 }
6227 
getCompatibleRenderPass(const vk::RenderPassDesc & desc,vk::RenderPass ** renderPassOut)6228 angle::Result ContextVk::getCompatibleRenderPass(const vk::RenderPassDesc &desc,
6229                                                  vk::RenderPass **renderPassOut)
6230 {
6231     // Note: Each context has it's own RenderPassCache so no locking needed.
6232     return mRenderPassCache.getCompatibleRenderPass(this, desc, renderPassOut);
6233 }
6234 
getRenderPassWithOps(const vk::RenderPassDesc & desc,const vk::AttachmentOpsArray & ops,vk::RenderPass ** renderPassOut)6235 angle::Result ContextVk::getRenderPassWithOps(const vk::RenderPassDesc &desc,
6236                                               const vk::AttachmentOpsArray &ops,
6237                                               vk::RenderPass **renderPassOut)
6238 {
6239     // Note: Each context has it's own RenderPassCache so no locking needed.
6240     return mRenderPassCache.getRenderPassWithOps(this, desc, ops, renderPassOut);
6241 }
6242 
getTimestamp(uint64_t * timestampOut)6243 angle::Result ContextVk::getTimestamp(uint64_t *timestampOut)
6244 {
6245     // The intent of this function is to query the timestamp without stalling the GPU.
6246     // Currently, that seems impossible, so instead, we are going to make a small submission
6247     // with just a timestamp query.  First, the disjoint timer query extension says:
6248     //
6249     // > This will return the GL time after all previous commands have reached the GL server but
6250     // have not yet necessarily executed.
6251     //
6252     // The previous commands may be deferred at the moment and not yet flushed. The wording allows
6253     // us to make a submission to get the timestamp without flushing.
6254     //
6255     // Second:
6256     //
6257     // > By using a combination of this synchronous get command and the asynchronous timestamp
6258     // query object target, applications can measure the latency between when commands reach the
6259     // GL server and when they are realized in the framebuffer.
6260     //
6261     // This fits with the above strategy as well, although inevitably we are possibly
6262     // introducing a GPU bubble.  This function directly generates a command buffer and submits
6263     // it instead of using the other member functions.  This is to avoid changing any state,
6264     // such as the queue serial.
6265 
6266     // Create a query used to receive the GPU timestamp
6267     VkDevice device = getDevice();
6268     vk::DeviceScoped<vk::DynamicQueryPool> timestampQueryPool(device);
6269     vk::QueryHelper timestampQuery;
6270     ANGLE_TRY(timestampQueryPool.get().init(this, VK_QUERY_TYPE_TIMESTAMP, 1));
6271     ANGLE_TRY(timestampQueryPool.get().allocateQuery(this, &timestampQuery, 1));
6272 
6273     vk::ResourceUseList scratchResourceUseList;
6274 
6275     // Record the command buffer
6276     vk::DeviceScoped<vk::PrimaryCommandBuffer> commandBatch(device);
6277     vk::PrimaryCommandBuffer &commandBuffer = commandBatch.get();
6278 
6279     ANGLE_TRY(mRenderer->getCommandBufferOneOff(this, hasProtectedContent(), &commandBuffer));
6280 
6281     timestampQuery.writeTimestampToPrimary(this, &commandBuffer);
6282     timestampQuery.retain(&scratchResourceUseList);
6283     ANGLE_VK_TRY(this, commandBuffer.end());
6284 
6285     // Create fence for the submission
6286     VkFenceCreateInfo fenceInfo = {};
6287     fenceInfo.sType             = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
6288     fenceInfo.flags             = 0;
6289 
6290     vk::DeviceScoped<vk::Fence> fence(device);
6291     ANGLE_VK_TRY(this, fence.get().init(device, fenceInfo));
6292 
6293     Serial throwAwaySerial;
6294     ANGLE_TRY(mRenderer->queueSubmitOneOff(this, std::move(commandBuffer), hasProtectedContent(),
6295                                            mContextPriority, nullptr, 0, &fence.get(),
6296                                            vk::SubmitPolicy::EnsureSubmitted, &throwAwaySerial));
6297 
6298     // Wait for the submission to finish.  Given no semaphores, there is hope that it would execute
6299     // in parallel with what's already running on the GPU.
6300     ANGLE_VK_TRY(this, fence.get().wait(device, mRenderer->getMaxFenceWaitTimeNs()));
6301     scratchResourceUseList.releaseResourceUsesAndUpdateSerials(throwAwaySerial);
6302 
6303     // Get the query results
6304     vk::QueryResult result(1);
6305     ANGLE_TRY(timestampQuery.getUint64Result(this, &result));
6306     *timestampOut = result.getResult(vk::QueryResult::kDefaultResultIndex);
6307     timestampQueryPool.get().freeQuery(this, &timestampQuery);
6308 
6309     // Convert results to nanoseconds.
6310     *timestampOut = static_cast<uint64_t>(
6311         *timestampOut *
6312         static_cast<double>(getRenderer()->getPhysicalDeviceProperties().limits.timestampPeriod));
6313 
6314     return angle::Result::Continue;
6315 }
6316 
invalidateDefaultAttribute(size_t attribIndex)6317 void ContextVk::invalidateDefaultAttribute(size_t attribIndex)
6318 {
6319     mDirtyDefaultAttribsMask.set(attribIndex);
6320     mGraphicsDirtyBits.set(DIRTY_BIT_DEFAULT_ATTRIBS);
6321 }
6322 
invalidateDefaultAttributes(const gl::AttributesMask & dirtyMask)6323 void ContextVk::invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask)
6324 {
6325     if (dirtyMask.any())
6326     {
6327         mDirtyDefaultAttribsMask |= dirtyMask;
6328         mGraphicsDirtyBits.set(DIRTY_BIT_DEFAULT_ATTRIBS);
6329         mGraphicsDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
6330     }
6331 }
6332 
getDriverUniformsDescriptorSetDesc() const6333 vk::DescriptorSetLayoutDesc ContextVk::getDriverUniformsDescriptorSetDesc() const
6334 {
6335     constexpr VkShaderStageFlags kShaderStages =
6336         VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT;
6337 
6338     vk::DescriptorSetLayoutDesc desc;
6339     desc.update(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, kShaderStages, nullptr);
6340     return desc;
6341 }
6342 
shouldEmulateSeamfulCubeMapSampling() const6343 bool ContextVk::shouldEmulateSeamfulCubeMapSampling() const
6344 {
6345     // Only allow seamful cube map sampling in non-webgl ES2.
6346     if (mState.getClientMajorVersion() != 2 || mState.isWebGL())
6347     {
6348         return false;
6349     }
6350 
6351     if (mRenderer->getFeatures().disallowSeamfulCubeMapEmulation.enabled)
6352     {
6353         return false;
6354     }
6355 
6356     return true;
6357 }
6358 
onBufferReleaseToExternal(const vk::BufferHelper & buffer)6359 angle::Result ContextVk::onBufferReleaseToExternal(const vk::BufferHelper &buffer)
6360 {
6361     if (mRenderPassCommands->usesBuffer(buffer))
6362     {
6363         return flushCommandsAndEndRenderPass(
6364             RenderPassClosureReason::BufferUseThenReleaseToExternal);
6365     }
6366     return angle::Result::Continue;
6367 }
6368 
onImageReleaseToExternal(const vk::ImageHelper & image)6369 angle::Result ContextVk::onImageReleaseToExternal(const vk::ImageHelper &image)
6370 {
6371     if (IsRenderPassStartedAndUsesImage(*mRenderPassCommands, image))
6372     {
6373         return flushCommandsAndEndRenderPass(
6374             RenderPassClosureReason::ImageUseThenReleaseToExternal);
6375     }
6376     return angle::Result::Continue;
6377 }
6378 
beginNewRenderPass(const vk::Framebuffer & 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)6379 angle::Result ContextVk::beginNewRenderPass(
6380     const vk::Framebuffer &framebuffer,
6381     const gl::Rectangle &renderArea,
6382     const vk::RenderPassDesc &renderPassDesc,
6383     const vk::AttachmentOpsArray &renderPassAttachmentOps,
6384     const vk::PackedAttachmentCount colorAttachmentCount,
6385     const vk::PackedAttachmentIndex depthStencilAttachmentIndex,
6386     const vk::PackedClearValuesArray &clearValues,
6387     vk::RenderPassCommandBuffer **commandBufferOut)
6388 {
6389     // Next end any currently outstanding render pass.  The render pass is normally closed before
6390     // reaching here for various reasons, except typically when UtilsVk needs to start one.
6391     ANGLE_TRY(flushCommandsAndEndRenderPass(RenderPassClosureReason::NewRenderPass));
6392 
6393     mPerfCounters.renderPasses++;
6394     return mRenderPassCommands->beginRenderPass(
6395         this, framebuffer, renderArea, renderPassDesc, renderPassAttachmentOps,
6396         colorAttachmentCount, depthStencilAttachmentIndex, clearValues, commandBufferOut);
6397 }
6398 
startRenderPass(gl::Rectangle renderArea,vk::RenderPassCommandBuffer ** commandBufferOut,bool * renderPassDescChangedOut)6399 angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea,
6400                                          vk::RenderPassCommandBuffer **commandBufferOut,
6401                                          bool *renderPassDescChangedOut)
6402 {
6403     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
6404     ASSERT(drawFramebufferVk == vk::GetImpl(mState.getDrawFramebuffer()));
6405 
6406     ANGLE_TRY(drawFramebufferVk->startNewRenderPass(this, renderArea, &mRenderPassCommandBuffer,
6407                                                     renderPassDescChangedOut));
6408 
6409     // Make sure the render pass is not restarted if it is started by UtilsVk (as opposed to
6410     // setupDraw(), which clears this bit automatically).
6411     mGraphicsDirtyBits.reset(DIRTY_BIT_RENDER_PASS);
6412 
6413     ANGLE_TRY(resumeRenderPassQueriesIfActive());
6414 
6415     if (commandBufferOut)
6416     {
6417         *commandBufferOut = mRenderPassCommandBuffer;
6418     }
6419 
6420     return angle::Result::Continue;
6421 }
6422 
startNextSubpass()6423 angle::Result ContextVk::startNextSubpass()
6424 {
6425     ASSERT(hasStartedRenderPass());
6426 
6427     // The graphics pipelines are bound to a subpass, so update the subpass as well.
6428     mGraphicsPipelineDesc->nextSubpass(&mGraphicsPipelineTransition);
6429 
6430     return mRenderPassCommands->nextSubpass(this, &mRenderPassCommandBuffer);
6431 }
6432 
restoreFinishedRenderPass(vk::Framebuffer * framebuffer)6433 void ContextVk::restoreFinishedRenderPass(vk::Framebuffer *framebuffer)
6434 {
6435     if (mRenderPassCommandBuffer != nullptr)
6436     {
6437         // The render pass isn't finished yet, so nothing to restore.
6438         return;
6439     }
6440 
6441     if (mRenderPassCommands->started() &&
6442         mRenderPassCommands->getFramebufferHandle() == framebuffer->getHandle())
6443     {
6444         // There is already a render pass open for this framebuffer, so just restore the
6445         // pointer rather than starting a whole new render pass. One possible path here
6446         // is if the draw framebuffer binding has changed from FBO A -> B -> A, without
6447         // any commands that started a new render pass for FBO B (such as a clear being
6448         // issued that was deferred).
6449         mRenderPassCommandBuffer = &mRenderPassCommands->getCommandBuffer();
6450         ASSERT(hasStartedRenderPass());
6451     }
6452 }
6453 
getCurrentSubpassIndex() const6454 uint32_t ContextVk::getCurrentSubpassIndex() const
6455 {
6456     return mGraphicsPipelineDesc->getSubpass();
6457 }
6458 
getCurrentViewCount() const6459 uint32_t ContextVk::getCurrentViewCount() const
6460 {
6461     FramebufferVk *drawFBO = vk::GetImpl(mState.getDrawFramebuffer());
6462     return drawFBO->getRenderPassDesc().viewCount();
6463 }
6464 
flushCommandsAndEndRenderPassImpl(QueueSubmitType queueSubmit,RenderPassClosureReason reason)6465 angle::Result ContextVk::flushCommandsAndEndRenderPassImpl(QueueSubmitType queueSubmit,
6466                                                            RenderPassClosureReason reason)
6467 {
6468     // Ensure we flush the RenderPass *after* the prior commands.
6469     ANGLE_TRY(flushOutsideRenderPassCommands());
6470     ASSERT(mOutsideRenderPassCommands->empty());
6471 
6472     if (!mRenderPassCommands->started())
6473     {
6474         onRenderPassFinished(RenderPassClosureReason::AlreadySpecifiedElsewhere);
6475         return angle::Result::Continue;
6476     }
6477 
6478     // Set dirty bits if render pass was open (and thus will be closed).
6479     mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
6480     // Restart at subpass 0.
6481     mGraphicsPipelineDesc->resetSubpass(&mGraphicsPipelineTransition);
6482 
6483     mCurrentTransformFeedbackBuffers.clear();
6484 
6485     // Reset serials for XFB if active.
6486     if (mState.isTransformFeedbackActiveUnpaused())
6487     {
6488         const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6489         ASSERT(executable);
6490         size_t xfbBufferCount = executable->getTransformFeedbackBufferCount();
6491 
6492         TransformFeedbackVk *transformFeedbackVk =
6493             vk::GetImpl(mState.getCurrentTransformFeedback());
6494 
6495         populateTransformFeedbackBufferSet(xfbBufferCount, transformFeedbackVk->getBufferHelpers());
6496     }
6497 
6498     onRenderPassFinished(reason);
6499 
6500     if (mGpuEventsEnabled)
6501     {
6502         EventName eventName = GetTraceEventName("RP", mPerfCounters.renderPasses);
6503         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
6504                                 TRACE_EVENT_PHASE_BEGIN, eventName));
6505         ANGLE_TRY(flushOutsideRenderPassCommands());
6506     }
6507 
6508     addOverlayUsedBuffersCount(mRenderPassCommands);
6509 
6510     pauseTransformFeedbackIfActiveUnpaused();
6511 
6512     ANGLE_TRY(mRenderPassCommands->endRenderPass(this));
6513 
6514     if (vk::CommandBufferHelperCommon::kEnableCommandStreamDiagnostics)
6515     {
6516         mRenderPassCommands->addCommandDiagnostics(this);
6517     }
6518 
6519     vk::RenderPass *renderPass = nullptr;
6520     ANGLE_TRY(getRenderPassWithOps(mRenderPassCommands->getRenderPassDesc(),
6521                                    mRenderPassCommands->getAttachmentOps(), &renderPass));
6522 
6523     flushDescriptorSetUpdates();
6524 
6525     getShareGroupVk()->acquireResourceUseList(std::move(mRenderPassCommands->getResourceUseList()));
6526 
6527     ANGLE_TRY(mRenderer->flushRenderPassCommands(this, hasProtectedContent(), *renderPass,
6528                                                  &mRenderPassCommands));
6529 
6530     if (mGpuEventsEnabled)
6531     {
6532         EventName eventName = GetTraceEventName("RP", mPerfCounters.renderPasses);
6533         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
6534                                 TRACE_EVENT_PHASE_END, eventName));
6535         ANGLE_TRY(flushOutsideRenderPassCommands());
6536     }
6537 
6538     if (mHasDeferredFlush && queueSubmit == QueueSubmitType::PerformQueueSubmit)
6539     {
6540         // If we have deferred glFlush call in the middle of renderpass, flush them now.
6541         ANGLE_TRY(flushImpl(nullptr, RenderPassClosureReason::AlreadySpecifiedElsewhere));
6542     }
6543 
6544     return angle::Result::Continue;
6545 }
6546 
flushCommandsAndEndRenderPass(RenderPassClosureReason reason)6547 angle::Result ContextVk::flushCommandsAndEndRenderPass(RenderPassClosureReason reason)
6548 {
6549     return flushCommandsAndEndRenderPassImpl(QueueSubmitType::PerformQueueSubmit, reason);
6550 }
6551 
flushCommandsAndEndRenderPassWithoutQueueSubmit(RenderPassClosureReason reason)6552 angle::Result ContextVk::flushCommandsAndEndRenderPassWithoutQueueSubmit(
6553     RenderPassClosureReason reason)
6554 {
6555     return flushCommandsAndEndRenderPassImpl(QueueSubmitType::SkipQueueSubmit, reason);
6556 }
6557 
flushDirtyGraphicsRenderPass(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask,RenderPassClosureReason reason)6558 angle::Result ContextVk::flushDirtyGraphicsRenderPass(DirtyBits::Iterator *dirtyBitsIterator,
6559                                                       DirtyBits dirtyBitMask,
6560                                                       RenderPassClosureReason reason)
6561 {
6562     ASSERT(mRenderPassCommands->started());
6563 
6564     ANGLE_TRY(flushCommandsAndEndRenderPassImpl(QueueSubmitType::PerformQueueSubmit, reason));
6565 
6566     // Set dirty bits that need processing on new render pass on the dirty bits iterator that's
6567     // being processed right now.
6568     dirtyBitsIterator->setLaterBits(mNewGraphicsCommandBufferDirtyBits & dirtyBitMask);
6569 
6570     // Additionally, make sure any dirty bits not included in the mask are left for future
6571     // processing.  Note that |dirtyBitMask| is removed from |mNewGraphicsCommandBufferDirtyBits|
6572     // after dirty bits are iterated, so there's no need to mask them out.
6573     mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
6574 
6575     // Restart at subpass 0.
6576     mGraphicsPipelineDesc->resetSubpass(&mGraphicsPipelineTransition);
6577 
6578     return angle::Result::Continue;
6579 }
6580 
syncExternalMemory()6581 angle::Result ContextVk::syncExternalMemory()
6582 {
6583     VkMemoryBarrier memoryBarrier = {};
6584     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
6585     memoryBarrier.srcAccessMask   = VK_ACCESS_MEMORY_WRITE_BIT;
6586     memoryBarrier.dstAccessMask   = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
6587 
6588     mOutsideRenderPassCommands->getCommandBuffer().memoryBarrier(
6589         VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memoryBarrier);
6590     return angle::Result::Continue;
6591 }
6592 
addCommandBufferDiagnostics(const std::string & commandBufferDiagnostics)6593 void ContextVk::addCommandBufferDiagnostics(const std::string &commandBufferDiagnostics)
6594 {
6595     mCommandBufferDiagnostics.push_back(commandBufferDiagnostics);
6596 }
6597 
dumpCommandStreamDiagnostics()6598 void ContextVk::dumpCommandStreamDiagnostics()
6599 {
6600     std::ostream &out = std::cout;
6601 
6602     if (mCommandBufferDiagnostics.empty())
6603         return;
6604 
6605     out << "digraph {\n"
6606         << "  node [shape=plaintext fontname=\"Consolas\"]\n";
6607 
6608     for (size_t index = 0; index < mCommandBufferDiagnostics.size(); ++index)
6609     {
6610         const std::string &payload = mCommandBufferDiagnostics[index];
6611         out << "  cb" << index << " [label =\"" << payload << "\"];\n";
6612     }
6613 
6614     for (size_t index = 0; index < mCommandBufferDiagnostics.size() - 1; ++index)
6615     {
6616         out << "  cb" << index << " -> cb" << index + 1 << "\n";
6617     }
6618 
6619     mCommandBufferDiagnostics.clear();
6620 
6621     out << "}\n";
6622 }
6623 
initIndexTypeMap()6624 void ContextVk::initIndexTypeMap()
6625 {
6626     // Init gles-vulkan index type map
6627     mIndexTypeMap[gl::DrawElementsType::UnsignedByte] =
6628         mRenderer->getFeatures().supportsIndexTypeUint8.enabled ? VK_INDEX_TYPE_UINT8_EXT
6629                                                                 : VK_INDEX_TYPE_UINT16;
6630     mIndexTypeMap[gl::DrawElementsType::UnsignedShort] = VK_INDEX_TYPE_UINT16;
6631     mIndexTypeMap[gl::DrawElementsType::UnsignedInt]   = VK_INDEX_TYPE_UINT32;
6632 }
6633 
getVkIndexType(gl::DrawElementsType glIndexType) const6634 VkIndexType ContextVk::getVkIndexType(gl::DrawElementsType glIndexType) const
6635 {
6636     return mIndexTypeMap[glIndexType];
6637 }
6638 
getVkIndexTypeSize(gl::DrawElementsType glIndexType) const6639 size_t ContextVk::getVkIndexTypeSize(gl::DrawElementsType glIndexType) const
6640 {
6641     gl::DrawElementsType elementsType = shouldConvertUint8VkIndexType(glIndexType)
6642                                             ? gl::DrawElementsType::UnsignedShort
6643                                             : glIndexType;
6644     ASSERT(elementsType < gl::DrawElementsType::EnumCount);
6645 
6646     // Use GetDrawElementsTypeSize() to get the size
6647     return static_cast<size_t>(gl::GetDrawElementsTypeSize(elementsType));
6648 }
6649 
shouldConvertUint8VkIndexType(gl::DrawElementsType glIndexType) const6650 bool ContextVk::shouldConvertUint8VkIndexType(gl::DrawElementsType glIndexType) const
6651 {
6652     return (glIndexType == gl::DrawElementsType::UnsignedByte &&
6653             !mRenderer->getFeatures().supportsIndexTypeUint8.enabled);
6654 }
6655 
submitOutsideRenderPassCommandsImpl()6656 angle::Result ContextVk::submitOutsideRenderPassCommandsImpl()
6657 {
6658     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::submitOutsideRenderPassCommandsImpl");
6659     ANGLE_TRY(flushOutsideRenderPassCommands());
6660     Serial unusedSerial;
6661     ANGLE_TRY(submitFrameOutsideCommandBufferOnly(&unusedSerial));
6662     return angle::Result::Continue;
6663 }
6664 
flushOutsideRenderPassCommands()6665 angle::Result ContextVk::flushOutsideRenderPassCommands()
6666 {
6667     if (mOutsideRenderPassCommands->empty())
6668     {
6669         return angle::Result::Continue;
6670     }
6671 
6672     addOverlayUsedBuffersCount(mOutsideRenderPassCommands);
6673 
6674     if (vk::CommandBufferHelperCommon::kEnableCommandStreamDiagnostics)
6675     {
6676         mOutsideRenderPassCommands->addCommandDiagnostics(this);
6677     }
6678 
6679     flushDescriptorSetUpdates();
6680 
6681     getShareGroupVk()->acquireResourceUseList(
6682         std::move(mOutsideRenderPassCommands->getResourceUseList()));
6683 
6684     ANGLE_TRY(mRenderer->flushOutsideRPCommands(this, hasProtectedContent(),
6685                                                 &mOutsideRenderPassCommands));
6686 
6687     // Make sure appropriate dirty bits are set, in case another thread makes a submission before
6688     // the next dispatch call.
6689     mComputeDirtyBits |= mNewComputeCommandBufferDirtyBits;
6690 
6691     mPerfCounters.flushedOutsideRenderPassCommandBuffers++;
6692     return angle::Result::Continue;
6693 }
6694 
beginRenderPassQuery(QueryVk * queryVk)6695 angle::Result ContextVk::beginRenderPassQuery(QueryVk *queryVk)
6696 {
6697     // Emit debug-util markers before calling the query command.
6698     ANGLE_TRY(handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd));
6699 
6700     // To avoid complexity, we always start and end these queries inside the render pass.  If the
6701     // render pass has not yet started, the query is deferred until it does.
6702     if (mRenderPassCommandBuffer)
6703     {
6704         ANGLE_TRY(queryVk->getQueryHelper()->beginRenderPassQuery(this));
6705     }
6706 
6707     // Update rasterizer discard emulation with primitives generated query if necessary.
6708     if (queryVk->getType() == gl::QueryType::PrimitivesGenerated)
6709     {
6710         updateRasterizerDiscardEnabled(true);
6711     }
6712 
6713     gl::QueryType type = queryVk->getType();
6714 
6715     ASSERT(mActiveRenderPassQueries[type] == nullptr);
6716     mActiveRenderPassQueries[type] = queryVk;
6717 
6718     return angle::Result::Continue;
6719 }
6720 
endRenderPassQuery(QueryVk * queryVk)6721 angle::Result ContextVk::endRenderPassQuery(QueryVk *queryVk)
6722 {
6723     gl::QueryType type = queryVk->getType();
6724 
6725     // Emit debug-util markers before calling the query command.
6726     ANGLE_TRY(handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd));
6727 
6728     // End the query inside the render pass.  In some situations, the query may not have actually
6729     // been issued, so there is nothing to do there.  That is the case for transform feedback
6730     // queries which are deferred until a draw call with transform feedback active is issued, which
6731     // may have never happened.
6732     ASSERT(mRenderPassCommandBuffer == nullptr ||
6733            type == gl::QueryType::TransformFeedbackPrimitivesWritten || queryVk->hasQueryBegun());
6734     if (mRenderPassCommandBuffer && queryVk->hasQueryBegun())
6735     {
6736         queryVk->getQueryHelper()->endRenderPassQuery(this);
6737     }
6738 
6739     // Update rasterizer discard emulation with primitives generated query if necessary.
6740     if (type == gl::QueryType::PrimitivesGenerated)
6741     {
6742         updateRasterizerDiscardEnabled(false);
6743     }
6744 
6745     ASSERT(mActiveRenderPassQueries[type] == queryVk);
6746     mActiveRenderPassQueries[type] = nullptr;
6747 
6748     return angle::Result::Continue;
6749 }
6750 
pauseRenderPassQueriesIfActive()6751 void ContextVk::pauseRenderPassQueriesIfActive()
6752 {
6753     if (mRenderPassCommandBuffer == nullptr)
6754     {
6755         return;
6756     }
6757 
6758     for (QueryVk *activeQuery : mActiveRenderPassQueries)
6759     {
6760         if (activeQuery)
6761         {
6762             activeQuery->onRenderPassEnd(this);
6763 
6764             // No need to update rasterizer discard emulation with primitives generated query.  The
6765             // state will be updated when the next render pass starts.
6766         }
6767     }
6768 }
6769 
resumeRenderPassQueriesIfActive()6770 angle::Result ContextVk::resumeRenderPassQueriesIfActive()
6771 {
6772     ASSERT(mRenderPassCommandBuffer);
6773 
6774     // Note: these queries should be processed in order.  See comment in QueryVk::onRenderPassStart.
6775     for (QueryVk *activeQuery : mActiveRenderPassQueries)
6776     {
6777         if (activeQuery)
6778         {
6779             // Transform feedback queries are handled separately.
6780             if (activeQuery->getType() == gl::QueryType::TransformFeedbackPrimitivesWritten)
6781             {
6782                 continue;
6783             }
6784 
6785             ANGLE_TRY(activeQuery->onRenderPassStart(this));
6786 
6787             // Update rasterizer discard emulation with primitives generated query if necessary.
6788             if (activeQuery->getType() == gl::QueryType::PrimitivesGenerated)
6789             {
6790                 updateRasterizerDiscardEnabled(true);
6791             }
6792         }
6793     }
6794 
6795     return angle::Result::Continue;
6796 }
6797 
resumeXfbRenderPassQueriesIfActive()6798 angle::Result ContextVk::resumeXfbRenderPassQueriesIfActive()
6799 {
6800     ASSERT(mRenderPassCommandBuffer);
6801 
6802     // All other queries are handled separately.
6803     QueryVk *xfbQuery = mActiveRenderPassQueries[gl::QueryType::TransformFeedbackPrimitivesWritten];
6804     if (xfbQuery && mState.isTransformFeedbackActiveUnpaused())
6805     {
6806         ANGLE_TRY(xfbQuery->onRenderPassStart(this));
6807     }
6808 
6809     return angle::Result::Continue;
6810 }
6811 
doesPrimitivesGeneratedQuerySupportRasterizerDiscard() const6812 bool ContextVk::doesPrimitivesGeneratedQuerySupportRasterizerDiscard() const
6813 {
6814     // TODO: If primitives generated is implemented with VK_EXT_primitives_generated_query, check
6815     // the corresponding feature bit.  http://anglebug.com/5430.
6816 
6817     // If primitives generated is emulated with pipeline statistics query, it's unknown on which
6818     // hardware rasterizer discard is supported.  Assume it's supported on none.
6819     if (getFeatures().supportsPipelineStatisticsQuery.enabled)
6820     {
6821         return false;
6822     }
6823 
6824     return true;
6825 }
6826 
isEmulatingRasterizerDiscardDuringPrimitivesGeneratedQuery(bool isPrimitivesGeneratedQueryActive) const6827 bool ContextVk::isEmulatingRasterizerDiscardDuringPrimitivesGeneratedQuery(
6828     bool isPrimitivesGeneratedQueryActive) const
6829 {
6830     return isPrimitivesGeneratedQueryActive && mState.isRasterizerDiscardEnabled() &&
6831            !doesPrimitivesGeneratedQuerySupportRasterizerDiscard();
6832 }
6833 
getActiveRenderPassQuery(gl::QueryType queryType) const6834 QueryVk *ContextVk::getActiveRenderPassQuery(gl::QueryType queryType) const
6835 {
6836     return mActiveRenderPassQueries[queryType];
6837 }
6838 
isRobustResourceInitEnabled() const6839 bool ContextVk::isRobustResourceInitEnabled() const
6840 {
6841     return mState.isRobustResourceInitEnabled();
6842 }
6843 
setDefaultUniformBlocksMinSizeForTesting(size_t minSize)6844 void ContextVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize)
6845 {
6846     mDefaultUniformStorage.setMinimumSizeForTesting(minSize);
6847 }
6848 
initializeMultisampleTextureToBlack(const gl::Context * context,gl::Texture * glTexture)6849 angle::Result ContextVk::initializeMultisampleTextureToBlack(const gl::Context *context,
6850                                                              gl::Texture *glTexture)
6851 {
6852     ASSERT(glTexture->getType() == gl::TextureType::_2DMultisample);
6853     TextureVk *textureVk = vk::GetImpl(glTexture);
6854 
6855     return textureVk->initializeContents(context, gl::ImageIndex::Make2DMultisample());
6856 }
6857 
onProgramExecutableReset(ProgramExecutableVk * executableVk)6858 void ContextVk::onProgramExecutableReset(ProgramExecutableVk *executableVk)
6859 {
6860     const gl::ProgramExecutable *executable = getState().getProgramExecutable();
6861     if (!executable)
6862     {
6863         return;
6864     }
6865 
6866     // Only do this for the currently bound ProgramExecutableVk, since Program A can be linked while
6867     // Program B is currently in use and we don't want to reset/invalidate Program B's pipeline.
6868     if (executableVk != getExecutable())
6869     {
6870         return;
6871     }
6872 
6873     // Reset *ContextVk::mCurrentGraphicsPipeline, since programInfo.release() freed the
6874     // PipelineHelper that it's currently pointing to.
6875     // TODO(http://anglebug.com/5624): rework updateActiveTextures(), createPipelineLayout(),
6876     // handleDirtyGraphicsPipeline(), and ProgramPipelineVk::link().
6877     resetCurrentGraphicsPipeline();
6878 
6879     if (executable->hasLinkedShaderStage(gl::ShaderType::Compute))
6880     {
6881         invalidateCurrentComputePipeline();
6882     }
6883 
6884     if (executable->hasLinkedShaderStage(gl::ShaderType::Vertex))
6885     {
6886         invalidateCurrentGraphicsPipeline();
6887     }
6888 }
6889 
shouldSwitchToReadOnlyDepthFeedbackLoopMode(gl::Texture * texture,gl::Command command) const6890 bool ContextVk::shouldSwitchToReadOnlyDepthFeedbackLoopMode(gl::Texture *texture,
6891                                                             gl::Command command) const
6892 {
6893     ASSERT(texture->isDepthOrStencil());
6894 
6895     // When running compute we don't have a draw FBO.
6896     if (command == gl::Command::Dispatch)
6897     {
6898         return false;
6899     }
6900 
6901     // The "readOnlyDepthMode" feature enables read-only depth-stencil feedback loops. We
6902     // only switch to "read-only" mode when there's loop. We track the depth-stencil access
6903     // mode in the RenderPass. The tracking tells us when we can retroactively go back and
6904     // change the RenderPass to read-only. If there are any writes we need to break and
6905     // finish the current RP before starting the read-only one.
6906     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
6907     return texture->isBoundToFramebuffer(drawFramebufferVk->getState().getFramebufferSerial()) &&
6908            !mState.isDepthWriteEnabled() && !drawFramebufferVk->isReadOnlyDepthFeedbackLoopMode();
6909 }
6910 
onResourceAccess(const vk::CommandBufferAccess & access)6911 angle::Result ContextVk::onResourceAccess(const vk::CommandBufferAccess &access)
6912 {
6913     ANGLE_TRY(flushCommandBuffersIfNecessary(access));
6914 
6915     vk::OutsideRenderPassCommandBuffer *commandBuffer =
6916         &mOutsideRenderPassCommands->getCommandBuffer();
6917 
6918     for (const vk::CommandBufferImageAccess &imageAccess : access.getReadImages())
6919     {
6920         ASSERT(!IsRenderPassStartedAndUsesImage(*mRenderPassCommands, *imageAccess.image));
6921 
6922         imageAccess.image->recordReadBarrier(this, imageAccess.aspectFlags, imageAccess.imageLayout,
6923                                              commandBuffer);
6924         imageAccess.image->retain(&mResourceUseList);
6925     }
6926 
6927     for (const vk::CommandBufferImageWrite &imageWrite : access.getWriteImages())
6928     {
6929         ASSERT(!IsRenderPassStartedAndUsesImage(*mRenderPassCommands, *imageWrite.access.image));
6930 
6931         imageWrite.access.image->recordWriteBarrier(this, imageWrite.access.aspectFlags,
6932                                                     imageWrite.access.imageLayout, commandBuffer);
6933         imageWrite.access.image->retain(&mResourceUseList);
6934         imageWrite.access.image->onWrite(imageWrite.levelStart, imageWrite.levelCount,
6935                                          imageWrite.layerStart, imageWrite.layerCount,
6936                                          imageWrite.access.aspectFlags);
6937     }
6938 
6939     for (const vk::CommandBufferBufferAccess &bufferAccess : access.getReadBuffers())
6940     {
6941         ASSERT(!mRenderPassCommands->usesBufferForWrite(*bufferAccess.buffer));
6942         ASSERT(!mOutsideRenderPassCommands->usesBufferForWrite(*bufferAccess.buffer));
6943 
6944         mOutsideRenderPassCommands->bufferRead(this, bufferAccess.accessType, bufferAccess.stage,
6945                                                bufferAccess.buffer);
6946     }
6947 
6948     for (const vk::CommandBufferBufferAccess &bufferAccess : access.getWriteBuffers())
6949     {
6950         ASSERT(!mRenderPassCommands->usesBuffer(*bufferAccess.buffer));
6951         ASSERT(!mOutsideRenderPassCommands->usesBuffer(*bufferAccess.buffer));
6952 
6953         mOutsideRenderPassCommands->bufferWrite(this, bufferAccess.accessType, bufferAccess.stage,
6954                                                 vk::AliasingMode::Disallowed, bufferAccess.buffer);
6955     }
6956 
6957     return angle::Result::Continue;
6958 }
6959 
flushCommandBuffersIfNecessary(const vk::CommandBufferAccess & access)6960 angle::Result ContextVk::flushCommandBuffersIfNecessary(const vk::CommandBufferAccess &access)
6961 {
6962     // Go over resources and decide whether the render pass needs to close, whether the outside
6963     // render pass commands need to be flushed, or neither.  Note that closing the render pass
6964     // implies flushing the outside render pass as well, so if that needs to be done, we can close
6965     // the render pass and immediately return from this function.  Otherwise, this function keeps
6966     // track of whether the outside render pass commands need to be closed, and if so, it will do
6967     // that once at the end.
6968 
6969     // Read images only need to close the render pass if they need a layout transition.
6970     for (const vk::CommandBufferImageAccess &imageAccess : access.getReadImages())
6971     {
6972         // Note that different read methods are not compatible. A shader read uses a different
6973         // layout than a transfer read. So we cannot support simultaneous read usage as easily as
6974         // for Buffers.  TODO: Don't close the render pass if the image was only used read-only in
6975         // the render pass.  http://anglebug.com/4984
6976         if (IsRenderPassStartedAndUsesImage(*mRenderPassCommands, *imageAccess.image))
6977         {
6978             return flushCommandsAndEndRenderPass(RenderPassClosureReason::ImageUseThenOutOfRPRead);
6979         }
6980     }
6981 
6982     // Write images only need to close the render pass if they need a layout transition.
6983     for (const vk::CommandBufferImageWrite &imageWrite : access.getWriteImages())
6984     {
6985         if (IsRenderPassStartedAndUsesImage(*mRenderPassCommands, *imageWrite.access.image))
6986         {
6987             return flushCommandsAndEndRenderPass(RenderPassClosureReason::ImageUseThenOutOfRPWrite);
6988         }
6989     }
6990 
6991     bool shouldCloseOutsideRenderPassCommands = false;
6992 
6993     // Read buffers only need a new command buffer if previously used for write.
6994     for (const vk::CommandBufferBufferAccess &bufferAccess : access.getReadBuffers())
6995     {
6996         if (mRenderPassCommands->usesBufferForWrite(*bufferAccess.buffer))
6997         {
6998             return flushCommandsAndEndRenderPass(RenderPassClosureReason::BufferUseThenOutOfRPRead);
6999         }
7000         else if (mOutsideRenderPassCommands->usesBufferForWrite(*bufferAccess.buffer))
7001         {
7002             shouldCloseOutsideRenderPassCommands = true;
7003         }
7004     }
7005 
7006     // Write buffers always need a new command buffer if previously used.
7007     for (const vk::CommandBufferBufferAccess &bufferAccess : access.getWriteBuffers())
7008     {
7009         if (mRenderPassCommands->usesBuffer(*bufferAccess.buffer))
7010         {
7011             return flushCommandsAndEndRenderPass(
7012                 RenderPassClosureReason::BufferUseThenOutOfRPWrite);
7013         }
7014         else if (mOutsideRenderPassCommands->usesBuffer(*bufferAccess.buffer))
7015         {
7016             shouldCloseOutsideRenderPassCommands = true;
7017         }
7018     }
7019 
7020     if (shouldCloseOutsideRenderPassCommands)
7021     {
7022         return flushOutsideRenderPassCommands();
7023     }
7024 
7025     return angle::Result::Continue;
7026 }
7027 
endRenderPassIfComputeReadAfterTransformFeedbackWrite()7028 angle::Result ContextVk::endRenderPassIfComputeReadAfterTransformFeedbackWrite()
7029 {
7030     // Similar to flushCommandBuffersIfNecessary(), but using uniform buffers currently bound and
7031     // used by the current (compute) program.  This is to handle read-after-write hazards where the
7032     // write originates from transform feedback.
7033     if (mCurrentTransformFeedbackBuffers.empty())
7034     {
7035         return angle::Result::Continue;
7036     }
7037 
7038     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
7039     ASSERT(executable && executable->hasLinkedShaderStage(gl::ShaderType::Compute));
7040 
7041     // Uniform buffers:
7042     const std::vector<gl::InterfaceBlock> &blocks = executable->getUniformBlocks();
7043 
7044     for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
7045     {
7046         const gl::InterfaceBlock &block = blocks[bufferIndex];
7047         const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
7048             mState.getIndexedUniformBuffer(block.binding);
7049 
7050         if (bufferBinding.get() == nullptr)
7051         {
7052             continue;
7053         }
7054 
7055         vk::BufferHelper &buffer = vk::GetImpl(bufferBinding.get())->getBuffer();
7056         if (mCurrentTransformFeedbackBuffers.contains(&buffer))
7057         {
7058             return flushCommandsAndEndRenderPass(RenderPassClosureReason::XfbWriteThenComputeRead);
7059         }
7060     }
7061 
7062     return angle::Result::Continue;
7063 }
7064 
endRenderPassIfComputeReadAfterAttachmentWrite()7065 angle::Result ContextVk::endRenderPassIfComputeReadAfterAttachmentWrite()
7066 {
7067     // Similar to flushCommandBuffersIfNecessary(), but using textures currently bound and used by
7068     // the current (compute) program.  This is to handle read-after-write hazards where the write
7069     // originates from a framebuffer attachment.
7070     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
7071     ASSERT(executable && executable->hasLinkedShaderStage(gl::ShaderType::Compute) &&
7072            executable->hasTextures());
7073 
7074     const gl::ActiveTexturesCache &textures        = mState.getActiveTexturesCache();
7075     const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
7076 
7077     for (size_t textureUnit : executable->getActiveSamplersMask())
7078     {
7079         gl::Texture *texture        = textures[textureUnit];
7080         gl::TextureType textureType = textureTypes[textureUnit];
7081 
7082         if (texture == nullptr || textureType == gl::TextureType::Buffer)
7083         {
7084             continue;
7085         }
7086 
7087         TextureVk *textureVk = vk::GetImpl(texture);
7088         ASSERT(textureVk != nullptr);
7089         vk::ImageHelper &image = textureVk->getImage();
7090 
7091         if (IsRenderPassStartedAndUsesImage(*mRenderPassCommands, image))
7092         {
7093             return flushCommandsAndEndRenderPass(
7094                 RenderPassClosureReason::ImageAttachmentThenComputeRead);
7095         }
7096     }
7097 
7098     return angle::Result::Continue;
7099 }
7100 
getExecutable() const7101 ProgramExecutableVk *ContextVk::getExecutable() const
7102 {
7103     gl::Program *program = mState.getProgram();
7104     if (program)
7105     {
7106         if (!program->hasLinkingState())
7107         {
7108             return &vk::GetImpl(program)->getExecutable();
7109         }
7110     }
7111     else
7112     {
7113         ProgramPipelineVk *programPipelineVk = getProgramPipeline();
7114         if (programPipelineVk)
7115         {
7116             return &programPipelineVk->getExecutable();
7117         }
7118     }
7119     return nullptr;
7120 }
7121 
getPerfMonitorCounters()7122 const angle::PerfMonitorCounterGroups &ContextVk::getPerfMonitorCounters()
7123 {
7124     syncObjectPerfCounters();
7125 
7126     angle::PerfMonitorCounters &counters =
7127         angle::GetPerfMonitorCounterGroup(mPerfMonitorCounters, "vulkan").counters;
7128 
7129 #define ANGLE_UPDATE_PERF_MAP(COUNTER) \
7130     angle::GetPerfMonitorCounter(counters, #COUNTER).value = mPerfCounters.COUNTER;
7131 
7132     ANGLE_VK_PERF_COUNTERS_X(ANGLE_UPDATE_PERF_MAP)
7133 
7134 #undef ANGLE_UPDATE_PERF_MAP
7135 
7136     return mPerfMonitorCounters;
7137 }
7138 
7139 // UpdateDescriptorSetsBuilder implementation.
UpdateDescriptorSetsBuilder()7140 UpdateDescriptorSetsBuilder::UpdateDescriptorSetsBuilder()
7141 {
7142     // Reserve reasonable amount of spaces so that for majority of apps we don't need to grow at all
7143     mDescriptorBufferInfos.reserve(kDescriptorBufferInfosInitialSize);
7144     mDescriptorImageInfos.reserve(kDescriptorImageInfosInitialSize);
7145     mWriteDescriptorSets.reserve(kDescriptorWriteInfosInitialSize);
7146 }
7147 
7148 UpdateDescriptorSetsBuilder::~UpdateDescriptorSetsBuilder() = default;
7149 
7150 template <typename T, const T *VkWriteDescriptorSet::*pInfo>
growDescriptorCapacity(std::vector<T> * descriptorVector,size_t newSize)7151 void UpdateDescriptorSetsBuilder::growDescriptorCapacity(std::vector<T> *descriptorVector,
7152                                                          size_t newSize)
7153 {
7154     const T *const oldInfoStart = descriptorVector->empty() ? nullptr : &(*descriptorVector)[0];
7155     size_t newCapacity          = std::max(descriptorVector->capacity() << 1, newSize);
7156     descriptorVector->reserve(newCapacity);
7157 
7158     if (oldInfoStart)
7159     {
7160         // patch mWriteInfo with new BufferInfo/ImageInfo pointers
7161         for (VkWriteDescriptorSet &set : mWriteDescriptorSets)
7162         {
7163             if (set.*pInfo)
7164             {
7165                 size_t index = set.*pInfo - oldInfoStart;
7166                 set.*pInfo   = &(*descriptorVector)[index];
7167             }
7168         }
7169     }
7170 }
7171 
7172 template <typename T, const T *VkWriteDescriptorSet::*pInfo>
allocDescriptorInfos(std::vector<T> * descriptorVector,size_t count)7173 T *UpdateDescriptorSetsBuilder::allocDescriptorInfos(std::vector<T> *descriptorVector, size_t count)
7174 {
7175     size_t oldSize = descriptorVector->size();
7176     size_t newSize = oldSize + count;
7177     if (newSize > descriptorVector->capacity())
7178     {
7179         // If we have reached capacity, grow the storage and patch the descriptor set with new
7180         // buffer info pointer
7181         growDescriptorCapacity<T, pInfo>(descriptorVector, newSize);
7182     }
7183     descriptorVector->resize(newSize);
7184     return &(*descriptorVector)[oldSize];
7185 }
7186 
allocDescriptorBufferInfos(size_t count)7187 VkDescriptorBufferInfo *UpdateDescriptorSetsBuilder::allocDescriptorBufferInfos(size_t count)
7188 {
7189     return allocDescriptorInfos<VkDescriptorBufferInfo, &VkWriteDescriptorSet::pBufferInfo>(
7190         &mDescriptorBufferInfos, count);
7191 }
7192 
allocDescriptorImageInfos(size_t count)7193 VkDescriptorImageInfo *UpdateDescriptorSetsBuilder::allocDescriptorImageInfos(size_t count)
7194 {
7195     return allocDescriptorInfos<VkDescriptorImageInfo, &VkWriteDescriptorSet::pImageInfo>(
7196         &mDescriptorImageInfos, count);
7197 }
7198 
allocWriteDescriptorSets(size_t count)7199 VkWriteDescriptorSet *UpdateDescriptorSetsBuilder::allocWriteDescriptorSets(size_t count)
7200 {
7201     size_t oldSize = mWriteDescriptorSets.size();
7202     size_t newSize = oldSize + count;
7203     mWriteDescriptorSets.resize(newSize);
7204     return &mWriteDescriptorSets[oldSize];
7205 }
7206 
flushDescriptorSetUpdates(VkDevice device)7207 uint32_t UpdateDescriptorSetsBuilder::flushDescriptorSetUpdates(VkDevice device)
7208 {
7209     if (mWriteDescriptorSets.empty())
7210     {
7211         ASSERT(mDescriptorBufferInfos.empty());
7212         ASSERT(mDescriptorImageInfos.empty());
7213         return 0;
7214     }
7215 
7216     vkUpdateDescriptorSets(device, static_cast<uint32_t>(mWriteDescriptorSets.size()),
7217                            mWriteDescriptorSets.data(), 0, nullptr);
7218 
7219     uint32_t retVal = static_cast<uint32_t>(mDescriptorImageInfos.size());
7220 
7221     mWriteDescriptorSets.clear();
7222     mDescriptorBufferInfos.clear();
7223     mDescriptorImageInfos.clear();
7224 
7225     return retVal;
7226 }
7227 
resetPerFramePerfCounters()7228 void ContextVk::resetPerFramePerfCounters()
7229 {
7230     mPerfCounters.renderPasses                           = 0;
7231     mPerfCounters.writeDescriptorSets                    = 0;
7232     mPerfCounters.flushedOutsideRenderPassCommandBuffers = 0;
7233     mPerfCounters.resolveImageCommands                   = 0;
7234     mPerfCounters.descriptorSetAllocations               = 0;
7235 
7236     const gl::ResourceMap<gl::Program, gl::ShaderProgramID> &programs =
7237         mState.getShaderProgramManagerForCapture().getProgramsForCaptureAndPerf();
7238     for (const std::pair<GLuint, gl::Program *> &resource : programs)
7239     {
7240         gl::Program *program = resource.second;
7241         if (program->hasLinkingState())
7242         {
7243             continue;
7244         }
7245         ProgramVk *programVk = vk::GetImpl(program);
7246         programVk->getExecutable().resetDescriptorSetPerfCounters();
7247     }
7248 }
7249 }  // namespace rx
7250