• 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/Program.h"
17 #include "libANGLE/Semaphore.h"
18 #include "libANGLE/Surface.h"
19 #include "libANGLE/angletypes.h"
20 #include "libANGLE/renderer/renderer_utils.h"
21 #include "libANGLE/renderer/vulkan/BufferVk.h"
22 #include "libANGLE/renderer/vulkan/CompilerVk.h"
23 #include "libANGLE/renderer/vulkan/FenceNVVk.h"
24 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
25 #include "libANGLE/renderer/vulkan/MemoryObjectVk.h"
26 #include "libANGLE/renderer/vulkan/OverlayVk.h"
27 #include "libANGLE/renderer/vulkan/ProgramPipelineVk.h"
28 #include "libANGLE/renderer/vulkan/ProgramVk.h"
29 #include "libANGLE/renderer/vulkan/QueryVk.h"
30 #include "libANGLE/renderer/vulkan/RenderbufferVk.h"
31 #include "libANGLE/renderer/vulkan/RendererVk.h"
32 #include "libANGLE/renderer/vulkan/SamplerVk.h"
33 #include "libANGLE/renderer/vulkan/SemaphoreVk.h"
34 #include "libANGLE/renderer/vulkan/ShaderVk.h"
35 #include "libANGLE/renderer/vulkan/SurfaceVk.h"
36 #include "libANGLE/renderer/vulkan/SyncVk.h"
37 #include "libANGLE/renderer/vulkan/TextureVk.h"
38 #include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
39 #include "libANGLE/renderer/vulkan/VertexArrayVk.h"
40 
41 #include "libANGLE/trace.h"
42 
43 #include <iostream>
44 
45 namespace rx
46 {
47 
48 namespace
49 {
50 // For shader uniforms such as gl_DepthRange and the viewport size.
51 struct GraphicsDriverUniforms
52 {
53     std::array<float, 4> viewport;
54 
55     // Used to flip gl_FragCoord (both .xy for Android pre-rotation; only .y for desktop)
56     std::array<float, 2> halfRenderArea;
57     std::array<float, 2> flipXY;
58     std::array<float, 2> negFlipXY;
59 
60     // 32 bits for 32 clip planes
61     uint32_t enabledClipPlanes;
62 
63     uint32_t xfbActiveUnpaused;
64     uint32_t xfbVerticesPerDraw;
65     std::array<int32_t, 3> padding;
66 
67     std::array<int32_t, 4> xfbBufferOffsets;
68 
69     // .xy contain packed 8-bit values for atomic counter buffer offsets.  These offsets are
70     // within Vulkan's minStorageBufferOffsetAlignment limit and are used to support unaligned
71     // offsets allowed in GL.
72     //
73     // .zw are unused.
74     std::array<uint32_t, 4> acbBufferOffsets;
75 
76     // We'll use x, y, z for near / far / diff respectively.
77     std::array<float, 4> depthRange;
78 
79     // Used to pre-rotate gl_Position for swapchain images on Android (a mat2, which is padded to
80     // the size of two vec4's).
81     std::array<float, 8> preRotation;
82     // Used to pre-rotate gl_FragCoord for swapchain images on Android (a mat2, which is padded to
83     // the size of two vec4's).
84     std::array<float, 8> fragRotation;
85 };
86 
87 struct ComputeDriverUniforms
88 {
89     // Atomic counter buffer offsets with the same layout as in GraphicsDriverUniforms.
90     std::array<uint32_t, 4> acbBufferOffsets;
91 };
92 
DefaultGLErrorCode(VkResult result)93 GLenum DefaultGLErrorCode(VkResult result)
94 {
95     switch (result)
96     {
97         case VK_ERROR_OUT_OF_HOST_MEMORY:
98         case VK_ERROR_OUT_OF_DEVICE_MEMORY:
99         case VK_ERROR_TOO_MANY_OBJECTS:
100             return GL_OUT_OF_MEMORY;
101         default:
102             return GL_INVALID_OPERATION;
103     }
104 }
105 
106 constexpr gl::ShaderMap<vk::ImageLayout> kShaderReadOnlyImageLayouts = {
107     {gl::ShaderType::Vertex, vk::ImageLayout::VertexShaderReadOnly},
108     {gl::ShaderType::Fragment, vk::ImageLayout::FragmentShaderReadOnly},
109     {gl::ShaderType::Geometry, vk::ImageLayout::GeometryShaderReadOnly},
110     {gl::ShaderType::Compute, vk::ImageLayout::ComputeShaderReadOnly}};
111 
112 constexpr gl::ShaderMap<vk::ImageLayout> kShaderWriteImageLayouts = {
113     {gl::ShaderType::Vertex, vk::ImageLayout::VertexShaderWrite},
114     {gl::ShaderType::Fragment, vk::ImageLayout::FragmentShaderWrite},
115     {gl::ShaderType::Geometry, vk::ImageLayout::GeometryShaderWrite},
116     {gl::ShaderType::Compute, vk::ImageLayout::ComputeShaderWrite}};
117 
118 constexpr VkColorComponentFlags kAllColorChannelsMask =
119     (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
120      VK_COLOR_COMPONENT_A_BIT);
121 
122 constexpr VkBufferUsageFlags kVertexBufferUsage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
123 constexpr size_t kDefaultValueSize              = sizeof(gl::VertexAttribCurrentValueData::Values);
124 constexpr size_t kDefaultBufferSize             = kDefaultValueSize * 16;
125 constexpr size_t kDriverUniformsAllocatorPageSize = 4 * 1024;
126 
127 constexpr size_t kInFlightCommandsLimit = 100u;
128 
InitializeSubmitInfo(VkSubmitInfo * submitInfo,const vk::PrimaryCommandBuffer & commandBuffer,const std::vector<VkSemaphore> & waitSemaphores,const std::vector<VkPipelineStageFlags> & waitSemaphoreStageMasks,const vk::Semaphore * signalSemaphore)129 void InitializeSubmitInfo(VkSubmitInfo *submitInfo,
130                           const vk::PrimaryCommandBuffer &commandBuffer,
131                           const std::vector<VkSemaphore> &waitSemaphores,
132                           const std::vector<VkPipelineStageFlags> &waitSemaphoreStageMasks,
133                           const vk::Semaphore *signalSemaphore)
134 {
135     // Verify that the submitInfo has been zero'd out.
136     ASSERT(submitInfo->signalSemaphoreCount == 0);
137     ASSERT(waitSemaphores.size() == waitSemaphoreStageMasks.size());
138     submitInfo->sType              = VK_STRUCTURE_TYPE_SUBMIT_INFO;
139     submitInfo->commandBufferCount = commandBuffer.valid() ? 1 : 0;
140     submitInfo->pCommandBuffers    = commandBuffer.ptr();
141     submitInfo->waitSemaphoreCount = static_cast<uint32_t>(waitSemaphores.size());
142     submitInfo->pWaitSemaphores    = waitSemaphores.data();
143     submitInfo->pWaitDstStageMask  = waitSemaphoreStageMasks.data();
144 
145     if (signalSemaphore)
146     {
147         submitInfo->signalSemaphoreCount = 1;
148         submitInfo->pSignalSemaphores    = signalSemaphore->ptr();
149     }
150 }
151 
GetCoverageSampleCount(const gl::State & glState,FramebufferVk * drawFramebuffer)152 uint32_t GetCoverageSampleCount(const gl::State &glState, FramebufferVk *drawFramebuffer)
153 {
154     if (!glState.isSampleCoverageEnabled())
155     {
156         return 0;
157     }
158 
159     // Get a fraction of the samples based on the coverage parameters.
160     return static_cast<uint32_t>(
161         std::round(glState.getSampleCoverageValue() * drawFramebuffer->getSamples()));
162 }
163 
ApplySampleCoverage(const gl::State & glState,uint32_t coverageSampleCount,uint32_t maskNumber,uint32_t * maskOut)164 void ApplySampleCoverage(const gl::State &glState,
165                          uint32_t coverageSampleCount,
166                          uint32_t maskNumber,
167                          uint32_t *maskOut)
168 {
169     if (!glState.isSampleCoverageEnabled())
170     {
171         return;
172     }
173 
174     uint32_t maskBitOffset = maskNumber * 32;
175     uint32_t coverageMask  = coverageSampleCount >= (maskBitOffset + 32)
176                                 ? std::numeric_limits<uint32_t>::max()
177                                 : (1u << (coverageSampleCount - maskBitOffset)) - 1;
178 
179     if (glState.getSampleCoverageInvert())
180     {
181         coverageMask = ~coverageMask;
182     }
183 
184     *maskOut &= coverageMask;
185 }
186 
187 // When an Android surface is rotated differently than the device's native orientation, ANGLE must
188 // rotate gl_Position in the vertex shader and gl_FragCoord in the fragment shader.  The following
189 // are the rotation matrices used.
190 //
191 // Note: these are mat2's that are appropriately padded (4 floats per row).
192 using PreRotationMatrixValues = std::array<float, 8>;
193 constexpr angle::PackedEnumMap<rx::SurfaceRotation,
194                                PreRotationMatrixValues,
195                                angle::EnumSize<rx::SurfaceRotation>()>
196     kPreRotationMatrices = {
197         {{rx::SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
198          {rx::SurfaceRotation::Rotated90Degrees,
199           {{0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
200          {rx::SurfaceRotation::Rotated180Degrees,
201           {{-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}}},
202          {rx::SurfaceRotation::Rotated270Degrees,
203           {{0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f}}},
204          {rx::SurfaceRotation::FlippedIdentity,
205           {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}}},
206          {rx::SurfaceRotation::FlippedRotated90Degrees,
207           {{0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f}}},
208          {rx::SurfaceRotation::FlippedRotated180Degrees,
209           {{-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
210          {rx::SurfaceRotation::FlippedRotated270Degrees,
211           {{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}}}};
212 
213 constexpr angle::PackedEnumMap<rx::SurfaceRotation,
214                                PreRotationMatrixValues,
215                                angle::EnumSize<rx::SurfaceRotation>()>
216     kFragRotationMatrices = {
217         {{rx::SurfaceRotation::Identity, {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
218          {rx::SurfaceRotation::Rotated90Degrees,
219           {{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
220          {rx::SurfaceRotation::Rotated180Degrees,
221           {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
222          {rx::SurfaceRotation::Rotated270Degrees,
223           {{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
224          {rx::SurfaceRotation::FlippedIdentity, {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
225          {rx::SurfaceRotation::FlippedRotated90Degrees,
226           {{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}},
227          {rx::SurfaceRotation::FlippedRotated180Degrees,
228           {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}}},
229          {rx::SurfaceRotation::FlippedRotated270Degrees,
230           {{0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}}}}};
231 
IsRotatedAspectRatio(SurfaceRotation rotation)232 bool IsRotatedAspectRatio(SurfaceRotation rotation)
233 {
234     return ((rotation == SurfaceRotation::Rotated90Degrees) ||
235             (rotation == SurfaceRotation::Rotated270Degrees) ||
236             (rotation == SurfaceRotation::FlippedRotated90Degrees) ||
237             (rotation == SurfaceRotation::FlippedRotated270Degrees));
238 }
239 
DetermineSurfaceRotation(gl::Framebuffer * framebuffer,WindowSurfaceVk * windowSurface)240 SurfaceRotation DetermineSurfaceRotation(gl::Framebuffer *framebuffer,
241                                          WindowSurfaceVk *windowSurface)
242 {
243     if (windowSurface && framebuffer->isDefault())
244     {
245         switch (windowSurface->getPreTransform())
246         {
247             case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
248                 // Do not rotate gl_Position (surface matches the device's orientation):
249                 return SurfaceRotation::Identity;
250             case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
251                 // Rotate gl_Position 90 degrees:
252                 return SurfaceRotation::Rotated90Degrees;
253             case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
254                 // Rotate gl_Position 180 degrees:
255                 return SurfaceRotation::Rotated180Degrees;
256             case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
257                 // Rotate gl_Position 270 degrees:
258                 return SurfaceRotation::Rotated270Degrees;
259             default:
260                 UNREACHABLE();
261                 return SurfaceRotation::Identity;
262         }
263     }
264     else
265     {
266         // Do not rotate gl_Position (offscreen framebuffer):
267         return SurfaceRotation::Identity;
268     }
269 }
270 
271 // Should not generate a copy with modern C++.
GetTraceEventName(const char * title,uint32_t counter)272 EventName GetTraceEventName(const char *title, uint32_t counter)
273 {
274     EventName buf;
275     snprintf(buf.data(), kMaxGpuEventNameLen - 1, "%s %u", title, counter);
276     return buf;
277 }
278 }  // anonymous namespace
279 
DriverUniformsDescriptorSet()280 ContextVk::DriverUniformsDescriptorSet::DriverUniformsDescriptorSet()
281     : descriptorSet(VK_NULL_HANDLE), dynamicOffset(0)
282 {}
283 
284 ContextVk::DriverUniformsDescriptorSet::~DriverUniformsDescriptorSet() = default;
285 
init(RendererVk * rendererVk)286 void ContextVk::DriverUniformsDescriptorSet::init(RendererVk *rendererVk)
287 {
288     size_t minAlignment = static_cast<size_t>(
289         rendererVk->getPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment);
290     dynamicBuffer.init(rendererVk, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, minAlignment,
291                        kDriverUniformsAllocatorPageSize, true);
292 }
293 
destroy(RendererVk * renderer)294 void ContextVk::DriverUniformsDescriptorSet::destroy(RendererVk *renderer)
295 {
296     descriptorSetLayout.reset();
297     descriptorPoolBinding.reset();
298     dynamicBuffer.destroy(renderer);
299 }
300 
301 // CommandBatch implementation.
302 CommandBatch::CommandBatch() = default;
303 
304 CommandBatch::~CommandBatch() = default;
305 
CommandBatch(CommandBatch && other)306 CommandBatch::CommandBatch(CommandBatch &&other)
307 {
308     *this = std::move(other);
309 }
310 
operator =(CommandBatch && other)311 CommandBatch &CommandBatch::operator=(CommandBatch &&other)
312 {
313     std::swap(primaryCommands, other.primaryCommands);
314     std::swap(commandPool, other.commandPool);
315     std::swap(fence, other.fence);
316     std::swap(serial, other.serial);
317     return *this;
318 }
319 
destroy(VkDevice device)320 void CommandBatch::destroy(VkDevice device)
321 {
322     primaryCommands.destroy(device);
323     commandPool.destroy(device);
324     fence.reset(device);
325 }
326 
327 // CommandQueue implementation.
328 CommandQueue::CommandQueue()  = default;
329 CommandQueue::~CommandQueue() = default;
330 
destroy(VkDevice device)331 void CommandQueue::destroy(VkDevice device)
332 {
333     mPrimaryCommandPool.destroy(device);
334     ASSERT(mInFlightCommands.empty() && mGarbageQueue.empty());
335 }
336 
init(vk::Context * context)337 angle::Result CommandQueue::init(vk::Context *context)
338 {
339     RendererVk *renderer = context->getRenderer();
340 
341     // Initialize the command pool now that we know the queue family index.
342     uint32_t queueFamilyIndex = renderer->getQueueFamilyIndex();
343     ANGLE_TRY(mPrimaryCommandPool.init(context, queueFamilyIndex));
344 
345     return angle::Result::Continue;
346 }
347 
checkCompletedCommands(vk::Context * context)348 angle::Result CommandQueue::checkCompletedCommands(vk::Context *context)
349 {
350     RendererVk *renderer = context->getRenderer();
351     VkDevice device      = renderer->getDevice();
352 
353     int finishedCount = 0;
354 
355     for (CommandBatch &batch : mInFlightCommands)
356     {
357         VkResult result = batch.fence.get().getStatus(device);
358         if (result == VK_NOT_READY)
359         {
360             break;
361         }
362         ANGLE_VK_TRY(context, result);
363 
364         renderer->onCompletedSerial(batch.serial);
365 
366         renderer->resetSharedFence(&batch.fence);
367         ANGLE_TRACE_EVENT0("gpu.angle", "command buffer recycling");
368         batch.commandPool.destroy(device);
369         ANGLE_TRY(releasePrimaryCommandBuffer(context, std::move(batch.primaryCommands)));
370         ++finishedCount;
371     }
372 
373     if (finishedCount > 0)
374     {
375         auto beginIter = mInFlightCommands.begin();
376         mInFlightCommands.erase(beginIter, beginIter + finishedCount);
377     }
378 
379     Serial lastCompleted = renderer->getLastCompletedQueueSerial();
380 
381     size_t freeIndex = 0;
382     for (; freeIndex < mGarbageQueue.size(); ++freeIndex)
383     {
384         vk::GarbageAndSerial &garbageList = mGarbageQueue[freeIndex];
385         if (garbageList.getSerial() < lastCompleted)
386         {
387             for (vk::GarbageObject &garbage : garbageList.get())
388             {
389                 garbage.destroy(renderer);
390             }
391         }
392         else
393         {
394             break;
395         }
396     }
397 
398     // Remove the entries from the garbage list - they should be ready to go.
399     if (freeIndex > 0)
400     {
401         mGarbageQueue.erase(mGarbageQueue.begin(), mGarbageQueue.begin() + freeIndex);
402     }
403 
404     return angle::Result::Continue;
405 }
406 
releaseToCommandBatch(vk::Context * context,vk::PrimaryCommandBuffer && commandBuffer,vk::CommandPool * commandPool,CommandBatch * batch)407 angle::Result CommandQueue::releaseToCommandBatch(vk::Context *context,
408                                                   vk::PrimaryCommandBuffer &&commandBuffer,
409                                                   vk::CommandPool *commandPool,
410                                                   CommandBatch *batch)
411 {
412     RendererVk *renderer = context->getRenderer();
413     VkDevice device      = renderer->getDevice();
414 
415     batch->primaryCommands = std::move(commandBuffer);
416 
417     if (commandPool->valid())
418     {
419         batch->commandPool = std::move(*commandPool);
420         // Recreate CommandPool
421         VkCommandPoolCreateInfo poolInfo = {};
422         poolInfo.sType                   = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
423         poolInfo.flags                   = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
424         poolInfo.queueFamilyIndex        = renderer->getQueueFamilyIndex();
425 
426         ANGLE_VK_TRY(context, commandPool->init(device, poolInfo));
427     }
428 
429     return angle::Result::Continue;
430 }
431 
clearAllGarbage(RendererVk * renderer)432 void CommandQueue::clearAllGarbage(RendererVk *renderer)
433 {
434     for (vk::GarbageAndSerial &garbageList : mGarbageQueue)
435     {
436         for (vk::GarbageObject &garbage : garbageList.get())
437         {
438             garbage.destroy(renderer);
439         }
440     }
441     mGarbageQueue.clear();
442 }
443 
allocatePrimaryCommandBuffer(vk::Context * context,const vk::CommandPool & commandPool,vk::PrimaryCommandBuffer * commandBufferOut)444 angle::Result CommandQueue::allocatePrimaryCommandBuffer(vk::Context *context,
445                                                          const vk::CommandPool &commandPool,
446                                                          vk::PrimaryCommandBuffer *commandBufferOut)
447 {
448     return mPrimaryCommandPool.allocate(context, commandBufferOut);
449 }
450 
releasePrimaryCommandBuffer(vk::Context * context,vk::PrimaryCommandBuffer && commandBuffer)451 angle::Result CommandQueue::releasePrimaryCommandBuffer(vk::Context *context,
452                                                         vk::PrimaryCommandBuffer &&commandBuffer)
453 {
454     ASSERT(mPrimaryCommandPool.valid());
455     ANGLE_TRY(mPrimaryCommandPool.collect(context, std::move(commandBuffer)));
456 
457     return angle::Result::Continue;
458 }
459 
handleDeviceLost(RendererVk * renderer)460 void CommandQueue::handleDeviceLost(RendererVk *renderer)
461 {
462     VkDevice device = renderer->getDevice();
463 
464     for (CommandBatch &batch : mInFlightCommands)
465     {
466         // On device loss we need to wait for fence to be signaled before destroying it
467         VkResult status = batch.fence.get().wait(device, renderer->getMaxFenceWaitTimeNs());
468         // If the wait times out, it is probably not possible to recover from lost device
469         ASSERT(status == VK_SUCCESS || status == VK_ERROR_DEVICE_LOST);
470 
471         // On device lost, here simply destroy the CommandBuffer, it will fully cleared later
472         // by CommandPool::destroy
473         batch.primaryCommands.destroy(device);
474 
475         batch.commandPool.destroy(device);
476         batch.fence.reset(device);
477     }
478     mInFlightCommands.clear();
479 }
480 
hasInFlightCommands() const481 bool CommandQueue::hasInFlightCommands() const
482 {
483     return !mInFlightCommands.empty();
484 }
485 
finishToSerial(vk::Context * context,Serial serial,uint64_t timeout)486 angle::Result CommandQueue::finishToSerial(vk::Context *context, Serial serial, uint64_t timeout)
487 {
488     if (mInFlightCommands.empty())
489     {
490         return angle::Result::Continue;
491     }
492     ANGLE_TRACE_EVENT0("gpu.angle", "CommandQueue::finishToSerial");
493     // Find the first batch with serial equal to or bigger than given serial (note that
494     // the batch serials are unique, otherwise upper-bound would have been necessary).
495     //
496     // Note: we don't check for the exact serial, because it may belong to another context.  For
497     // example, imagine the following submissions:
498     //
499     // - Context 1: Serial 1, Serial 3, Serial 5
500     // - Context 2: Serial 2, Serial 4, Serial 6
501     //
502     // And imagine none of the submissions have finished yet.  Now if Context 2 asks for
503     // finishToSerial(3), it will have no choice but to finish until Serial 4 instead.
504     size_t batchIndex = mInFlightCommands.size() - 1;
505     for (size_t i = 0; i < mInFlightCommands.size(); ++i)
506     {
507         if (mInFlightCommands[i].serial >= serial)
508         {
509             batchIndex = i;
510             break;
511         }
512     }
513     const CommandBatch &batch = mInFlightCommands[batchIndex];
514 
515     // Wait for it finish
516     VkDevice device = context->getDevice();
517     VkResult status = batch.fence.get().wait(device, timeout);
518 
519     ANGLE_VK_TRY(context, status);
520 
521     // Clean up finished batches.
522     return checkCompletedCommands(context);
523 }
524 
submitFrame(vk::Context * context,egl::ContextPriority priority,const VkSubmitInfo & submitInfo,const vk::Shared<vk::Fence> & sharedFence,vk::GarbageList * currentGarbage,vk::CommandPool * commandPool,vk::PrimaryCommandBuffer && commandBuffer)525 angle::Result CommandQueue::submitFrame(vk::Context *context,
526                                         egl::ContextPriority priority,
527                                         const VkSubmitInfo &submitInfo,
528                                         const vk::Shared<vk::Fence> &sharedFence,
529                                         vk::GarbageList *currentGarbage,
530                                         vk::CommandPool *commandPool,
531                                         vk::PrimaryCommandBuffer &&commandBuffer)
532 {
533     ANGLE_TRACE_EVENT0("gpu.angle", "CommandQueue::submitFrame");
534 
535     RendererVk *renderer = context->getRenderer();
536     VkDevice device      = renderer->getDevice();
537 
538     vk::DeviceScoped<CommandBatch> scopedBatch(device);
539     CommandBatch &batch = scopedBatch.get();
540     batch.fence.copy(device, sharedFence);
541 
542     ANGLE_TRY(
543         renderer->queueSubmit(context, priority, submitInfo, &batch.fence.get(), &batch.serial));
544 
545     if (!currentGarbage->empty())
546     {
547         mGarbageQueue.emplace_back(std::move(*currentGarbage), batch.serial);
548     }
549 
550     // Store the primary CommandBuffer and command pool used for secondary CommandBuffers
551     // in the in-flight list.
552     ANGLE_TRY(releaseToCommandBatch(context, std::move(commandBuffer), commandPool, &batch));
553 
554     mInFlightCommands.emplace_back(scopedBatch.release());
555 
556     ANGLE_TRY(checkCompletedCommands(context));
557 
558     // CPU should be throttled to avoid mInFlightCommands from growing too fast. Important for
559     // off-screen scenarios.
560     while (mInFlightCommands.size() > kInFlightCommandsLimit)
561     {
562         ANGLE_TRY(finishToSerial(context, mInFlightCommands[0].serial,
563                                  renderer->getMaxFenceWaitTimeNs()));
564     }
565 
566     return angle::Result::Continue;
567 }
568 
getLastSubmittedFence(const vk::Context * context) const569 vk::Shared<vk::Fence> CommandQueue::getLastSubmittedFence(const vk::Context *context) const
570 {
571     vk::Shared<vk::Fence> fence;
572     if (!mInFlightCommands.empty())
573     {
574         fence.copy(context->getDevice(), mInFlightCommands.back().fence);
575     }
576 
577     return fence;
578 }
579 
GetContextPriority(const gl::State & state)580 egl::ContextPriority GetContextPriority(const gl::State &state)
581 {
582     return egl::FromEGLenum<egl::ContextPriority>(state.getContextPriority());
583 }
584 
585 // ContextVk implementation.
ContextVk(const gl::State & state,gl::ErrorSet * errorSet,RendererVk * renderer)586 ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk *renderer)
587     : ContextImpl(state, errorSet),
588       vk::Context(renderer),
589       mGraphicsDirtyBitHandlers{},
590       mComputeDirtyBitHandlers{},
591       mRenderPassCommandBuffer(nullptr),
592       mCurrentGraphicsPipeline(nullptr),
593       mCurrentComputePipeline(nullptr),
594       mCurrentDrawMode(gl::PrimitiveMode::InvalidEnum),
595       mCurrentWindowSurface(nullptr),
596       mCurrentRotationDrawFramebuffer(SurfaceRotation::Identity),
597       mCurrentRotationReadFramebuffer(SurfaceRotation::Identity),
598       mVertexArray(nullptr),
599       mDrawFramebuffer(nullptr),
600       mProgram(nullptr),
601       mExecutable(nullptr),
602       mActiveQueryAnySamples(nullptr),
603       mActiveQueryAnySamplesConservative(nullptr),
604       mLastIndexBufferOffset(0),
605       mCurrentDrawElementsType(gl::DrawElementsType::InvalidEnum),
606       mXfbBaseVertex(0),
607       mXfbVertexCountPerInstance(0),
608       mClearColorMask(kAllColorChannelsMask),
609       mFlipYForCurrentSurface(false),
610       mIsAnyHostVisibleBufferWritten(false),
611       mEmulateSeamfulCubeMapSampling(false),
612       mUseOldRewriteStructSamplers(false),
613       mOutsideRenderPassCommands(nullptr),
614       mRenderPassCommands(nullptr),
615       mHasPrimaryCommands(false),
616       mGpuEventsEnabled(false),
617       mGpuClockSync{std::numeric_limits<double>::max(), std::numeric_limits<double>::max()},
618       mGpuEventTimestampOrigin(0),
619       mPrimaryBufferCounter(0),
620       mRenderPassCounter(0),
621       mContextPriority(renderer->getDriverPriority(GetContextPriority(state)))
622 {
623     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::ContextVk");
624     memset(&mClearColorValue, 0, sizeof(mClearColorValue));
625     memset(&mClearDepthStencilValue, 0, sizeof(mClearDepthStencilValue));
626 
627     mNonIndexedDirtyBitsMask.set();
628     mNonIndexedDirtyBitsMask.reset(DIRTY_BIT_INDEX_BUFFER);
629 
630     mIndexedDirtyBitsMask.set();
631 
632     mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_PIPELINE);
633     mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TEXTURES);
634     mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
635     mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
636     mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
637     if (getFeatures().supportsTransformFeedbackExtension.enabled ||
638         getFeatures().emulateTransformFeedback.enabled)
639     {
640         mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS);
641     }
642     if (getFeatures().supportsTransformFeedbackExtension.enabled)
643     {
644         mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_STATE);
645         mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
646     }
647     mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
648     mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING);
649 
650     mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_PIPELINE);
651     mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_TEXTURES);
652     mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
653     mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
654     mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING);
655 
656     mNewGraphicsPipelineDirtyBits.set(DIRTY_BIT_PIPELINE);
657     if (getFeatures().supportsTransformFeedbackExtension.enabled)
658     {
659         mNewGraphicsPipelineDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
660     }
661 
662     mGraphicsDirtyBitHandlers[DIRTY_BIT_DEFAULT_ATTRIBS] =
663         &ContextVk::handleDirtyGraphicsDefaultAttribs;
664     mGraphicsDirtyBitHandlers[DIRTY_BIT_PIPELINE] = &ContextVk::handleDirtyGraphicsPipeline;
665     mGraphicsDirtyBitHandlers[DIRTY_BIT_TEXTURES] = &ContextVk::handleDirtyGraphicsTextures;
666     mGraphicsDirtyBitHandlers[DIRTY_BIT_VERTEX_BUFFERS] =
667         &ContextVk::handleDirtyGraphicsVertexBuffers;
668     mGraphicsDirtyBitHandlers[DIRTY_BIT_INDEX_BUFFER] = &ContextVk::handleDirtyGraphicsIndexBuffer;
669     mGraphicsDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS] =
670         &ContextVk::handleDirtyGraphicsDriverUniforms;
671     mGraphicsDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS_BINDING] =
672         &ContextVk::handleDirtyGraphicsDriverUniformsBinding;
673     mGraphicsDirtyBitHandlers[DIRTY_BIT_SHADER_RESOURCES] =
674         &ContextVk::handleDirtyGraphicsShaderResources;
675     if (getFeatures().supportsTransformFeedbackExtension.enabled)
676     {
677         mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS] =
678             &ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension;
679         mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_STATE] =
680             &ContextVk::handleDirtyGraphicsTransformFeedbackState;
681         mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME] =
682             &ContextVk::handleDirtyGraphicsTransformFeedbackResume;
683     }
684     else if (getFeatures().emulateTransformFeedback.enabled)
685     {
686         mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS] =
687             &ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation;
688     }
689 
690     mGraphicsDirtyBitHandlers[DIRTY_BIT_DESCRIPTOR_SETS] = &ContextVk::handleDirtyDescriptorSets;
691 
692     mComputeDirtyBitHandlers[DIRTY_BIT_PIPELINE] = &ContextVk::handleDirtyComputePipeline;
693     mComputeDirtyBitHandlers[DIRTY_BIT_TEXTURES] = &ContextVk::handleDirtyComputeTextures;
694     mComputeDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS] =
695         &ContextVk::handleDirtyComputeDriverUniforms;
696     mComputeDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS_BINDING] =
697         &ContextVk::handleDirtyComputeDriverUniformsBinding;
698     mComputeDirtyBitHandlers[DIRTY_BIT_SHADER_RESOURCES] =
699         &ContextVk::handleDirtyComputeShaderResources;
700     mComputeDirtyBitHandlers[DIRTY_BIT_DESCRIPTOR_SETS] = &ContextVk::handleDirtyDescriptorSets;
701 
702     mGraphicsDirtyBits = mNewGraphicsCommandBufferDirtyBits;
703     mComputeDirtyBits  = mNewComputeCommandBufferDirtyBits;
704 
705     mActiveTextures.fill({nullptr, nullptr});
706     mActiveImages.fill(nullptr);
707 
708     mPipelineDirtyBitsMask.set();
709     mPipelineDirtyBitsMask.reset(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
710 }
711 
712 ContextVk::~ContextVk() = default;
713 
onDestroy(const gl::Context * context)714 void ContextVk::onDestroy(const gl::Context *context)
715 {
716     // This will not destroy any resources. It will release them to be collected after finish.
717     mIncompleteTextures.onDestroy(context);
718 
719     // Flush and complete current outstanding work before destruction.
720     (void)finishImpl();
721 
722     VkDevice device = getDevice();
723 
724     for (DriverUniformsDescriptorSet &driverUniforms : mDriverUniforms)
725     {
726         driverUniforms.destroy(mRenderer);
727     }
728 
729     mDriverUniformsDescriptorPool.destroy(device);
730 
731     for (vk::DynamicBuffer &defaultBuffer : mDefaultAttribBuffers)
732     {
733         defaultBuffer.destroy(mRenderer);
734     }
735 
736     for (vk::DynamicQueryPool &queryPool : mQueryPools)
737     {
738         queryPool.destroy(device);
739     }
740 
741     ASSERT(mCurrentGarbage.empty());
742 
743     mCommandQueue.destroy(device);
744 
745     mResourceUseList.releaseResourceUses();
746 
747     mUtils.destroy(device);
748 
749     mRenderPassCache.destroy(device);
750     mSubmitFence.reset(device);
751     mShaderLibrary.destroy(device);
752     mGpuEventQueryPool.destroy(device);
753     mCommandPool.destroy(device);
754     mPrimaryCommands.destroy(device);
755 }
756 
getIncompleteTexture(const gl::Context * context,gl::TextureType type,gl::Texture ** textureOut)757 angle::Result ContextVk::getIncompleteTexture(const gl::Context *context,
758                                               gl::TextureType type,
759                                               gl::Texture **textureOut)
760 {
761     // At some point, we'll need to support multisample and we'll pass "this" instead of nullptr
762     // and implement the necessary interface.
763     return mIncompleteTextures.getIncompleteTexture(context, type, nullptr, textureOut);
764 }
765 
initialize()766 angle::Result ContextVk::initialize()
767 {
768     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::initialize");
769 
770     VkDescriptorPoolSize driverSetSize = {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1};
771     ANGLE_TRY(mDriverUniformsDescriptorPool.init(this, &driverSetSize, 1));
772 
773     ANGLE_TRY(mQueryPools[gl::QueryType::AnySamples].init(this, VK_QUERY_TYPE_OCCLUSION,
774                                                           vk::kDefaultOcclusionQueryPoolSize));
775     ANGLE_TRY(mQueryPools[gl::QueryType::AnySamplesConservative].init(
776         this, VK_QUERY_TYPE_OCCLUSION, vk::kDefaultOcclusionQueryPoolSize));
777 
778     // Only initialize the timestamp query pools if the extension is available.
779     if (mRenderer->getQueueFamilyProperties().timestampValidBits > 0)
780     {
781         ANGLE_TRY(mQueryPools[gl::QueryType::Timestamp].init(this, VK_QUERY_TYPE_TIMESTAMP,
782                                                              vk::kDefaultTimestampQueryPoolSize));
783         ANGLE_TRY(mQueryPools[gl::QueryType::TimeElapsed].init(this, VK_QUERY_TYPE_TIMESTAMP,
784                                                                vk::kDefaultTimestampQueryPoolSize));
785     }
786 
787     // Init gles to vulkan index type map
788     initIndexTypeMap();
789 
790     // Init driver uniforms and get the descriptor set layouts.
791     constexpr angle::PackedEnumMap<PipelineType, VkShaderStageFlags> kPipelineStages = {
792         {PipelineType::Graphics, VK_SHADER_STAGE_ALL_GRAPHICS},
793         {PipelineType::Compute, VK_SHADER_STAGE_COMPUTE_BIT},
794     };
795     for (PipelineType pipeline : angle::AllEnums<PipelineType>())
796     {
797         mDriverUniforms[pipeline].init(mRenderer);
798 
799         vk::DescriptorSetLayoutDesc desc =
800             getDriverUniformsDescriptorSetDesc(kPipelineStages[pipeline]);
801         ANGLE_TRY(mRenderer->getDescriptorSetLayout(
802             this, desc, &mDriverUniforms[pipeline].descriptorSetLayout));
803     }
804 
805     mGraphicsPipelineDesc.reset(new vk::GraphicsPipelineDesc());
806     mGraphicsPipelineDesc->initDefaults();
807 
808     // Initialize current value/default attribute buffers.
809     for (vk::DynamicBuffer &buffer : mDefaultAttribBuffers)
810     {
811         buffer.init(mRenderer, kVertexBufferUsage, 1, kDefaultBufferSize, true);
812     }
813 
814     ANGLE_TRY(mCommandQueue.init(this));
815 
816 #if ANGLE_ENABLE_VULKAN_GPU_TRACE_EVENTS
817     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
818     ASSERT(platform);
819 
820     // GPU tracing workaround for anglebug.com/2927.  The renderer should not emit gpu events
821     // during platform discovery.
822     const unsigned char *gpuEventsEnabled =
823         platform->getTraceCategoryEnabledFlag(platform, "gpu.angle.gpu");
824     mGpuEventsEnabled = gpuEventsEnabled && *gpuEventsEnabled;
825 #endif
826 
827     mEmulateSeamfulCubeMapSampling = shouldEmulateSeamfulCubeMapSampling();
828 
829     mUseOldRewriteStructSamplers = shouldUseOldRewriteStructSamplers();
830 
831     // Prepare command buffer queue by:
832     //  1. Initializing each command buffer (as non-renderpass initially)
833     //  2. Put a pointer to each command buffer into queue
834     for (vk::CommandBufferHelper &commandBuffer : mCommandBuffers)
835     {
836         // TODO: b/157508684 Don't cache feature in class like this, just check when needed
837         commandBuffer.initialize(false,
838                                  mRenderer->getFeatures().preferAggregateBarrierCalls.enabled);
839         recycleCommandBuffer(&commandBuffer);
840     }
841     // Now assign initial command buffers from queue
842     getNextAvailableCommandBuffer(&mOutsideRenderPassCommands, false);
843     getNextAvailableCommandBuffer(&mRenderPassCommands, true);
844 
845     ANGLE_TRY(startPrimaryCommandBuffer());
846 
847     if (mGpuEventsEnabled)
848     {
849         // GPU events should only be available if timestamp queries are available.
850         ASSERT(mRenderer->getQueueFamilyProperties().timestampValidBits > 0);
851         // Calculate the difference between CPU and GPU clocks for GPU event reporting.
852         ANGLE_TRY(mGpuEventQueryPool.init(this, VK_QUERY_TYPE_TIMESTAMP,
853                                           vk::kDefaultTimestampQueryPoolSize));
854         ANGLE_TRY(synchronizeCpuGpuTime());
855 
856         mPrimaryBufferCounter++;
857 
858         EventName eventName = GetTraceEventName("Primary", mPrimaryBufferCounter);
859         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
860                                 TRACE_EVENT_PHASE_BEGIN, eventName));
861     }
862 
863     return angle::Result::Continue;
864 }
865 
startPrimaryCommandBuffer()866 angle::Result ContextVk::startPrimaryCommandBuffer()
867 {
868     ANGLE_TRY(mCommandQueue.allocatePrimaryCommandBuffer(this, mCommandPool, &mPrimaryCommands));
869 
870     VkCommandBufferBeginInfo beginInfo = {};
871     beginInfo.sType                    = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
872     beginInfo.flags                    = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
873     beginInfo.pInheritanceInfo         = nullptr;
874     ANGLE_VK_TRY(this, mPrimaryCommands.begin(beginInfo));
875 
876     mHasPrimaryCommands = false;
877     return angle::Result::Continue;
878 }
879 
flush(const gl::Context * context)880 angle::Result ContextVk::flush(const gl::Context *context)
881 {
882     return flushImpl(nullptr);
883 }
884 
finish(const gl::Context * context)885 angle::Result ContextVk::finish(const gl::Context *context)
886 {
887     return finishImpl();
888 }
889 
setupDraw(const gl::Context * context,gl::PrimitiveMode mode,GLint firstVertexOrInvalid,GLsizei vertexOrIndexCount,GLsizei instanceCount,gl::DrawElementsType indexTypeOrInvalid,const void * indices,DirtyBits dirtyBitMask,vk::CommandBuffer ** commandBufferOut)890 angle::Result ContextVk::setupDraw(const gl::Context *context,
891                                    gl::PrimitiveMode mode,
892                                    GLint firstVertexOrInvalid,
893                                    GLsizei vertexOrIndexCount,
894                                    GLsizei instanceCount,
895                                    gl::DrawElementsType indexTypeOrInvalid,
896                                    const void *indices,
897                                    DirtyBits dirtyBitMask,
898                                    vk::CommandBuffer **commandBufferOut)
899 {
900     // Set any dirty bits that depend on draw call parameters or other objects.
901     if (mode != mCurrentDrawMode)
902     {
903         invalidateCurrentGraphicsPipeline();
904         mCurrentDrawMode = mode;
905         mGraphicsPipelineDesc->updateTopology(&mGraphicsPipelineTransition, mCurrentDrawMode);
906     }
907 
908     // Must be called before the command buffer is started. Can call finish.
909     if (mVertexArray->getStreamingVertexAttribsMask().any())
910     {
911         // All client attribs & any emulated buffered attribs will be updated
912         ANGLE_TRY(mVertexArray->updateStreamedAttribs(context, firstVertexOrInvalid,
913                                                       vertexOrIndexCount, instanceCount,
914                                                       indexTypeOrInvalid, indices));
915 
916         mGraphicsDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
917     }
918 
919     // This could be improved using a dirty bit. But currently it's slower to use a handler
920     // function than an inlined if. We should probably replace the dirty bit dispatch table
921     // with a switch with inlined handler functions.
922     // TODO(jmadill): Use dirty bit. http://anglebug.com/3014
923     if (!mRenderPassCommandBuffer)
924     {
925         gl::Rectangle scissoredRenderArea = mDrawFramebuffer->getScissoredRenderArea(this);
926         ANGLE_TRY(startRenderPass(scissoredRenderArea, nullptr));
927     }
928 
929     // We keep a local copy of the command buffer. It's possible that some state changes could
930     // trigger a command buffer invalidation. The local copy ensures we retain the reference.
931     // Command buffers are pool allocated and only deleted after submit. Thus we know the
932     // command buffer will still be valid for the duration of this API call.
933     *commandBufferOut = mRenderPassCommandBuffer;
934     ASSERT(*commandBufferOut);
935 
936     if (mProgram && mProgram->dirtyUniforms())
937     {
938         ANGLE_TRY(mProgram->updateUniforms(this));
939         mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
940     }
941     else if (mProgramPipeline && mProgramPipeline->dirtyUniforms(getState()))
942     {
943         ANGLE_TRY(mProgramPipeline->updateUniforms(this));
944         mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
945     }
946 
947     // Update transform feedback offsets on every draw call.
948     if (mState.isTransformFeedbackActiveUnpaused())
949     {
950         ASSERT(firstVertexOrInvalid != -1);
951         mXfbBaseVertex             = firstVertexOrInvalid;
952         mXfbVertexCountPerInstance = vertexOrIndexCount;
953         invalidateGraphicsDriverUniforms();
954     }
955 
956     DirtyBits dirtyBits = mGraphicsDirtyBits & dirtyBitMask;
957 
958     if (dirtyBits.none())
959         return angle::Result::Continue;
960 
961     // Flush any relevant dirty bits.
962     for (size_t dirtyBit : dirtyBits)
963     {
964         ASSERT(mGraphicsDirtyBitHandlers[dirtyBit]);
965         ANGLE_TRY((this->*mGraphicsDirtyBitHandlers[dirtyBit])(context, *commandBufferOut));
966     }
967 
968     mGraphicsDirtyBits &= ~dirtyBitMask;
969 
970     return angle::Result::Continue;
971 }
972 
setupIndexedDraw(const gl::Context * context,gl::PrimitiveMode mode,GLsizei indexCount,GLsizei instanceCount,gl::DrawElementsType indexType,const void * indices,vk::CommandBuffer ** commandBufferOut)973 angle::Result ContextVk::setupIndexedDraw(const gl::Context *context,
974                                           gl::PrimitiveMode mode,
975                                           GLsizei indexCount,
976                                           GLsizei instanceCount,
977                                           gl::DrawElementsType indexType,
978                                           const void *indices,
979                                           vk::CommandBuffer **commandBufferOut)
980 {
981     ASSERT(mode != gl::PrimitiveMode::LineLoop);
982 
983     if (indexType != mCurrentDrawElementsType)
984     {
985         mCurrentDrawElementsType = indexType;
986         setIndexBufferDirty();
987     }
988 
989     const gl::Buffer *elementArrayBuffer = mVertexArray->getState().getElementArrayBuffer();
990     if (!elementArrayBuffer)
991     {
992         mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
993         ANGLE_TRY(mVertexArray->convertIndexBufferCPU(this, indexType, indexCount, indices));
994     }
995     else
996     {
997         if (indices != mLastIndexBufferOffset)
998         {
999             mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
1000             mLastIndexBufferOffset = indices;
1001             mVertexArray->updateCurrentElementArrayBufferOffset(mLastIndexBufferOffset);
1002         }
1003         if (shouldConvertUint8VkIndexType(indexType) && mGraphicsDirtyBits[DIRTY_BIT_INDEX_BUFFER])
1004         {
1005             BufferVk *bufferVk             = vk::GetImpl(elementArrayBuffer);
1006             vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
1007 
1008             if (bufferHelper.isHostVisible() &&
1009                 !bufferHelper.isCurrentlyInUse(getLastCompletedQueueSerial()))
1010             {
1011                 uint8_t *src = nullptr;
1012                 ANGLE_TRY(bufferVk->mapImpl(this, reinterpret_cast<void **>(&src)));
1013                 src += reinterpret_cast<uintptr_t>(indices);
1014                 const size_t byteCount = static_cast<size_t>(elementArrayBuffer->getSize()) -
1015                                          reinterpret_cast<uintptr_t>(indices);
1016                 ANGLE_TRY(mVertexArray->convertIndexBufferCPU(this, indexType, byteCount, src));
1017                 ANGLE_TRY(bufferVk->unmapImpl(this));
1018             }
1019             else
1020             {
1021                 ANGLE_TRY(mVertexArray->convertIndexBufferGPU(this, bufferVk, indices));
1022             }
1023         }
1024     }
1025 
1026     return setupDraw(context, mode, 0, indexCount, instanceCount, indexType, indices,
1027                      mIndexedDirtyBitsMask, commandBufferOut);
1028 }
1029 
setupIndirectDraw(const gl::Context * context,gl::PrimitiveMode mode,DirtyBits dirtyBitMask,vk::BufferHelper * indirectBuffer,VkDeviceSize indirectBufferOffset,vk::CommandBuffer ** commandBufferOut)1030 angle::Result ContextVk::setupIndirectDraw(const gl::Context *context,
1031                                            gl::PrimitiveMode mode,
1032                                            DirtyBits dirtyBitMask,
1033                                            vk::BufferHelper *indirectBuffer,
1034                                            VkDeviceSize indirectBufferOffset,
1035                                            vk::CommandBuffer **commandBufferOut)
1036 {
1037     GLint firstVertex     = -1;
1038     GLsizei vertexCount   = 0;
1039     GLsizei instanceCount = 1;
1040 
1041     mRenderPassCommands->bufferRead(&mResourceUseList, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
1042                                     vk::PipelineStage::DrawIndirect, indirectBuffer);
1043 
1044     ANGLE_TRY(setupDraw(context, mode, firstVertex, vertexCount, instanceCount,
1045                         gl::DrawElementsType::InvalidEnum, nullptr, dirtyBitMask,
1046                         commandBufferOut));
1047 
1048     return angle::Result::Continue;
1049 }
1050 
setupIndexedIndirectDraw(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType indexType,vk::BufferHelper * indirectBuffer,VkDeviceSize indirectBufferOffset,vk::CommandBuffer ** commandBufferOut)1051 angle::Result ContextVk::setupIndexedIndirectDraw(const gl::Context *context,
1052                                                   gl::PrimitiveMode mode,
1053                                                   gl::DrawElementsType indexType,
1054                                                   vk::BufferHelper *indirectBuffer,
1055                                                   VkDeviceSize indirectBufferOffset,
1056                                                   vk::CommandBuffer **commandBufferOut)
1057 {
1058     ASSERT(mode != gl::PrimitiveMode::LineLoop);
1059 
1060     if (indexType != mCurrentDrawElementsType)
1061     {
1062         mCurrentDrawElementsType = indexType;
1063         setIndexBufferDirty();
1064     }
1065 
1066     return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, indirectBuffer,
1067                              indirectBufferOffset, commandBufferOut);
1068 }
1069 
setupLineLoopIndexedIndirectDraw(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType indexType,vk::BufferHelper * srcIndirectBuf,VkDeviceSize indirectBufferOffset,vk::CommandBuffer ** commandBufferOut,vk::BufferHelper ** indirectBufferOut,VkDeviceSize * indirectBufferOffsetOut)1070 angle::Result ContextVk::setupLineLoopIndexedIndirectDraw(const gl::Context *context,
1071                                                           gl::PrimitiveMode mode,
1072                                                           gl::DrawElementsType indexType,
1073                                                           vk::BufferHelper *srcIndirectBuf,
1074                                                           VkDeviceSize indirectBufferOffset,
1075                                                           vk::CommandBuffer **commandBufferOut,
1076                                                           vk::BufferHelper **indirectBufferOut,
1077                                                           VkDeviceSize *indirectBufferOffsetOut)
1078 {
1079     ASSERT(mode == gl::PrimitiveMode::LineLoop);
1080 
1081     vk::BufferHelper *dstIndirectBuf  = nullptr;
1082     VkDeviceSize dstIndirectBufOffset = 0;
1083 
1084     ANGLE_TRY(mVertexArray->handleLineLoopIndexIndirect(this, indexType, srcIndirectBuf,
1085                                                         indirectBufferOffset, &dstIndirectBuf,
1086                                                         &dstIndirectBufOffset));
1087 
1088     *indirectBufferOut       = dstIndirectBuf;
1089     *indirectBufferOffsetOut = dstIndirectBufOffset;
1090 
1091     if (indexType != mCurrentDrawElementsType)
1092     {
1093         mCurrentDrawElementsType = indexType;
1094         setIndexBufferDirty();
1095     }
1096 
1097     return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, dstIndirectBuf,
1098                              dstIndirectBufOffset, commandBufferOut);
1099 }
1100 
setupLineLoopIndirectDraw(const gl::Context * context,gl::PrimitiveMode mode,vk::BufferHelper * indirectBuffer,VkDeviceSize indirectBufferOffset,vk::CommandBuffer ** commandBufferOut,vk::BufferHelper ** indirectBufferOut,VkDeviceSize * indirectBufferOffsetOut)1101 angle::Result ContextVk::setupLineLoopIndirectDraw(const gl::Context *context,
1102                                                    gl::PrimitiveMode mode,
1103                                                    vk::BufferHelper *indirectBuffer,
1104                                                    VkDeviceSize indirectBufferOffset,
1105                                                    vk::CommandBuffer **commandBufferOut,
1106                                                    vk::BufferHelper **indirectBufferOut,
1107                                                    VkDeviceSize *indirectBufferOffsetOut)
1108 {
1109     ASSERT(mode == gl::PrimitiveMode::LineLoop);
1110 
1111     vk::BufferHelper *indirectBufferHelperOut = nullptr;
1112 
1113     ANGLE_TRY(mVertexArray->handleLineLoopIndirectDraw(
1114         context, indirectBuffer, indirectBufferOffset, &indirectBufferHelperOut,
1115         indirectBufferOffsetOut));
1116 
1117     *indirectBufferOut = indirectBufferHelperOut;
1118 
1119     if (gl::DrawElementsType::UnsignedInt != mCurrentDrawElementsType)
1120     {
1121         mCurrentDrawElementsType = gl::DrawElementsType::UnsignedInt;
1122         setIndexBufferDirty();
1123     }
1124 
1125     return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, indirectBufferHelperOut,
1126                              *indirectBufferOffsetOut, commandBufferOut);
1127 }
1128 
setupLineLoopDraw(const gl::Context * context,gl::PrimitiveMode mode,GLint firstVertex,GLsizei vertexOrIndexCount,gl::DrawElementsType indexTypeOrInvalid,const void * indices,vk::CommandBuffer ** commandBufferOut,uint32_t * numIndicesOut)1129 angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
1130                                            gl::PrimitiveMode mode,
1131                                            GLint firstVertex,
1132                                            GLsizei vertexOrIndexCount,
1133                                            gl::DrawElementsType indexTypeOrInvalid,
1134                                            const void *indices,
1135                                            vk::CommandBuffer **commandBufferOut,
1136                                            uint32_t *numIndicesOut)
1137 {
1138     ANGLE_TRY(mVertexArray->handleLineLoop(this, firstVertex, vertexOrIndexCount,
1139                                            indexTypeOrInvalid, indices, numIndicesOut));
1140     setIndexBufferDirty();
1141     mCurrentDrawElementsType = indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum
1142                                    ? indexTypeOrInvalid
1143                                    : gl::DrawElementsType::UnsignedInt;
1144     return setupDraw(context, mode, firstVertex, vertexOrIndexCount, 1, indexTypeOrInvalid, indices,
1145                      mIndexedDirtyBitsMask, commandBufferOut);
1146 }
1147 
setupDispatch(const gl::Context * context,vk::CommandBuffer ** commandBufferOut)1148 angle::Result ContextVk::setupDispatch(const gl::Context *context,
1149                                        vk::CommandBuffer **commandBufferOut)
1150 {
1151     // |setupDispatch| and |setupDraw| are special in that they flush dirty bits. Therefore they
1152     // don't use the same APIs to record commands as the functions outside ContextVk.
1153     // The following ensures prior commands are flushed before we start processing dirty bits.
1154     ANGLE_TRY(flushOutsideRenderPassCommands());
1155     ANGLE_TRY(endRenderPass());
1156     *commandBufferOut = &mOutsideRenderPassCommands->getCommandBuffer();
1157 
1158     if (mProgram && mProgram->dirtyUniforms())
1159     {
1160         ANGLE_TRY(mProgram->updateUniforms(this));
1161         mComputeDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
1162     }
1163     else if (mProgramPipeline && mProgramPipeline->dirtyUniforms(getState()))
1164     {
1165         ANGLE_TRY(mProgramPipeline->updateUniforms(this));
1166         mComputeDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
1167     }
1168 
1169     DirtyBits dirtyBits = mComputeDirtyBits;
1170 
1171     // Flush any relevant dirty bits.
1172     for (size_t dirtyBit : dirtyBits)
1173     {
1174         ASSERT(mComputeDirtyBitHandlers[dirtyBit]);
1175         ANGLE_TRY((this->*mComputeDirtyBitHandlers[dirtyBit])(context, *commandBufferOut));
1176     }
1177 
1178     mComputeDirtyBits.reset();
1179 
1180     return angle::Result::Continue;
1181 }
1182 
handleDirtyGraphicsDefaultAttribs(const gl::Context * context,vk::CommandBuffer * commandBuffer)1183 angle::Result ContextVk::handleDirtyGraphicsDefaultAttribs(const gl::Context *context,
1184                                                            vk::CommandBuffer *commandBuffer)
1185 {
1186     ASSERT(mDirtyDefaultAttribsMask.any());
1187 
1188     for (size_t attribIndex : mDirtyDefaultAttribsMask)
1189     {
1190         ANGLE_TRY(updateDefaultAttribute(attribIndex));
1191     }
1192 
1193     mDirtyDefaultAttribsMask.reset();
1194     return angle::Result::Continue;
1195 }
1196 
handleDirtyGraphicsPipeline(const gl::Context * context,vk::CommandBuffer * commandBuffer)1197 angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context,
1198                                                      vk::CommandBuffer *commandBuffer)
1199 {
1200     ASSERT(mExecutable);
1201     mExecutable->updateEarlyFragmentTestsOptimization(this);
1202 
1203     if (!mCurrentGraphicsPipeline)
1204     {
1205         const vk::GraphicsPipelineDesc *descPtr;
1206 
1207         // Draw call shader patching, shader compilation, and pipeline cache query.
1208         ANGLE_TRY(mExecutable->getGraphicsPipeline(
1209             this, mCurrentDrawMode, *mGraphicsPipelineDesc,
1210             context->getState().getProgramExecutable()->getNonBuiltinAttribLocationsMask(),
1211             &descPtr, &mCurrentGraphicsPipeline));
1212         mGraphicsPipelineTransition.reset();
1213     }
1214     else if (mGraphicsPipelineTransition.any())
1215     {
1216         if (!mCurrentGraphicsPipeline->findTransition(
1217                 mGraphicsPipelineTransition, *mGraphicsPipelineDesc, &mCurrentGraphicsPipeline))
1218         {
1219             vk::PipelineHelper *oldPipeline = mCurrentGraphicsPipeline;
1220             const vk::GraphicsPipelineDesc *descPtr;
1221 
1222             ANGLE_TRY(mExecutable->getGraphicsPipeline(
1223                 this, mCurrentDrawMode, *mGraphicsPipelineDesc,
1224                 context->getState().getProgramExecutable()->getNonBuiltinAttribLocationsMask(),
1225                 &descPtr, &mCurrentGraphicsPipeline));
1226 
1227             oldPipeline->addTransition(mGraphicsPipelineTransition, descPtr,
1228                                        mCurrentGraphicsPipeline);
1229         }
1230 
1231         mGraphicsPipelineTransition.reset();
1232     }
1233     mRenderPassCommands->pauseTransformFeedbackIfStarted();
1234     commandBuffer->bindGraphicsPipeline(mCurrentGraphicsPipeline->getPipeline());
1235     // Update the queue serial for the pipeline object.
1236     ASSERT(mCurrentGraphicsPipeline && mCurrentGraphicsPipeline->valid());
1237     mCurrentGraphicsPipeline->updateSerial(getCurrentQueueSerial());
1238     return angle::Result::Continue;
1239 }
1240 
handleDirtyComputePipeline(const gl::Context * context,vk::CommandBuffer * commandBuffer)1241 angle::Result ContextVk::handleDirtyComputePipeline(const gl::Context *context,
1242                                                     vk::CommandBuffer *commandBuffer)
1243 {
1244     if (!mCurrentComputePipeline)
1245     {
1246         ASSERT(mExecutable);
1247         ANGLE_TRY(mExecutable->getComputePipeline(this, &mCurrentComputePipeline));
1248     }
1249 
1250     commandBuffer->bindComputePipeline(mCurrentComputePipeline->get());
1251     mCurrentComputePipeline->updateSerial(getCurrentQueueSerial());
1252 
1253     return angle::Result::Continue;
1254 }
1255 
handleDirtyTexturesImpl(vk::CommandBufferHelper * commandBufferHelper)1256 ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
1257     vk::CommandBufferHelper *commandBufferHelper)
1258 {
1259     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
1260     ASSERT(executable);
1261     const gl::ActiveTextureMask &activeTextures = executable->getActiveSamplersMask();
1262 
1263     for (size_t textureUnit : activeTextures)
1264     {
1265         const vk::TextureUnit &unit = mActiveTextures[textureUnit];
1266         TextureVk *textureVk        = unit.texture;
1267         vk::ImageHelper &image      = textureVk->getImage();
1268 
1269         // The image should be flushed and ready to use at this point. There may still be
1270         // lingering staged updates in its staging buffer for unused texture mip levels or
1271         // layers. Therefore we can't verify it has no staged updates right here.
1272 
1273         // Select the appropriate vk::ImageLayout depending on whether the texture is also bound as
1274         // a GL image, and whether the program is a compute or graphics shader.
1275         vk::ImageLayout textureLayout;
1276         if (textureVk->isBoundAsImageTexture(mState.getContextID()))
1277         {
1278             textureLayout = executable->isCompute() ? vk::ImageLayout::ComputeShaderWrite
1279                                                     : vk::ImageLayout::AllGraphicsShadersReadWrite;
1280         }
1281         else
1282         {
1283             gl::ShaderBitSet shaderBits =
1284                 executable->getSamplerShaderBitsForTextureUnitIndex(textureUnit);
1285             if (shaderBits.any())
1286             {
1287                 gl::ShaderType shader =
1288                     static_cast<gl::ShaderType>(gl::ScanForward(shaderBits.bits()));
1289                 shaderBits.reset(shader);
1290                 // If we have multiple shader accessing it, we barrier against all shader stage read
1291                 // given that we only support vertex/frag shaders
1292                 if (shaderBits.any())
1293                 {
1294                     textureLayout = vk::ImageLayout::AllGraphicsShadersReadOnly;
1295                 }
1296                 else
1297                 {
1298                     textureLayout = kShaderReadOnlyImageLayouts[shader];
1299                 }
1300             }
1301             else
1302             {
1303                 textureLayout = vk::ImageLayout::AllGraphicsShadersReadOnly;
1304             }
1305         }
1306         // Ensure the image is in read-only layout
1307         commandBufferHelper->imageRead(&mResourceUseList, image.getAspectFlags(), textureLayout,
1308                                        &image);
1309 
1310         textureVk->retainImageViews(&mResourceUseList);
1311     }
1312 
1313     if (executable->hasTextures())
1314     {
1315         ANGLE_TRY(mExecutable->updateTexturesDescriptorSet(this));
1316     }
1317 
1318     return angle::Result::Continue;
1319 }
1320 
handleDirtyGraphicsTextures(const gl::Context * context,vk::CommandBuffer * commandBuffer)1321 angle::Result ContextVk::handleDirtyGraphicsTextures(const gl::Context *context,
1322                                                      vk::CommandBuffer *commandBuffer)
1323 {
1324     return handleDirtyTexturesImpl(mRenderPassCommands);
1325 }
1326 
handleDirtyComputeTextures(const gl::Context * context,vk::CommandBuffer * commandBuffer)1327 angle::Result ContextVk::handleDirtyComputeTextures(const gl::Context *context,
1328                                                     vk::CommandBuffer *commandBuffer)
1329 {
1330     return handleDirtyTexturesImpl(mOutsideRenderPassCommands);
1331 }
1332 
handleDirtyGraphicsVertexBuffers(const gl::Context * context,vk::CommandBuffer * commandBuffer)1333 angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(const gl::Context *context,
1334                                                           vk::CommandBuffer *commandBuffer)
1335 {
1336     uint32_t maxAttrib = context->getState().getProgramExecutable()->getMaxActiveAttribLocation();
1337     const gl::AttribArray<VkBuffer> &bufferHandles = mVertexArray->getCurrentArrayBufferHandles();
1338     const gl::AttribArray<VkDeviceSize> &bufferOffsets =
1339         mVertexArray->getCurrentArrayBufferOffsets();
1340 
1341     commandBuffer->bindVertexBuffers(0, maxAttrib, bufferHandles.data(), bufferOffsets.data());
1342 
1343     const gl::AttribArray<vk::BufferHelper *> &arrayBufferResources =
1344         mVertexArray->getCurrentArrayBuffers();
1345 
1346     // Mark all active vertex buffers as accessed.
1347     const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
1348     gl::AttributesMask attribsMask          = executable->getActiveAttribLocationsMask();
1349     for (size_t attribIndex : attribsMask)
1350     {
1351         vk::BufferHelper *arrayBuffer = arrayBufferResources[attribIndex];
1352         if (arrayBuffer)
1353         {
1354             mRenderPassCommands->bufferRead(&mResourceUseList, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
1355                                             vk::PipelineStage::VertexInput, arrayBuffer);
1356         }
1357     }
1358 
1359     return angle::Result::Continue;
1360 }
1361 
handleDirtyGraphicsIndexBuffer(const gl::Context * context,vk::CommandBuffer * commandBuffer)1362 angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(const gl::Context *context,
1363                                                         vk::CommandBuffer *commandBuffer)
1364 {
1365     vk::BufferHelper *elementArrayBuffer = mVertexArray->getCurrentElementArrayBuffer();
1366     ASSERT(elementArrayBuffer != nullptr);
1367 
1368     commandBuffer->bindIndexBuffer(elementArrayBuffer->getBuffer(),
1369                                    mVertexArray->getCurrentElementArrayBufferOffset(),
1370                                    getVkIndexType(mCurrentDrawElementsType));
1371 
1372     mRenderPassCommands->bufferRead(&mResourceUseList, VK_ACCESS_INDEX_READ_BIT,
1373                                     vk::PipelineStage::VertexInput, elementArrayBuffer);
1374 
1375     return angle::Result::Continue;
1376 }
1377 
handleDirtyShaderResourcesImpl(const gl::Context * context,vk::CommandBufferHelper * commandBufferHelper)1378 ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl(
1379     const gl::Context *context,
1380     vk::CommandBufferHelper *commandBufferHelper)
1381 {
1382     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
1383     ASSERT(executable);
1384 
1385     if (executable->hasImages())
1386     {
1387         ANGLE_TRY(updateActiveImages(context, commandBufferHelper));
1388     }
1389 
1390     if (executable->hasUniformBuffers() || executable->hasStorageBuffers() ||
1391         executable->hasAtomicCounterBuffers() || executable->hasImages())
1392     {
1393         ANGLE_TRY(mExecutable->updateShaderResourcesDescriptorSet(this, &mResourceUseList,
1394                                                                   commandBufferHelper));
1395     }
1396     return angle::Result::Continue;
1397 }
1398 
handleDirtyGraphicsShaderResources(const gl::Context * context,vk::CommandBuffer * commandBuffer)1399 angle::Result ContextVk::handleDirtyGraphicsShaderResources(const gl::Context *context,
1400                                                             vk::CommandBuffer *commandBuffer)
1401 {
1402     return handleDirtyShaderResourcesImpl(context, mRenderPassCommands);
1403 }
1404 
handleDirtyComputeShaderResources(const gl::Context * context,vk::CommandBuffer * commandBuffer)1405 angle::Result ContextVk::handleDirtyComputeShaderResources(const gl::Context *context,
1406                                                            vk::CommandBuffer *commandBuffer)
1407 {
1408     return handleDirtyShaderResourcesImpl(context, mOutsideRenderPassCommands);
1409 }
1410 
handleDirtyGraphicsTransformFeedbackBuffersEmulation(const gl::Context * context,vk::CommandBuffer * commandBuffer)1411 angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation(
1412     const gl::Context *context,
1413     vk::CommandBuffer *commandBuffer)
1414 {
1415     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
1416     ASSERT(executable);
1417 
1418     if (!executable->hasTransformFeedbackOutput() || !mState.isTransformFeedbackActive())
1419     {
1420         return angle::Result::Continue;
1421     }
1422 
1423     TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(mState.getCurrentTransformFeedback());
1424     size_t bufferCount                       = executable->getTransformFeedbackBufferCount();
1425     const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &bufferHelpers =
1426         transformFeedbackVk->getBufferHelpers();
1427 
1428     for (size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
1429     {
1430         vk::BufferHelper *bufferHelper = bufferHelpers[bufferIndex];
1431         ASSERT(bufferHelper);
1432         mRenderPassCommands->bufferWrite(&mResourceUseList, VK_ACCESS_SHADER_WRITE_BIT,
1433                                          vk::PipelineStage::VertexShader, bufferHelper);
1434     }
1435 
1436     // TODO(http://anglebug.com/3570): Need to update to handle Program Pipelines
1437     return mProgram->getExecutable().updateTransformFeedbackDescriptorSet(
1438         mProgram->getState(), mProgram->getDefaultUniformBlocks(), this);
1439 }
1440 
handleDirtyGraphicsTransformFeedbackBuffersExtension(const gl::Context * context,vk::CommandBuffer * commandBuffer)1441 angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension(
1442     const gl::Context *context,
1443     vk::CommandBuffer *commandBuffer)
1444 {
1445     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
1446     ASSERT(executable);
1447 
1448     if (!executable->hasTransformFeedbackOutput() || !mState.isTransformFeedbackActive())
1449         return angle::Result::Continue;
1450 
1451     TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(mState.getCurrentTransformFeedback());
1452     size_t bufferCount                       = executable->getTransformFeedbackBufferCount();
1453 
1454     const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &bufferHelpers =
1455         transformFeedbackVk->getBufferHelpers();
1456 
1457     for (size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
1458     {
1459         vk::BufferHelper *bufferHelper = bufferHelpers[bufferIndex];
1460         ASSERT(bufferHelper);
1461         mRenderPassCommands->bufferWrite(&mResourceUseList,
1462                                          VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT,
1463                                          vk::PipelineStage::TransformFeedback, bufferHelper);
1464     }
1465 
1466     const gl::TransformFeedbackBuffersArray<VkBuffer> &bufferHandles =
1467         transformFeedbackVk->getBufferHandles();
1468     const gl::TransformFeedbackBuffersArray<VkDeviceSize> &bufferOffsets =
1469         transformFeedbackVk->getBufferOffsets();
1470     const gl::TransformFeedbackBuffersArray<VkDeviceSize> &bufferSizes =
1471         transformFeedbackVk->getBufferSizes();
1472 
1473     commandBuffer->bindTransformFeedbackBuffers(static_cast<uint32_t>(bufferCount),
1474                                                 bufferHandles.data(), bufferOffsets.data(),
1475                                                 bufferSizes.data());
1476 
1477     return angle::Result::Continue;
1478 }
1479 
handleDirtyGraphicsTransformFeedbackState(const gl::Context * context,vk::CommandBuffer * commandBuffer)1480 angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(const gl::Context *context,
1481                                                                    vk::CommandBuffer *commandBuffer)
1482 {
1483     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
1484     ASSERT(executable);
1485 
1486     if (!executable->hasTransformFeedbackOutput() || !mState.isTransformFeedbackActiveUnpaused())
1487     {
1488         return angle::Result::Continue;
1489     }
1490 
1491     TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(mState.getCurrentTransformFeedback());
1492 
1493     // We should have same number of counter buffers as xfb buffers have
1494     size_t bufferCount = executable->getTransformFeedbackBufferCount();
1495     const gl::TransformFeedbackBuffersArray<VkBuffer> &counterBufferHandles =
1496         transformFeedbackVk->getCounterBufferHandles();
1497 
1498     bool rebindBuffers = transformFeedbackVk->getAndResetBufferRebindState();
1499 
1500     mRenderPassCommands->beginTransformFeedback(bufferCount, counterBufferHandles.data(),
1501                                                 rebindBuffers);
1502 
1503     return angle::Result::Continue;
1504 }
1505 
handleDirtyGraphicsTransformFeedbackResume(const gl::Context * context,vk::CommandBuffer * commandBuffer)1506 angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackResume(
1507     const gl::Context *context,
1508     vk::CommandBuffer *commandBuffer)
1509 {
1510     mRenderPassCommands->resumeTransformFeedbackIfStarted();
1511     return angle::Result::Continue;
1512 }
1513 
handleDirtyDescriptorSets(const gl::Context * context,vk::CommandBuffer * commandBuffer)1514 angle::Result ContextVk::handleDirtyDescriptorSets(const gl::Context *context,
1515                                                    vk::CommandBuffer *commandBuffer)
1516 {
1517     ANGLE_TRY(mExecutable->updateDescriptorSets(this, commandBuffer));
1518     return angle::Result::Continue;
1519 }
1520 
updateOverlayOnPresent()1521 void ContextVk::updateOverlayOnPresent()
1522 {
1523     // Update overlay if active.
1524     gl::RunningGraphWidget *renderPassCount =
1525         mState.getOverlay()->getRunningGraphWidget(gl::WidgetId::VulkanRenderPassCount);
1526     renderPassCount->add(mRenderPassCommands->getAndResetCounter());
1527     renderPassCount->next();
1528 }
1529 
submitFrame(const VkSubmitInfo & submitInfo,vk::PrimaryCommandBuffer && commandBuffer)1530 angle::Result ContextVk::submitFrame(const VkSubmitInfo &submitInfo,
1531                                      vk::PrimaryCommandBuffer &&commandBuffer)
1532 {
1533     if (vk::CommandBufferHelper::kEnableCommandStreamDiagnostics)
1534     {
1535         dumpCommandStreamDiagnostics();
1536     }
1537 
1538     ANGLE_TRY(ensureSubmitFenceInitialized());
1539     ANGLE_TRY(mCommandQueue.submitFrame(this, mContextPriority, submitInfo, mSubmitFence,
1540                                         &mCurrentGarbage, &mCommandPool, std::move(commandBuffer)));
1541 
1542     // we need to explicitly notify every other Context using this VkQueue that their current
1543     // command buffer is no longer valid.
1544     onRenderPassFinished();
1545     mComputeDirtyBits |= mNewComputeCommandBufferDirtyBits;
1546 
1547     // Make sure a new fence is created for the next submission.
1548     mRenderer->resetSharedFence(&mSubmitFence);
1549 
1550     if (mGpuEventsEnabled)
1551     {
1552         ANGLE_TRY(checkCompletedGpuEvents());
1553     }
1554 
1555     return angle::Result::Continue;
1556 }
1557 
synchronizeCpuGpuTime()1558 angle::Result ContextVk::synchronizeCpuGpuTime()
1559 {
1560     ASSERT(mGpuEventsEnabled);
1561 
1562     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
1563     ASSERT(platform);
1564 
1565     // To synchronize CPU and GPU times, we need to get the CPU timestamp as close as possible
1566     // to the GPU timestamp.  The process of getting the GPU timestamp is as follows:
1567     //
1568     //             CPU                            GPU
1569     //
1570     //     Record command buffer
1571     //     with timestamp query
1572     //
1573     //     Submit command buffer
1574     //
1575     //     Post-submission work             Begin execution
1576     //
1577     //            ????                    Write timestamp Tgpu
1578     //
1579     //            ????                       End execution
1580     //
1581     //            ????                    Return query results
1582     //
1583     //            ????
1584     //
1585     //       Get query results
1586     //
1587     // The areas of unknown work (????) on the CPU indicate that the CPU may or may not have
1588     // finished post-submission work while the GPU is executing in parallel. With no further
1589     // work, querying CPU timestamps before submission and after getting query results give the
1590     // bounds to Tgpu, which could be quite large.
1591     //
1592     // Using VkEvents, the GPU can be made to wait for the CPU and vice versa, in an effort to
1593     // reduce this range. This function implements the following procedure:
1594     //
1595     //             CPU                            GPU
1596     //
1597     //     Record command buffer
1598     //     with timestamp query
1599     //
1600     //     Submit command buffer
1601     //
1602     //     Post-submission work             Begin execution
1603     //
1604     //            ????                    Set Event GPUReady
1605     //
1606     //    Wait on Event GPUReady         Wait on Event CPUReady
1607     //
1608     //       Get CPU Time Ts             Wait on Event CPUReady
1609     //
1610     //      Set Event CPUReady           Wait on Event CPUReady
1611     //
1612     //      Get CPU Time Tcpu              Get GPU Time Tgpu
1613     //
1614     //    Wait on Event GPUDone            Set Event GPUDone
1615     //
1616     //       Get CPU Time Te                 End Execution
1617     //
1618     //            Idle                    Return query results
1619     //
1620     //      Get query results
1621     //
1622     // If Te-Ts > epsilon, a GPU or CPU interruption can be assumed and the operation can be
1623     // retried.  Once Te-Ts < epsilon, Tcpu can be taken to presumably match Tgpu.  Finding an
1624     // epsilon that's valid for all devices may be difficult, so the loop can be performed only
1625     // a limited number of times and the Tcpu,Tgpu pair corresponding to smallest Te-Ts used for
1626     // calibration.
1627     //
1628     // Note: Once VK_EXT_calibrated_timestamps is ubiquitous, this should be redone.
1629 
1630     // Make sure nothing is running
1631     ASSERT(!hasRecordedCommands());
1632 
1633     ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::synchronizeCpuGpuTime");
1634 
1635     // Create a query used to receive the GPU timestamp
1636     vk::QueryHelper timestampQuery;
1637     ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, &timestampQuery));
1638 
1639     // Create the three events
1640     VkEventCreateInfo eventCreateInfo = {};
1641     eventCreateInfo.sType             = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
1642     eventCreateInfo.flags             = 0;
1643 
1644     VkDevice device = getDevice();
1645     vk::DeviceScoped<vk::Event> cpuReady(device), gpuReady(device), gpuDone(device);
1646     ANGLE_VK_TRY(this, cpuReady.get().init(device, eventCreateInfo));
1647     ANGLE_VK_TRY(this, gpuReady.get().init(device, eventCreateInfo));
1648     ANGLE_VK_TRY(this, gpuDone.get().init(device, eventCreateInfo));
1649 
1650     constexpr uint32_t kRetries = 10;
1651 
1652     // Time suffixes used are S for seconds and Cycles for cycles
1653     double tightestRangeS = 1e6f;
1654     double TcpuS          = 0;
1655     uint64_t TgpuCycles   = 0;
1656     for (uint32_t i = 0; i < kRetries; ++i)
1657     {
1658         // Reset the events
1659         ANGLE_VK_TRY(this, cpuReady.get().reset(device));
1660         ANGLE_VK_TRY(this, gpuReady.get().reset(device));
1661         ANGLE_VK_TRY(this, gpuDone.get().reset(device));
1662 
1663         // Record the command buffer
1664         vk::DeviceScoped<vk::PrimaryCommandBuffer> commandBatch(device);
1665         vk::PrimaryCommandBuffer &commandBuffer = commandBatch.get();
1666 
1667         ANGLE_TRY(mRenderer->getCommandBufferOneOff(this, &commandBuffer));
1668 
1669         commandBuffer.setEvent(gpuReady.get().getHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
1670         commandBuffer.waitEvents(1, cpuReady.get().ptr(), VK_PIPELINE_STAGE_HOST_BIT,
1671                                  VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, nullptr, 0, nullptr, 0,
1672                                  nullptr);
1673         timestampQuery.writeTimestamp(this, &commandBuffer);
1674         commandBuffer.setEvent(gpuDone.get().getHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
1675 
1676         ANGLE_VK_TRY(this, commandBuffer.end());
1677 
1678         Serial throwAwaySerial;
1679         ANGLE_TRY(mRenderer->queueSubmitOneOff(this, std::move(commandBuffer), mContextPriority,
1680                                                nullptr, &throwAwaySerial));
1681 
1682         // Wait for GPU to be ready.  This is a short busy wait.
1683         VkResult result = VK_EVENT_RESET;
1684         do
1685         {
1686             result = gpuReady.get().getStatus(device);
1687             if (result != VK_EVENT_SET && result != VK_EVENT_RESET)
1688             {
1689                 ANGLE_VK_TRY(this, result);
1690             }
1691         } while (result == VK_EVENT_RESET);
1692 
1693         double TsS = platform->monotonicallyIncreasingTime(platform);
1694 
1695         // Tell the GPU to go ahead with the timestamp query.
1696         ANGLE_VK_TRY(this, cpuReady.get().set(device));
1697         double cpuTimestampS = platform->monotonicallyIncreasingTime(platform);
1698 
1699         // Wait for GPU to be done.  Another short busy wait.
1700         do
1701         {
1702             result = gpuDone.get().getStatus(device);
1703             if (result != VK_EVENT_SET && result != VK_EVENT_RESET)
1704             {
1705                 ANGLE_VK_TRY(this, result);
1706             }
1707         } while (result == VK_EVENT_RESET);
1708 
1709         double TeS = platform->monotonicallyIncreasingTime(platform);
1710 
1711         // Get the query results
1712         ANGLE_TRY(finishToSerial(getLastSubmittedQueueSerial()));
1713 
1714         uint64_t gpuTimestampCycles = 0;
1715         ANGLE_TRY(timestampQuery.getUint64Result(this, &gpuTimestampCycles));
1716 
1717         // Use the first timestamp queried as origin.
1718         if (mGpuEventTimestampOrigin == 0)
1719         {
1720             mGpuEventTimestampOrigin = gpuTimestampCycles;
1721         }
1722 
1723         // Take these CPU and GPU timestamps if there is better confidence.
1724         double confidenceRangeS = TeS - TsS;
1725         if (confidenceRangeS < tightestRangeS)
1726         {
1727             tightestRangeS = confidenceRangeS;
1728             TcpuS          = cpuTimestampS;
1729             TgpuCycles     = gpuTimestampCycles;
1730         }
1731     }
1732 
1733     mGpuEventQueryPool.freeQuery(this, &timestampQuery);
1734 
1735     // timestampPeriod gives nanoseconds/cycle.
1736     double TgpuS =
1737         (TgpuCycles - mGpuEventTimestampOrigin) *
1738         static_cast<double>(getRenderer()->getPhysicalDeviceProperties().limits.timestampPeriod) /
1739         1'000'000'000.0;
1740 
1741     flushGpuEvents(TgpuS, TcpuS);
1742 
1743     mGpuClockSync.gpuTimestampS = TgpuS;
1744     mGpuClockSync.cpuTimestampS = TcpuS;
1745 
1746     return angle::Result::Continue;
1747 }
1748 
traceGpuEventImpl(vk::CommandBuffer * commandBuffer,char phase,const EventName & name)1749 angle::Result ContextVk::traceGpuEventImpl(vk::CommandBuffer *commandBuffer,
1750                                            char phase,
1751                                            const EventName &name)
1752 {
1753     ASSERT(mGpuEventsEnabled);
1754 
1755     GpuEventQuery gpuEvent;
1756     gpuEvent.name  = name;
1757     gpuEvent.phase = phase;
1758     ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, &gpuEvent.queryHelper));
1759 
1760     gpuEvent.queryHelper.writeTimestamp(this, commandBuffer);
1761 
1762     mInFlightGpuEventQueries.push_back(std::move(gpuEvent));
1763     return angle::Result::Continue;
1764 }
1765 
checkCompletedGpuEvents()1766 angle::Result ContextVk::checkCompletedGpuEvents()
1767 {
1768     ASSERT(mGpuEventsEnabled);
1769 
1770     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
1771     ASSERT(platform);
1772 
1773     int finishedCount = 0;
1774 
1775     Serial lastCompletedSerial = getLastCompletedQueueSerial();
1776 
1777     for (GpuEventQuery &eventQuery : mInFlightGpuEventQueries)
1778     {
1779         // Only check the timestamp query if the submission has finished.
1780         if (eventQuery.queryHelper.getStoredQueueSerial() > lastCompletedSerial)
1781         {
1782             break;
1783         }
1784 
1785         // See if the results are available.
1786         uint64_t gpuTimestampCycles = 0;
1787         bool available              = false;
1788         ANGLE_TRY(eventQuery.queryHelper.getUint64ResultNonBlocking(this, &gpuTimestampCycles,
1789                                                                     &available));
1790         if (!available)
1791         {
1792             break;
1793         }
1794 
1795         mGpuEventQueryPool.freeQuery(this, &eventQuery.queryHelper);
1796 
1797         GpuEvent gpuEvent;
1798         gpuEvent.gpuTimestampCycles = gpuTimestampCycles;
1799         gpuEvent.name               = eventQuery.name;
1800         gpuEvent.phase              = eventQuery.phase;
1801 
1802         mGpuEvents.emplace_back(gpuEvent);
1803 
1804         ++finishedCount;
1805     }
1806 
1807     mInFlightGpuEventQueries.erase(mInFlightGpuEventQueries.begin(),
1808                                    mInFlightGpuEventQueries.begin() + finishedCount);
1809 
1810     return angle::Result::Continue;
1811 }
1812 
flushGpuEvents(double nextSyncGpuTimestampS,double nextSyncCpuTimestampS)1813 void ContextVk::flushGpuEvents(double nextSyncGpuTimestampS, double nextSyncCpuTimestampS)
1814 {
1815     if (mGpuEvents.empty())
1816     {
1817         return;
1818     }
1819 
1820     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
1821     ASSERT(platform);
1822 
1823     // Find the slope of the clock drift for adjustment
1824     double lastGpuSyncTimeS  = mGpuClockSync.gpuTimestampS;
1825     double lastGpuSyncDiffS  = mGpuClockSync.cpuTimestampS - mGpuClockSync.gpuTimestampS;
1826     double gpuSyncDriftSlope = 0;
1827 
1828     double nextGpuSyncTimeS = nextSyncGpuTimestampS;
1829     double nextGpuSyncDiffS = nextSyncCpuTimestampS - nextSyncGpuTimestampS;
1830 
1831     // No gpu trace events should have been generated before the clock sync, so if there is no
1832     // "previous" clock sync, there should be no gpu events (i.e. the function early-outs
1833     // above).
1834     ASSERT(mGpuClockSync.gpuTimestampS != std::numeric_limits<double>::max() &&
1835            mGpuClockSync.cpuTimestampS != std::numeric_limits<double>::max());
1836 
1837     gpuSyncDriftSlope =
1838         (nextGpuSyncDiffS - lastGpuSyncDiffS) / (nextGpuSyncTimeS - lastGpuSyncTimeS);
1839 
1840     for (const GpuEvent &gpuEvent : mGpuEvents)
1841     {
1842         double gpuTimestampS =
1843             (gpuEvent.gpuTimestampCycles - mGpuEventTimestampOrigin) *
1844             static_cast<double>(
1845                 getRenderer()->getPhysicalDeviceProperties().limits.timestampPeriod) *
1846             1e-9;
1847 
1848         // Account for clock drift.
1849         gpuTimestampS += lastGpuSyncDiffS + gpuSyncDriftSlope * (gpuTimestampS - lastGpuSyncTimeS);
1850 
1851         // Generate the trace now that the GPU timestamp is available and clock drifts are
1852         // accounted for.
1853         static long long eventId = 1;
1854         static const unsigned char *categoryEnabled =
1855             TRACE_EVENT_API_GET_CATEGORY_ENABLED(platform, "gpu.angle.gpu");
1856         platform->addTraceEvent(platform, gpuEvent.phase, categoryEnabled, gpuEvent.name.data(),
1857                                 eventId++, gpuTimestampS, 0, nullptr, nullptr, nullptr,
1858                                 TRACE_EVENT_FLAG_NONE);
1859     }
1860 
1861     mGpuEvents.clear();
1862 }
1863 
clearAllGarbage()1864 void ContextVk::clearAllGarbage()
1865 {
1866     for (vk::GarbageObject &garbage : mCurrentGarbage)
1867     {
1868         garbage.destroy(mRenderer);
1869     }
1870     mCurrentGarbage.clear();
1871     mCommandQueue.clearAllGarbage(mRenderer);
1872 }
1873 
handleDeviceLost()1874 void ContextVk::handleDeviceLost()
1875 {
1876     mOutsideRenderPassCommands->reset();
1877     mRenderPassCommands->reset();
1878 
1879     mCommandQueue.handleDeviceLost(mRenderer);
1880     clearAllGarbage();
1881 
1882     mRenderer->notifyDeviceLost();
1883 }
1884 
drawArrays(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count)1885 angle::Result ContextVk::drawArrays(const gl::Context *context,
1886                                     gl::PrimitiveMode mode,
1887                                     GLint first,
1888                                     GLsizei count)
1889 {
1890     vk::CommandBuffer *commandBuffer = nullptr;
1891     uint32_t clampedVertexCount      = gl::GetClampedVertexCount<uint32_t>(count);
1892 
1893     if (mode == gl::PrimitiveMode::LineLoop)
1894     {
1895         uint32_t numIndices;
1896         ANGLE_TRY(setupLineLoopDraw(context, mode, first, count, gl::DrawElementsType::InvalidEnum,
1897                                     nullptr, &commandBuffer, &numIndices));
1898         vk::LineLoopHelper::Draw(numIndices, 0, commandBuffer);
1899     }
1900     else
1901     {
1902         ANGLE_TRY(setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum,
1903                             nullptr, mNonIndexedDirtyBitsMask, &commandBuffer));
1904         commandBuffer->draw(clampedVertexCount, first);
1905     }
1906 
1907     return angle::Result::Continue;
1908 }
1909 
drawArraysInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instances)1910 angle::Result ContextVk::drawArraysInstanced(const gl::Context *context,
1911                                              gl::PrimitiveMode mode,
1912                                              GLint first,
1913                                              GLsizei count,
1914                                              GLsizei instances)
1915 {
1916     vk::CommandBuffer *commandBuffer = nullptr;
1917 
1918     if (mode == gl::PrimitiveMode::LineLoop)
1919     {
1920         uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
1921         uint32_t numIndices;
1922         ANGLE_TRY(setupLineLoopDraw(context, mode, first, clampedVertexCount,
1923                                     gl::DrawElementsType::InvalidEnum, nullptr, &commandBuffer,
1924                                     &numIndices));
1925         commandBuffer->drawIndexedInstanced(numIndices, instances);
1926         return angle::Result::Continue;
1927     }
1928 
1929     ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
1930                         nullptr, mNonIndexedDirtyBitsMask, &commandBuffer));
1931     commandBuffer->drawInstanced(gl::GetClampedVertexCount<uint32_t>(count), instances, first);
1932     return angle::Result::Continue;
1933 }
1934 
drawArraysInstancedBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instances,GLuint baseInstance)1935 angle::Result ContextVk::drawArraysInstancedBaseInstance(const gl::Context *context,
1936                                                          gl::PrimitiveMode mode,
1937                                                          GLint first,
1938                                                          GLsizei count,
1939                                                          GLsizei instances,
1940                                                          GLuint baseInstance)
1941 {
1942     vk::CommandBuffer *commandBuffer = nullptr;
1943 
1944     if (mode == gl::PrimitiveMode::LineLoop)
1945     {
1946         uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
1947         uint32_t numIndices;
1948         ANGLE_TRY(setupLineLoopDraw(context, mode, first, clampedVertexCount,
1949                                     gl::DrawElementsType::InvalidEnum, nullptr, &commandBuffer,
1950                                     &numIndices));
1951         commandBuffer->drawIndexedInstancedBaseVertexBaseInstance(numIndices, instances, 0, 0,
1952                                                                   baseInstance);
1953         return angle::Result::Continue;
1954     }
1955 
1956     ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
1957                         nullptr, mNonIndexedDirtyBitsMask, &commandBuffer));
1958     commandBuffer->drawInstancedBaseInstance(gl::GetClampedVertexCount<uint32_t>(count), instances,
1959                                              first, baseInstance);
1960     return angle::Result::Continue;
1961 }
1962 
drawElements(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices)1963 angle::Result ContextVk::drawElements(const gl::Context *context,
1964                                       gl::PrimitiveMode mode,
1965                                       GLsizei count,
1966                                       gl::DrawElementsType type,
1967                                       const void *indices)
1968 {
1969     vk::CommandBuffer *commandBuffer = nullptr;
1970     if (mode == gl::PrimitiveMode::LineLoop)
1971     {
1972         uint32_t indexCount;
1973         ANGLE_TRY(
1974             setupLineLoopDraw(context, mode, 0, count, type, indices, &commandBuffer, &indexCount));
1975         vk::LineLoopHelper::Draw(indexCount, 0, commandBuffer);
1976     }
1977     else
1978     {
1979         ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices, &commandBuffer));
1980         commandBuffer->drawIndexed(count);
1981     }
1982 
1983     return angle::Result::Continue;
1984 }
1985 
drawElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)1986 angle::Result ContextVk::drawElementsBaseVertex(const gl::Context *context,
1987                                                 gl::PrimitiveMode mode,
1988                                                 GLsizei count,
1989                                                 gl::DrawElementsType type,
1990                                                 const void *indices,
1991                                                 GLint baseVertex)
1992 {
1993     vk::CommandBuffer *commandBuffer = nullptr;
1994     if (mode == gl::PrimitiveMode::LineLoop)
1995     {
1996         uint32_t indexCount;
1997         ANGLE_TRY(
1998             setupLineLoopDraw(context, mode, 0, count, type, indices, &commandBuffer, &indexCount));
1999         vk::LineLoopHelper::Draw(indexCount, baseVertex, commandBuffer);
2000     }
2001     else
2002     {
2003         ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices, &commandBuffer));
2004         commandBuffer->drawIndexedBaseVertex(count, baseVertex);
2005     }
2006 
2007     return angle::Result::Continue;
2008 }
2009 
drawElementsInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances)2010 angle::Result ContextVk::drawElementsInstanced(const gl::Context *context,
2011                                                gl::PrimitiveMode mode,
2012                                                GLsizei count,
2013                                                gl::DrawElementsType type,
2014                                                const void *indices,
2015                                                GLsizei instances)
2016 {
2017     vk::CommandBuffer *commandBuffer = nullptr;
2018 
2019     if (mode == gl::PrimitiveMode::LineLoop)
2020     {
2021         uint32_t indexCount;
2022         ANGLE_TRY(
2023             setupLineLoopDraw(context, mode, 0, count, type, indices, &commandBuffer, &indexCount));
2024         count = indexCount;
2025     }
2026     else
2027     {
2028         ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices, &commandBuffer));
2029     }
2030 
2031     commandBuffer->drawIndexedInstanced(count, instances);
2032     return angle::Result::Continue;
2033 }
2034 
drawElementsInstancedBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex)2035 angle::Result ContextVk::drawElementsInstancedBaseVertex(const gl::Context *context,
2036                                                          gl::PrimitiveMode mode,
2037                                                          GLsizei count,
2038                                                          gl::DrawElementsType type,
2039                                                          const void *indices,
2040                                                          GLsizei instances,
2041                                                          GLint baseVertex)
2042 {
2043     vk::CommandBuffer *commandBuffer = nullptr;
2044 
2045     if (mode == gl::PrimitiveMode::LineLoop)
2046     {
2047         uint32_t indexCount;
2048         ANGLE_TRY(
2049             setupLineLoopDraw(context, mode, 0, count, type, indices, &commandBuffer, &indexCount));
2050         count = indexCount;
2051     }
2052     else
2053     {
2054         ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices, &commandBuffer));
2055     }
2056 
2057     commandBuffer->drawIndexedInstancedBaseVertex(count, instances, baseVertex);
2058     return angle::Result::Continue;
2059 }
2060 
drawElementsInstancedBaseVertexBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex,GLuint baseInstance)2061 angle::Result ContextVk::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
2062                                                                      gl::PrimitiveMode mode,
2063                                                                      GLsizei count,
2064                                                                      gl::DrawElementsType type,
2065                                                                      const void *indices,
2066                                                                      GLsizei instances,
2067                                                                      GLint baseVertex,
2068                                                                      GLuint baseInstance)
2069 {
2070     vk::CommandBuffer *commandBuffer = nullptr;
2071 
2072     if (mode == gl::PrimitiveMode::LineLoop)
2073     {
2074         uint32_t indexCount;
2075         ANGLE_TRY(
2076             setupLineLoopDraw(context, mode, 0, count, type, indices, &commandBuffer, &indexCount));
2077         commandBuffer->drawIndexedInstancedBaseVertexBaseInstance(indexCount, instances, 0,
2078                                                                   baseVertex, baseInstance);
2079         return angle::Result::Continue;
2080     }
2081 
2082     ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices, &commandBuffer));
2083     commandBuffer->drawIndexedInstancedBaseVertexBaseInstance(count, instances, 0, baseVertex,
2084                                                               baseInstance);
2085     return angle::Result::Continue;
2086 }
2087 
drawRangeElements(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices)2088 angle::Result ContextVk::drawRangeElements(const gl::Context *context,
2089                                            gl::PrimitiveMode mode,
2090                                            GLuint start,
2091                                            GLuint end,
2092                                            GLsizei count,
2093                                            gl::DrawElementsType type,
2094                                            const void *indices)
2095 {
2096     return drawElements(context, mode, count, type, indices);
2097 }
2098 
drawRangeElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)2099 angle::Result ContextVk::drawRangeElementsBaseVertex(const gl::Context *context,
2100                                                      gl::PrimitiveMode mode,
2101                                                      GLuint start,
2102                                                      GLuint end,
2103                                                      GLsizei count,
2104                                                      gl::DrawElementsType type,
2105                                                      const void *indices,
2106                                                      GLint baseVertex)
2107 {
2108     return drawElementsBaseVertex(context, mode, count, type, indices, baseVertex);
2109 }
2110 
getDevice() const2111 VkDevice ContextVk::getDevice() const
2112 {
2113     return mRenderer->getDevice();
2114 }
2115 
drawArraysIndirect(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect)2116 angle::Result ContextVk::drawArraysIndirect(const gl::Context *context,
2117                                             gl::PrimitiveMode mode,
2118                                             const void *indirect)
2119 {
2120     gl::Buffer *indirectBuffer            = mState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
2121     vk::BufferHelper *currentIndirectBuf  = &vk::GetImpl(indirectBuffer)->getBuffer();
2122     VkDeviceSize currentIndirectBufOffset = reinterpret_cast<VkDeviceSize>(indirect);
2123 
2124     if (mVertexArray->getStreamingVertexAttribsMask().any())
2125     {
2126         mRenderPassCommands->bufferRead(&mResourceUseList, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
2127                                         vk::PipelineStage::DrawIndirect, currentIndirectBuf);
2128 
2129         // We have instanced vertex attributes that need to be emulated for Vulkan.
2130         // invalidate any cache and map the buffer so that we can read the indirect data.
2131         // Mapping the buffer will cause a flush.
2132         ANGLE_TRY(currentIndirectBuf->invalidate(mRenderer, 0, sizeof(VkDrawIndirectCommand)));
2133         uint8_t *buffPtr;
2134         ANGLE_TRY(currentIndirectBuf->map(this, &buffPtr));
2135         const VkDrawIndirectCommand *indirectData =
2136             reinterpret_cast<VkDrawIndirectCommand *>(buffPtr + currentIndirectBufOffset);
2137 
2138         ANGLE_TRY(drawArraysInstanced(context, mode, indirectData->firstVertex,
2139                                       indirectData->vertexCount, indirectData->instanceCount));
2140 
2141         currentIndirectBuf->unmap(mRenderer);
2142         return angle::Result::Continue;
2143     }
2144 
2145     vk::CommandBuffer *commandBuffer = nullptr;
2146 
2147     if (mode == gl::PrimitiveMode::LineLoop)
2148     {
2149         ASSERT(indirectBuffer);
2150         vk::BufferHelper *dstIndirectBuf  = nullptr;
2151         VkDeviceSize dstIndirectBufOffset = 0;
2152 
2153         ANGLE_TRY(setupLineLoopIndirectDraw(context, mode, currentIndirectBuf,
2154                                             currentIndirectBufOffset, &commandBuffer,
2155                                             &dstIndirectBuf, &dstIndirectBufOffset));
2156 
2157         commandBuffer->drawIndexedIndirect(dstIndirectBuf->getBuffer(), dstIndirectBufOffset, 1, 0);
2158         return angle::Result::Continue;
2159     }
2160 
2161     ANGLE_TRY(setupIndirectDraw(context, mode, mNonIndexedDirtyBitsMask, currentIndirectBuf,
2162                                 currentIndirectBufOffset, &commandBuffer));
2163 
2164     commandBuffer->drawIndirect(currentIndirectBuf->getBuffer(), currentIndirectBufOffset, 1, 0);
2165     return angle::Result::Continue;
2166 }
2167 
drawElementsIndirect(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect)2168 angle::Result ContextVk::drawElementsIndirect(const gl::Context *context,
2169                                               gl::PrimitiveMode mode,
2170                                               gl::DrawElementsType type,
2171                                               const void *indirect)
2172 {
2173     VkDeviceSize currentIndirectBufOffset = reinterpret_cast<VkDeviceSize>(indirect);
2174     gl::Buffer *indirectBuffer            = mState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
2175     ASSERT(indirectBuffer);
2176     vk::BufferHelper *currentIndirectBuf = &vk::GetImpl(indirectBuffer)->getBuffer();
2177 
2178     if (mVertexArray->getStreamingVertexAttribsMask().any())
2179     {
2180         mRenderPassCommands->bufferRead(&mResourceUseList, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
2181                                         vk::PipelineStage::DrawIndirect, currentIndirectBuf);
2182 
2183         // We have instanced vertex attributes that need to be emulated for Vulkan.
2184         // invalidate any cache and map the buffer so that we can read the indirect data.
2185         // Mapping the buffer will cause a flush.
2186         ANGLE_TRY(
2187             currentIndirectBuf->invalidate(mRenderer, 0, sizeof(VkDrawIndexedIndirectCommand)));
2188         uint8_t *buffPtr;
2189         ANGLE_TRY(currentIndirectBuf->map(this, &buffPtr));
2190         const VkDrawIndexedIndirectCommand *indirectData =
2191             reinterpret_cast<VkDrawIndexedIndirectCommand *>(buffPtr + currentIndirectBufOffset);
2192 
2193         ANGLE_TRY(drawElementsInstanced(context, mode, indirectData->indexCount, type, nullptr,
2194                                         indirectData->instanceCount));
2195 
2196         currentIndirectBuf->unmap(mRenderer);
2197         return angle::Result::Continue;
2198     }
2199 
2200     if (shouldConvertUint8VkIndexType(type) && mGraphicsDirtyBits[DIRTY_BIT_INDEX_BUFFER])
2201     {
2202         vk::BufferHelper *dstIndirectBuf;
2203         VkDeviceSize dstIndirectBufOffset;
2204 
2205         ANGLE_TRY(mVertexArray->convertIndexBufferIndirectGPU(
2206             this, currentIndirectBuf, currentIndirectBufOffset, &dstIndirectBuf,
2207             &dstIndirectBufOffset));
2208 
2209         currentIndirectBuf       = dstIndirectBuf;
2210         currentIndirectBufOffset = dstIndirectBufOffset;
2211     }
2212 
2213     vk::CommandBuffer *commandBuffer = nullptr;
2214 
2215     if (mode == gl::PrimitiveMode::LineLoop)
2216     {
2217         vk::BufferHelper *dstIndirectBuf;
2218         VkDeviceSize dstIndirectBufOffset;
2219 
2220         ANGLE_TRY(setupLineLoopIndexedIndirectDraw(context, mode, type, currentIndirectBuf,
2221                                                    currentIndirectBufOffset, &commandBuffer,
2222                                                    &dstIndirectBuf, &dstIndirectBufOffset));
2223 
2224         currentIndirectBuf       = dstIndirectBuf;
2225         currentIndirectBufOffset = dstIndirectBufOffset;
2226     }
2227     else
2228     {
2229         ANGLE_TRY(setupIndexedIndirectDraw(context, mode, type, currentIndirectBuf,
2230                                            currentIndirectBufOffset, &commandBuffer));
2231     }
2232 
2233     commandBuffer->drawIndexedIndirect(currentIndirectBuf->getBuffer(), currentIndirectBufOffset, 1,
2234                                        0);
2235     return angle::Result::Continue;
2236 }
2237 
optimizeRenderPassForPresent(VkFramebuffer framebufferHandle)2238 void ContextVk::optimizeRenderPassForPresent(VkFramebuffer framebufferHandle)
2239 {
2240     if (!mRenderPassCommands->started())
2241     {
2242         return;
2243     }
2244 
2245     if (framebufferHandle != mRenderPassCommands->getFramebufferHandle())
2246     {
2247         return;
2248     }
2249 
2250     RenderTargetVk *color0RenderTarget = mDrawFramebuffer->getColorDrawRenderTarget(0);
2251     if (!color0RenderTarget)
2252     {
2253         return;
2254     }
2255 
2256     // EGL1.5 spec: The contents of ancillary buffers are always undefined after calling
2257     // eglSwapBuffers
2258     RenderTargetVk *depthStencilRenderTarget = mDrawFramebuffer->getDepthStencilRenderTarget();
2259     if (depthStencilRenderTarget)
2260     {
2261         size_t depthStencilAttachmentIndexVk = mDrawFramebuffer->getDepthStencilAttachmentIndexVk();
2262         // Change depthstencil attachment storeOp to DONT_CARE
2263         mRenderPassCommands->invalidateRenderPassStencilAttachment(depthStencilAttachmentIndexVk);
2264         mRenderPassCommands->invalidateRenderPassDepthAttachment(depthStencilAttachmentIndexVk);
2265         // Mark content as invalid so that we will not load them in next renderpass
2266         depthStencilRenderTarget->invalidateContent();
2267     }
2268 
2269     // Use finalLayout instead of extra barrier for layout change to present
2270     vk::ImageHelper &image = color0RenderTarget->getImage();
2271     image.setCurrentImageLayout(vk::ImageLayout::Present);
2272     mRenderPassCommands->updateRenderPassAttachmentFinalLayout(0, image.getCurrentImageLayout());
2273 }
2274 
getResetStatus()2275 gl::GraphicsResetStatus ContextVk::getResetStatus()
2276 {
2277     if (mRenderer->isDeviceLost())
2278     {
2279         // TODO(geofflang): It may be possible to track which context caused the device lost and
2280         // return either GL_GUILTY_CONTEXT_RESET or GL_INNOCENT_CONTEXT_RESET.
2281         // http://anglebug.com/2787
2282         return gl::GraphicsResetStatus::UnknownContextReset;
2283     }
2284 
2285     return gl::GraphicsResetStatus::NoError;
2286 }
2287 
getVendorString() const2288 std::string ContextVk::getVendorString() const
2289 {
2290     UNIMPLEMENTED();
2291     return std::string();
2292 }
2293 
getRendererDescription() const2294 std::string ContextVk::getRendererDescription() const
2295 {
2296     return mRenderer->getRendererDescription();
2297 }
2298 
insertEventMarker(GLsizei length,const char * marker)2299 angle::Result ContextVk::insertEventMarker(GLsizei length, const char *marker)
2300 {
2301     if (!mRenderer->enableDebugUtils())
2302         return angle::Result::Continue;
2303 
2304     vk::CommandBuffer *outsideRenderPassCommandBuffer;
2305     ANGLE_TRY(endRenderPassAndGetCommandBuffer(&outsideRenderPassCommandBuffer));
2306 
2307     VkDebugUtilsLabelEXT label;
2308     vk::MakeDebugUtilsLabel(GL_DEBUG_SOURCE_APPLICATION, marker, &label);
2309     outsideRenderPassCommandBuffer->insertDebugUtilsLabelEXT(label);
2310 
2311     return angle::Result::Continue;
2312 }
2313 
pushGroupMarker(GLsizei length,const char * marker)2314 angle::Result ContextVk::pushGroupMarker(GLsizei length, const char *marker)
2315 {
2316     if (!mRenderer->enableDebugUtils())
2317         return angle::Result::Continue;
2318 
2319     vk::CommandBuffer *outsideRenderPassCommandBuffer;
2320     ANGLE_TRY(endRenderPassAndGetCommandBuffer(&outsideRenderPassCommandBuffer));
2321 
2322     VkDebugUtilsLabelEXT label;
2323     vk::MakeDebugUtilsLabel(GL_DEBUG_SOURCE_APPLICATION, marker, &label);
2324     outsideRenderPassCommandBuffer->beginDebugUtilsLabelEXT(label);
2325 
2326     return angle::Result::Continue;
2327 }
2328 
popGroupMarker()2329 angle::Result ContextVk::popGroupMarker()
2330 {
2331     if (!mRenderer->enableDebugUtils())
2332         return angle::Result::Continue;
2333 
2334     vk::CommandBuffer *outsideRenderPassCommandBuffer;
2335     ANGLE_TRY(endRenderPassAndGetCommandBuffer(&outsideRenderPassCommandBuffer));
2336     outsideRenderPassCommandBuffer->endDebugUtilsLabelEXT();
2337 
2338     return angle::Result::Continue;
2339 }
2340 
pushDebugGroup(const gl::Context * context,GLenum source,GLuint id,const std::string & message)2341 angle::Result ContextVk::pushDebugGroup(const gl::Context *context,
2342                                         GLenum source,
2343                                         GLuint id,
2344                                         const std::string &message)
2345 {
2346     if (!mRenderer->enableDebugUtils())
2347         return angle::Result::Continue;
2348 
2349     vk::CommandBuffer *outsideRenderPassCommandBuffer;
2350     ANGLE_TRY(endRenderPassAndGetCommandBuffer(&outsideRenderPassCommandBuffer));
2351 
2352     VkDebugUtilsLabelEXT label;
2353     vk::MakeDebugUtilsLabel(source, message.c_str(), &label);
2354     outsideRenderPassCommandBuffer->beginDebugUtilsLabelEXT(label);
2355 
2356     return angle::Result::Continue;
2357 }
2358 
popDebugGroup(const gl::Context * context)2359 angle::Result ContextVk::popDebugGroup(const gl::Context *context)
2360 {
2361     if (!mRenderer->enableDebugUtils())
2362         return angle::Result::Continue;
2363 
2364     vk::CommandBuffer *outsideRenderPassCommandBuffer;
2365     ANGLE_TRY(endRenderPassAndGetCommandBuffer(&outsideRenderPassCommandBuffer));
2366     outsideRenderPassCommandBuffer->endDebugUtilsLabelEXT();
2367 
2368     return angle::Result::Continue;
2369 }
2370 
isViewportFlipEnabledForDrawFBO() const2371 bool ContextVk::isViewportFlipEnabledForDrawFBO() const
2372 {
2373     return mFlipViewportForDrawFramebuffer && mFlipYForCurrentSurface;
2374 }
2375 
isViewportFlipEnabledForReadFBO() const2376 bool ContextVk::isViewportFlipEnabledForReadFBO() const
2377 {
2378     return mFlipViewportForReadFramebuffer;
2379 }
2380 
isRotatedAspectRatioForDrawFBO() const2381 bool ContextVk::isRotatedAspectRatioForDrawFBO() const
2382 {
2383     return IsRotatedAspectRatio(mCurrentRotationDrawFramebuffer);
2384 }
2385 
isRotatedAspectRatioForReadFBO() const2386 bool ContextVk::isRotatedAspectRatioForReadFBO() const
2387 {
2388     return IsRotatedAspectRatio(mCurrentRotationReadFramebuffer);
2389 }
2390 
getRotationDrawFramebuffer() const2391 SurfaceRotation ContextVk::getRotationDrawFramebuffer() const
2392 {
2393     return mCurrentRotationDrawFramebuffer;
2394 }
2395 
getRotationReadFramebuffer() const2396 SurfaceRotation ContextVk::getRotationReadFramebuffer() const
2397 {
2398     return mCurrentRotationReadFramebuffer;
2399 }
2400 
updateColorMask(const gl::BlendState & blendState)2401 void ContextVk::updateColorMask(const gl::BlendState &blendState)
2402 {
2403     mClearColorMask =
2404         gl_vk::GetColorComponentFlags(blendState.colorMaskRed, blendState.colorMaskGreen,
2405                                       blendState.colorMaskBlue, blendState.colorMaskAlpha);
2406 
2407     FramebufferVk *framebufferVk = vk::GetImpl(mState.getDrawFramebuffer());
2408     mGraphicsPipelineDesc->updateColorWriteMask(&mGraphicsPipelineTransition, mClearColorMask,
2409                                                 framebufferVk->getEmulatedAlphaAttachmentMask());
2410 }
2411 
updateSampleMask(const gl::State & glState)2412 void ContextVk::updateSampleMask(const gl::State &glState)
2413 {
2414     // If sample coverage is enabled, emulate it by generating and applying a mask on top of the
2415     // sample mask.
2416     uint32_t coverageSampleCount = GetCoverageSampleCount(glState, mDrawFramebuffer);
2417 
2418     static_assert(sizeof(uint32_t) == sizeof(GLbitfield), "Vulkan assumes 32-bit sample masks");
2419     for (uint32_t maskNumber = 0; maskNumber < glState.getMaxSampleMaskWords(); ++maskNumber)
2420     {
2421         uint32_t mask = glState.isSampleMaskEnabled() ? glState.getSampleMaskWord(maskNumber)
2422                                                       : std::numeric_limits<uint32_t>::max();
2423 
2424         ApplySampleCoverage(glState, coverageSampleCount, maskNumber, &mask);
2425 
2426         mGraphicsPipelineDesc->updateSampleMask(&mGraphicsPipelineTransition, maskNumber, mask);
2427     }
2428 }
2429 
getCorrectedViewport(const gl::Rectangle & viewport) const2430 gl::Rectangle ContextVk::getCorrectedViewport(const gl::Rectangle &viewport) const
2431 {
2432     const gl::Caps &caps                   = getCaps();
2433     const VkPhysicalDeviceLimits &limitsVk = mRenderer->getPhysicalDeviceProperties().limits;
2434     const int viewportBoundsRangeLow       = static_cast<int>(limitsVk.viewportBoundsRange[0]);
2435     const int viewportBoundsRangeHigh      = static_cast<int>(limitsVk.viewportBoundsRange[1]);
2436 
2437     // Clamp the viewport values to what Vulkan specifies
2438 
2439     // width must be greater than 0.0 and less than or equal to
2440     // VkPhysicalDeviceLimits::maxViewportDimensions[0]
2441     int correctedWidth = std::min<int>(viewport.width, caps.maxViewportWidth);
2442     correctedWidth     = std::max<int>(correctedWidth, 0);
2443     // height must be greater than 0.0 and less than or equal to
2444     // VkPhysicalDeviceLimits::maxViewportDimensions[1]
2445     int correctedHeight = std::min<int>(viewport.height, caps.maxViewportHeight);
2446     correctedHeight     = std::max<int>(correctedHeight, 0);
2447     // x and y must each be between viewportBoundsRange[0] and viewportBoundsRange[1], inclusive.
2448     // Viewport size cannot be 0 so ensure there is always size for a 1x1 viewport
2449     int correctedX = std::min<int>(viewport.x, viewportBoundsRangeHigh - 1);
2450     correctedX     = std::max<int>(correctedX, viewportBoundsRangeLow);
2451     int correctedY = std::min<int>(viewport.y, viewportBoundsRangeHigh - 1);
2452     correctedY     = std::max<int>(correctedY, viewportBoundsRangeLow);
2453     // x + width must be less than or equal to viewportBoundsRange[1]
2454     if ((correctedX + correctedWidth) > viewportBoundsRangeHigh)
2455     {
2456         correctedWidth = viewportBoundsRangeHigh - correctedX;
2457     }
2458     // y + height must be less than or equal to viewportBoundsRange[1]
2459     if ((correctedY + correctedHeight) > viewportBoundsRangeHigh)
2460     {
2461         correctedHeight = viewportBoundsRangeHigh - correctedY;
2462     }
2463 
2464     return gl::Rectangle(correctedX, correctedY, correctedWidth, correctedHeight);
2465 }
2466 
updateViewport(FramebufferVk * framebufferVk,const gl::Rectangle & viewport,float nearPlane,float farPlane,bool invertViewport)2467 void ContextVk::updateViewport(FramebufferVk *framebufferVk,
2468                                const gl::Rectangle &viewport,
2469                                float nearPlane,
2470                                float farPlane,
2471                                bool invertViewport)
2472 {
2473 
2474     gl::Box fbDimensions        = framebufferVk->getState().getDimensions();
2475     gl::Rectangle correctedRect = getCorrectedViewport(viewport);
2476     gl::Rectangle rotatedRect;
2477     RotateRectangle(getRotationDrawFramebuffer(), false, fbDimensions.width, fbDimensions.height,
2478                     correctedRect, &rotatedRect);
2479 
2480     VkViewport vkViewport;
2481     gl_vk::GetViewport(rotatedRect, nearPlane, farPlane, invertViewport,
2482                        // If the surface is rotated 90/270 degrees, use the framebuffer's width
2483                        // instead of the height for calculating the final viewport.
2484                        isRotatedAspectRatioForDrawFBO() ? fbDimensions.width : fbDimensions.height,
2485                        &vkViewport);
2486     mGraphicsPipelineDesc->updateViewport(&mGraphicsPipelineTransition, vkViewport);
2487     invalidateGraphicsDriverUniforms();
2488 }
2489 
updateDepthRange(float nearPlane,float farPlane)2490 void ContextVk::updateDepthRange(float nearPlane, float farPlane)
2491 {
2492     invalidateGraphicsDriverUniforms();
2493     mGraphicsPipelineDesc->updateDepthRange(&mGraphicsPipelineTransition, nearPlane, farPlane);
2494 }
2495 
updateScissor(const gl::State & glState)2496 angle::Result ContextVk::updateScissor(const gl::State &glState)
2497 {
2498     FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer());
2499     gl::Rectangle renderArea     = framebufferVk->getCompleteRenderArea();
2500 
2501     // Clip the render area to the viewport.
2502     gl::Rectangle viewportClippedRenderArea;
2503     gl::ClipRectangle(renderArea, getCorrectedViewport(glState.getViewport()),
2504                       &viewportClippedRenderArea);
2505 
2506     gl::Rectangle scissoredArea = ClipRectToScissor(getState(), viewportClippedRenderArea, false);
2507     gl::Rectangle rotatedScissoredArea;
2508     RotateRectangle(getRotationDrawFramebuffer(), isViewportFlipEnabledForDrawFBO(),
2509                     renderArea.width, renderArea.height, scissoredArea, &rotatedScissoredArea);
2510 
2511     mGraphicsPipelineDesc->updateScissor(&mGraphicsPipelineTransition,
2512                                          gl_vk::GetRect(rotatedScissoredArea));
2513 
2514     // If the scissor has grown beyond the previous scissoredRenderArea, make sure the render pass
2515     // is restarted.  Otherwise, we can continue using the same renderpass area.
2516     //
2517     // Without a scissor, the render pass area covers the whole of the framebuffer.  With a
2518     // scissored clear, the render pass area could be smaller than the framebuffer size.  When the
2519     // scissor changes, if the scissor area is completely encompassed by the render pass area, it's
2520     // possible to continue using the same render pass.  However, if the current render pass area
2521     // is too small, we need to start a new one.  The latter can happen if a scissored clear starts
2522     // a render pass, the scissor is disabled and a draw call is issued to affect the whole
2523     // framebuffer.
2524     gl::Rectangle scissoredRenderArea = framebufferVk->getScissoredRenderArea(this);
2525     if (!mRenderPassCommands->empty())
2526     {
2527         if (!mRenderPassCommands->getRenderArea().encloses(scissoredRenderArea))
2528         {
2529             ANGLE_TRY(endRenderPass());
2530         }
2531     }
2532 
2533     return angle::Result::Continue;
2534 }
2535 
invalidateProgramBindingHelper(const gl::State & glState)2536 void ContextVk::invalidateProgramBindingHelper(const gl::State &glState)
2537 {
2538     mProgram         = nullptr;
2539     mProgramPipeline = nullptr;
2540     mExecutable      = nullptr;
2541 
2542     if (glState.getProgram())
2543     {
2544         mProgram    = vk::GetImpl(glState.getProgram());
2545         mExecutable = &mProgram->getExecutable();
2546     }
2547 
2548     if (glState.getProgramPipeline())
2549     {
2550         mProgramPipeline = vk::GetImpl(glState.getProgramPipeline());
2551         if (!mExecutable)
2552         {
2553             // A bound program always overrides a program pipeline
2554             mExecutable = &mProgramPipeline->getExecutable();
2555         }
2556     }
2557 }
2558 
invalidateProgramExecutableHelper(const gl::Context * context)2559 angle::Result ContextVk::invalidateProgramExecutableHelper(const gl::Context *context)
2560 {
2561     const gl::State &glState = context->getState();
2562 
2563     if (glState.getProgramExecutable()->isCompute())
2564     {
2565         invalidateCurrentComputePipeline();
2566     }
2567     else
2568     {
2569         // No additional work is needed here. We will update the pipeline desc
2570         // later.
2571         invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask());
2572         invalidateVertexAndIndexBuffers();
2573         bool useVertexBuffer = (glState.getProgramExecutable()->getMaxActiveAttribLocation() > 0);
2574         mNonIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer);
2575         mIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer);
2576         mCurrentGraphicsPipeline = nullptr;
2577         mGraphicsPipelineTransition.reset();
2578     }
2579 
2580     return angle::Result::Continue;
2581 }
2582 
syncState(const gl::Context * context,const gl::State::DirtyBits & dirtyBits,const gl::State::DirtyBits & bitMask)2583 angle::Result ContextVk::syncState(const gl::Context *context,
2584                                    const gl::State::DirtyBits &dirtyBits,
2585                                    const gl::State::DirtyBits &bitMask)
2586 {
2587     const gl::State &glState                       = context->getState();
2588     const gl::ProgramExecutable *programExecutable = glState.getProgramExecutable();
2589 
2590     if ((dirtyBits & mPipelineDirtyBitsMask).any() &&
2591         (programExecutable == nullptr || !programExecutable->isCompute()))
2592     {
2593         invalidateCurrentGraphicsPipeline();
2594     }
2595 
2596     for (auto iter = dirtyBits.begin(), endIter = dirtyBits.end(); iter != endIter; ++iter)
2597     {
2598         size_t dirtyBit = *iter;
2599         switch (dirtyBit)
2600         {
2601             case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
2602             case gl::State::DIRTY_BIT_SCISSOR:
2603                 ANGLE_TRY(updateScissor(glState));
2604                 break;
2605             case gl::State::DIRTY_BIT_VIEWPORT:
2606             {
2607                 FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer());
2608                 updateViewport(framebufferVk, glState.getViewport(), glState.getNearPlane(),
2609                                glState.getFarPlane(), isViewportFlipEnabledForDrawFBO());
2610                 // Update the scissor, which will be constrained to the viewport
2611                 ANGLE_TRY(updateScissor(glState));
2612                 break;
2613             }
2614             case gl::State::DIRTY_BIT_DEPTH_RANGE:
2615                 updateDepthRange(glState.getNearPlane(), glState.getFarPlane());
2616                 break;
2617             case gl::State::DIRTY_BIT_BLEND_ENABLED:
2618                 mGraphicsPipelineDesc->updateBlendEnabled(&mGraphicsPipelineTransition,
2619                                                           glState.isBlendEnabled());
2620                 break;
2621             case gl::State::DIRTY_BIT_BLEND_COLOR:
2622                 mGraphicsPipelineDesc->updateBlendColor(&mGraphicsPipelineTransition,
2623                                                         glState.getBlendColor());
2624                 break;
2625             case gl::State::DIRTY_BIT_BLEND_FUNCS:
2626                 mGraphicsPipelineDesc->updateBlendFuncs(&mGraphicsPipelineTransition,
2627                                                         glState.getBlendState());
2628                 break;
2629             case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
2630                 mGraphicsPipelineDesc->updateBlendEquations(&mGraphicsPipelineTransition,
2631                                                             glState.getBlendState());
2632                 break;
2633             case gl::State::DIRTY_BIT_COLOR_MASK:
2634                 updateColorMask(glState.getBlendState());
2635                 break;
2636             case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
2637                 mGraphicsPipelineDesc->updateAlphaToCoverageEnable(
2638                     &mGraphicsPipelineTransition, glState.isSampleAlphaToCoverageEnabled());
2639                 ASSERT(gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE >
2640                        gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED);
2641                 iter.setLaterBit(gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE);
2642                 break;
2643             case gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED:
2644                 updateSampleMask(glState);
2645                 break;
2646             case gl::State::DIRTY_BIT_SAMPLE_COVERAGE:
2647                 updateSampleMask(glState);
2648                 break;
2649             case gl::State::DIRTY_BIT_SAMPLE_MASK_ENABLED:
2650                 updateSampleMask(glState);
2651                 break;
2652             case gl::State::DIRTY_BIT_SAMPLE_MASK:
2653                 updateSampleMask(glState);
2654                 break;
2655             case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
2656                 mGraphicsPipelineDesc->updateDepthTestEnabled(&mGraphicsPipelineTransition,
2657                                                               glState.getDepthStencilState(),
2658                                                               glState.getDrawFramebuffer());
2659                 break;
2660             case gl::State::DIRTY_BIT_DEPTH_FUNC:
2661                 mGraphicsPipelineDesc->updateDepthFunc(&mGraphicsPipelineTransition,
2662                                                        glState.getDepthStencilState());
2663                 break;
2664             case gl::State::DIRTY_BIT_DEPTH_MASK:
2665                 mGraphicsPipelineDesc->updateDepthWriteEnabled(&mGraphicsPipelineTransition,
2666                                                                glState.getDepthStencilState(),
2667                                                                glState.getDrawFramebuffer());
2668                 break;
2669             case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
2670                 mGraphicsPipelineDesc->updateStencilTestEnabled(&mGraphicsPipelineTransition,
2671                                                                 glState.getDepthStencilState(),
2672                                                                 glState.getDrawFramebuffer());
2673                 break;
2674             case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
2675                 mGraphicsPipelineDesc->updateStencilFrontFuncs(&mGraphicsPipelineTransition,
2676                                                                glState.getStencilRef(),
2677                                                                glState.getDepthStencilState());
2678                 break;
2679             case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
2680                 mGraphicsPipelineDesc->updateStencilBackFuncs(&mGraphicsPipelineTransition,
2681                                                               glState.getStencilBackRef(),
2682                                                               glState.getDepthStencilState());
2683                 break;
2684             case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
2685                 mGraphicsPipelineDesc->updateStencilFrontOps(&mGraphicsPipelineTransition,
2686                                                              glState.getDepthStencilState());
2687                 break;
2688             case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
2689                 mGraphicsPipelineDesc->updateStencilBackOps(&mGraphicsPipelineTransition,
2690                                                             glState.getDepthStencilState());
2691                 break;
2692             case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
2693                 mGraphicsPipelineDesc->updateStencilFrontWriteMask(&mGraphicsPipelineTransition,
2694                                                                    glState.getDepthStencilState(),
2695                                                                    glState.getDrawFramebuffer());
2696                 break;
2697             case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
2698                 mGraphicsPipelineDesc->updateStencilBackWriteMask(&mGraphicsPipelineTransition,
2699                                                                   glState.getDepthStencilState(),
2700                                                                   glState.getDrawFramebuffer());
2701                 break;
2702             case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
2703             case gl::State::DIRTY_BIT_CULL_FACE:
2704                 mGraphicsPipelineDesc->updateCullMode(&mGraphicsPipelineTransition,
2705                                                       glState.getRasterizerState());
2706                 break;
2707             case gl::State::DIRTY_BIT_FRONT_FACE:
2708                 mGraphicsPipelineDesc->updateFrontFace(&mGraphicsPipelineTransition,
2709                                                        glState.getRasterizerState(),
2710                                                        isViewportFlipEnabledForDrawFBO());
2711                 break;
2712             case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
2713                 mGraphicsPipelineDesc->updatePolygonOffsetFillEnabled(
2714                     &mGraphicsPipelineTransition, glState.isPolygonOffsetFillEnabled());
2715                 break;
2716             case gl::State::DIRTY_BIT_POLYGON_OFFSET:
2717                 mGraphicsPipelineDesc->updatePolygonOffset(&mGraphicsPipelineTransition,
2718                                                            glState.getRasterizerState());
2719                 break;
2720             case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
2721                 mGraphicsPipelineDesc->updateRasterizerDiscardEnabled(
2722                     &mGraphicsPipelineTransition, glState.isRasterizerDiscardEnabled());
2723                 break;
2724             case gl::State::DIRTY_BIT_LINE_WIDTH:
2725                 mGraphicsPipelineDesc->updateLineWidth(&mGraphicsPipelineTransition,
2726                                                        glState.getLineWidth());
2727                 break;
2728             case gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED:
2729                 mGraphicsPipelineDesc->updatePrimitiveRestartEnabled(
2730                     &mGraphicsPipelineTransition, glState.isPrimitiveRestartEnabled());
2731                 break;
2732             case gl::State::DIRTY_BIT_CLEAR_COLOR:
2733                 mClearColorValue.color.float32[0] = glState.getColorClearValue().red;
2734                 mClearColorValue.color.float32[1] = glState.getColorClearValue().green;
2735                 mClearColorValue.color.float32[2] = glState.getColorClearValue().blue;
2736                 mClearColorValue.color.float32[3] = glState.getColorClearValue().alpha;
2737                 break;
2738             case gl::State::DIRTY_BIT_CLEAR_DEPTH:
2739                 mClearDepthStencilValue.depthStencil.depth = glState.getDepthClearValue();
2740                 break;
2741             case gl::State::DIRTY_BIT_CLEAR_STENCIL:
2742                 mClearDepthStencilValue.depthStencil.stencil =
2743                     static_cast<uint32_t>(glState.getStencilClearValue());
2744                 break;
2745             case gl::State::DIRTY_BIT_UNPACK_STATE:
2746                 // This is a no-op, it's only important to use the right unpack state when we do
2747                 // setImage or setSubImage in TextureVk, which is plumbed through the frontend
2748                 // call
2749                 break;
2750             case gl::State::DIRTY_BIT_UNPACK_BUFFER_BINDING:
2751                 break;
2752             case gl::State::DIRTY_BIT_PACK_STATE:
2753                 // This is a no-op, its only important to use the right pack state when we do
2754                 // call readPixels later on.
2755                 break;
2756             case gl::State::DIRTY_BIT_PACK_BUFFER_BINDING:
2757                 break;
2758             case gl::State::DIRTY_BIT_DITHER_ENABLED:
2759                 break;
2760             case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING:
2761                 updateFlipViewportReadFramebuffer(context->getState());
2762                 updateSurfaceRotationReadFramebuffer(glState);
2763                 break;
2764             case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
2765             {
2766                 // FramebufferVk::syncState signals that we should start a new command buffer.
2767                 // But changing the binding can skip FramebufferVk::syncState if the Framebuffer
2768                 // has no dirty bits. Thus we need to explicitly clear the current command
2769                 // buffer to ensure we start a new one. Note that we always start a new command
2770                 // buffer because we currently can only support one open RenderPass at a time.
2771                 onRenderPassFinished();
2772 
2773                 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
2774                 mDrawFramebuffer                 = vk::GetImpl(drawFramebuffer);
2775                 updateFlipViewportDrawFramebuffer(glState);
2776                 updateSurfaceRotationDrawFramebuffer(glState);
2777                 updateViewport(mDrawFramebuffer, glState.getViewport(), glState.getNearPlane(),
2778                                glState.getFarPlane(), isViewportFlipEnabledForDrawFBO());
2779                 updateColorMask(glState.getBlendState());
2780                 updateSampleMask(glState);
2781                 mGraphicsPipelineDesc->updateRasterizationSamples(&mGraphicsPipelineTransition,
2782                                                                   mDrawFramebuffer->getSamples());
2783                 mGraphicsPipelineDesc->updateFrontFace(&mGraphicsPipelineTransition,
2784                                                        glState.getRasterizerState(),
2785                                                        isViewportFlipEnabledForDrawFBO());
2786                 ANGLE_TRY(updateScissor(glState));
2787                 const gl::DepthStencilState depthStencilState = glState.getDepthStencilState();
2788                 mGraphicsPipelineDesc->updateDepthTestEnabled(&mGraphicsPipelineTransition,
2789                                                               depthStencilState, drawFramebuffer);
2790                 mGraphicsPipelineDesc->updateDepthWriteEnabled(&mGraphicsPipelineTransition,
2791                                                                depthStencilState, drawFramebuffer);
2792                 mGraphicsPipelineDesc->updateStencilTestEnabled(&mGraphicsPipelineTransition,
2793                                                                 depthStencilState, drawFramebuffer);
2794                 mGraphicsPipelineDesc->updateStencilFrontWriteMask(
2795                     &mGraphicsPipelineTransition, depthStencilState, drawFramebuffer);
2796                 mGraphicsPipelineDesc->updateStencilBackWriteMask(
2797                     &mGraphicsPipelineTransition, depthStencilState, drawFramebuffer);
2798                 mGraphicsPipelineDesc->updateRenderPassDesc(&mGraphicsPipelineTransition,
2799                                                             mDrawFramebuffer->getRenderPassDesc());
2800                 break;
2801             }
2802             case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
2803                 break;
2804             case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
2805             {
2806                 mVertexArray = vk::GetImpl(glState.getVertexArray());
2807                 invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask());
2808                 mVertexArray->updateActiveAttribInfo(this);
2809                 setIndexBufferDirty();
2810                 break;
2811             }
2812             case gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
2813                 break;
2814             case gl::State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING:
2815                 break;
2816             case gl::State::DIRTY_BIT_PROGRAM_BINDING:
2817                 invalidateProgramBindingHelper(glState);
2818                 break;
2819             case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
2820             {
2821                 ASSERT(programExecutable);
2822                 invalidateCurrentDefaultUniforms();
2823                 ASSERT(gl::State::DIRTY_BIT_TEXTURE_BINDINGS >
2824                        gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE);
2825                 iter.setLaterBit(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
2826                 invalidateCurrentShaderResources();
2827                 ANGLE_TRY(invalidateProgramExecutableHelper(context));
2828                 break;
2829             }
2830             case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
2831             {
2832                 ASSERT(gl::State::DIRTY_BIT_TEXTURE_BINDINGS >
2833                        gl::State::DIRTY_BIT_SAMPLER_BINDINGS);
2834                 iter.setLaterBit(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
2835                 break;
2836             }
2837             case gl::State::DIRTY_BIT_TEXTURE_BINDINGS:
2838                 ANGLE_TRY(invalidateCurrentTextures(context));
2839                 break;
2840             case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
2841                 // Nothing to do.
2842                 break;
2843             case gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
2844                 invalidateCurrentShaderResources();
2845                 break;
2846             case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
2847                 invalidateCurrentShaderResources();
2848                 break;
2849             case gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
2850                 invalidateCurrentShaderResources();
2851                 invalidateDriverUniforms();
2852                 break;
2853             case gl::State::DIRTY_BIT_IMAGE_BINDINGS:
2854                 invalidateCurrentShaderResources();
2855                 break;
2856             case gl::State::DIRTY_BIT_MULTISAMPLING:
2857                 // TODO(syoussefi): this should configure the pipeline to render as if
2858                 // single-sampled, and write the results to all samples of a pixel regardless of
2859                 // coverage. See EXT_multisample_compatibility.  http://anglebug.com/3204
2860                 break;
2861             case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE:
2862                 // TODO(syoussefi): this is part of EXT_multisample_compatibility.  The
2863                 // alphaToOne Vulkan feature should be enabled to support this extension.
2864                 // http://anglebug.com/3204
2865                 mGraphicsPipelineDesc->updateAlphaToOneEnable(&mGraphicsPipelineTransition,
2866                                                               glState.isSampleAlphaToOneEnabled());
2867                 break;
2868             case gl::State::DIRTY_BIT_COVERAGE_MODULATION:
2869                 break;
2870             case gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB:
2871                 break;
2872             case gl::State::DIRTY_BIT_CURRENT_VALUES:
2873             {
2874                 invalidateDefaultAttributes(glState.getAndResetDirtyCurrentValues());
2875                 break;
2876             }
2877             case gl::State::DIRTY_BIT_PROVOKING_VERTEX:
2878                 break;
2879             case gl::State::DIRTY_BIT_EXTENDED:
2880                 // Handling clip distance enabled flags, mipmap generation hint & shader derivative
2881                 // hint.
2882                 invalidateGraphicsDriverUniforms();
2883                 break;
2884             default:
2885                 UNREACHABLE();
2886                 break;
2887         }
2888     }
2889 
2890     return angle::Result::Continue;
2891 }
2892 
getGPUDisjoint()2893 GLint ContextVk::getGPUDisjoint()
2894 {
2895     // No extension seems to be available to query this information.
2896     return 0;
2897 }
2898 
getTimestamp()2899 GLint64 ContextVk::getTimestamp()
2900 {
2901     // This function should only be called if timestamp queries are available.
2902     ASSERT(mRenderer->getQueueFamilyProperties().timestampValidBits > 0);
2903 
2904     uint64_t timestamp = 0;
2905 
2906     (void)getTimestamp(&timestamp);
2907 
2908     return static_cast<GLint64>(timestamp);
2909 }
2910 
onMakeCurrent(const gl::Context * context)2911 angle::Result ContextVk::onMakeCurrent(const gl::Context *context)
2912 {
2913     mRenderer->reloadVolkIfNeeded();
2914 
2915     // Flip viewports if FeaturesVk::flipViewportY is enabled and the user did not request that
2916     // the surface is flipped.
2917     egl::Surface *drawSurface = context->getCurrentDrawSurface();
2918     mFlipYForCurrentSurface =
2919         drawSurface != nullptr && mRenderer->getFeatures().flipViewportY.enabled &&
2920         !IsMaskFlagSet(drawSurface->getOrientation(), EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE);
2921 
2922     if (drawSurface && drawSurface->getType() == EGL_WINDOW_BIT)
2923     {
2924         mCurrentWindowSurface = GetImplAs<WindowSurfaceVk>(drawSurface);
2925     }
2926     else
2927     {
2928         mCurrentWindowSurface = nullptr;
2929     }
2930 
2931     const gl::State &glState = context->getState();
2932     updateFlipViewportDrawFramebuffer(glState);
2933     updateFlipViewportReadFramebuffer(glState);
2934     updateSurfaceRotationDrawFramebuffer(glState);
2935     updateSurfaceRotationReadFramebuffer(glState);
2936     invalidateDriverUniforms();
2937 
2938     return angle::Result::Continue;
2939 }
2940 
onUnMakeCurrent(const gl::Context * context)2941 angle::Result ContextVk::onUnMakeCurrent(const gl::Context *context)
2942 {
2943     ANGLE_TRY(flushImpl(nullptr));
2944     mCurrentWindowSurface = nullptr;
2945     return angle::Result::Continue;
2946 }
2947 
updateFlipViewportDrawFramebuffer(const gl::State & glState)2948 void ContextVk::updateFlipViewportDrawFramebuffer(const gl::State &glState)
2949 {
2950     gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
2951     mFlipViewportForDrawFramebuffer =
2952         drawFramebuffer->isDefault() && mRenderer->getFeatures().flipViewportY.enabled;
2953 }
2954 
updateFlipViewportReadFramebuffer(const gl::State & glState)2955 void ContextVk::updateFlipViewportReadFramebuffer(const gl::State &glState)
2956 {
2957     gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2958     mFlipViewportForReadFramebuffer =
2959         readFramebuffer->isDefault() && mRenderer->getFeatures().flipViewportY.enabled;
2960 }
2961 
updateSurfaceRotationDrawFramebuffer(const gl::State & glState)2962 void ContextVk::updateSurfaceRotationDrawFramebuffer(const gl::State &glState)
2963 {
2964     gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
2965     mCurrentRotationDrawFramebuffer =
2966         DetermineSurfaceRotation(drawFramebuffer, mCurrentWindowSurface);
2967 }
2968 
updateSurfaceRotationReadFramebuffer(const gl::State & glState)2969 void ContextVk::updateSurfaceRotationReadFramebuffer(const gl::State &glState)
2970 {
2971     gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2972     mCurrentRotationReadFramebuffer =
2973         DetermineSurfaceRotation(readFramebuffer, mCurrentWindowSurface);
2974 }
2975 
getNativeCaps() const2976 gl::Caps ContextVk::getNativeCaps() const
2977 {
2978     return mRenderer->getNativeCaps();
2979 }
2980 
getNativeTextureCaps() const2981 const gl::TextureCapsMap &ContextVk::getNativeTextureCaps() const
2982 {
2983     return mRenderer->getNativeTextureCaps();
2984 }
2985 
getNativeExtensions() const2986 const gl::Extensions &ContextVk::getNativeExtensions() const
2987 {
2988     return mRenderer->getNativeExtensions();
2989 }
2990 
getNativeLimitations() const2991 const gl::Limitations &ContextVk::getNativeLimitations() const
2992 {
2993     return mRenderer->getNativeLimitations();
2994 }
2995 
createCompiler()2996 CompilerImpl *ContextVk::createCompiler()
2997 {
2998     return new CompilerVk();
2999 }
3000 
createShader(const gl::ShaderState & state)3001 ShaderImpl *ContextVk::createShader(const gl::ShaderState &state)
3002 {
3003     return new ShaderVk(state);
3004 }
3005 
createProgram(const gl::ProgramState & state)3006 ProgramImpl *ContextVk::createProgram(const gl::ProgramState &state)
3007 {
3008     return new ProgramVk(state);
3009 }
3010 
createFramebuffer(const gl::FramebufferState & state)3011 FramebufferImpl *ContextVk::createFramebuffer(const gl::FramebufferState &state)
3012 {
3013     return FramebufferVk::CreateUserFBO(mRenderer, state);
3014 }
3015 
createTexture(const gl::TextureState & state)3016 TextureImpl *ContextVk::createTexture(const gl::TextureState &state)
3017 {
3018     return new TextureVk(state, mRenderer);
3019 }
3020 
createRenderbuffer(const gl::RenderbufferState & state)3021 RenderbufferImpl *ContextVk::createRenderbuffer(const gl::RenderbufferState &state)
3022 {
3023     return new RenderbufferVk(state);
3024 }
3025 
createBuffer(const gl::BufferState & state)3026 BufferImpl *ContextVk::createBuffer(const gl::BufferState &state)
3027 {
3028     return new BufferVk(state);
3029 }
3030 
createVertexArray(const gl::VertexArrayState & state)3031 VertexArrayImpl *ContextVk::createVertexArray(const gl::VertexArrayState &state)
3032 {
3033     return new VertexArrayVk(this, state);
3034 }
3035 
createQuery(gl::QueryType type)3036 QueryImpl *ContextVk::createQuery(gl::QueryType type)
3037 {
3038     return new QueryVk(type);
3039 }
3040 
createFenceNV()3041 FenceNVImpl *ContextVk::createFenceNV()
3042 {
3043     return new FenceNVVk();
3044 }
3045 
createSync()3046 SyncImpl *ContextVk::createSync()
3047 {
3048     return new SyncVk();
3049 }
3050 
createTransformFeedback(const gl::TransformFeedbackState & state)3051 TransformFeedbackImpl *ContextVk::createTransformFeedback(const gl::TransformFeedbackState &state)
3052 {
3053     return new TransformFeedbackVk(state);
3054 }
3055 
createSampler(const gl::SamplerState & state)3056 SamplerImpl *ContextVk::createSampler(const gl::SamplerState &state)
3057 {
3058     return new SamplerVk(state);
3059 }
3060 
createProgramPipeline(const gl::ProgramPipelineState & state)3061 ProgramPipelineImpl *ContextVk::createProgramPipeline(const gl::ProgramPipelineState &state)
3062 {
3063     return new ProgramPipelineVk(state);
3064 }
3065 
createMemoryObject()3066 MemoryObjectImpl *ContextVk::createMemoryObject()
3067 {
3068     return new MemoryObjectVk();
3069 }
3070 
createSemaphore()3071 SemaphoreImpl *ContextVk::createSemaphore()
3072 {
3073     return new SemaphoreVk();
3074 }
3075 
createOverlay(const gl::OverlayState & state)3076 OverlayImpl *ContextVk::createOverlay(const gl::OverlayState &state)
3077 {
3078     return new OverlayVk(state);
3079 }
3080 
invalidateCurrentDefaultUniforms()3081 void ContextVk::invalidateCurrentDefaultUniforms()
3082 {
3083     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
3084     ASSERT(executable);
3085 
3086     if (executable->hasDefaultUniforms())
3087     {
3088         mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
3089         mComputeDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
3090     }
3091 }
3092 
invalidateCurrentTextures(const gl::Context * context)3093 angle::Result ContextVk::invalidateCurrentTextures(const gl::Context *context)
3094 {
3095     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
3096     ASSERT(executable);
3097 
3098     if (executable->hasTextures())
3099     {
3100         mGraphicsDirtyBits.set(DIRTY_BIT_TEXTURES);
3101         mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
3102         mComputeDirtyBits.set(DIRTY_BIT_TEXTURES);
3103         mComputeDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
3104 
3105         ANGLE_TRY(updateActiveTextures(context));
3106     }
3107 
3108     return angle::Result::Continue;
3109 }
3110 
invalidateCurrentShaderResources()3111 void ContextVk::invalidateCurrentShaderResources()
3112 {
3113     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
3114     ASSERT(executable);
3115 
3116     if (executable->hasUniformBuffers() || executable->hasStorageBuffers() ||
3117         executable->hasAtomicCounterBuffers() || executable->hasImages())
3118     {
3119         mGraphicsDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
3120         mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
3121         mComputeDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
3122         mComputeDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
3123     }
3124 }
3125 
invalidateGraphicsDriverUniforms()3126 void ContextVk::invalidateGraphicsDriverUniforms()
3127 {
3128     mGraphicsDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
3129     mGraphicsDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING);
3130 }
3131 
invalidateDriverUniforms()3132 void ContextVk::invalidateDriverUniforms()
3133 {
3134     mGraphicsDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
3135     mGraphicsDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING);
3136     mComputeDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
3137     mComputeDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING);
3138 }
3139 
onDrawFramebufferChange(FramebufferVk * framebufferVk)3140 void ContextVk::onDrawFramebufferChange(FramebufferVk *framebufferVk)
3141 {
3142     const vk::RenderPassDesc &renderPassDesc = framebufferVk->getRenderPassDesc();
3143 
3144     // Ensure that the RenderPass description is updated.
3145     invalidateCurrentGraphicsPipeline();
3146     if (mGraphicsPipelineDesc->getRasterizationSamples() !=
3147         static_cast<uint32_t>(framebufferVk->getSamples()))
3148     {
3149         mGraphicsPipelineDesc->updateRasterizationSamples(&mGraphicsPipelineTransition,
3150                                                           framebufferVk->getSamples());
3151     }
3152     mGraphicsPipelineDesc->updateRenderPassDesc(&mGraphicsPipelineTransition, renderPassDesc);
3153 }
3154 
invalidateCurrentTransformFeedbackBuffers()3155 void ContextVk::invalidateCurrentTransformFeedbackBuffers()
3156 {
3157     if (getFeatures().supportsTransformFeedbackExtension.enabled)
3158     {
3159         mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS);
3160     }
3161     if (getFeatures().emulateTransformFeedback.enabled)
3162     {
3163         mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
3164     }
3165 }
3166 
onTransformFeedbackStateChanged()3167 void ContextVk::onTransformFeedbackStateChanged()
3168 {
3169     if (getFeatures().supportsTransformFeedbackExtension.enabled)
3170     {
3171         mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_STATE);
3172     }
3173     else if (getFeatures().emulateTransformFeedback.enabled)
3174     {
3175         invalidateGraphicsDriverUniforms();
3176     }
3177 }
3178 
invalidateGraphicsDescriptorSet(uint32_t usedDescriptorSet)3179 void ContextVk::invalidateGraphicsDescriptorSet(uint32_t usedDescriptorSet)
3180 {
3181     // UtilsVk currently only uses set 0
3182     ASSERT(usedDescriptorSet == kDriverUniformsDescriptorSetIndex);
3183     if (mDriverUniforms[PipelineType::Graphics].descriptorSet != VK_NULL_HANDLE)
3184     {
3185         mGraphicsDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING);
3186     }
3187 }
3188 
invalidateComputeDescriptorSet(uint32_t usedDescriptorSet)3189 void ContextVk::invalidateComputeDescriptorSet(uint32_t usedDescriptorSet)
3190 {
3191     // UtilsVk currently only uses set 0
3192     ASSERT(usedDescriptorSet == kDriverUniformsDescriptorSetIndex);
3193     if (mDriverUniforms[PipelineType::Compute].descriptorSet != VK_NULL_HANDLE)
3194     {
3195         mComputeDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING);
3196     }
3197 }
3198 
dispatchCompute(const gl::Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)3199 angle::Result ContextVk::dispatchCompute(const gl::Context *context,
3200                                          GLuint numGroupsX,
3201                                          GLuint numGroupsY,
3202                                          GLuint numGroupsZ)
3203 {
3204     vk::CommandBuffer *commandBuffer;
3205     ANGLE_TRY(setupDispatch(context, &commandBuffer));
3206 
3207     commandBuffer->dispatch(numGroupsX, numGroupsY, numGroupsZ);
3208 
3209     return angle::Result::Continue;
3210 }
3211 
dispatchComputeIndirect(const gl::Context * context,GLintptr indirect)3212 angle::Result ContextVk::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
3213 {
3214     vk::CommandBuffer *commandBuffer;
3215     ANGLE_TRY(setupDispatch(context, &commandBuffer));
3216 
3217     gl::Buffer *glBuffer     = getState().getTargetBuffer(gl::BufferBinding::DispatchIndirect);
3218     vk::BufferHelper &buffer = vk::GetImpl(glBuffer)->getBuffer();
3219     mOutsideRenderPassCommands->bufferRead(&mResourceUseList, VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
3220                                            vk::PipelineStage::DrawIndirect, &buffer);
3221 
3222     commandBuffer->dispatchIndirect(buffer.getBuffer(), indirect);
3223 
3224     return angle::Result::Continue;
3225 }
3226 
memoryBarrier(const gl::Context * context,GLbitfield barriers)3227 angle::Result ContextVk::memoryBarrier(const gl::Context *context, GLbitfield barriers)
3228 {
3229     return memoryBarrierImpl(barriers, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
3230 }
3231 
memoryBarrierByRegion(const gl::Context * context,GLbitfield barriers)3232 angle::Result ContextVk::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers)
3233 {
3234     // Note: memoryBarrierByRegion is expected to affect only the fragment pipeline, but is
3235     // otherwise similar to memoryBarrier.
3236 
3237     return memoryBarrierImpl(barriers, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
3238 }
3239 
memoryBarrierImpl(GLbitfield barriers,VkPipelineStageFlags stageMask)3240 angle::Result ContextVk::memoryBarrierImpl(GLbitfield barriers, VkPipelineStageFlags stageMask)
3241 {
3242     // Note: many of the barriers specified here are already covered automatically.
3243     //
3244     // The barriers that are necessary all have SHADER_WRITE as src access and the dst access is
3245     // determined by the given bitfield.  Currently, all image-related barriers that require the
3246     // image to change usage are handled through image layout transitions.  Most buffer-related
3247     // barriers where the buffer usage changes are also handled automatically through dirty bits.
3248     // The only barriers that are necessary are thus barriers in situations where the resource can
3249     // be written to and read from without changing the bindings.
3250 
3251     VkAccessFlags srcAccess = 0;
3252     VkAccessFlags dstAccess = 0;
3253 
3254     // Both IMAGE_ACCESS and STORAGE barrier flags translate to the same Vulkan dst access mask.
3255     constexpr GLbitfield kShaderWriteBarriers =
3256         GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT;
3257 
3258     if ((barriers & kShaderWriteBarriers) != 0)
3259     {
3260         srcAccess |= VK_ACCESS_SHADER_WRITE_BIT;
3261         dstAccess |= VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
3262     }
3263 
3264     vk::CommandBuffer *commandBuffer;
3265     ANGLE_TRY(endRenderPassAndGetCommandBuffer(&commandBuffer));
3266 
3267     VkMemoryBarrier memoryBarrier = {};
3268     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
3269     memoryBarrier.srcAccessMask   = srcAccess;
3270     memoryBarrier.dstAccessMask   = dstAccess;
3271 
3272     commandBuffer->memoryBarrier(stageMask, stageMask, &memoryBarrier);
3273 
3274     return angle::Result::Continue;
3275 }
3276 
getQueryPool(gl::QueryType queryType)3277 vk::DynamicQueryPool *ContextVk::getQueryPool(gl::QueryType queryType)
3278 {
3279     ASSERT(queryType == gl::QueryType::AnySamples ||
3280            queryType == gl::QueryType::AnySamplesConservative ||
3281            queryType == gl::QueryType::Timestamp || queryType == gl::QueryType::TimeElapsed);
3282 
3283     // Assert that timestamp extension is available if needed.
3284     ASSERT(queryType != gl::QueryType::Timestamp && queryType != gl::QueryType::TimeElapsed ||
3285            mRenderer->getQueueFamilyProperties().timestampValidBits > 0);
3286     ASSERT(mQueryPools[queryType].isValid());
3287     return &mQueryPools[queryType];
3288 }
3289 
getClearColorValue() const3290 const VkClearValue &ContextVk::getClearColorValue() const
3291 {
3292     return mClearColorValue;
3293 }
3294 
getClearDepthStencilValue() const3295 const VkClearValue &ContextVk::getClearDepthStencilValue() const
3296 {
3297     return mClearDepthStencilValue;
3298 }
3299 
getClearColorMask() const3300 VkColorComponentFlags ContextVk::getClearColorMask() const
3301 {
3302     return mClearColorMask;
3303 }
3304 
writeAtomicCounterBufferDriverUniformOffsets(uint32_t * offsetsOut,size_t offsetsSize)3305 void ContextVk::writeAtomicCounterBufferDriverUniformOffsets(uint32_t *offsetsOut,
3306                                                              size_t offsetsSize)
3307 {
3308     const VkDeviceSize offsetAlignment =
3309         mRenderer->getPhysicalDeviceProperties().limits.minStorageBufferOffsetAlignment;
3310     size_t atomicCounterBufferCount = mState.getAtomicCounterBufferCount();
3311 
3312     ASSERT(atomicCounterBufferCount <= offsetsSize * 4);
3313 
3314     for (uint32_t bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
3315     {
3316         uint32_t offsetDiff = 0;
3317 
3318         const gl::OffsetBindingPointer<gl::Buffer> *atomicCounterBuffer =
3319             &mState.getIndexedAtomicCounterBuffer(bufferIndex);
3320         if (atomicCounterBuffer->get())
3321         {
3322             VkDeviceSize offset        = atomicCounterBuffer->getOffset();
3323             VkDeviceSize alignedOffset = (offset / offsetAlignment) * offsetAlignment;
3324 
3325             // GL requires the atomic counter buffer offset to be aligned with uint.
3326             ASSERT((offset - alignedOffset) % sizeof(uint32_t) == 0);
3327             offsetDiff = static_cast<uint32_t>((offset - alignedOffset) / sizeof(uint32_t));
3328 
3329             // We expect offsetDiff to fit in an 8-bit value.  The maximum difference is
3330             // minStorageBufferOffsetAlignment / 4, where minStorageBufferOffsetAlignment
3331             // currently has a maximum value of 256 on any device.
3332             ASSERT(offsetDiff < (1 << 8));
3333         }
3334 
3335         // The output array is already cleared prior to this call.
3336         ASSERT(bufferIndex % 4 != 0 || offsetsOut[bufferIndex / 4] == 0);
3337 
3338         offsetsOut[bufferIndex / 4] |= static_cast<uint8_t>(offsetDiff) << ((bufferIndex % 4) * 8);
3339     }
3340 }
3341 
handleDirtyGraphicsDriverUniforms(const gl::Context * context,vk::CommandBuffer * commandBuffer)3342 angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(const gl::Context *context,
3343                                                            vk::CommandBuffer *commandBuffer)
3344 {
3345     // Allocate a new region in the dynamic buffer.
3346     uint8_t *ptr;
3347     VkBuffer buffer;
3348     bool newBuffer;
3349     ANGLE_TRY(allocateDriverUniforms(sizeof(GraphicsDriverUniforms),
3350                                      &mDriverUniforms[PipelineType::Graphics], &buffer, &ptr,
3351                                      &newBuffer));
3352 
3353     gl::Rectangle glViewport = mState.getViewport();
3354     float halfRenderAreaWidth =
3355         static_cast<float>(mDrawFramebuffer->getState().getDimensions().width) * 0.5f;
3356     float halfRenderAreaHeight =
3357         static_cast<float>(mDrawFramebuffer->getState().getDimensions().height) * 0.5f;
3358     if (isRotatedAspectRatioForDrawFBO())
3359     {
3360         // The surface is rotated 90/270 degrees.  This changes the aspect ratio of the surface.
3361         std::swap(glViewport.x, glViewport.y);
3362         std::swap(glViewport.width, glViewport.height);
3363     }
3364     float flipX = 1.0f;
3365     float flipY = -1.0f;
3366     // Y-axis flipping only comes into play with the default framebuffer (i.e. a swapchain image).
3367     // For 0-degree rotation, an FBO or pbuffer could be the draw framebuffer, and so we must check
3368     // whether flipY should be positive or negative.  All other rotations, will be to the default
3369     // framebuffer, and so the value of isViewportFlipEnabledForDrawFBO() is assumed true; the
3370     // appropriate flipY value is chosen such that gl_FragCoord is positioned at the lower-left
3371     // corner of the window.
3372     switch (mCurrentRotationDrawFramebuffer)
3373     {
3374         case SurfaceRotation::Identity:
3375             flipX = 1.0f;
3376             flipY = isViewportFlipEnabledForDrawFBO() ? -1.0f : 1.0f;
3377             break;
3378         case SurfaceRotation::Rotated90Degrees:
3379             ASSERT(isViewportFlipEnabledForDrawFBO());
3380             flipX = 1.0f;
3381             flipY = 1.0f;
3382             std::swap(halfRenderAreaWidth, halfRenderAreaHeight);
3383             break;
3384         case SurfaceRotation::Rotated180Degrees:
3385             ASSERT(isViewportFlipEnabledForDrawFBO());
3386             flipX = -1.0f;
3387             flipY = 1.0f;
3388             break;
3389         case SurfaceRotation::Rotated270Degrees:
3390             ASSERT(isViewportFlipEnabledForDrawFBO());
3391             flipX = -1.0f;
3392             flipY = -1.0f;
3393             break;
3394         default:
3395             UNREACHABLE();
3396             break;
3397     }
3398 
3399     uint32_t xfbActiveUnpaused = mState.isTransformFeedbackActiveUnpaused();
3400 
3401     float depthRangeNear = mState.getNearPlane();
3402     float depthRangeFar  = mState.getFarPlane();
3403     float depthRangeDiff = depthRangeFar - depthRangeNear;
3404 
3405     // Copy and flush to the device.
3406     GraphicsDriverUniforms *driverUniforms = reinterpret_cast<GraphicsDriverUniforms *>(ptr);
3407     *driverUniforms                        = {
3408         {static_cast<float>(glViewport.x), static_cast<float>(glViewport.y),
3409          static_cast<float>(glViewport.width), static_cast<float>(glViewport.height)},
3410         {halfRenderAreaWidth, halfRenderAreaHeight},
3411         {flipX, flipY},
3412         {flipX, -flipY},
3413         mState.getEnabledClipDistances().bits(),
3414         xfbActiveUnpaused,
3415         mXfbVertexCountPerInstance,
3416         {},
3417         {},
3418         {},
3419         {depthRangeNear, depthRangeFar, depthRangeDiff, 0.0f},
3420         {},
3421         {}};
3422     memcpy(&driverUniforms->preRotation, &kPreRotationMatrices[mCurrentRotationDrawFramebuffer],
3423            sizeof(PreRotationMatrixValues));
3424     memcpy(&driverUniforms->fragRotation, &kFragRotationMatrices[mCurrentRotationDrawFramebuffer],
3425            sizeof(PreRotationMatrixValues));
3426 
3427     if (xfbActiveUnpaused)
3428     {
3429         TransformFeedbackVk *transformFeedbackVk =
3430             vk::GetImpl(mState.getCurrentTransformFeedback());
3431         transformFeedbackVk->getBufferOffsets(this, mXfbBaseVertex,
3432                                               driverUniforms->xfbBufferOffsets.data(),
3433                                               driverUniforms->xfbBufferOffsets.size());
3434     }
3435 
3436     writeAtomicCounterBufferDriverUniformOffsets(driverUniforms->acbBufferOffsets.data(),
3437                                                  driverUniforms->acbBufferOffsets.size());
3438 
3439     return updateDriverUniformsDescriptorSet(buffer, newBuffer, sizeof(GraphicsDriverUniforms),
3440                                              &mDriverUniforms[PipelineType::Graphics]);
3441 }
3442 
handleDirtyComputeDriverUniforms(const gl::Context * context,vk::CommandBuffer * commandBuffer)3443 angle::Result ContextVk::handleDirtyComputeDriverUniforms(const gl::Context *context,
3444                                                           vk::CommandBuffer *commandBuffer)
3445 {
3446     // Allocate a new region in the dynamic buffer.
3447     uint8_t *ptr;
3448     VkBuffer buffer;
3449     bool newBuffer;
3450     ANGLE_TRY(allocateDriverUniforms(sizeof(ComputeDriverUniforms),
3451                                      &mDriverUniforms[PipelineType::Compute], &buffer, &ptr,
3452                                      &newBuffer));
3453 
3454     // Copy and flush to the device.
3455     ComputeDriverUniforms *driverUniforms = reinterpret_cast<ComputeDriverUniforms *>(ptr);
3456     *driverUniforms                       = {};
3457 
3458     writeAtomicCounterBufferDriverUniformOffsets(driverUniforms->acbBufferOffsets.data(),
3459                                                  driverUniforms->acbBufferOffsets.size());
3460 
3461     return updateDriverUniformsDescriptorSet(buffer, newBuffer, sizeof(ComputeDriverUniforms),
3462                                              &mDriverUniforms[PipelineType::Compute]);
3463 }
3464 
handleDirtyDriverUniformsBindingImpl(vk::CommandBuffer * commandBuffer,VkPipelineBindPoint bindPoint,const DriverUniformsDescriptorSet & driverUniforms)3465 void ContextVk::handleDirtyDriverUniformsBindingImpl(
3466     vk::CommandBuffer *commandBuffer,
3467     VkPipelineBindPoint bindPoint,
3468     const DriverUniformsDescriptorSet &driverUniforms)
3469 {
3470     commandBuffer->bindDescriptorSets(
3471         mExecutable->getPipelineLayout(), bindPoint, kDriverUniformsDescriptorSetIndex, 1,
3472         &driverUniforms.descriptorSet, 1, &driverUniforms.dynamicOffset);
3473 }
3474 
handleDirtyGraphicsDriverUniformsBinding(const gl::Context * context,vk::CommandBuffer * commandBuffer)3475 angle::Result ContextVk::handleDirtyGraphicsDriverUniformsBinding(const gl::Context *context,
3476                                                                   vk::CommandBuffer *commandBuffer)
3477 {
3478     // Bind the driver descriptor set.
3479     handleDirtyDriverUniformsBindingImpl(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
3480                                          mDriverUniforms[PipelineType::Graphics]);
3481     return angle::Result::Continue;
3482 }
3483 
handleDirtyComputeDriverUniformsBinding(const gl::Context * context,vk::CommandBuffer * commandBuffer)3484 angle::Result ContextVk::handleDirtyComputeDriverUniformsBinding(const gl::Context *context,
3485                                                                  vk::CommandBuffer *commandBuffer)
3486 {
3487     // Bind the driver descriptor set.
3488     handleDirtyDriverUniformsBindingImpl(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE,
3489                                          mDriverUniforms[PipelineType::Compute]);
3490     return angle::Result::Continue;
3491 }
3492 
allocateDriverUniforms(size_t driverUniformsSize,DriverUniformsDescriptorSet * driverUniforms,VkBuffer * bufferOut,uint8_t ** ptrOut,bool * newBufferOut)3493 angle::Result ContextVk::allocateDriverUniforms(size_t driverUniformsSize,
3494                                                 DriverUniformsDescriptorSet *driverUniforms,
3495                                                 VkBuffer *bufferOut,
3496                                                 uint8_t **ptrOut,
3497                                                 bool *newBufferOut)
3498 {
3499     // Release any previously retained buffers.
3500     driverUniforms->dynamicBuffer.releaseInFlightBuffers(this);
3501 
3502     // Allocate a new region in the dynamic buffer.
3503     VkDeviceSize offset;
3504     ANGLE_TRY(driverUniforms->dynamicBuffer.allocate(this, driverUniformsSize, ptrOut, bufferOut,
3505                                                      &offset, newBufferOut));
3506 
3507     driverUniforms->dynamicOffset = static_cast<uint32_t>(offset);
3508 
3509     return angle::Result::Continue;
3510 }
3511 
updateDriverUniformsDescriptorSet(VkBuffer buffer,bool newBuffer,size_t driverUniformsSize,DriverUniformsDescriptorSet * driverUniforms)3512 angle::Result ContextVk::updateDriverUniformsDescriptorSet(
3513     VkBuffer buffer,
3514     bool newBuffer,
3515     size_t driverUniformsSize,
3516     DriverUniformsDescriptorSet *driverUniforms)
3517 {
3518     ANGLE_TRY(driverUniforms->dynamicBuffer.flush(this));
3519 
3520     if (!newBuffer)
3521     {
3522         return angle::Result::Continue;
3523     }
3524 
3525     // Allocate a new descriptor set.
3526     ANGLE_TRY(mDriverUniformsDescriptorPool.allocateSets(
3527         this, driverUniforms->descriptorSetLayout.get().ptr(), 1,
3528         &driverUniforms->descriptorPoolBinding, &driverUniforms->descriptorSet));
3529 
3530     // Update the driver uniform descriptor set.
3531     VkDescriptorBufferInfo bufferInfo = {};
3532     bufferInfo.buffer                 = buffer;
3533     bufferInfo.offset                 = 0;
3534     bufferInfo.range                  = driverUniformsSize;
3535 
3536     VkWriteDescriptorSet writeInfo = {};
3537     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3538     writeInfo.dstSet               = driverUniforms->descriptorSet;
3539     writeInfo.dstBinding           = 0;
3540     writeInfo.dstArrayElement      = 0;
3541     writeInfo.descriptorCount      = 1;
3542     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
3543     writeInfo.pImageInfo           = nullptr;
3544     writeInfo.pTexelBufferView     = nullptr;
3545     writeInfo.pBufferInfo          = &bufferInfo;
3546 
3547     vkUpdateDescriptorSets(getDevice(), 1, &writeInfo, 0, nullptr);
3548 
3549     return angle::Result::Continue;
3550 }
3551 
handleError(VkResult errorCode,const char * file,const char * function,unsigned int line)3552 void ContextVk::handleError(VkResult errorCode,
3553                             const char *file,
3554                             const char *function,
3555                             unsigned int line)
3556 {
3557     ASSERT(errorCode != VK_SUCCESS);
3558 
3559     GLenum glErrorCode = DefaultGLErrorCode(errorCode);
3560 
3561     std::stringstream errorStream;
3562     errorStream << "Internal Vulkan error (" << errorCode << "): " << VulkanResultString(errorCode)
3563                 << ".";
3564 
3565     if (errorCode == VK_ERROR_DEVICE_LOST)
3566     {
3567         WARN() << errorStream.str();
3568         handleDeviceLost();
3569     }
3570 
3571     mErrors->handleError(glErrorCode, errorStream.str().c_str(), file, function, line);
3572 }
3573 
updateActiveTextures(const gl::Context * context)3574 angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
3575 {
3576     const gl::State &glState                = mState;
3577     const gl::ProgramExecutable *executable = glState.getProgramExecutable();
3578     ASSERT(executable);
3579 
3580     uint32_t prevMaxIndex = mActiveTexturesDesc.getMaxIndex();
3581     memset(mActiveTextures.data(), 0, sizeof(mActiveTextures[0]) * prevMaxIndex);
3582     mActiveTexturesDesc.reset();
3583 
3584     const gl::ActiveTexturesCache &textures        = glState.getActiveTexturesCache();
3585     const gl::ActiveTextureMask &activeTextures    = executable->getActiveSamplersMask();
3586     const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
3587 
3588     for (size_t textureUnit : activeTextures)
3589     {
3590         gl::Texture *texture        = textures[textureUnit];
3591         gl::Sampler *sampler        = mState.getSampler(static_cast<uint32_t>(textureUnit));
3592         gl::TextureType textureType = textureTypes[textureUnit];
3593 
3594         // Null textures represent incomplete textures.
3595         if (texture == nullptr)
3596         {
3597             ANGLE_TRY(getIncompleteTexture(context, textureType, &texture));
3598         }
3599 
3600         TextureVk *textureVk = vk::GetImpl(texture);
3601 
3602         SamplerVk *samplerVk;
3603         Serial samplerSerial;
3604         if (sampler == nullptr)
3605         {
3606             samplerVk     = nullptr;
3607             samplerSerial = rx::kZeroSerial;
3608         }
3609         else
3610         {
3611             samplerVk     = vk::GetImpl(sampler);
3612             samplerSerial = samplerVk->getSerial();
3613         }
3614 
3615         mActiveTextures[textureUnit].texture = textureVk;
3616         mActiveTextures[textureUnit].sampler = samplerVk;
3617         // Cache serials from sampler and texture, but re-use texture if no sampler bound
3618         ASSERT(textureVk != nullptr);
3619         mActiveTexturesDesc.update(textureUnit, textureVk->getSerial(), samplerSerial);
3620     }
3621 
3622     return angle::Result::Continue;
3623 }
3624 
updateActiveImages(const gl::Context * context,vk::CommandBufferHelper * commandBufferHelper)3625 angle::Result ContextVk::updateActiveImages(const gl::Context *context,
3626                                             vk::CommandBufferHelper *commandBufferHelper)
3627 {
3628     const gl::State &glState                = mState;
3629     const gl::ProgramExecutable *executable = glState.getProgramExecutable();
3630     ASSERT(executable);
3631 
3632     mActiveImages.fill(nullptr);
3633 
3634     const gl::ActiveTextureMask &activeImages = executable->getActiveImagesMask();
3635     const gl::ActiveTextureArray<gl::ShaderBitSet> &activeImageShaderBits =
3636         executable->getActiveImageShaderBits();
3637 
3638     // Note: currently, the image layout is transitioned entirely even if only one level or layer is
3639     // used.  This is an issue if one subresource of the image is used as framebuffer attachment and
3640     // the other as image.  This is a similar issue to http://anglebug.com/2914.  Another issue
3641     // however is if multiple subresources of the same image are used at the same time.
3642     // Inefficiencies aside, setting write dependency on the same image multiple times is not
3643     // supported.  The following makes sure write dependencies are set only once per image.
3644     std::set<vk::ImageHelper *> alreadyProcessed;
3645 
3646     for (size_t imageUnitIndex : activeImages)
3647     {
3648         const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
3649         const gl::Texture *texture     = imageUnit.texture.get();
3650         if (texture == nullptr)
3651         {
3652             continue;
3653         }
3654 
3655         TextureVk *textureVk   = vk::GetImpl(texture);
3656         vk::ImageHelper *image = &textureVk->getImage();
3657 
3658         mActiveImages[imageUnitIndex] = textureVk;
3659 
3660         if (alreadyProcessed.find(image) != alreadyProcessed.end())
3661         {
3662             continue;
3663         }
3664         alreadyProcessed.insert(image);
3665 
3666         // The image should be flushed and ready to use at this point. There may still be
3667         // lingering staged updates in its staging buffer for unused texture mip levels or
3668         // layers. Therefore we can't verify it has no staged updates right here.
3669         vk::ImageLayout imageLayout;
3670         gl::ShaderBitSet shaderBits = activeImageShaderBits[imageUnitIndex];
3671         if (shaderBits.any())
3672         {
3673             gl::ShaderType shader = static_cast<gl::ShaderType>(gl::ScanForward(shaderBits.bits()));
3674             shaderBits.reset(shader);
3675             // This is accessed by multiple shaders
3676             if (shaderBits.any())
3677             {
3678                 imageLayout = vk::ImageLayout::AllGraphicsShadersReadWrite;
3679             }
3680             else
3681             {
3682                 imageLayout = kShaderWriteImageLayouts[shader];
3683             }
3684         }
3685         else
3686         {
3687             imageLayout = vk::ImageLayout::AllGraphicsShadersReadWrite;
3688         }
3689         VkImageAspectFlags aspectFlags = image->getAspectFlags();
3690 
3691         commandBufferHelper->imageWrite(&mResourceUseList, aspectFlags, imageLayout, image);
3692     }
3693 
3694     return angle::Result::Continue;
3695 }
3696 
hasRecordedCommands()3697 bool ContextVk::hasRecordedCommands()
3698 {
3699     ASSERT(mOutsideRenderPassCommands && mRenderPassCommands);
3700     return !mOutsideRenderPassCommands->empty() || !mRenderPassCommands->empty() ||
3701            mHasPrimaryCommands;
3702 }
3703 
flushImpl(const vk::Semaphore * signalSemaphore)3704 angle::Result ContextVk::flushImpl(const vk::Semaphore *signalSemaphore)
3705 {
3706     bool hasPendingSemaphore = signalSemaphore || !mWaitSemaphores.empty();
3707     if (!hasRecordedCommands() && !hasPendingSemaphore && !mGpuEventsEnabled)
3708     {
3709         return angle::Result::Continue;
3710     }
3711 
3712     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::flush");
3713 
3714     ANGLE_TRY(flushOutsideRenderPassCommands());
3715     ANGLE_TRY(endRenderPass());
3716 
3717     if (mIsAnyHostVisibleBufferWritten)
3718     {
3719         // Make sure all writes to host-visible buffers are flushed.  We have no way of knowing
3720         // whether any buffer will be mapped for readback in the future, and we can't afford to
3721         // flush and wait on a one-pipeline-barrier command buffer on every map().
3722         VkMemoryBarrier memoryBarrier = {};
3723         memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
3724         memoryBarrier.srcAccessMask   = VK_ACCESS_MEMORY_WRITE_BIT;
3725         memoryBarrier.dstAccessMask   = VK_ACCESS_HOST_READ_BIT;
3726 
3727         mOutsideRenderPassCommands->getCommandBuffer().memoryBarrier(
3728             VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_HOST_BIT, &memoryBarrier);
3729         mIsAnyHostVisibleBufferWritten = false;
3730     }
3731 
3732     if (mGpuEventsEnabled)
3733     {
3734         EventName eventName = GetTraceEventName("Primary", mPrimaryBufferCounter);
3735         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
3736                                 TRACE_EVENT_PHASE_END, eventName));
3737     }
3738     ANGLE_TRY(flushOutsideRenderPassCommands());
3739 
3740     if (mRenderer->getFeatures().enableCommandProcessingThread.enabled)
3741     {
3742         // Worker thread must complete adding any commands that were just flushed above to the
3743         //  primary command buffer before we can End the primary command buffer below.
3744         mRenderer->waitForWorkerThreadIdle();
3745     }
3746 
3747     ANGLE_VK_TRY(this, mPrimaryCommands.end());
3748 
3749     Serial serial = getCurrentQueueSerial();
3750     mResourceUseList.releaseResourceUsesAndUpdateSerials(serial);
3751 
3752     waitForSwapchainImageIfNecessary();
3753 
3754     VkSubmitInfo submitInfo = {};
3755     InitializeSubmitInfo(&submitInfo, mPrimaryCommands, mWaitSemaphores, mWaitSemaphoreStageMasks,
3756                          signalSemaphore);
3757 
3758     ANGLE_TRY(submitFrame(submitInfo, std::move(mPrimaryCommands)));
3759 
3760     ANGLE_TRY(startPrimaryCommandBuffer());
3761 
3762     mRenderPassCounter = 0;
3763     mWaitSemaphores.clear();
3764     mWaitSemaphoreStageMasks.clear();
3765 
3766     mPrimaryBufferCounter++;
3767 
3768     if (mGpuEventsEnabled)
3769     {
3770         EventName eventName = GetTraceEventName("Primary", mPrimaryBufferCounter);
3771         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
3772                                 TRACE_EVENT_PHASE_BEGIN, eventName));
3773     }
3774 
3775     return angle::Result::Continue;
3776 }
3777 
finishImpl()3778 angle::Result ContextVk::finishImpl()
3779 {
3780     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::finish");
3781 
3782     ANGLE_TRY(flushImpl(nullptr));
3783 
3784     ANGLE_TRY(finishToSerial(getLastSubmittedQueueSerial()));
3785     ASSERT(!mCommandQueue.hasInFlightCommands());
3786 
3787     clearAllGarbage();
3788 
3789     if (mGpuEventsEnabled)
3790     {
3791         // This loop should in practice execute once since the queue is already idle.
3792         while (mInFlightGpuEventQueries.size() > 0)
3793         {
3794             ANGLE_TRY(checkCompletedGpuEvents());
3795         }
3796         // Recalculate the CPU/GPU time difference to account for clock drifting.  Avoid
3797         // unnecessary synchronization if there is no event to be adjusted (happens when
3798         // finish() gets called multiple times towards the end of the application).
3799         if (mGpuEvents.size() > 0)
3800         {
3801             ANGLE_TRY(synchronizeCpuGpuTime());
3802         }
3803     }
3804 
3805     return angle::Result::Continue;
3806 }
3807 
addWaitSemaphore(VkSemaphore semaphore,VkPipelineStageFlags stageMask)3808 void ContextVk::addWaitSemaphore(VkSemaphore semaphore, VkPipelineStageFlags stageMask)
3809 {
3810     mWaitSemaphores.push_back(semaphore);
3811     mWaitSemaphoreStageMasks.push_back(stageMask);
3812 }
3813 
getCommandPool() const3814 const vk::CommandPool &ContextVk::getCommandPool() const
3815 {
3816     return mCommandPool;
3817 }
3818 
isSerialInUse(Serial serial) const3819 bool ContextVk::isSerialInUse(Serial serial) const
3820 {
3821     return serial > getLastCompletedQueueSerial();
3822 }
3823 
checkCompletedCommands()3824 angle::Result ContextVk::checkCompletedCommands()
3825 {
3826     return mCommandQueue.checkCompletedCommands(this);
3827 }
3828 
finishToSerial(Serial serial)3829 angle::Result ContextVk::finishToSerial(Serial serial)
3830 {
3831     return mCommandQueue.finishToSerial(this, serial, mRenderer->getMaxFenceWaitTimeNs());
3832 }
3833 
getCompatibleRenderPass(const vk::RenderPassDesc & desc,vk::RenderPass ** renderPassOut)3834 angle::Result ContextVk::getCompatibleRenderPass(const vk::RenderPassDesc &desc,
3835                                                  vk::RenderPass **renderPassOut)
3836 {
3837     return mRenderPassCache.getCompatibleRenderPass(this, getCurrentQueueSerial(), desc,
3838                                                     renderPassOut);
3839 }
3840 
getRenderPassWithOps(const vk::RenderPassDesc & desc,const vk::AttachmentOpsArray & ops,vk::RenderPass ** renderPassOut)3841 angle::Result ContextVk::getRenderPassWithOps(const vk::RenderPassDesc &desc,
3842                                               const vk::AttachmentOpsArray &ops,
3843                                               vk::RenderPass **renderPassOut)
3844 {
3845     return mRenderPassCache.getRenderPassWithOps(this, getCurrentQueueSerial(), desc, ops,
3846                                                  renderPassOut);
3847 }
3848 
ensureSubmitFenceInitialized()3849 angle::Result ContextVk::ensureSubmitFenceInitialized()
3850 {
3851     if (mSubmitFence.isReferenced())
3852     {
3853         return angle::Result::Continue;
3854     }
3855 
3856     return mRenderer->newSharedFence(this, &mSubmitFence);
3857 }
3858 
getNextSubmitFence(vk::Shared<vk::Fence> * sharedFenceOut)3859 angle::Result ContextVk::getNextSubmitFence(vk::Shared<vk::Fence> *sharedFenceOut)
3860 {
3861     ANGLE_TRY(ensureSubmitFenceInitialized());
3862 
3863     ASSERT(!sharedFenceOut->isReferenced());
3864     sharedFenceOut->copy(getDevice(), mSubmitFence);
3865     return angle::Result::Continue;
3866 }
3867 
getLastSubmittedFence() const3868 vk::Shared<vk::Fence> ContextVk::getLastSubmittedFence() const
3869 {
3870     return mCommandQueue.getLastSubmittedFence(this);
3871 }
3872 
getTimestamp(uint64_t * timestampOut)3873 angle::Result ContextVk::getTimestamp(uint64_t *timestampOut)
3874 {
3875     // The intent of this function is to query the timestamp without stalling the GPU.
3876     // Currently, that seems impossible, so instead, we are going to make a small submission
3877     // with just a timestamp query.  First, the disjoint timer query extension says:
3878     //
3879     // > This will return the GL time after all previous commands have reached the GL server but
3880     // have not yet necessarily executed.
3881     //
3882     // The previous commands may be deferred at the moment and not yet flushed. The wording allows
3883     // us to make a submission to get the timestamp without flushing.
3884     //
3885     // Second:
3886     //
3887     // > By using a combination of this synchronous get command and the asynchronous timestamp
3888     // query object target, applications can measure the latency between when commands reach the
3889     // GL server and when they are realized in the framebuffer.
3890     //
3891     // This fits with the above strategy as well, although inevitably we are possibly
3892     // introducing a GPU bubble.  This function directly generates a command buffer and submits
3893     // it instead of using the other member functions.  This is to avoid changing any state,
3894     // such as the queue serial.
3895 
3896     // Create a query used to receive the GPU timestamp
3897     VkDevice device = getDevice();
3898     vk::DeviceScoped<vk::DynamicQueryPool> timestampQueryPool(device);
3899     vk::QueryHelper timestampQuery;
3900     ANGLE_TRY(timestampQueryPool.get().init(this, VK_QUERY_TYPE_TIMESTAMP, 1));
3901     ANGLE_TRY(timestampQueryPool.get().allocateQuery(this, &timestampQuery));
3902 
3903     // Record the command buffer
3904     vk::DeviceScoped<vk::PrimaryCommandBuffer> commandBatch(device);
3905     vk::PrimaryCommandBuffer &commandBuffer = commandBatch.get();
3906 
3907     ANGLE_TRY(mRenderer->getCommandBufferOneOff(this, &commandBuffer));
3908 
3909     timestampQuery.writeTimestamp(this, &commandBuffer);
3910     ANGLE_VK_TRY(this, commandBuffer.end());
3911 
3912     // Create fence for the submission
3913     VkFenceCreateInfo fenceInfo = {};
3914     fenceInfo.sType             = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
3915     fenceInfo.flags             = 0;
3916 
3917     vk::DeviceScoped<vk::Fence> fence(device);
3918     ANGLE_VK_TRY(this, fence.get().init(device, fenceInfo));
3919 
3920     // Submit the command buffer
3921     VkSubmitInfo submitInfo         = {};
3922     submitInfo.sType                = VK_STRUCTURE_TYPE_SUBMIT_INFO;
3923     submitInfo.waitSemaphoreCount   = 0;
3924     submitInfo.pWaitSemaphores      = nullptr;
3925     submitInfo.pWaitDstStageMask    = nullptr;
3926     submitInfo.commandBufferCount   = 1;
3927     submitInfo.pCommandBuffers      = commandBuffer.ptr();
3928     submitInfo.signalSemaphoreCount = 0;
3929     submitInfo.pSignalSemaphores    = nullptr;
3930 
3931     Serial throwAwaySerial;
3932     ANGLE_TRY(mRenderer->queueSubmitOneOff(this, std::move(commandBuffer), mContextPriority,
3933                                            &fence.get(), &throwAwaySerial));
3934 
3935     // Wait for the submission to finish.  Given no semaphores, there is hope that it would execute
3936     // in parallel with what's already running on the GPU.
3937     ANGLE_VK_TRY(this, fence.get().wait(device, mRenderer->getMaxFenceWaitTimeNs()));
3938 
3939     // Get the query results
3940     ANGLE_TRY(timestampQuery.getUint64Result(this, timestampOut));
3941     timestampQueryPool.get().freeQuery(this, &timestampQuery);
3942 
3943     // Convert results to nanoseconds.
3944     *timestampOut = static_cast<uint64_t>(
3945         *timestampOut *
3946         static_cast<double>(getRenderer()->getPhysicalDeviceProperties().limits.timestampPeriod));
3947 
3948     return angle::Result::Continue;
3949 }
3950 
invalidateDefaultAttribute(size_t attribIndex)3951 void ContextVk::invalidateDefaultAttribute(size_t attribIndex)
3952 {
3953     mDirtyDefaultAttribsMask.set(attribIndex);
3954     mGraphicsDirtyBits.set(DIRTY_BIT_DEFAULT_ATTRIBS);
3955 }
3956 
invalidateDefaultAttributes(const gl::AttributesMask & dirtyMask)3957 void ContextVk::invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask)
3958 {
3959     if (dirtyMask.any())
3960     {
3961         mDirtyDefaultAttribsMask |= dirtyMask;
3962         mGraphicsDirtyBits.set(DIRTY_BIT_DEFAULT_ATTRIBS);
3963     }
3964 }
3965 
updateDefaultAttribute(size_t attribIndex)3966 angle::Result ContextVk::updateDefaultAttribute(size_t attribIndex)
3967 {
3968     vk::DynamicBuffer &defaultBuffer = mDefaultAttribBuffers[attribIndex];
3969 
3970     defaultBuffer.releaseInFlightBuffers(this);
3971 
3972     uint8_t *ptr;
3973     VkBuffer bufferHandle = VK_NULL_HANDLE;
3974     VkDeviceSize offset   = 0;
3975     ANGLE_TRY(
3976         defaultBuffer.allocate(this, kDefaultValueSize, &ptr, &bufferHandle, &offset, nullptr));
3977 
3978     const gl::State &glState = mState;
3979     const gl::VertexAttribCurrentValueData &defaultValue =
3980         glState.getVertexAttribCurrentValues()[attribIndex];
3981     memcpy(ptr, &defaultValue.Values, kDefaultValueSize);
3982     ASSERT(!defaultBuffer.isCoherent());
3983     ANGLE_TRY(defaultBuffer.flush(this));
3984 
3985     mVertexArray->updateDefaultAttrib(this, attribIndex, bufferHandle,
3986                                       defaultBuffer.getCurrentBuffer(),
3987                                       static_cast<uint32_t>(offset));
3988     return angle::Result::Continue;
3989 }
3990 
waitForSwapchainImageIfNecessary()3991 void ContextVk::waitForSwapchainImageIfNecessary()
3992 {
3993     if (mCurrentWindowSurface)
3994     {
3995         vk::Semaphore waitSemaphore = mCurrentWindowSurface->getAcquireImageSemaphore();
3996         if (waitSemaphore.valid())
3997         {
3998             addWaitSemaphore(waitSemaphore.getHandle(),
3999                              VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
4000             addGarbage(&waitSemaphore);
4001         }
4002     }
4003 }
4004 
getDriverUniformsDescriptorSetDesc(VkShaderStageFlags shaderStages) const4005 vk::DescriptorSetLayoutDesc ContextVk::getDriverUniformsDescriptorSetDesc(
4006     VkShaderStageFlags shaderStages) const
4007 {
4008     vk::DescriptorSetLayoutDesc desc;
4009     desc.update(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, shaderStages);
4010     return desc;
4011 }
4012 
shouldEmulateSeamfulCubeMapSampling() const4013 bool ContextVk::shouldEmulateSeamfulCubeMapSampling() const
4014 {
4015     // Only allow seamful cube map sampling in non-webgl ES2.
4016     if (mState.getClientMajorVersion() != 2 || mState.isWebGL())
4017     {
4018         return false;
4019     }
4020 
4021     if (mRenderer->getFeatures().disallowSeamfulCubeMapEmulation.enabled)
4022     {
4023         return false;
4024     }
4025 
4026     return true;
4027 }
4028 
shouldUseOldRewriteStructSamplers() const4029 bool ContextVk::shouldUseOldRewriteStructSamplers() const
4030 {
4031     return mRenderer->getFeatures().forceOldRewriteStructSamplers.enabled;
4032 }
4033 
onBufferRead(VkAccessFlags readAccessType,vk::PipelineStage readStage,vk::BufferHelper * buffer)4034 angle::Result ContextVk::onBufferRead(VkAccessFlags readAccessType,
4035                                       vk::PipelineStage readStage,
4036                                       vk::BufferHelper *buffer)
4037 {
4038     ASSERT(!buffer->isReleasedToExternal());
4039 
4040     ANGLE_TRY(endRenderPass());
4041 
4042     if (!buffer->canAccumulateRead(this, readAccessType))
4043     {
4044         ANGLE_TRY(flushOutsideRenderPassCommands());
4045     }
4046 
4047     mOutsideRenderPassCommands->bufferRead(&mResourceUseList, readAccessType, readStage, buffer);
4048 
4049     return angle::Result::Continue;
4050 }
4051 
onBufferWrite(VkAccessFlags writeAccessType,vk::PipelineStage writeStage,vk::BufferHelper * buffer)4052 angle::Result ContextVk::onBufferWrite(VkAccessFlags writeAccessType,
4053                                        vk::PipelineStage writeStage,
4054                                        vk::BufferHelper *buffer)
4055 {
4056     ASSERT(!buffer->isReleasedToExternal());
4057 
4058     ANGLE_TRY(endRenderPass());
4059 
4060     if (!buffer->canAccumulateWrite(this, writeAccessType))
4061     {
4062         ANGLE_TRY(flushOutsideRenderPassCommands());
4063     }
4064 
4065     mOutsideRenderPassCommands->bufferWrite(&mResourceUseList, writeAccessType, writeStage, buffer);
4066 
4067     return angle::Result::Continue;
4068 }
4069 
onImageRead(VkImageAspectFlags aspectFlags,vk::ImageLayout imageLayout,vk::ImageHelper * image)4070 angle::Result ContextVk::onImageRead(VkImageAspectFlags aspectFlags,
4071                                      vk::ImageLayout imageLayout,
4072                                      vk::ImageHelper *image)
4073 {
4074     ASSERT(!image->isReleasedToExternal());
4075 
4076     ANGLE_TRY(endRenderPass());
4077 
4078     if (image->isLayoutChangeNecessary(imageLayout))
4079     {
4080         vk::CommandBuffer *commandBuffer;
4081         ANGLE_TRY(endRenderPassAndGetCommandBuffer(&commandBuffer));
4082         image->changeLayout(aspectFlags, imageLayout, commandBuffer);
4083     }
4084     image->retain(&mResourceUseList);
4085     return angle::Result::Continue;
4086 }
4087 
onImageWrite(VkImageAspectFlags aspectFlags,vk::ImageLayout imageLayout,vk::ImageHelper * image)4088 angle::Result ContextVk::onImageWrite(VkImageAspectFlags aspectFlags,
4089                                       vk::ImageLayout imageLayout,
4090                                       vk::ImageHelper *image)
4091 {
4092     ASSERT(!image->isReleasedToExternal());
4093 
4094     ANGLE_TRY(endRenderPass());
4095 
4096     // Barriers are always required for image writes.
4097     ASSERT(image->isLayoutChangeNecessary(imageLayout));
4098 
4099     vk::CommandBuffer *commandBuffer;
4100     ANGLE_TRY(endRenderPassAndGetCommandBuffer(&commandBuffer));
4101 
4102     image->changeLayout(aspectFlags, imageLayout, commandBuffer);
4103     image->retain(&mResourceUseList);
4104 
4105     return angle::Result::Continue;
4106 }
4107 
flushAndBeginRenderPass(const vk::Framebuffer & framebuffer,const gl::Rectangle & renderArea,const vk::RenderPassDesc & renderPassDesc,const vk::AttachmentOpsArray & renderPassAttachmentOps,const vk::ClearValuesArray & clearValues,vk::CommandBuffer ** commandBufferOut)4108 angle::Result ContextVk::flushAndBeginRenderPass(
4109     const vk::Framebuffer &framebuffer,
4110     const gl::Rectangle &renderArea,
4111     const vk::RenderPassDesc &renderPassDesc,
4112     const vk::AttachmentOpsArray &renderPassAttachmentOps,
4113     const vk::ClearValuesArray &clearValues,
4114     vk::CommandBuffer **commandBufferOut)
4115 {
4116     // Flush any outside renderPass commands first
4117     ANGLE_TRY(flushOutsideRenderPassCommands());
4118     // Next end any currently outstanding renderPass
4119     vk::CommandBuffer *outsideRenderPassCommandBuffer;
4120     ANGLE_TRY(endRenderPassAndGetCommandBuffer(&outsideRenderPassCommandBuffer));
4121 
4122     mRenderPassCommands->beginRenderPass(framebuffer, renderArea, renderPassDesc,
4123                                          renderPassAttachmentOps, clearValues, commandBufferOut);
4124     return angle::Result::Continue;
4125 }
4126 
startRenderPass(gl::Rectangle renderArea,vk::CommandBuffer ** commandBufferOut)4127 angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea,
4128                                          vk::CommandBuffer **commandBufferOut)
4129 {
4130     mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
4131     ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, renderArea, &mRenderPassCommandBuffer));
4132     if (mActiveQueryAnySamples)
4133     {
4134         mActiveQueryAnySamples->getQueryHelper()->beginOcclusionQuery(this,
4135                                                                       mRenderPassCommandBuffer);
4136     }
4137     if (mActiveQueryAnySamplesConservative)
4138     {
4139         mActiveQueryAnySamplesConservative->getQueryHelper()->beginOcclusionQuery(
4140             this, mRenderPassCommandBuffer);
4141     }
4142 
4143     if (commandBufferOut)
4144     {
4145         *commandBufferOut = mRenderPassCommandBuffer;
4146     }
4147 
4148     return angle::Result::Continue;
4149 }
4150 
endRenderPass()4151 angle::Result ContextVk::endRenderPass()
4152 {
4153     if (mRenderPassCommands->empty())
4154     {
4155         onRenderPassFinished();
4156         return angle::Result::Continue;
4157     }
4158 
4159     ASSERT(mOutsideRenderPassCommands->empty());
4160     if (mActiveQueryAnySamples)
4161     {
4162         mActiveQueryAnySamples->getQueryHelper()->endOcclusionQuery(this, mRenderPassCommandBuffer);
4163         ANGLE_TRY(mActiveQueryAnySamples->stashQueryHelper(this));
4164     }
4165     if (mActiveQueryAnySamplesConservative)
4166     {
4167         mActiveQueryAnySamplesConservative->getQueryHelper()->endOcclusionQuery(
4168             this, mRenderPassCommandBuffer);
4169         ANGLE_TRY(mActiveQueryAnySamplesConservative->stashQueryHelper(this));
4170     }
4171 
4172     onRenderPassFinished();
4173 
4174     if (mGpuEventsEnabled)
4175     {
4176         mRenderPassCounter++;
4177 
4178         EventName eventName = GetTraceEventName("RP", mRenderPassCounter);
4179         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
4180                                 TRACE_EVENT_PHASE_BEGIN, eventName));
4181         ANGLE_TRY(flushOutsideRenderPassCommands());
4182     }
4183 
4184     mRenderPassCommands->pauseTransformFeedbackIfStarted();
4185 
4186     if (mRenderer->getFeatures().enableCommandProcessingThread.enabled)
4187     {
4188         vk::CommandProcessorTask task = {this, &mPrimaryCommands, mRenderPassCommands};
4189         queueCommandsToWorker(task);
4190         getNextAvailableCommandBuffer(&mRenderPassCommands, true);
4191     }
4192     else
4193     {
4194         ANGLE_TRY(mRenderPassCommands->flushToPrimary(this, &mPrimaryCommands));
4195     }
4196 
4197     mHasPrimaryCommands = true;
4198 
4199     if (mGpuEventsEnabled)
4200     {
4201         EventName eventName = GetTraceEventName("RP", mRenderPassCounter);
4202         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
4203                                 TRACE_EVENT_PHASE_END, eventName));
4204         ANGLE_TRY(flushOutsideRenderPassCommands());
4205     }
4206 
4207     return angle::Result::Continue;
4208 }
4209 
onRenderPassImageWrite(VkImageAspectFlags aspectFlags,vk::ImageLayout imageLayout,vk::ImageHelper * image)4210 void ContextVk::onRenderPassImageWrite(VkImageAspectFlags aspectFlags,
4211                                        vk::ImageLayout imageLayout,
4212                                        vk::ImageHelper *image)
4213 {
4214     mRenderPassCommands->imageWrite(&mResourceUseList, aspectFlags, imageLayout, image);
4215 }
4216 
getNextAvailableCommandBuffer(vk::CommandBufferHelper ** commandBuffer,bool hasRenderPass)4217 void ContextVk::getNextAvailableCommandBuffer(vk::CommandBufferHelper **commandBuffer,
4218                                               bool hasRenderPass)
4219 {
4220     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::getNextAvailableCommandBuffer");
4221     std::unique_lock<std::mutex> lock(mCommandBufferQueueMutex);
4222     // Only wake if notified and command queue is not empty
4223     mAvailableCommandBufferCondition.wait(lock,
4224                                           [this] { return !mAvailableCommandBuffers.empty(); });
4225     *commandBuffer = mAvailableCommandBuffers.front();
4226     ASSERT((*commandBuffer)->empty());
4227     mAvailableCommandBuffers.pop();
4228     lock.unlock();
4229     (*commandBuffer)->setHasRenderPass(hasRenderPass);
4230 }
4231 
recycleCommandBuffer(vk::CommandBufferHelper * commandBuffer)4232 void ContextVk::recycleCommandBuffer(vk::CommandBufferHelper *commandBuffer)
4233 {
4234     ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::waitForWorkerThreadIdle");
4235     std::lock_guard<std::mutex> queueLock(mCommandBufferQueueMutex);
4236     ASSERT(commandBuffer->empty());
4237     mAvailableCommandBuffers.push(commandBuffer);
4238     mAvailableCommandBufferCondition.notify_one();
4239 }
4240 
syncExternalMemory()4241 angle::Result ContextVk::syncExternalMemory()
4242 {
4243     vk::CommandBuffer *commandBuffer;
4244     ANGLE_TRY(endRenderPassAndGetCommandBuffer(&commandBuffer));
4245 
4246     VkMemoryBarrier memoryBarrier = {};
4247     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
4248     memoryBarrier.srcAccessMask   = VK_ACCESS_MEMORY_WRITE_BIT;
4249     memoryBarrier.dstAccessMask   = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
4250 
4251     commandBuffer->memoryBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
4252                                  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &memoryBarrier);
4253     return angle::Result::Continue;
4254 }
4255 
addCommandBufferDiagnostics(const std::string & commandBufferDiagnostics)4256 void ContextVk::addCommandBufferDiagnostics(const std::string &commandBufferDiagnostics)
4257 {
4258     mCommandBufferDiagnostics.push_back(commandBufferDiagnostics);
4259 }
4260 
dumpCommandStreamDiagnostics()4261 void ContextVk::dumpCommandStreamDiagnostics()
4262 {
4263     std::ostream &out = std::cout;
4264 
4265     if (mCommandBufferDiagnostics.empty())
4266         return;
4267 
4268     out << "digraph {\n"
4269         << "  node [shape=plaintext fontname=\"Consolas\"]\n";
4270 
4271     for (size_t index = 0; index < mCommandBufferDiagnostics.size(); ++index)
4272     {
4273         const std::string &payload = mCommandBufferDiagnostics[index];
4274         out << "  cb" << index << " [label =\"" << payload << "\"];\n";
4275     }
4276 
4277     for (size_t index = 0; index < mCommandBufferDiagnostics.size() - 1; ++index)
4278     {
4279         out << "  cb" << index << " -> cb" << index + 1 << "\n";
4280     }
4281 
4282     mCommandBufferDiagnostics.clear();
4283 
4284     out << "}\n";
4285 }
4286 
initIndexTypeMap()4287 void ContextVk::initIndexTypeMap()
4288 {
4289     // Init gles-vulkan index type map
4290     mIndexTypeMap[gl::DrawElementsType::UnsignedByte] =
4291         mRenderer->getFeatures().supportsIndexTypeUint8.enabled ? VK_INDEX_TYPE_UINT8_EXT
4292                                                                 : VK_INDEX_TYPE_UINT16;
4293     mIndexTypeMap[gl::DrawElementsType::UnsignedShort] = VK_INDEX_TYPE_UINT16;
4294     mIndexTypeMap[gl::DrawElementsType::UnsignedInt]   = VK_INDEX_TYPE_UINT32;
4295 }
4296 
getVkIndexType(gl::DrawElementsType glIndexType) const4297 VkIndexType ContextVk::getVkIndexType(gl::DrawElementsType glIndexType) const
4298 {
4299     return mIndexTypeMap[glIndexType];
4300 }
4301 
getVkIndexTypeSize(gl::DrawElementsType glIndexType) const4302 size_t ContextVk::getVkIndexTypeSize(gl::DrawElementsType glIndexType) const
4303 {
4304     gl::DrawElementsType elementsType = shouldConvertUint8VkIndexType(glIndexType)
4305                                             ? gl::DrawElementsType::UnsignedShort
4306                                             : glIndexType;
4307     ASSERT(elementsType < gl::DrawElementsType::EnumCount);
4308 
4309     // Use GetDrawElementsTypeSize() to get the size
4310     return static_cast<size_t>(gl::GetDrawElementsTypeSize(elementsType));
4311 }
4312 
shouldConvertUint8VkIndexType(gl::DrawElementsType glIndexType) const4313 bool ContextVk::shouldConvertUint8VkIndexType(gl::DrawElementsType glIndexType) const
4314 {
4315     return (glIndexType == gl::DrawElementsType::UnsignedByte &&
4316             !mRenderer->getFeatures().supportsIndexTypeUint8.enabled);
4317 }
4318 
flushOutsideRenderPassCommands()4319 angle::Result ContextVk::flushOutsideRenderPassCommands()
4320 {
4321     if (!mOutsideRenderPassCommands->empty())
4322     {
4323         if (mRenderer->getFeatures().enableCommandProcessingThread.enabled)
4324         {
4325             vk::CommandProcessorTask task = {this, &mPrimaryCommands, mOutsideRenderPassCommands};
4326             queueCommandsToWorker(task);
4327             getNextAvailableCommandBuffer(&mOutsideRenderPassCommands, false);
4328         }
4329         else
4330         {
4331             ANGLE_TRY(mOutsideRenderPassCommands->flushToPrimary(this, &mPrimaryCommands));
4332         }
4333         mHasPrimaryCommands = true;
4334     }
4335     return angle::Result::Continue;
4336 }
4337 
beginOcclusionQuery(QueryVk * queryVk)4338 void ContextVk::beginOcclusionQuery(QueryVk *queryVk)
4339 {
4340     // To avoid complexity, we always start and end occlusion query inside renderpass. if renderpass
4341     // not yet started, we just remember it and defer the start call.
4342     if (mRenderPassCommands->started())
4343     {
4344         queryVk->getQueryHelper()->beginOcclusionQuery(this, mRenderPassCommandBuffer);
4345     }
4346     if (queryVk->isAnySamplesQuery())
4347     {
4348         ASSERT(mActiveQueryAnySamples == nullptr);
4349         mActiveQueryAnySamples = queryVk;
4350     }
4351     else if (queryVk->isAnySamplesConservativeQuery())
4352     {
4353         ASSERT(mActiveQueryAnySamplesConservative == nullptr);
4354         mActiveQueryAnySamplesConservative = queryVk;
4355     }
4356     else
4357     {
4358         UNREACHABLE();
4359     }
4360 }
4361 
endOcclusionQuery(QueryVk * queryVk)4362 void ContextVk::endOcclusionQuery(QueryVk *queryVk)
4363 {
4364     if (mRenderPassCommands->started())
4365     {
4366         queryVk->getQueryHelper()->endOcclusionQuery(this, mRenderPassCommandBuffer);
4367     }
4368     if (queryVk->isAnySamplesQuery())
4369     {
4370         ASSERT(mActiveQueryAnySamples == queryVk);
4371         mActiveQueryAnySamples = nullptr;
4372     }
4373     else if (queryVk->isAnySamplesConservativeQuery())
4374     {
4375         ASSERT(mActiveQueryAnySamplesConservative == queryVk);
4376         mActiveQueryAnySamplesConservative = nullptr;
4377     }
4378     else
4379     {
4380         UNREACHABLE();
4381     }
4382 }
4383 
isRobustResourceInitEnabled() const4384 bool ContextVk::isRobustResourceInitEnabled() const
4385 {
4386     return mState.isRobustResourceInitEnabled();
4387 }
4388 
4389 }  // namespace rx
4390