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