xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // ContextVk.cpp:
7*8975f5c5SAndroid Build Coastguard Worker //    Implements the class methods for ContextVk.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/ContextVk.h"
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker #include "common/bitset_utils.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "common/system_utils.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "image_util/loadimage.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Display.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Program.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Semaphore.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/ShareGroup.h"
22*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Surface.h"
23*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/angletypes.h"
24*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/renderer_utils.h"
25*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/BufferVk.h"
26*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/CompilerVk.h"
27*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/DisplayVk.h"
28*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/FenceNVVk.h"
29*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/FramebufferVk.h"
30*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/MemoryObjectVk.h"
31*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/OverlayVk.h"
32*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/ProgramPipelineVk.h"
33*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/ProgramVk.h"
34*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/QueryVk.h"
35*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/RenderbufferVk.h"
36*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/SamplerVk.h"
37*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/SemaphoreVk.h"
38*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/ShaderVk.h"
39*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/SurfaceVk.h"
40*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/SyncVk.h"
41*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/TextureVk.h"
42*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
43*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/VertexArrayVk.h"
44*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/vk_renderer.h"
45*8975f5c5SAndroid Build Coastguard Worker 
46*8975f5c5SAndroid Build Coastguard Worker #include <fstream>
47*8975f5c5SAndroid Build Coastguard Worker #include <iostream>
48*8975f5c5SAndroid Build Coastguard Worker #include <sstream>
49*8975f5c5SAndroid Build Coastguard Worker 
50*8975f5c5SAndroid Build Coastguard Worker namespace rx
51*8975f5c5SAndroid Build Coastguard Worker {
52*8975f5c5SAndroid Build Coastguard Worker namespace
53*8975f5c5SAndroid Build Coastguard Worker {
54*8975f5c5SAndroid Build Coastguard Worker // If the total size of copyBufferToImage commands in the outside command buffer reaches the
55*8975f5c5SAndroid Build Coastguard Worker // threshold below, the latter is flushed.
56*8975f5c5SAndroid Build Coastguard Worker static constexpr VkDeviceSize kMaxBufferToImageCopySize = 64 * 1024 * 1024;
57*8975f5c5SAndroid Build Coastguard Worker // The number of queueSerials we will reserve for outsideRenderPassCommands when we generate one for
58*8975f5c5SAndroid Build Coastguard Worker // RenderPassCommands.
59*8975f5c5SAndroid Build Coastguard Worker static constexpr size_t kMaxReservedOutsideRenderPassQueueSerials = 15;
60*8975f5c5SAndroid Build Coastguard Worker 
61*8975f5c5SAndroid Build Coastguard Worker // Dumping the command stream is disabled by default.
62*8975f5c5SAndroid Build Coastguard Worker static constexpr bool kEnableCommandStreamDiagnostics = false;
63*8975f5c5SAndroid Build Coastguard Worker 
64*8975f5c5SAndroid Build Coastguard Worker // All glMemoryBarrier bits that related to texture usage
65*8975f5c5SAndroid Build Coastguard Worker static constexpr GLbitfield kWriteAfterAccessImageMemoryBarriers =
66*8975f5c5SAndroid Build Coastguard Worker     GL_SHADER_IMAGE_ACCESS_BARRIER_BIT;
67*8975f5c5SAndroid Build Coastguard Worker static constexpr GLbitfield kWriteAfterAccessMemoryBarriers =
68*8975f5c5SAndroid Build Coastguard Worker     kWriteAfterAccessImageMemoryBarriers | GL_SHADER_STORAGE_BARRIER_BIT;
69*8975f5c5SAndroid Build Coastguard Worker 
70*8975f5c5SAndroid Build Coastguard Worker // For shader uniforms such as gl_DepthRange and the viewport size.
71*8975f5c5SAndroid Build Coastguard Worker struct GraphicsDriverUniforms
72*8975f5c5SAndroid Build Coastguard Worker {
73*8975f5c5SAndroid Build Coastguard Worker     // Contain packed 8-bit values for atomic counter buffer offsets.  These offsets are within
74*8975f5c5SAndroid Build Coastguard Worker     // Vulkan's minStorageBufferOffsetAlignment limit and are used to support unaligned offsets
75*8975f5c5SAndroid Build Coastguard Worker     // allowed in GL.
76*8975f5c5SAndroid Build Coastguard Worker     std::array<uint32_t, 2> acbBufferOffsets;
77*8975f5c5SAndroid Build Coastguard Worker 
78*8975f5c5SAndroid Build Coastguard Worker     // .x is near, .y is far
79*8975f5c5SAndroid Build Coastguard Worker     std::array<float, 2> depthRange;
80*8975f5c5SAndroid Build Coastguard Worker 
81*8975f5c5SAndroid Build Coastguard Worker     // Used to flip gl_FragCoord.  Packed uvec2
82*8975f5c5SAndroid Build Coastguard Worker     uint32_t renderArea;
83*8975f5c5SAndroid Build Coastguard Worker 
84*8975f5c5SAndroid Build Coastguard Worker     // Packed vec4 of snorm8
85*8975f5c5SAndroid Build Coastguard Worker     uint32_t flipXY;
86*8975f5c5SAndroid Build Coastguard Worker 
87*8975f5c5SAndroid Build Coastguard Worker     // Only the lower 16 bits used
88*8975f5c5SAndroid Build Coastguard Worker     uint32_t dither;
89*8975f5c5SAndroid Build Coastguard Worker 
90*8975f5c5SAndroid Build Coastguard Worker     // Various bits of state:
91*8975f5c5SAndroid Build Coastguard Worker     // - Surface rotation
92*8975f5c5SAndroid Build Coastguard Worker     // - Advanced blend equation
93*8975f5c5SAndroid Build Coastguard Worker     // - Sample count
94*8975f5c5SAndroid Build Coastguard Worker     // - Enabled clip planes
95*8975f5c5SAndroid Build Coastguard Worker     // - Depth transformation
96*8975f5c5SAndroid Build Coastguard Worker     uint32_t misc;
97*8975f5c5SAndroid Build Coastguard Worker };
98*8975f5c5SAndroid Build Coastguard Worker static_assert(sizeof(GraphicsDriverUniforms) % (sizeof(uint32_t) * 4) == 0,
99*8975f5c5SAndroid Build Coastguard Worker               "GraphicsDriverUniforms should be 16bytes aligned");
100*8975f5c5SAndroid Build Coastguard Worker 
101*8975f5c5SAndroid Build Coastguard Worker // Only used when transform feedback is emulated.
102*8975f5c5SAndroid Build Coastguard Worker struct GraphicsDriverUniformsExtended
103*8975f5c5SAndroid Build Coastguard Worker {
104*8975f5c5SAndroid Build Coastguard Worker     GraphicsDriverUniforms common;
105*8975f5c5SAndroid Build Coastguard Worker 
106*8975f5c5SAndroid Build Coastguard Worker     // Only used with transform feedback emulation
107*8975f5c5SAndroid Build Coastguard Worker     std::array<int32_t, 4> xfbBufferOffsets;
108*8975f5c5SAndroid Build Coastguard Worker     int32_t xfbVerticesPerInstance;
109*8975f5c5SAndroid Build Coastguard Worker 
110*8975f5c5SAndroid Build Coastguard Worker     int32_t padding[3];
111*8975f5c5SAndroid Build Coastguard Worker };
112*8975f5c5SAndroid Build Coastguard Worker static_assert(sizeof(GraphicsDriverUniformsExtended) % (sizeof(uint32_t) * 4) == 0,
113*8975f5c5SAndroid Build Coastguard Worker               "GraphicsDriverUniformsExtended should be 16bytes aligned");
114*8975f5c5SAndroid Build Coastguard Worker 
115*8975f5c5SAndroid Build Coastguard Worker struct ComputeDriverUniforms
116*8975f5c5SAndroid Build Coastguard Worker {
117*8975f5c5SAndroid Build Coastguard Worker     // Atomic counter buffer offsets with the same layout as in GraphicsDriverUniforms.
118*8975f5c5SAndroid Build Coastguard Worker     std::array<uint32_t, 4> acbBufferOffsets;
119*8975f5c5SAndroid Build Coastguard Worker };
120*8975f5c5SAndroid Build Coastguard Worker 
MakeFlipUniform(bool flipX,bool flipY,bool invertViewport)121*8975f5c5SAndroid Build Coastguard Worker uint32_t MakeFlipUniform(bool flipX, bool flipY, bool invertViewport)
122*8975f5c5SAndroid Build Coastguard Worker {
123*8975f5c5SAndroid Build Coastguard Worker     // Create snorm values of either -1 or 1, based on whether flipping is enabled or not
124*8975f5c5SAndroid Build Coastguard Worker     // respectively.
125*8975f5c5SAndroid Build Coastguard Worker     constexpr uint8_t kSnormOne      = 0x7F;
126*8975f5c5SAndroid Build Coastguard Worker     constexpr uint8_t kSnormMinusOne = 0x81;
127*8975f5c5SAndroid Build Coastguard Worker 
128*8975f5c5SAndroid Build Coastguard Worker     // .xy are flips for the fragment stage.
129*8975f5c5SAndroid Build Coastguard Worker     uint32_t x = flipX ? kSnormMinusOne : kSnormOne;
130*8975f5c5SAndroid Build Coastguard Worker     uint32_t y = flipY ? kSnormMinusOne : kSnormOne;
131*8975f5c5SAndroid Build Coastguard Worker 
132*8975f5c5SAndroid Build Coastguard Worker     // .zw are flips for the vertex stage.
133*8975f5c5SAndroid Build Coastguard Worker     uint32_t z = x;
134*8975f5c5SAndroid Build Coastguard Worker     uint32_t w = flipY != invertViewport ? kSnormMinusOne : kSnormOne;
135*8975f5c5SAndroid Build Coastguard Worker 
136*8975f5c5SAndroid Build Coastguard Worker     return x | y << 8 | z << 16 | w << 24;
137*8975f5c5SAndroid Build Coastguard Worker }
138*8975f5c5SAndroid Build Coastguard Worker 
DefaultGLErrorCode(VkResult result)139*8975f5c5SAndroid Build Coastguard Worker GLenum DefaultGLErrorCode(VkResult result)
140*8975f5c5SAndroid Build Coastguard Worker {
141*8975f5c5SAndroid Build Coastguard Worker     switch (result)
142*8975f5c5SAndroid Build Coastguard Worker     {
143*8975f5c5SAndroid Build Coastguard Worker         case VK_ERROR_OUT_OF_HOST_MEMORY:
144*8975f5c5SAndroid Build Coastguard Worker         case VK_ERROR_OUT_OF_DEVICE_MEMORY:
145*8975f5c5SAndroid Build Coastguard Worker         case VK_ERROR_TOO_MANY_OBJECTS:
146*8975f5c5SAndroid Build Coastguard Worker             return GL_OUT_OF_MEMORY;
147*8975f5c5SAndroid Build Coastguard Worker         case VK_ERROR_DEVICE_LOST:
148*8975f5c5SAndroid Build Coastguard Worker             return GL_CONTEXT_LOST;
149*8975f5c5SAndroid Build Coastguard Worker         default:
150*8975f5c5SAndroid Build Coastguard Worker             return GL_INVALID_OPERATION;
151*8975f5c5SAndroid Build Coastguard Worker     }
152*8975f5c5SAndroid Build Coastguard Worker }
153*8975f5c5SAndroid Build Coastguard Worker 
154*8975f5c5SAndroid Build Coastguard Worker constexpr gl::ShaderMap<vk::ImageLayout> kShaderReadOnlyImageLayouts = {
155*8975f5c5SAndroid Build Coastguard Worker     {gl::ShaderType::Vertex, vk::ImageLayout::VertexShaderReadOnly},
156*8975f5c5SAndroid Build Coastguard Worker     {gl::ShaderType::TessControl, vk::ImageLayout::PreFragmentShadersReadOnly},
157*8975f5c5SAndroid Build Coastguard Worker     {gl::ShaderType::TessEvaluation, vk::ImageLayout::PreFragmentShadersReadOnly},
158*8975f5c5SAndroid Build Coastguard Worker     {gl::ShaderType::Geometry, vk::ImageLayout::PreFragmentShadersReadOnly},
159*8975f5c5SAndroid Build Coastguard Worker     {gl::ShaderType::Fragment, vk::ImageLayout::FragmentShaderReadOnly},
160*8975f5c5SAndroid Build Coastguard Worker     {gl::ShaderType::Compute, vk::ImageLayout::ComputeShaderReadOnly}};
161*8975f5c5SAndroid Build Coastguard Worker 
162*8975f5c5SAndroid Build Coastguard Worker constexpr gl::ShaderMap<vk::ImageLayout> kShaderWriteImageLayouts = {
163*8975f5c5SAndroid Build Coastguard Worker     {gl::ShaderType::Vertex, vk::ImageLayout::VertexShaderWrite},
164*8975f5c5SAndroid Build Coastguard Worker     {gl::ShaderType::TessControl, vk::ImageLayout::PreFragmentShadersWrite},
165*8975f5c5SAndroid Build Coastguard Worker     {gl::ShaderType::TessEvaluation, vk::ImageLayout::PreFragmentShadersWrite},
166*8975f5c5SAndroid Build Coastguard Worker     {gl::ShaderType::Geometry, vk::ImageLayout::PreFragmentShadersWrite},
167*8975f5c5SAndroid Build Coastguard Worker     {gl::ShaderType::Fragment, vk::ImageLayout::FragmentShaderWrite},
168*8975f5c5SAndroid Build Coastguard Worker     {gl::ShaderType::Compute, vk::ImageLayout::ComputeShaderWrite}};
169*8975f5c5SAndroid Build Coastguard Worker 
170*8975f5c5SAndroid Build Coastguard Worker constexpr VkBufferUsageFlags kVertexBufferUsage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
171*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kDynamicVertexDataSize         = 16 * 1024;
172*8975f5c5SAndroid Build Coastguard Worker 
CanMultiDrawIndirectUseCmd(ContextVk * contextVk,VertexArrayVk * vertexArray,gl::PrimitiveMode mode,GLsizei drawcount,GLsizei stride)173*8975f5c5SAndroid Build Coastguard Worker bool CanMultiDrawIndirectUseCmd(ContextVk *contextVk,
174*8975f5c5SAndroid Build Coastguard Worker                                 VertexArrayVk *vertexArray,
175*8975f5c5SAndroid Build Coastguard Worker                                 gl::PrimitiveMode mode,
176*8975f5c5SAndroid Build Coastguard Worker                                 GLsizei drawcount,
177*8975f5c5SAndroid Build Coastguard Worker                                 GLsizei stride)
178*8975f5c5SAndroid Build Coastguard Worker {
179*8975f5c5SAndroid Build Coastguard Worker     // Use the generic implementation if multiDrawIndirect is disabled, if line loop is being used
180*8975f5c5SAndroid Build Coastguard Worker     // for multiDraw, if drawcount is greater than maxDrawIndirectCount, or if there are streaming
181*8975f5c5SAndroid Build Coastguard Worker     // vertex attributes.
182*8975f5c5SAndroid Build Coastguard Worker     ASSERT(drawcount > 1);
183*8975f5c5SAndroid Build Coastguard Worker     const bool supportsMultiDrawIndirect =
184*8975f5c5SAndroid Build Coastguard Worker         contextVk->getFeatures().supportsMultiDrawIndirect.enabled;
185*8975f5c5SAndroid Build Coastguard Worker     const bool isMultiDrawLineLoop = (mode == gl::PrimitiveMode::LineLoop);
186*8975f5c5SAndroid Build Coastguard Worker     const bool isDrawCountBeyondLimit =
187*8975f5c5SAndroid Build Coastguard Worker         (static_cast<uint32_t>(drawcount) >
188*8975f5c5SAndroid Build Coastguard Worker          contextVk->getRenderer()->getPhysicalDeviceProperties().limits.maxDrawIndirectCount);
189*8975f5c5SAndroid Build Coastguard Worker     const bool isMultiDrawWithStreamingAttribs = vertexArray->getStreamingVertexAttribsMask().any();
190*8975f5c5SAndroid Build Coastguard Worker 
191*8975f5c5SAndroid Build Coastguard Worker     const bool canMultiDrawIndirectUseCmd = supportsMultiDrawIndirect && !isMultiDrawLineLoop &&
192*8975f5c5SAndroid Build Coastguard Worker                                             !isDrawCountBeyondLimit &&
193*8975f5c5SAndroid Build Coastguard Worker                                             !isMultiDrawWithStreamingAttribs;
194*8975f5c5SAndroid Build Coastguard Worker     return canMultiDrawIndirectUseCmd;
195*8975f5c5SAndroid Build Coastguard Worker }
196*8975f5c5SAndroid Build Coastguard Worker 
GetCoverageSampleCount(const gl::State & glState,GLint samples)197*8975f5c5SAndroid Build Coastguard Worker uint32_t GetCoverageSampleCount(const gl::State &glState, GLint samples)
198*8975f5c5SAndroid Build Coastguard Worker {
199*8975f5c5SAndroid Build Coastguard Worker     ASSERT(glState.isSampleCoverageEnabled());
200*8975f5c5SAndroid Build Coastguard Worker 
201*8975f5c5SAndroid Build Coastguard Worker     // Get a fraction of the samples based on the coverage parameters.
202*8975f5c5SAndroid Build Coastguard Worker     // There are multiple ways to obtain an integer value from a float -
203*8975f5c5SAndroid Build Coastguard Worker     //     truncation, ceil and round
204*8975f5c5SAndroid Build Coastguard Worker     //
205*8975f5c5SAndroid Build Coastguard Worker     // round() provides a more even distribution of values but doesn't seem to play well
206*8975f5c5SAndroid Build Coastguard Worker     // with all vendors (AMD). A way to work around this is to increase the comparison threshold
207*8975f5c5SAndroid Build Coastguard Worker     // of deqp tests. Though this takes care of deqp tests other apps would still have issues.
208*8975f5c5SAndroid Build Coastguard Worker     //
209*8975f5c5SAndroid Build Coastguard Worker     // Truncation provides an uneven distribution near the edges of the interval but seems to
210*8975f5c5SAndroid Build Coastguard Worker     // play well with all vendors.
211*8975f5c5SAndroid Build Coastguard Worker     //
212*8975f5c5SAndroid Build Coastguard Worker     // We are going with truncation for expediency.
213*8975f5c5SAndroid Build Coastguard Worker     return static_cast<uint32_t>(glState.getSampleCoverageValue() * samples);
214*8975f5c5SAndroid Build Coastguard Worker }
215*8975f5c5SAndroid Build Coastguard Worker 
ApplySampleCoverage(const gl::State & glState,uint32_t coverageSampleCount,uint32_t * maskOut)216*8975f5c5SAndroid Build Coastguard Worker void ApplySampleCoverage(const gl::State &glState, uint32_t coverageSampleCount, uint32_t *maskOut)
217*8975f5c5SAndroid Build Coastguard Worker {
218*8975f5c5SAndroid Build Coastguard Worker     ASSERT(glState.isSampleCoverageEnabled());
219*8975f5c5SAndroid Build Coastguard Worker 
220*8975f5c5SAndroid Build Coastguard Worker     uint32_t coverageMask = angle::BitMask<uint32_t>(coverageSampleCount);
221*8975f5c5SAndroid Build Coastguard Worker 
222*8975f5c5SAndroid Build Coastguard Worker     if (glState.getSampleCoverageInvert())
223*8975f5c5SAndroid Build Coastguard Worker     {
224*8975f5c5SAndroid Build Coastguard Worker         coverageMask = ~coverageMask;
225*8975f5c5SAndroid Build Coastguard Worker     }
226*8975f5c5SAndroid Build Coastguard Worker 
227*8975f5c5SAndroid Build Coastguard Worker     *maskOut &= coverageMask;
228*8975f5c5SAndroid Build Coastguard Worker }
229*8975f5c5SAndroid Build Coastguard Worker 
DetermineSurfaceRotation(const gl::Framebuffer * framebuffer,const WindowSurfaceVk * windowSurface)230*8975f5c5SAndroid Build Coastguard Worker SurfaceRotation DetermineSurfaceRotation(const gl::Framebuffer *framebuffer,
231*8975f5c5SAndroid Build Coastguard Worker                                          const WindowSurfaceVk *windowSurface)
232*8975f5c5SAndroid Build Coastguard Worker {
233*8975f5c5SAndroid Build Coastguard Worker     if (windowSurface && framebuffer->isDefault())
234*8975f5c5SAndroid Build Coastguard Worker     {
235*8975f5c5SAndroid Build Coastguard Worker         switch (windowSurface->getPreTransform())
236*8975f5c5SAndroid Build Coastguard Worker         {
237*8975f5c5SAndroid Build Coastguard Worker             case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
238*8975f5c5SAndroid Build Coastguard Worker                 // Do not rotate gl_Position (surface matches the device's orientation):
239*8975f5c5SAndroid Build Coastguard Worker                 return SurfaceRotation::Identity;
240*8975f5c5SAndroid Build Coastguard Worker             case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
241*8975f5c5SAndroid Build Coastguard Worker                 // Rotate gl_Position 90 degrees:
242*8975f5c5SAndroid Build Coastguard Worker                 return SurfaceRotation::Rotated90Degrees;
243*8975f5c5SAndroid Build Coastguard Worker             case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
244*8975f5c5SAndroid Build Coastguard Worker                 // Rotate gl_Position 180 degrees:
245*8975f5c5SAndroid Build Coastguard Worker                 return SurfaceRotation::Rotated180Degrees;
246*8975f5c5SAndroid Build Coastguard Worker             case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
247*8975f5c5SAndroid Build Coastguard Worker                 // Rotate gl_Position 270 degrees:
248*8975f5c5SAndroid Build Coastguard Worker                 return SurfaceRotation::Rotated270Degrees;
249*8975f5c5SAndroid Build Coastguard Worker             default:
250*8975f5c5SAndroid Build Coastguard Worker                 UNREACHABLE();
251*8975f5c5SAndroid Build Coastguard Worker                 return SurfaceRotation::Identity;
252*8975f5c5SAndroid Build Coastguard Worker         }
253*8975f5c5SAndroid Build Coastguard Worker     }
254*8975f5c5SAndroid Build Coastguard Worker     else
255*8975f5c5SAndroid Build Coastguard Worker     {
256*8975f5c5SAndroid Build Coastguard Worker         // Do not rotate gl_Position (offscreen framebuffer):
257*8975f5c5SAndroid Build Coastguard Worker         return SurfaceRotation::Identity;
258*8975f5c5SAndroid Build Coastguard Worker     }
259*8975f5c5SAndroid Build Coastguard Worker }
260*8975f5c5SAndroid Build Coastguard Worker 
261*8975f5c5SAndroid Build Coastguard Worker // Should not generate a copy with modern C++.
GetTraceEventName(const char * title,uint64_t counter)262*8975f5c5SAndroid Build Coastguard Worker EventName GetTraceEventName(const char *title, uint64_t counter)
263*8975f5c5SAndroid Build Coastguard Worker {
264*8975f5c5SAndroid Build Coastguard Worker     EventName buf;
265*8975f5c5SAndroid Build Coastguard Worker     snprintf(buf.data(), kMaxGpuEventNameLen - 1, "%s %llu", title,
266*8975f5c5SAndroid Build Coastguard Worker              static_cast<unsigned long long>(counter));
267*8975f5c5SAndroid Build Coastguard Worker     return buf;
268*8975f5c5SAndroid Build Coastguard Worker }
269*8975f5c5SAndroid Build Coastguard Worker 
GetColorAccess(const gl::State & state,const gl::FramebufferState & framebufferState,const gl::DrawBufferMask & emulatedAlphaMask,const gl::ProgramExecutable * executable,size_t colorIndexGL)270*8975f5c5SAndroid Build Coastguard Worker vk::ResourceAccess GetColorAccess(const gl::State &state,
271*8975f5c5SAndroid Build Coastguard Worker                                   const gl::FramebufferState &framebufferState,
272*8975f5c5SAndroid Build Coastguard Worker                                   const gl::DrawBufferMask &emulatedAlphaMask,
273*8975f5c5SAndroid Build Coastguard Worker                                   const gl::ProgramExecutable *executable,
274*8975f5c5SAndroid Build Coastguard Worker                                   size_t colorIndexGL)
275*8975f5c5SAndroid Build Coastguard Worker {
276*8975f5c5SAndroid Build Coastguard Worker     // No access if draw buffer is disabled altogether
277*8975f5c5SAndroid Build Coastguard Worker     // Without framebuffer fetch:
278*8975f5c5SAndroid Build Coastguard Worker     //   No access if color output is masked, or rasterizer discard is enabled
279*8975f5c5SAndroid Build Coastguard Worker     // With framebuffer fetch:
280*8975f5c5SAndroid Build Coastguard Worker     //   Read access if color output is masked, or rasterizer discard is enabled
281*8975f5c5SAndroid Build Coastguard Worker 
282*8975f5c5SAndroid Build Coastguard Worker     if (!framebufferState.getEnabledDrawBuffers().test(colorIndexGL))
283*8975f5c5SAndroid Build Coastguard Worker     {
284*8975f5c5SAndroid Build Coastguard Worker         return vk::ResourceAccess::Unused;
285*8975f5c5SAndroid Build Coastguard Worker     }
286*8975f5c5SAndroid Build Coastguard Worker 
287*8975f5c5SAndroid Build Coastguard Worker     const gl::BlendStateExt &blendStateExt = state.getBlendStateExt();
288*8975f5c5SAndroid Build Coastguard Worker     uint8_t colorMask                      = gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(
289*8975f5c5SAndroid Build Coastguard Worker         colorIndexGL, blendStateExt.getColorMaskBits());
290*8975f5c5SAndroid Build Coastguard Worker     if (emulatedAlphaMask[colorIndexGL])
291*8975f5c5SAndroid Build Coastguard Worker     {
292*8975f5c5SAndroid Build Coastguard Worker         colorMask &= ~VK_COLOR_COMPONENT_A_BIT;
293*8975f5c5SAndroid Build Coastguard Worker     }
294*8975f5c5SAndroid Build Coastguard Worker     const bool isOutputMasked = colorMask == 0 || state.isRasterizerDiscardEnabled();
295*8975f5c5SAndroid Build Coastguard Worker 
296*8975f5c5SAndroid Build Coastguard Worker     if (isOutputMasked)
297*8975f5c5SAndroid Build Coastguard Worker     {
298*8975f5c5SAndroid Build Coastguard Worker         const bool hasFramebufferFetch =
299*8975f5c5SAndroid Build Coastguard Worker             executable ? executable->usesColorFramebufferFetch() : false;
300*8975f5c5SAndroid Build Coastguard Worker         return hasFramebufferFetch ? vk::ResourceAccess::ReadOnly : vk::ResourceAccess::Unused;
301*8975f5c5SAndroid Build Coastguard Worker     }
302*8975f5c5SAndroid Build Coastguard Worker 
303*8975f5c5SAndroid Build Coastguard Worker     return vk::ResourceAccess::ReadWrite;
304*8975f5c5SAndroid Build Coastguard Worker }
305*8975f5c5SAndroid Build Coastguard Worker 
GetDepthAccess(const gl::DepthStencilState & dsState,const gl::ProgramExecutable * executable,UpdateDepthFeedbackLoopReason reason)306*8975f5c5SAndroid Build Coastguard Worker vk::ResourceAccess GetDepthAccess(const gl::DepthStencilState &dsState,
307*8975f5c5SAndroid Build Coastguard Worker                                   const gl::ProgramExecutable *executable,
308*8975f5c5SAndroid Build Coastguard Worker                                   UpdateDepthFeedbackLoopReason reason)
309*8975f5c5SAndroid Build Coastguard Worker {
310*8975f5c5SAndroid Build Coastguard Worker     // Skip if depth/stencil not actually accessed.
311*8975f5c5SAndroid Build Coastguard Worker     if (reason == UpdateDepthFeedbackLoopReason::None)
312*8975f5c5SAndroid Build Coastguard Worker     {
313*8975f5c5SAndroid Build Coastguard Worker         return vk::ResourceAccess::Unused;
314*8975f5c5SAndroid Build Coastguard Worker     }
315*8975f5c5SAndroid Build Coastguard Worker 
316*8975f5c5SAndroid Build Coastguard Worker     // Note that clear commands don't respect depth test enable, only the mask
317*8975f5c5SAndroid Build Coastguard Worker     // Note Other state can be stated here too in the future, such as rasterizer discard.
318*8975f5c5SAndroid Build Coastguard Worker     if (!dsState.depthTest && reason != UpdateDepthFeedbackLoopReason::Clear)
319*8975f5c5SAndroid Build Coastguard Worker     {
320*8975f5c5SAndroid Build Coastguard Worker         return vk::ResourceAccess::Unused;
321*8975f5c5SAndroid Build Coastguard Worker     }
322*8975f5c5SAndroid Build Coastguard Worker 
323*8975f5c5SAndroid Build Coastguard Worker     if (dsState.isDepthMaskedOut())
324*8975f5c5SAndroid Build Coastguard Worker     {
325*8975f5c5SAndroid Build Coastguard Worker         const bool hasFramebufferFetch =
326*8975f5c5SAndroid Build Coastguard Worker             executable ? executable->usesDepthFramebufferFetch() : false;
327*8975f5c5SAndroid Build Coastguard Worker 
328*8975f5c5SAndroid Build Coastguard Worker         // If depthFunc is GL_ALWAYS or GL_NEVER, we do not need to load depth value.
329*8975f5c5SAndroid Build Coastguard Worker         return (dsState.depthFunc == GL_ALWAYS || dsState.depthFunc == GL_NEVER) &&
330*8975f5c5SAndroid Build Coastguard Worker                        !hasFramebufferFetch
331*8975f5c5SAndroid Build Coastguard Worker                    ? vk::ResourceAccess::Unused
332*8975f5c5SAndroid Build Coastguard Worker                    : vk::ResourceAccess::ReadOnly;
333*8975f5c5SAndroid Build Coastguard Worker     }
334*8975f5c5SAndroid Build Coastguard Worker 
335*8975f5c5SAndroid Build Coastguard Worker     return vk::ResourceAccess::ReadWrite;
336*8975f5c5SAndroid Build Coastguard Worker }
337*8975f5c5SAndroid Build Coastguard Worker 
GetStencilAccess(const gl::DepthStencilState & dsState,GLuint framebufferStencilSize,const gl::ProgramExecutable * executable,UpdateDepthFeedbackLoopReason reason)338*8975f5c5SAndroid Build Coastguard Worker vk::ResourceAccess GetStencilAccess(const gl::DepthStencilState &dsState,
339*8975f5c5SAndroid Build Coastguard Worker                                     GLuint framebufferStencilSize,
340*8975f5c5SAndroid Build Coastguard Worker                                     const gl::ProgramExecutable *executable,
341*8975f5c5SAndroid Build Coastguard Worker                                     UpdateDepthFeedbackLoopReason reason)
342*8975f5c5SAndroid Build Coastguard Worker {
343*8975f5c5SAndroid Build Coastguard Worker     // Skip if depth/stencil not actually accessed.
344*8975f5c5SAndroid Build Coastguard Worker     if (reason == UpdateDepthFeedbackLoopReason::None)
345*8975f5c5SAndroid Build Coastguard Worker     {
346*8975f5c5SAndroid Build Coastguard Worker         return vk::ResourceAccess::Unused;
347*8975f5c5SAndroid Build Coastguard Worker     }
348*8975f5c5SAndroid Build Coastguard Worker 
349*8975f5c5SAndroid Build Coastguard Worker     // Note that clear commands don't respect stencil test enable, only the mask
350*8975f5c5SAndroid Build Coastguard Worker     // Note Other state can be stated here too in the future, such as rasterizer discard.
351*8975f5c5SAndroid Build Coastguard Worker     if (!dsState.stencilTest && reason != UpdateDepthFeedbackLoopReason::Clear)
352*8975f5c5SAndroid Build Coastguard Worker     {
353*8975f5c5SAndroid Build Coastguard Worker         return vk::ResourceAccess::Unused;
354*8975f5c5SAndroid Build Coastguard Worker     }
355*8975f5c5SAndroid Build Coastguard Worker 
356*8975f5c5SAndroid Build Coastguard Worker     const bool hasFramebufferFetch = executable ? executable->usesStencilFramebufferFetch() : false;
357*8975f5c5SAndroid Build Coastguard Worker 
358*8975f5c5SAndroid Build Coastguard Worker     return dsState.isStencilNoOp(framebufferStencilSize) &&
359*8975f5c5SAndroid Build Coastguard Worker                    dsState.isStencilBackNoOp(framebufferStencilSize) && !hasFramebufferFetch
360*8975f5c5SAndroid Build Coastguard Worker                ? vk::ResourceAccess::ReadOnly
361*8975f5c5SAndroid Build Coastguard Worker                : vk::ResourceAccess::ReadWrite;
362*8975f5c5SAndroid Build Coastguard Worker }
363*8975f5c5SAndroid Build Coastguard Worker 
GetContextPriority(const gl::State & state)364*8975f5c5SAndroid Build Coastguard Worker egl::ContextPriority GetContextPriority(const gl::State &state)
365*8975f5c5SAndroid Build Coastguard Worker {
366*8975f5c5SAndroid Build Coastguard Worker     return egl::FromEGLenum<egl::ContextPriority>(state.getContextPriority());
367*8975f5c5SAndroid Build Coastguard Worker }
368*8975f5c5SAndroid Build Coastguard Worker 
IsStencilSamplerBinding(const gl::ProgramExecutable & executable,size_t textureUnit)369*8975f5c5SAndroid Build Coastguard Worker bool IsStencilSamplerBinding(const gl::ProgramExecutable &executable, size_t textureUnit)
370*8975f5c5SAndroid Build Coastguard Worker {
371*8975f5c5SAndroid Build Coastguard Worker     const gl::SamplerFormat format = executable.getSamplerFormatForTextureUnitIndex(textureUnit);
372*8975f5c5SAndroid Build Coastguard Worker     const bool isStencilTexture    = format == gl::SamplerFormat::Unsigned;
373*8975f5c5SAndroid Build Coastguard Worker     return isStencilTexture;
374*8975f5c5SAndroid Build Coastguard Worker }
375*8975f5c5SAndroid Build Coastguard Worker 
GetDepthStencilAttachmentImageReadLayout(const vk::ImageHelper & image,gl::ShaderType firstShader)376*8975f5c5SAndroid Build Coastguard Worker vk::ImageLayout GetDepthStencilAttachmentImageReadLayout(const vk::ImageHelper &image,
377*8975f5c5SAndroid Build Coastguard Worker                                                          gl::ShaderType firstShader)
378*8975f5c5SAndroid Build Coastguard Worker {
379*8975f5c5SAndroid Build Coastguard Worker     const bool isDepthTexture =
380*8975f5c5SAndroid Build Coastguard Worker         image.hasRenderPassUsageFlag(vk::RenderPassUsage::DepthTextureSampler);
381*8975f5c5SAndroid Build Coastguard Worker     const bool isStencilTexture =
382*8975f5c5SAndroid Build Coastguard Worker         image.hasRenderPassUsageFlag(vk::RenderPassUsage::StencilTextureSampler);
383*8975f5c5SAndroid Build Coastguard Worker 
384*8975f5c5SAndroid Build Coastguard Worker     const bool isDepthReadOnlyAttachment =
385*8975f5c5SAndroid Build Coastguard Worker         image.hasRenderPassUsageFlag(vk::RenderPassUsage::DepthReadOnlyAttachment);
386*8975f5c5SAndroid Build Coastguard Worker     const bool isStencilReadOnlyAttachment =
387*8975f5c5SAndroid Build Coastguard Worker         image.hasRenderPassUsageFlag(vk::RenderPassUsage::StencilReadOnlyAttachment);
388*8975f5c5SAndroid Build Coastguard Worker 
389*8975f5c5SAndroid Build Coastguard Worker     const bool isFS = firstShader == gl::ShaderType::Fragment;
390*8975f5c5SAndroid Build Coastguard Worker 
391*8975f5c5SAndroid Build Coastguard Worker     // Only called when at least one aspect of the image is bound as texture
392*8975f5c5SAndroid Build Coastguard Worker     ASSERT(isDepthTexture || isStencilTexture);
393*8975f5c5SAndroid Build Coastguard Worker 
394*8975f5c5SAndroid Build Coastguard Worker     // Check for feedback loop; this is when depth or stencil is both bound as a texture and is used
395*8975f5c5SAndroid Build Coastguard Worker     // in a non-read-only way as attachment.
396*8975f5c5SAndroid Build Coastguard Worker     if ((isDepthTexture && !isDepthReadOnlyAttachment) ||
397*8975f5c5SAndroid Build Coastguard Worker         (isStencilTexture && !isStencilReadOnlyAttachment))
398*8975f5c5SAndroid Build Coastguard Worker     {
399*8975f5c5SAndroid Build Coastguard Worker         return isFS ? vk::ImageLayout::DepthStencilFragmentShaderFeedback
400*8975f5c5SAndroid Build Coastguard Worker                     : vk::ImageLayout::DepthStencilAllShadersFeedback;
401*8975f5c5SAndroid Build Coastguard Worker     }
402*8975f5c5SAndroid Build Coastguard Worker 
403*8975f5c5SAndroid Build Coastguard Worker     if (isDepthReadOnlyAttachment)
404*8975f5c5SAndroid Build Coastguard Worker     {
405*8975f5c5SAndroid Build Coastguard Worker         if (isStencilReadOnlyAttachment)
406*8975f5c5SAndroid Build Coastguard Worker         {
407*8975f5c5SAndroid Build Coastguard Worker             // Depth read + stencil read
408*8975f5c5SAndroid Build Coastguard Worker             return isFS ? vk::ImageLayout::DepthReadStencilReadFragmentShaderRead
409*8975f5c5SAndroid Build Coastguard Worker                         : vk::ImageLayout::DepthReadStencilReadAllShadersRead;
410*8975f5c5SAndroid Build Coastguard Worker         }
411*8975f5c5SAndroid Build Coastguard Worker         else
412*8975f5c5SAndroid Build Coastguard Worker         {
413*8975f5c5SAndroid Build Coastguard Worker             // Depth read + stencil write
414*8975f5c5SAndroid Build Coastguard Worker             return isFS ? vk::ImageLayout::DepthReadStencilWriteFragmentShaderDepthRead
415*8975f5c5SAndroid Build Coastguard Worker                         : vk::ImageLayout::DepthReadStencilWriteAllShadersDepthRead;
416*8975f5c5SAndroid Build Coastguard Worker         }
417*8975f5c5SAndroid Build Coastguard Worker     }
418*8975f5c5SAndroid Build Coastguard Worker     else
419*8975f5c5SAndroid Build Coastguard Worker     {
420*8975f5c5SAndroid Build Coastguard Worker         if (isStencilReadOnlyAttachment)
421*8975f5c5SAndroid Build Coastguard Worker         {
422*8975f5c5SAndroid Build Coastguard Worker             // Depth write + stencil read
423*8975f5c5SAndroid Build Coastguard Worker             return isFS ? vk::ImageLayout::DepthWriteStencilReadFragmentShaderStencilRead
424*8975f5c5SAndroid Build Coastguard Worker                         : vk::ImageLayout::DepthWriteStencilReadAllShadersStencilRead;
425*8975f5c5SAndroid Build Coastguard Worker         }
426*8975f5c5SAndroid Build Coastguard Worker         else
427*8975f5c5SAndroid Build Coastguard Worker         {
428*8975f5c5SAndroid Build Coastguard Worker             // Depth write + stencil write: This is definitely a feedback loop and is handled above.
429*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
430*8975f5c5SAndroid Build Coastguard Worker             return vk::ImageLayout::DepthStencilAllShadersFeedback;
431*8975f5c5SAndroid Build Coastguard Worker         }
432*8975f5c5SAndroid Build Coastguard Worker     }
433*8975f5c5SAndroid Build Coastguard Worker }
434*8975f5c5SAndroid Build Coastguard Worker 
GetImageReadLayout(TextureVk * textureVk,const gl::ProgramExecutable & executable,size_t textureUnit,PipelineType pipelineType)435*8975f5c5SAndroid Build Coastguard Worker vk::ImageLayout GetImageReadLayout(TextureVk *textureVk,
436*8975f5c5SAndroid Build Coastguard Worker                                    const gl::ProgramExecutable &executable,
437*8975f5c5SAndroid Build Coastguard Worker                                    size_t textureUnit,
438*8975f5c5SAndroid Build Coastguard Worker                                    PipelineType pipelineType)
439*8975f5c5SAndroid Build Coastguard Worker {
440*8975f5c5SAndroid Build Coastguard Worker     vk::ImageHelper &image = textureVk->getImage();
441*8975f5c5SAndroid Build Coastguard Worker 
442*8975f5c5SAndroid Build Coastguard Worker     // If this texture has been bound as image and the current executable program accesses images,
443*8975f5c5SAndroid Build Coastguard Worker     // we consider this image's layout as writeable.
444*8975f5c5SAndroid Build Coastguard Worker     if (textureVk->hasBeenBoundAsImage() && executable.hasImages())
445*8975f5c5SAndroid Build Coastguard Worker     {
446*8975f5c5SAndroid Build Coastguard Worker         return pipelineType == PipelineType::Compute ? vk::ImageLayout::ComputeShaderWrite
447*8975f5c5SAndroid Build Coastguard Worker                                                      : vk::ImageLayout::AllGraphicsShadersWrite;
448*8975f5c5SAndroid Build Coastguard Worker     }
449*8975f5c5SAndroid Build Coastguard Worker 
450*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderBitSet remainingShaderBits =
451*8975f5c5SAndroid Build Coastguard Worker         executable.getSamplerShaderBitsForTextureUnitIndex(textureUnit);
452*8975f5c5SAndroid Build Coastguard Worker     ASSERT(remainingShaderBits.any());
453*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderType firstShader = remainingShaderBits.first();
454*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderType lastShader  = remainingShaderBits.last();
455*8975f5c5SAndroid Build Coastguard Worker     remainingShaderBits.reset(firstShader);
456*8975f5c5SAndroid Build Coastguard Worker     remainingShaderBits.reset(lastShader);
457*8975f5c5SAndroid Build Coastguard Worker 
458*8975f5c5SAndroid Build Coastguard Worker     const bool isFragmentShaderOnly = firstShader == gl::ShaderType::Fragment;
459*8975f5c5SAndroid Build Coastguard Worker     if (isFragmentShaderOnly)
460*8975f5c5SAndroid Build Coastguard Worker     {
461*8975f5c5SAndroid Build Coastguard Worker         ASSERT(remainingShaderBits.none() && lastShader == firstShader);
462*8975f5c5SAndroid Build Coastguard Worker     }
463*8975f5c5SAndroid Build Coastguard Worker 
464*8975f5c5SAndroid Build Coastguard Worker     if (image.hasRenderPassUsageFlag(vk::RenderPassUsage::RenderTargetAttachment))
465*8975f5c5SAndroid Build Coastguard Worker     {
466*8975f5c5SAndroid Build Coastguard Worker         // Right now we set the *TextureSampler flag only when RenderTargetAttachment is set since
467*8975f5c5SAndroid Build Coastguard Worker         // we do not track all textures in the render pass.
468*8975f5c5SAndroid Build Coastguard Worker 
469*8975f5c5SAndroid Build Coastguard Worker         if (image.isDepthOrStencil())
470*8975f5c5SAndroid Build Coastguard Worker         {
471*8975f5c5SAndroid Build Coastguard Worker             if (IsStencilSamplerBinding(executable, textureUnit))
472*8975f5c5SAndroid Build Coastguard Worker             {
473*8975f5c5SAndroid Build Coastguard Worker                 image.setRenderPassUsageFlag(vk::RenderPassUsage::StencilTextureSampler);
474*8975f5c5SAndroid Build Coastguard Worker             }
475*8975f5c5SAndroid Build Coastguard Worker             else
476*8975f5c5SAndroid Build Coastguard Worker             {
477*8975f5c5SAndroid Build Coastguard Worker                 image.setRenderPassUsageFlag(vk::RenderPassUsage::DepthTextureSampler);
478*8975f5c5SAndroid Build Coastguard Worker             }
479*8975f5c5SAndroid Build Coastguard Worker 
480*8975f5c5SAndroid Build Coastguard Worker             return GetDepthStencilAttachmentImageReadLayout(image, firstShader);
481*8975f5c5SAndroid Build Coastguard Worker         }
482*8975f5c5SAndroid Build Coastguard Worker 
483*8975f5c5SAndroid Build Coastguard Worker         image.setRenderPassUsageFlag(vk::RenderPassUsage::ColorTextureSampler);
484*8975f5c5SAndroid Build Coastguard Worker 
485*8975f5c5SAndroid Build Coastguard Worker         return isFragmentShaderOnly ? vk::ImageLayout::ColorWriteFragmentShaderFeedback
486*8975f5c5SAndroid Build Coastguard Worker                                     : vk::ImageLayout::ColorWriteAllShadersFeedback;
487*8975f5c5SAndroid Build Coastguard Worker     }
488*8975f5c5SAndroid Build Coastguard Worker 
489*8975f5c5SAndroid Build Coastguard Worker     if (image.isDepthOrStencil())
490*8975f5c5SAndroid Build Coastguard Worker     {
491*8975f5c5SAndroid Build Coastguard Worker         // We always use a depth-stencil read-only layout for any depth Textures to simplify
492*8975f5c5SAndroid Build Coastguard Worker         // our implementation's handling of depth-stencil read-only mode. We don't have to
493*8975f5c5SAndroid Build Coastguard Worker         // split a RenderPass to transition a depth texture from shader-read to read-only.
494*8975f5c5SAndroid Build Coastguard Worker         // This improves performance in Manhattan. Future optimizations are likely possible
495*8975f5c5SAndroid Build Coastguard Worker         // here including using specialized barriers without breaking the RenderPass.
496*8975f5c5SAndroid Build Coastguard Worker         return isFragmentShaderOnly ? vk::ImageLayout::DepthReadStencilReadFragmentShaderRead
497*8975f5c5SAndroid Build Coastguard Worker                                     : vk::ImageLayout::DepthReadStencilReadAllShadersRead;
498*8975f5c5SAndroid Build Coastguard Worker     }
499*8975f5c5SAndroid Build Coastguard Worker 
500*8975f5c5SAndroid Build Coastguard Worker     // We barrier against either:
501*8975f5c5SAndroid Build Coastguard Worker     // - Vertex only
502*8975f5c5SAndroid Build Coastguard Worker     // - Fragment only
503*8975f5c5SAndroid Build Coastguard Worker     // - Pre-fragment only (vertex, geometry and tessellation together)
504*8975f5c5SAndroid Build Coastguard Worker     if (remainingShaderBits.any() || firstShader != lastShader)
505*8975f5c5SAndroid Build Coastguard Worker     {
506*8975f5c5SAndroid Build Coastguard Worker         return lastShader == gl::ShaderType::Fragment ? vk::ImageLayout::AllGraphicsShadersReadOnly
507*8975f5c5SAndroid Build Coastguard Worker                                                       : vk::ImageLayout::PreFragmentShadersReadOnly;
508*8975f5c5SAndroid Build Coastguard Worker     }
509*8975f5c5SAndroid Build Coastguard Worker 
510*8975f5c5SAndroid Build Coastguard Worker     return kShaderReadOnlyImageLayouts[firstShader];
511*8975f5c5SAndroid Build Coastguard Worker }
512*8975f5c5SAndroid Build Coastguard Worker 
GetImageWriteLayoutAndSubresource(const gl::ImageUnit & imageUnit,vk::ImageHelper & image,gl::ShaderBitSet shaderStages,gl::LevelIndex * levelOut,uint32_t * layerStartOut,uint32_t * layerCountOut)513*8975f5c5SAndroid Build Coastguard Worker vk::ImageLayout GetImageWriteLayoutAndSubresource(const gl::ImageUnit &imageUnit,
514*8975f5c5SAndroid Build Coastguard Worker                                                   vk::ImageHelper &image,
515*8975f5c5SAndroid Build Coastguard Worker                                                   gl::ShaderBitSet shaderStages,
516*8975f5c5SAndroid Build Coastguard Worker                                                   gl::LevelIndex *levelOut,
517*8975f5c5SAndroid Build Coastguard Worker                                                   uint32_t *layerStartOut,
518*8975f5c5SAndroid Build Coastguard Worker                                                   uint32_t *layerCountOut)
519*8975f5c5SAndroid Build Coastguard Worker {
520*8975f5c5SAndroid Build Coastguard Worker     *levelOut = gl::LevelIndex(static_cast<uint32_t>(imageUnit.level));
521*8975f5c5SAndroid Build Coastguard Worker 
522*8975f5c5SAndroid Build Coastguard Worker     *layerStartOut = 0;
523*8975f5c5SAndroid Build Coastguard Worker     *layerCountOut = image.getLayerCount();
524*8975f5c5SAndroid Build Coastguard Worker     if (imageUnit.layered)
525*8975f5c5SAndroid Build Coastguard Worker     {
526*8975f5c5SAndroid Build Coastguard Worker         *layerStartOut = imageUnit.layered;
527*8975f5c5SAndroid Build Coastguard Worker         *layerCountOut = 1;
528*8975f5c5SAndroid Build Coastguard Worker     }
529*8975f5c5SAndroid Build Coastguard Worker 
530*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderType firstShader = shaderStages.first();
531*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderType lastShader  = shaderStages.last();
532*8975f5c5SAndroid Build Coastguard Worker     shaderStages.reset(firstShader);
533*8975f5c5SAndroid Build Coastguard Worker     shaderStages.reset(lastShader);
534*8975f5c5SAndroid Build Coastguard Worker     // We barrier against either:
535*8975f5c5SAndroid Build Coastguard Worker     // - Vertex only
536*8975f5c5SAndroid Build Coastguard Worker     // - Fragment only
537*8975f5c5SAndroid Build Coastguard Worker     // - Pre-fragment only (vertex, geometry and tessellation together)
538*8975f5c5SAndroid Build Coastguard Worker     if (shaderStages.any() || firstShader != lastShader)
539*8975f5c5SAndroid Build Coastguard Worker     {
540*8975f5c5SAndroid Build Coastguard Worker         return lastShader == gl::ShaderType::Fragment ? vk::ImageLayout::AllGraphicsShadersWrite
541*8975f5c5SAndroid Build Coastguard Worker                                                       : vk::ImageLayout::PreFragmentShadersWrite;
542*8975f5c5SAndroid Build Coastguard Worker     }
543*8975f5c5SAndroid Build Coastguard Worker 
544*8975f5c5SAndroid Build Coastguard Worker     return kShaderWriteImageLayouts[firstShader];
545*8975f5c5SAndroid Build Coastguard Worker }
546*8975f5c5SAndroid Build Coastguard Worker 
547*8975f5c5SAndroid Build Coastguard Worker template <typename CommandBufferT>
OnTextureBufferRead(vk::BufferHelper * buffer,gl::ShaderBitSet stages,CommandBufferT * commandBufferHelper)548*8975f5c5SAndroid Build Coastguard Worker void OnTextureBufferRead(vk::BufferHelper *buffer,
549*8975f5c5SAndroid Build Coastguard Worker                          gl::ShaderBitSet stages,
550*8975f5c5SAndroid Build Coastguard Worker                          CommandBufferT *commandBufferHelper)
551*8975f5c5SAndroid Build Coastguard Worker {
552*8975f5c5SAndroid Build Coastguard Worker     ASSERT(stages.any());
553*8975f5c5SAndroid Build Coastguard Worker 
554*8975f5c5SAndroid Build Coastguard Worker     // TODO: accept multiple stages in bufferRead.  http://anglebug.com/42262235
555*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType stage : stages)
556*8975f5c5SAndroid Build Coastguard Worker     {
557*8975f5c5SAndroid Build Coastguard Worker         // Note: if another range of the same buffer is simultaneously used for storage,
558*8975f5c5SAndroid Build Coastguard Worker         // such as for transform feedback output, or SSBO, unnecessary barriers can be
559*8975f5c5SAndroid Build Coastguard Worker         // generated.
560*8975f5c5SAndroid Build Coastguard Worker         commandBufferHelper->bufferRead(VK_ACCESS_SHADER_READ_BIT, vk::GetPipelineStage(stage),
561*8975f5c5SAndroid Build Coastguard Worker                                         buffer);
562*8975f5c5SAndroid Build Coastguard Worker     }
563*8975f5c5SAndroid Build Coastguard Worker }
564*8975f5c5SAndroid Build Coastguard Worker 
OnImageBufferWrite(BufferVk * bufferVk,gl::ShaderBitSet stages,vk::CommandBufferHelperCommon * commandBufferHelper)565*8975f5c5SAndroid Build Coastguard Worker void OnImageBufferWrite(BufferVk *bufferVk,
566*8975f5c5SAndroid Build Coastguard Worker                         gl::ShaderBitSet stages,
567*8975f5c5SAndroid Build Coastguard Worker                         vk::CommandBufferHelperCommon *commandBufferHelper)
568*8975f5c5SAndroid Build Coastguard Worker {
569*8975f5c5SAndroid Build Coastguard Worker     vk::BufferHelper &buffer = bufferVk->getBuffer();
570*8975f5c5SAndroid Build Coastguard Worker 
571*8975f5c5SAndroid Build Coastguard Worker     // TODO: accept multiple stages in bufferWrite.  http://anglebug.com/42262235
572*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType stage : stages)
573*8975f5c5SAndroid Build Coastguard Worker     {
574*8975f5c5SAndroid Build Coastguard Worker         commandBufferHelper->bufferWrite(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
575*8975f5c5SAndroid Build Coastguard Worker                                          vk::GetPipelineStage(stage), &buffer);
576*8975f5c5SAndroid Build Coastguard Worker     }
577*8975f5c5SAndroid Build Coastguard Worker }
578*8975f5c5SAndroid Build Coastguard Worker 
579*8975f5c5SAndroid Build Coastguard Worker constexpr angle::PackedEnumMap<RenderPassClosureReason, const char *> kRenderPassClosureReason = {{
580*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::AlreadySpecifiedElsewhere, nullptr},
581*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::ContextDestruction, "Render pass closed due to context destruction"},
582*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::ContextChange, "Render pass closed due to context change"},
583*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::GLFlush, "Render pass closed due to glFlush()"},
584*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::GLFinish, "Render pass closed due to glFinish()"},
585*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::EGLSwapBuffers, "Render pass closed due to eglSwapBuffers()"},
586*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::EGLWaitClient, "Render pass closed due to eglWaitClient()"},
587*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::SurfaceUnMakeCurrent,
588*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to onSurfaceUnMakeCurrent()"},
589*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::FramebufferBindingChange,
590*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to framebuffer binding change"},
591*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::FramebufferChange, "Render pass closed due to framebuffer change"},
592*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::NewRenderPass,
593*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to starting a new render pass"},
594*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::BufferUseThenXfbWrite,
595*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to buffer use as transform feedback output after prior use in render "
596*8975f5c5SAndroid Build Coastguard Worker      "pass"},
597*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::XfbWriteThenVertexIndexBuffer,
598*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to transform feedback buffer use as vertex/index input"},
599*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::XfbWriteThenIndirectDrawBuffer,
600*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to indirect draw buffer previously used as transform feedback output "
601*8975f5c5SAndroid Build Coastguard Worker      "in render pass"},
602*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::XfbResumeAfterDrawBasedClear,
603*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to transform feedback resume after clear through draw"},
604*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::DepthStencilUseInFeedbackLoop,
605*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to depth/stencil attachment use under feedback loop"},
606*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::DepthStencilWriteAfterFeedbackLoop,
607*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to depth/stencil attachment write after feedback loop"},
608*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::PipelineBindWhileXfbActive,
609*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to graphics pipeline change while transform feedback is active"},
610*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::BufferWriteThenMap,
611*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to mapping buffer being written to by said render pass"},
612*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::BufferWriteThenOutOfRPRead,
613*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to non-render-pass read of buffer that was written to in render pass"},
614*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::BufferUseThenOutOfRPWrite,
615*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to non-render-pass write of buffer that was used in render pass"},
616*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::ImageUseThenOutOfRPRead,
617*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to non-render-pass read of image that was used in render pass"},
618*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::ImageUseThenOutOfRPWrite,
619*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to non-render-pass write of image that was used in render pass"},
620*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::XfbWriteThenComputeRead,
621*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to compute read of buffer previously used as transform feedback "
622*8975f5c5SAndroid Build Coastguard Worker      "output in render pass"},
623*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::XfbWriteThenIndirectDispatchBuffer,
624*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to indirect dispatch buffer previously used as transform feedback "
625*8975f5c5SAndroid Build Coastguard Worker      "output in render pass"},
626*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::ImageAttachmentThenComputeRead,
627*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to compute read of image previously used as framebuffer attachment in "
628*8975f5c5SAndroid Build Coastguard Worker      "render pass"},
629*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::GetQueryResult, "Render pass closed due to getting query result"},
630*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::BeginNonRenderPassQuery,
631*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to non-render-pass query begin"},
632*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::EndNonRenderPassQuery,
633*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to non-render-pass query end"},
634*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::TimestampQuery, "Render pass closed due to timestamp query"},
635*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::EndRenderPassQuery,
636*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to switch from query enabled draw to query disabled draw"},
637*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::GLReadPixels, "Render pass closed due to glReadPixels()"},
638*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::BufferUseThenReleaseToExternal,
639*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to buffer (used by render pass) release to external"},
640*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::ImageUseThenReleaseToExternal,
641*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to image (used by render pass) release to external"},
642*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::BufferInUseWhenSynchronizedMap,
643*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to mapping buffer in use by GPU without GL_MAP_UNSYNCHRONIZED_BIT"},
644*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::GLMemoryBarrierThenStorageResource,
645*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to glMemoryBarrier before storage output in render pass"},
646*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::StorageResourceUseThenGLMemoryBarrier,
647*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to glMemoryBarrier after storage output in render pass"},
648*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::ExternalSemaphoreSignal,
649*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to external semaphore signal"},
650*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::SyncObjectInit, "Render pass closed due to sync object insertion"},
651*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::SyncObjectWithFdInit,
652*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to sync object with fd insertion"},
653*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::SyncObjectClientWait,
654*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to sync object client wait"},
655*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::SyncObjectServerWait,
656*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to sync object server wait"},
657*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::SyncObjectGetStatus,
658*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to sync object get status"},
659*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::XfbPause, "Render pass closed due to transform feedback pause"},
660*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::FramebufferFetchEmulation,
661*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to framebuffer fetch emulation"},
662*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::GenerateMipmapOnCPU,
663*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to fallback to CPU when generating mipmaps"},
664*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::CopyTextureOnCPU,
665*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to fallback to CPU when copying texture"},
666*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::TextureReformatToRenderable,
667*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to reformatting texture to a renderable fallback"},
668*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::DeviceLocalBufferMap,
669*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed due to mapping device local buffer"},
670*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::PrepareForBlit, "Render pass closed prior to draw-based blit"},
671*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::PrepareForImageCopy,
672*8975f5c5SAndroid Build Coastguard Worker      "Render pass closed prior to draw-based image copy"},
673*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::TemporaryForImageClear,
674*8975f5c5SAndroid Build Coastguard Worker      "Temporary render pass used for image clear closed"},
675*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::TemporaryForImageCopy,
676*8975f5c5SAndroid Build Coastguard Worker      "Temporary render pass used for image copy closed"},
677*8975f5c5SAndroid Build Coastguard Worker     {RenderPassClosureReason::TemporaryForOverlayDraw,
678*8975f5c5SAndroid Build Coastguard Worker      "Temporary render pass used for overlay draw closed"},
679*8975f5c5SAndroid Build Coastguard Worker }};
680*8975f5c5SAndroid Build Coastguard Worker 
GetLocalDependencyFlags(ContextVk * contextVk)681*8975f5c5SAndroid Build Coastguard Worker VkDependencyFlags GetLocalDependencyFlags(ContextVk *contextVk)
682*8975f5c5SAndroid Build Coastguard Worker {
683*8975f5c5SAndroid Build Coastguard Worker     VkDependencyFlags dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
684*8975f5c5SAndroid Build Coastguard Worker     if (contextVk->getCurrentViewCount() > 0)
685*8975f5c5SAndroid Build Coastguard Worker     {
686*8975f5c5SAndroid Build Coastguard Worker         dependencyFlags |= VK_DEPENDENCY_VIEW_LOCAL_BIT;
687*8975f5c5SAndroid Build Coastguard Worker     }
688*8975f5c5SAndroid Build Coastguard Worker     return dependencyFlags;
689*8975f5c5SAndroid Build Coastguard Worker }
690*8975f5c5SAndroid Build Coastguard Worker 
BlendModeSupportsDither(const ContextVk * contextVk,size_t colorIndex)691*8975f5c5SAndroid Build Coastguard Worker bool BlendModeSupportsDither(const ContextVk *contextVk, size_t colorIndex)
692*8975f5c5SAndroid Build Coastguard Worker {
693*8975f5c5SAndroid Build Coastguard Worker     const gl::State &state = contextVk->getState();
694*8975f5c5SAndroid Build Coastguard Worker 
695*8975f5c5SAndroid Build Coastguard Worker     // Specific combinations of color blend modes are known to work with our dithering emulation.
696*8975f5c5SAndroid Build Coastguard Worker     // Note we specifically don't check alpha blend, as dither isn't applied to alpha.
697*8975f5c5SAndroid Build Coastguard Worker     // See http://b/232574868 for more discussion and reasoning.
698*8975f5c5SAndroid Build Coastguard Worker     gl::BlendFactorType srcBlendFactor = state.getBlendStateExt().getSrcColorIndexed(colorIndex);
699*8975f5c5SAndroid Build Coastguard Worker     gl::BlendFactorType dstBlendFactor = state.getBlendStateExt().getDstColorIndexed(colorIndex);
700*8975f5c5SAndroid Build Coastguard Worker 
701*8975f5c5SAndroid Build Coastguard Worker     const bool ditheringCompatibleBlendFactors =
702*8975f5c5SAndroid Build Coastguard Worker         (srcBlendFactor == gl::BlendFactorType::SrcAlpha &&
703*8975f5c5SAndroid Build Coastguard Worker          dstBlendFactor == gl::BlendFactorType::OneMinusSrcAlpha);
704*8975f5c5SAndroid Build Coastguard Worker 
705*8975f5c5SAndroid Build Coastguard Worker     const bool allowAdditionalBlendFactors =
706*8975f5c5SAndroid Build Coastguard Worker         contextVk->getFeatures().enableAdditionalBlendFactorsForDithering.enabled &&
707*8975f5c5SAndroid Build Coastguard Worker         (srcBlendFactor == gl::BlendFactorType::One &&
708*8975f5c5SAndroid Build Coastguard Worker          dstBlendFactor == gl::BlendFactorType::OneMinusSrcAlpha);
709*8975f5c5SAndroid Build Coastguard Worker 
710*8975f5c5SAndroid Build Coastguard Worker     return ditheringCompatibleBlendFactors || allowAdditionalBlendFactors;
711*8975f5c5SAndroid Build Coastguard Worker }
712*8975f5c5SAndroid Build Coastguard Worker 
ShouldUseGraphicsDriverUniformsExtended(const vk::Context * context)713*8975f5c5SAndroid Build Coastguard Worker bool ShouldUseGraphicsDriverUniformsExtended(const vk::Context *context)
714*8975f5c5SAndroid Build Coastguard Worker {
715*8975f5c5SAndroid Build Coastguard Worker     return context->getFeatures().emulateTransformFeedback.enabled;
716*8975f5c5SAndroid Build Coastguard Worker }
717*8975f5c5SAndroid Build Coastguard Worker 
IsAnySamplesQuery(gl::QueryType type)718*8975f5c5SAndroid Build Coastguard Worker bool IsAnySamplesQuery(gl::QueryType type)
719*8975f5c5SAndroid Build Coastguard Worker {
720*8975f5c5SAndroid Build Coastguard Worker     return type == gl::QueryType::AnySamples || type == gl::QueryType::AnySamplesConservative;
721*8975f5c5SAndroid Build Coastguard Worker }
722*8975f5c5SAndroid Build Coastguard Worker 
723*8975f5c5SAndroid Build Coastguard Worker enum class GraphicsPipelineSubsetRenderPass
724*8975f5c5SAndroid Build Coastguard Worker {
725*8975f5c5SAndroid Build Coastguard Worker     Unused,
726*8975f5c5SAndroid Build Coastguard Worker     Required,
727*8975f5c5SAndroid Build Coastguard Worker };
728*8975f5c5SAndroid Build Coastguard Worker 
729*8975f5c5SAndroid Build Coastguard Worker template <typename Cache>
CreateGraphicsPipelineSubset(ContextVk * contextVk,const vk::GraphicsPipelineDesc & desc,vk::GraphicsPipelineTransitionBits transition,GraphicsPipelineSubsetRenderPass renderPass,Cache * cache,vk::PipelineCacheAccess * pipelineCache,vk::PipelineHelper ** pipelineOut)730*8975f5c5SAndroid Build Coastguard Worker angle::Result CreateGraphicsPipelineSubset(ContextVk *contextVk,
731*8975f5c5SAndroid Build Coastguard Worker                                            const vk::GraphicsPipelineDesc &desc,
732*8975f5c5SAndroid Build Coastguard Worker                                            vk::GraphicsPipelineTransitionBits transition,
733*8975f5c5SAndroid Build Coastguard Worker                                            GraphicsPipelineSubsetRenderPass renderPass,
734*8975f5c5SAndroid Build Coastguard Worker                                            Cache *cache,
735*8975f5c5SAndroid Build Coastguard Worker                                            vk::PipelineCacheAccess *pipelineCache,
736*8975f5c5SAndroid Build Coastguard Worker                                            vk::PipelineHelper **pipelineOut)
737*8975f5c5SAndroid Build Coastguard Worker {
738*8975f5c5SAndroid Build Coastguard Worker     const vk::PipelineLayout unusedPipelineLayout;
739*8975f5c5SAndroid Build Coastguard Worker     const vk::ShaderModuleMap unusedShaders;
740*8975f5c5SAndroid Build Coastguard Worker     const vk::SpecializationConstants unusedSpecConsts = {};
741*8975f5c5SAndroid Build Coastguard Worker 
742*8975f5c5SAndroid Build Coastguard Worker     if (*pipelineOut != nullptr && !transition.any())
743*8975f5c5SAndroid Build Coastguard Worker     {
744*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
745*8975f5c5SAndroid Build Coastguard Worker     }
746*8975f5c5SAndroid Build Coastguard Worker 
747*8975f5c5SAndroid Build Coastguard Worker     if (*pipelineOut != nullptr)
748*8975f5c5SAndroid Build Coastguard Worker     {
749*8975f5c5SAndroid Build Coastguard Worker         ASSERT((*pipelineOut)->valid());
750*8975f5c5SAndroid Build Coastguard Worker         if ((*pipelineOut)->findTransition(transition, desc, pipelineOut))
751*8975f5c5SAndroid Build Coastguard Worker         {
752*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Continue;
753*8975f5c5SAndroid Build Coastguard Worker         }
754*8975f5c5SAndroid Build Coastguard Worker     }
755*8975f5c5SAndroid Build Coastguard Worker 
756*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineHelper *oldPipeline = *pipelineOut;
757*8975f5c5SAndroid Build Coastguard Worker 
758*8975f5c5SAndroid Build Coastguard Worker     const vk::GraphicsPipelineDesc *descPtr = nullptr;
759*8975f5c5SAndroid Build Coastguard Worker     if (!cache->getPipeline(desc, &descPtr, pipelineOut))
760*8975f5c5SAndroid Build Coastguard Worker     {
761*8975f5c5SAndroid Build Coastguard Worker         const vk::RenderPass unusedRenderPass;
762*8975f5c5SAndroid Build Coastguard Worker         const vk::RenderPass *compatibleRenderPass = &unusedRenderPass;
763*8975f5c5SAndroid Build Coastguard Worker         if (renderPass == GraphicsPipelineSubsetRenderPass::Required)
764*8975f5c5SAndroid Build Coastguard Worker         {
765*8975f5c5SAndroid Build Coastguard Worker             // Pull in a compatible RenderPass if used by this subset.
766*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(contextVk->getCompatibleRenderPass(desc.getRenderPassDesc(),
767*8975f5c5SAndroid Build Coastguard Worker                                                          &compatibleRenderPass));
768*8975f5c5SAndroid Build Coastguard Worker         }
769*8975f5c5SAndroid Build Coastguard Worker 
770*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(cache->createPipeline(contextVk, pipelineCache, *compatibleRenderPass,
771*8975f5c5SAndroid Build Coastguard Worker                                         unusedPipelineLayout, unusedShaders, unusedSpecConsts,
772*8975f5c5SAndroid Build Coastguard Worker                                         PipelineSource::Draw, desc, &descPtr, pipelineOut));
773*8975f5c5SAndroid Build Coastguard Worker     }
774*8975f5c5SAndroid Build Coastguard Worker 
775*8975f5c5SAndroid Build Coastguard Worker     if (oldPipeline)
776*8975f5c5SAndroid Build Coastguard Worker     {
777*8975f5c5SAndroid Build Coastguard Worker         oldPipeline->addTransition(transition, descPtr, *pipelineOut);
778*8975f5c5SAndroid Build Coastguard Worker     }
779*8975f5c5SAndroid Build Coastguard Worker 
780*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
781*8975f5c5SAndroid Build Coastguard Worker }
782*8975f5c5SAndroid Build Coastguard Worker 
QueueSerialsHaveDifferentIndexOrSmaller(const QueueSerial & queueSerial1,const QueueSerial & queueSerial2)783*8975f5c5SAndroid Build Coastguard Worker bool QueueSerialsHaveDifferentIndexOrSmaller(const QueueSerial &queueSerial1,
784*8975f5c5SAndroid Build Coastguard Worker                                              const QueueSerial &queueSerial2)
785*8975f5c5SAndroid Build Coastguard Worker {
786*8975f5c5SAndroid Build Coastguard Worker     return queueSerial1.getIndex() != queueSerial2.getIndex() || queueSerial1 < queueSerial2;
787*8975f5c5SAndroid Build Coastguard Worker }
788*8975f5c5SAndroid Build Coastguard Worker 
UpdateImagesWithSharedCacheKey(const gl::ActiveTextureArray<TextureVk * > & activeImages,const std::vector<gl::ImageBinding> & imageBindings,const vk::SharedDescriptorSetCacheKey & sharedCacheKey)789*8975f5c5SAndroid Build Coastguard Worker void UpdateImagesWithSharedCacheKey(const gl::ActiveTextureArray<TextureVk *> &activeImages,
790*8975f5c5SAndroid Build Coastguard Worker                                     const std::vector<gl::ImageBinding> &imageBindings,
791*8975f5c5SAndroid Build Coastguard Worker                                     const vk::SharedDescriptorSetCacheKey &sharedCacheKey)
792*8975f5c5SAndroid Build Coastguard Worker {
793*8975f5c5SAndroid Build Coastguard Worker     for (const gl::ImageBinding &imageBinding : imageBindings)
794*8975f5c5SAndroid Build Coastguard Worker     {
795*8975f5c5SAndroid Build Coastguard Worker         uint32_t arraySize = static_cast<uint32_t>(imageBinding.boundImageUnits.size());
796*8975f5c5SAndroid Build Coastguard Worker         for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
797*8975f5c5SAndroid Build Coastguard Worker         {
798*8975f5c5SAndroid Build Coastguard Worker             GLuint imageUnit = imageBinding.boundImageUnits[arrayElement];
799*8975f5c5SAndroid Build Coastguard Worker             // For simplicity, we do not check if uniform is active or duplicate. The worst case is
800*8975f5c5SAndroid Build Coastguard Worker             // we unnecessarily delete the cache entry when image bound to inactive uniform is
801*8975f5c5SAndroid Build Coastguard Worker             // destroyed.
802*8975f5c5SAndroid Build Coastguard Worker             activeImages[imageUnit]->onNewDescriptorSet(sharedCacheKey);
803*8975f5c5SAndroid Build Coastguard Worker         }
804*8975f5c5SAndroid Build Coastguard Worker     }
805*8975f5c5SAndroid Build Coastguard Worker }
806*8975f5c5SAndroid Build Coastguard Worker 
UpdateBufferWithSharedCacheKey(const gl::OffsetBindingPointer<gl::Buffer> & bufferBinding,VkDescriptorType descriptorType,const vk::SharedDescriptorSetCacheKey & sharedCacheKey)807*8975f5c5SAndroid Build Coastguard Worker void UpdateBufferWithSharedCacheKey(const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding,
808*8975f5c5SAndroid Build Coastguard Worker                                     VkDescriptorType descriptorType,
809*8975f5c5SAndroid Build Coastguard Worker                                     const vk::SharedDescriptorSetCacheKey &sharedCacheKey)
810*8975f5c5SAndroid Build Coastguard Worker {
811*8975f5c5SAndroid Build Coastguard Worker     if (bufferBinding.get() != nullptr)
812*8975f5c5SAndroid Build Coastguard Worker     {
813*8975f5c5SAndroid Build Coastguard Worker         // For simplicity, we do not check if uniform is active or duplicate. The worst case is
814*8975f5c5SAndroid Build Coastguard Worker         // we unnecessarily delete the cache entry when buffer bound to inactive uniform is
815*8975f5c5SAndroid Build Coastguard Worker         // destroyed.
816*8975f5c5SAndroid Build Coastguard Worker         BufferVk *bufferVk             = vk::GetImpl(bufferBinding.get());
817*8975f5c5SAndroid Build Coastguard Worker         vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
818*8975f5c5SAndroid Build Coastguard Worker         if (vk::IsDynamicDescriptor(descriptorType))
819*8975f5c5SAndroid Build Coastguard Worker         {
820*8975f5c5SAndroid Build Coastguard Worker             bufferHelper.getBufferBlock()->onNewDescriptorSet(sharedCacheKey);
821*8975f5c5SAndroid Build Coastguard Worker         }
822*8975f5c5SAndroid Build Coastguard Worker         else
823*8975f5c5SAndroid Build Coastguard Worker         {
824*8975f5c5SAndroid Build Coastguard Worker             bufferHelper.onNewDescriptorSet(sharedCacheKey);
825*8975f5c5SAndroid Build Coastguard Worker         }
826*8975f5c5SAndroid Build Coastguard Worker     }
827*8975f5c5SAndroid Build Coastguard Worker }
828*8975f5c5SAndroid Build Coastguard Worker 
GenerateTextureUnitSamplerIndexMap(const std::vector<GLuint> & samplerBoundTextureUnits,std::unordered_map<size_t,uint32_t> * textureUnitSamplerIndexMapOut)829*8975f5c5SAndroid Build Coastguard Worker void GenerateTextureUnitSamplerIndexMap(
830*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLuint> &samplerBoundTextureUnits,
831*8975f5c5SAndroid Build Coastguard Worker     std::unordered_map<size_t, uint32_t> *textureUnitSamplerIndexMapOut)
832*8975f5c5SAndroid Build Coastguard Worker {
833*8975f5c5SAndroid Build Coastguard Worker     // Create a map of textureUnit <-> samplerIndex
834*8975f5c5SAndroid Build Coastguard Worker     for (size_t samplerIndex = 0; samplerIndex < samplerBoundTextureUnits.size(); samplerIndex++)
835*8975f5c5SAndroid Build Coastguard Worker     {
836*8975f5c5SAndroid Build Coastguard Worker         textureUnitSamplerIndexMapOut->insert(
837*8975f5c5SAndroid Build Coastguard Worker             {samplerBoundTextureUnits[samplerIndex], static_cast<uint32_t>(samplerIndex)});
838*8975f5c5SAndroid Build Coastguard Worker     }
839*8975f5c5SAndroid Build Coastguard Worker }
840*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
841*8975f5c5SAndroid Build Coastguard Worker 
flushDescriptorSetUpdates()842*8975f5c5SAndroid Build Coastguard Worker void ContextVk::flushDescriptorSetUpdates()
843*8975f5c5SAndroid Build Coastguard Worker {
844*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.writeDescriptorSets +=
845*8975f5c5SAndroid Build Coastguard Worker         mShareGroupVk->getUpdateDescriptorSetsBuilder()->flushDescriptorSetUpdates(getDevice());
846*8975f5c5SAndroid Build Coastguard Worker }
847*8975f5c5SAndroid Build Coastguard Worker 
onRenderPassFinished(RenderPassClosureReason reason)848*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE void ContextVk::onRenderPassFinished(RenderPassClosureReason reason)
849*8975f5c5SAndroid Build Coastguard Worker {
850*8975f5c5SAndroid Build Coastguard Worker     if (mRenderPassCommandBuffer != nullptr)
851*8975f5c5SAndroid Build Coastguard Worker     {
852*8975f5c5SAndroid Build Coastguard Worker         pauseRenderPassQueriesIfActive();
853*8975f5c5SAndroid Build Coastguard Worker 
854*8975f5c5SAndroid Build Coastguard Worker         // If reason is specified, add it to the command buffer right before ending the render pass,
855*8975f5c5SAndroid Build Coastguard Worker         // so it will show up in GPU debuggers.
856*8975f5c5SAndroid Build Coastguard Worker         const char *reasonText = kRenderPassClosureReason[reason];
857*8975f5c5SAndroid Build Coastguard Worker         if (reasonText)
858*8975f5c5SAndroid Build Coastguard Worker         {
859*8975f5c5SAndroid Build Coastguard Worker             insertEventMarkerImpl(GL_DEBUG_SOURCE_API, reasonText);
860*8975f5c5SAndroid Build Coastguard Worker         }
861*8975f5c5SAndroid Build Coastguard Worker 
862*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommandBuffer = nullptr;
863*8975f5c5SAndroid Build Coastguard Worker 
864*8975f5c5SAndroid Build Coastguard Worker         // Restart at subpass 0.
865*8975f5c5SAndroid Build Coastguard Worker         mGraphicsPipelineDesc->resetSubpass(&mGraphicsPipelineTransition);
866*8975f5c5SAndroid Build Coastguard Worker     }
867*8975f5c5SAndroid Build Coastguard Worker 
868*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits.set(DIRTY_BIT_RENDER_PASS);
869*8975f5c5SAndroid Build Coastguard Worker }
870*8975f5c5SAndroid Build Coastguard Worker 
871*8975f5c5SAndroid Build Coastguard Worker // ContextVk implementation.
ContextVk(const gl::State & state,gl::ErrorSet * errorSet,vk::Renderer * renderer)872*8975f5c5SAndroid Build Coastguard Worker ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, vk::Renderer *renderer)
873*8975f5c5SAndroid Build Coastguard Worker     : ContextImpl(state, errorSet),
874*8975f5c5SAndroid Build Coastguard Worker       vk::Context(renderer),
875*8975f5c5SAndroid Build Coastguard Worker       mGraphicsDirtyBitHandlers{},
876*8975f5c5SAndroid Build Coastguard Worker       mComputeDirtyBitHandlers{},
877*8975f5c5SAndroid Build Coastguard Worker       mRenderPassCommandBuffer(nullptr),
878*8975f5c5SAndroid Build Coastguard Worker       mCurrentGraphicsPipeline(nullptr),
879*8975f5c5SAndroid Build Coastguard Worker       mCurrentGraphicsPipelineShaders(nullptr),
880*8975f5c5SAndroid Build Coastguard Worker       mCurrentGraphicsPipelineVertexInput(nullptr),
881*8975f5c5SAndroid Build Coastguard Worker       mCurrentGraphicsPipelineFragmentOutput(nullptr),
882*8975f5c5SAndroid Build Coastguard Worker       mCurrentComputePipeline(nullptr),
883*8975f5c5SAndroid Build Coastguard Worker       mCurrentDrawMode(gl::PrimitiveMode::InvalidEnum),
884*8975f5c5SAndroid Build Coastguard Worker       mCurrentWindowSurface(nullptr),
885*8975f5c5SAndroid Build Coastguard Worker       mCurrentRotationDrawFramebuffer(SurfaceRotation::Identity),
886*8975f5c5SAndroid Build Coastguard Worker       mCurrentRotationReadFramebuffer(SurfaceRotation::Identity),
887*8975f5c5SAndroid Build Coastguard Worker       mActiveRenderPassQueries{},
888*8975f5c5SAndroid Build Coastguard Worker       mLastIndexBufferOffset(nullptr),
889*8975f5c5SAndroid Build Coastguard Worker       mCurrentIndexBuffer(nullptr),
890*8975f5c5SAndroid Build Coastguard Worker       mCurrentIndexBufferOffset(0),
891*8975f5c5SAndroid Build Coastguard Worker       mCurrentDrawElementsType(gl::DrawElementsType::InvalidEnum),
892*8975f5c5SAndroid Build Coastguard Worker       mXfbBaseVertex(0),
893*8975f5c5SAndroid Build Coastguard Worker       mXfbVertexCountPerInstance(0),
894*8975f5c5SAndroid Build Coastguard Worker       mClearColorValue{},
895*8975f5c5SAndroid Build Coastguard Worker       mClearDepthStencilValue{},
896*8975f5c5SAndroid Build Coastguard Worker       mClearColorMasks(0),
897*8975f5c5SAndroid Build Coastguard Worker       mDeferredMemoryBarriers(0),
898*8975f5c5SAndroid Build Coastguard Worker       mFlipYForCurrentSurface(false),
899*8975f5c5SAndroid Build Coastguard Worker       mFlipViewportForDrawFramebuffer(false),
900*8975f5c5SAndroid Build Coastguard Worker       mFlipViewportForReadFramebuffer(false),
901*8975f5c5SAndroid Build Coastguard Worker       mIsAnyHostVisibleBufferWritten(false),
902*8975f5c5SAndroid Build Coastguard Worker       mCurrentQueueSerialIndex(kInvalidQueueSerialIndex),
903*8975f5c5SAndroid Build Coastguard Worker       mOutsideRenderPassCommands(nullptr),
904*8975f5c5SAndroid Build Coastguard Worker       mRenderPassCommands(nullptr),
905*8975f5c5SAndroid Build Coastguard Worker       mQueryEventType(GraphicsEventCmdBuf::NotInQueryCmd),
906*8975f5c5SAndroid Build Coastguard Worker       mGpuEventsEnabled(false),
907*8975f5c5SAndroid Build Coastguard Worker       mPrimaryBufferEventCounter(0),
908*8975f5c5SAndroid Build Coastguard Worker       mHasDeferredFlush(false),
909*8975f5c5SAndroid Build Coastguard Worker       mHasAnyCommandsPendingSubmission(false),
910*8975f5c5SAndroid Build Coastguard Worker       mIsInColorFramebufferFetchMode(false),
911*8975f5c5SAndroid Build Coastguard Worker       mAllowRenderPassToReactivate(true),
912*8975f5c5SAndroid Build Coastguard Worker       mTotalBufferToImageCopySize(0),
913*8975f5c5SAndroid Build Coastguard Worker       mEstimatedPendingImageGarbageSize(0),
914*8975f5c5SAndroid Build Coastguard Worker       mHasWaitSemaphoresPendingSubmission(false),
915*8975f5c5SAndroid Build Coastguard Worker       mGpuClockSync{std::numeric_limits<double>::max(), std::numeric_limits<double>::max()},
916*8975f5c5SAndroid Build Coastguard Worker       mGpuEventTimestampOrigin(0),
917*8975f5c5SAndroid Build Coastguard Worker       mInitialContextPriority(renderer->getDriverPriority(GetContextPriority(state))),
918*8975f5c5SAndroid Build Coastguard Worker       mContextPriority(mInitialContextPriority),
919*8975f5c5SAndroid Build Coastguard Worker       mProtectionType(vk::ConvertProtectionBoolToType(state.hasProtectedContent())),
920*8975f5c5SAndroid Build Coastguard Worker       mShareGroupVk(vk::GetImpl(state.getShareGroup()))
921*8975f5c5SAndroid Build Coastguard Worker {
922*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::ContextVk");
923*8975f5c5SAndroid Build Coastguard Worker     memset(&mClearColorValue, 0, sizeof(mClearColorValue));
924*8975f5c5SAndroid Build Coastguard Worker     memset(&mClearDepthStencilValue, 0, sizeof(mClearDepthStencilValue));
925*8975f5c5SAndroid Build Coastguard Worker     memset(&mViewport, 0, sizeof(mViewport));
926*8975f5c5SAndroid Build Coastguard Worker     memset(&mScissor, 0, sizeof(mScissor));
927*8975f5c5SAndroid Build Coastguard Worker 
928*8975f5c5SAndroid Build Coastguard Worker     // Ensure viewport is within Vulkan requirements
929*8975f5c5SAndroid Build Coastguard Worker     vk::ClampViewport(&mViewport);
930*8975f5c5SAndroid Build Coastguard Worker 
931*8975f5c5SAndroid Build Coastguard Worker     mNonIndexedDirtyBitsMask.set();
932*8975f5c5SAndroid Build Coastguard Worker     mNonIndexedDirtyBitsMask.reset(DIRTY_BIT_INDEX_BUFFER);
933*8975f5c5SAndroid Build Coastguard Worker 
934*8975f5c5SAndroid Build Coastguard Worker     mIndexedDirtyBitsMask.set();
935*8975f5c5SAndroid Build Coastguard Worker 
936*8975f5c5SAndroid Build Coastguard Worker     // Once a command buffer is ended, all bindings (through |vkCmdBind*| calls) are lost per Vulkan
937*8975f5c5SAndroid Build Coastguard Worker     // spec.  Once a new command buffer is allocated, we must make sure every previously bound
938*8975f5c5SAndroid Build Coastguard Worker     // resource is bound again.
939*8975f5c5SAndroid Build Coastguard Worker     //
940*8975f5c5SAndroid Build Coastguard Worker     // Note that currently these dirty bits are set every time a new render pass command buffer is
941*8975f5c5SAndroid Build Coastguard Worker     // begun.  However, using ANGLE's SecondaryCommandBuffer, the Vulkan command buffer (which is
942*8975f5c5SAndroid Build Coastguard Worker     // the primary command buffer) is not ended, so technically we don't need to rebind these.
943*8975f5c5SAndroid Build Coastguard Worker     mNewGraphicsCommandBufferDirtyBits = DirtyBits{
944*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_RENDER_PASS,      DIRTY_BIT_COLOR_ACCESS,     DIRTY_BIT_DEPTH_STENCIL_ACCESS,
945*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_PIPELINE_BINDING, DIRTY_BIT_TEXTURES,         DIRTY_BIT_VERTEX_BUFFERS,
946*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_INDEX_BUFFER,     DIRTY_BIT_SHADER_RESOURCES, DIRTY_BIT_DESCRIPTOR_SETS,
947*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_DRIVER_UNIFORMS,
948*8975f5c5SAndroid Build Coastguard Worker     };
949*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().supportsTransformFeedbackExtension.enabled ||
950*8975f5c5SAndroid Build Coastguard Worker         getFeatures().emulateTransformFeedback.enabled)
951*8975f5c5SAndroid Build Coastguard Worker     {
952*8975f5c5SAndroid Build Coastguard Worker         mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS);
953*8975f5c5SAndroid Build Coastguard Worker     }
954*8975f5c5SAndroid Build Coastguard Worker 
955*8975f5c5SAndroid Build Coastguard Worker     mNewComputeCommandBufferDirtyBits =
956*8975f5c5SAndroid Build Coastguard Worker         DirtyBits{DIRTY_BIT_PIPELINE_BINDING, DIRTY_BIT_TEXTURES, DIRTY_BIT_SHADER_RESOURCES,
957*8975f5c5SAndroid Build Coastguard Worker                   DIRTY_BIT_DESCRIPTOR_SETS, DIRTY_BIT_DRIVER_UNIFORMS};
958*8975f5c5SAndroid Build Coastguard Worker 
959*8975f5c5SAndroid Build Coastguard Worker     mDynamicStateDirtyBits = DirtyBits{
960*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_DYNAMIC_VIEWPORT,           DIRTY_BIT_DYNAMIC_SCISSOR,
961*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_DYNAMIC_LINE_WIDTH,         DIRTY_BIT_DYNAMIC_DEPTH_BIAS,
962*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_DYNAMIC_BLEND_CONSTANTS,    DIRTY_BIT_DYNAMIC_STENCIL_COMPARE_MASK,
963*8975f5c5SAndroid Build Coastguard Worker         DIRTY_BIT_DYNAMIC_STENCIL_WRITE_MASK, DIRTY_BIT_DYNAMIC_STENCIL_REFERENCE,
964*8975f5c5SAndroid Build Coastguard Worker     };
965*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useVertexInputBindingStrideDynamicState.enabled ||
966*8975f5c5SAndroid Build Coastguard Worker         getFeatures().supportsVertexInputDynamicState.enabled)
967*8975f5c5SAndroid Build Coastguard Worker     {
968*8975f5c5SAndroid Build Coastguard Worker         mDynamicStateDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
969*8975f5c5SAndroid Build Coastguard Worker     }
970*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useCullModeDynamicState.enabled)
971*8975f5c5SAndroid Build Coastguard Worker     {
972*8975f5c5SAndroid Build Coastguard Worker         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_CULL_MODE);
973*8975f5c5SAndroid Build Coastguard Worker     }
974*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useFrontFaceDynamicState.enabled)
975*8975f5c5SAndroid Build Coastguard Worker     {
976*8975f5c5SAndroid Build Coastguard Worker         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_FRONT_FACE);
977*8975f5c5SAndroid Build Coastguard Worker     }
978*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useDepthTestEnableDynamicState.enabled)
979*8975f5c5SAndroid Build Coastguard Worker     {
980*8975f5c5SAndroid Build Coastguard Worker         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_TEST_ENABLE);
981*8975f5c5SAndroid Build Coastguard Worker     }
982*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useDepthWriteEnableDynamicState.enabled)
983*8975f5c5SAndroid Build Coastguard Worker     {
984*8975f5c5SAndroid Build Coastguard Worker         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_WRITE_ENABLE);
985*8975f5c5SAndroid Build Coastguard Worker     }
986*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useDepthCompareOpDynamicState.enabled)
987*8975f5c5SAndroid Build Coastguard Worker     {
988*8975f5c5SAndroid Build Coastguard Worker         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_COMPARE_OP);
989*8975f5c5SAndroid Build Coastguard Worker     }
990*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useStencilTestEnableDynamicState.enabled)
991*8975f5c5SAndroid Build Coastguard Worker     {
992*8975f5c5SAndroid Build Coastguard Worker         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_TEST_ENABLE);
993*8975f5c5SAndroid Build Coastguard Worker     }
994*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useStencilOpDynamicState.enabled)
995*8975f5c5SAndroid Build Coastguard Worker     {
996*8975f5c5SAndroid Build Coastguard Worker         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_OP);
997*8975f5c5SAndroid Build Coastguard Worker     }
998*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().usePrimitiveRestartEnableDynamicState.enabled)
999*8975f5c5SAndroid Build Coastguard Worker     {
1000*8975f5c5SAndroid Build Coastguard Worker         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_PRIMITIVE_RESTART_ENABLE);
1001*8975f5c5SAndroid Build Coastguard Worker     }
1002*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useRasterizerDiscardEnableDynamicState.enabled)
1003*8975f5c5SAndroid Build Coastguard Worker     {
1004*8975f5c5SAndroid Build Coastguard Worker         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_RASTERIZER_DISCARD_ENABLE);
1005*8975f5c5SAndroid Build Coastguard Worker     }
1006*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useDepthBiasEnableDynamicState.enabled)
1007*8975f5c5SAndroid Build Coastguard Worker     {
1008*8975f5c5SAndroid Build Coastguard Worker         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_BIAS_ENABLE);
1009*8975f5c5SAndroid Build Coastguard Worker     }
1010*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().supportsLogicOpDynamicState.enabled)
1011*8975f5c5SAndroid Build Coastguard Worker     {
1012*8975f5c5SAndroid Build Coastguard Worker         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_LOGIC_OP);
1013*8975f5c5SAndroid Build Coastguard Worker     }
1014*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().supportsFragmentShadingRate.enabled)
1015*8975f5c5SAndroid Build Coastguard Worker     {
1016*8975f5c5SAndroid Build Coastguard Worker         mDynamicStateDirtyBits.set(DIRTY_BIT_DYNAMIC_FRAGMENT_SHADING_RATE);
1017*8975f5c5SAndroid Build Coastguard Worker     }
1018*8975f5c5SAndroid Build Coastguard Worker 
1019*8975f5c5SAndroid Build Coastguard Worker     mNewGraphicsCommandBufferDirtyBits |= mDynamicStateDirtyBits;
1020*8975f5c5SAndroid Build Coastguard Worker 
1021*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_MEMORY_BARRIER] =
1022*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsMemoryBarrier;
1023*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DEFAULT_ATTRIBS] =
1024*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDefaultAttribs;
1025*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_PIPELINE_DESC] =
1026*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsPipelineDesc;
1027*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_READ_ONLY_DEPTH_FEEDBACK_LOOP_MODE] =
1028*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsReadOnlyDepthFeedbackLoopMode;
1029*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_ANY_SAMPLE_PASSED_QUERY_END] =
1030*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyAnySamplePassedQueryEnd;
1031*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_RENDER_PASS]  = &ContextVk::handleDirtyGraphicsRenderPass;
1032*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_EVENT_LOG]    = &ContextVk::handleDirtyGraphicsEventLog;
1033*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_COLOR_ACCESS] = &ContextVk::handleDirtyGraphicsColorAccess;
1034*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DEPTH_STENCIL_ACCESS] =
1035*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDepthStencilAccess;
1036*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_PIPELINE_BINDING] =
1037*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsPipelineBinding;
1038*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_TEXTURES] = &ContextVk::handleDirtyGraphicsTextures;
1039*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_VERTEX_BUFFERS] =
1040*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsVertexBuffers;
1041*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_INDEX_BUFFER] = &ContextVk::handleDirtyGraphicsIndexBuffer;
1042*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_UNIFORMS]     = &ContextVk::handleDirtyGraphicsUniforms;
1043*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS] =
1044*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDriverUniforms;
1045*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_SHADER_RESOURCES] =
1046*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsShaderResources;
1047*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_UNIFORM_BUFFERS] =
1048*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsUniformBuffers;
1049*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_FRAMEBUFFER_FETCH_BARRIER] =
1050*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsFramebufferFetchBarrier;
1051*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_BLEND_BARRIER] =
1052*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsBlendBarrier;
1053*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().supportsTransformFeedbackExtension.enabled)
1054*8975f5c5SAndroid Build Coastguard Worker     {
1055*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS] =
1056*8975f5c5SAndroid Build Coastguard Worker             &ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension;
1057*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME] =
1058*8975f5c5SAndroid Build Coastguard Worker             &ContextVk::handleDirtyGraphicsTransformFeedbackResume;
1059*8975f5c5SAndroid Build Coastguard Worker     }
1060*8975f5c5SAndroid Build Coastguard Worker     else if (getFeatures().emulateTransformFeedback.enabled)
1061*8975f5c5SAndroid Build Coastguard Worker     {
1062*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS] =
1063*8975f5c5SAndroid Build Coastguard Worker             &ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation;
1064*8975f5c5SAndroid Build Coastguard Worker     }
1065*8975f5c5SAndroid Build Coastguard Worker 
1066*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DESCRIPTOR_SETS] =
1067*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDescriptorSets;
1068*8975f5c5SAndroid Build Coastguard Worker 
1069*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_VIEWPORT] =
1070*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicViewport;
1071*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_SCISSOR] =
1072*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicScissor;
1073*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_LINE_WIDTH] =
1074*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicLineWidth;
1075*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_DEPTH_BIAS] =
1076*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicDepthBias;
1077*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_BLEND_CONSTANTS] =
1078*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicBlendConstants;
1079*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_STENCIL_COMPARE_MASK] =
1080*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicStencilCompareMask;
1081*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_STENCIL_WRITE_MASK] =
1082*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicStencilWriteMask;
1083*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_STENCIL_REFERENCE] =
1084*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicStencilReference;
1085*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_CULL_MODE] =
1086*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicCullMode;
1087*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_FRONT_FACE] =
1088*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicFrontFace;
1089*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_DEPTH_TEST_ENABLE] =
1090*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicDepthTestEnable;
1091*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_DEPTH_WRITE_ENABLE] =
1092*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicDepthWriteEnable;
1093*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_DEPTH_COMPARE_OP] =
1094*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicDepthCompareOp;
1095*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_STENCIL_TEST_ENABLE] =
1096*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicStencilTestEnable;
1097*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_STENCIL_OP] =
1098*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicStencilOp;
1099*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_RASTERIZER_DISCARD_ENABLE] =
1100*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicRasterizerDiscardEnable;
1101*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_DEPTH_BIAS_ENABLE] =
1102*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicDepthBiasEnable;
1103*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_LOGIC_OP] =
1104*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicLogicOp;
1105*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_PRIMITIVE_RESTART_ENABLE] =
1106*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicPrimitiveRestartEnable;
1107*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBitHandlers[DIRTY_BIT_DYNAMIC_FRAGMENT_SHADING_RATE] =
1108*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyGraphicsDynamicFragmentShadingRate;
1109*8975f5c5SAndroid Build Coastguard Worker 
1110*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBitHandlers[DIRTY_BIT_MEMORY_BARRIER] =
1111*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyComputeMemoryBarrier;
1112*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBitHandlers[DIRTY_BIT_EVENT_LOG]     = &ContextVk::handleDirtyComputeEventLog;
1113*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBitHandlers[DIRTY_BIT_PIPELINE_DESC] = &ContextVk::handleDirtyComputePipelineDesc;
1114*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBitHandlers[DIRTY_BIT_PIPELINE_BINDING] =
1115*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyComputePipelineBinding;
1116*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBitHandlers[DIRTY_BIT_TEXTURES] = &ContextVk::handleDirtyComputeTextures;
1117*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBitHandlers[DIRTY_BIT_UNIFORMS] = &ContextVk::handleDirtyComputeUniforms;
1118*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBitHandlers[DIRTY_BIT_DRIVER_UNIFORMS] =
1119*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyComputeDriverUniforms;
1120*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBitHandlers[DIRTY_BIT_SHADER_RESOURCES] =
1121*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyComputeShaderResources;
1122*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBitHandlers[DIRTY_BIT_UNIFORM_BUFFERS] =
1123*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyComputeUniformBuffers;
1124*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBitHandlers[DIRTY_BIT_DESCRIPTOR_SETS] =
1125*8975f5c5SAndroid Build Coastguard Worker         &ContextVk::handleDirtyComputeDescriptorSets;
1126*8975f5c5SAndroid Build Coastguard Worker 
1127*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits = mNewGraphicsCommandBufferDirtyBits;
1128*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBits  = mNewComputeCommandBufferDirtyBits;
1129*8975f5c5SAndroid Build Coastguard Worker 
1130*8975f5c5SAndroid Build Coastguard Worker     // If coherent framebuffer fetch is emulated, a barrier is implicitly issued between draw calls
1131*8975f5c5SAndroid Build Coastguard Worker     // that use framebuffer fetch.  As such, the corresponding dirty bit shouldn't be cleared until
1132*8975f5c5SAndroid Build Coastguard Worker     // a program without framebuffer fetch is used.
1133*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->isCoherentColorFramebufferFetchEmulated())
1134*8975f5c5SAndroid Build Coastguard Worker     {
1135*8975f5c5SAndroid Build Coastguard Worker         mPersistentGraphicsDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_FETCH_BARRIER);
1136*8975f5c5SAndroid Build Coastguard Worker     }
1137*8975f5c5SAndroid Build Coastguard Worker 
1138*8975f5c5SAndroid Build Coastguard Worker     FillWithNullptr(&mActiveImages);
1139*8975f5c5SAndroid Build Coastguard Worker 
1140*8975f5c5SAndroid Build Coastguard Worker     // The following dirty bits don't affect the program pipeline:
1141*8975f5c5SAndroid Build Coastguard Worker     //
1142*8975f5c5SAndroid Build Coastguard Worker     // - READ_FRAMEBUFFER_BINDING only affects operations that read from said framebuffer,
1143*8975f5c5SAndroid Build Coastguard Worker     // - CLEAR_* only affect following clear calls,
1144*8975f5c5SAndroid Build Coastguard Worker     // - PACK/UNPACK_STATE only affect texture data upload/download,
1145*8975f5c5SAndroid Build Coastguard Worker     // - *_BINDING only affect descriptor sets.
1146*8975f5c5SAndroid Build Coastguard Worker     //
1147*8975f5c5SAndroid Build Coastguard Worker     // Additionally, state that is set dynamically doesn't invalidate the program pipeline.
1148*8975f5c5SAndroid Build Coastguard Worker     //
1149*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.set();
1150*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
1151*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_CLEAR_COLOR);
1152*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_CLEAR_DEPTH);
1153*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_CLEAR_STENCIL);
1154*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_UNPACK_STATE);
1155*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_UNPACK_BUFFER_BINDING);
1156*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_PACK_STATE);
1157*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_PACK_BUFFER_BINDING);
1158*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_RENDERBUFFER_BINDING);
1159*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING);
1160*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING);
1161*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_SAMPLER_BINDINGS);
1162*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_TEXTURE_BINDINGS);
1163*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_IMAGE_BINDINGS);
1164*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING);
1165*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
1166*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
1167*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
1168*8975f5c5SAndroid Build Coastguard Worker 
1169*8975f5c5SAndroid Build Coastguard Worker     // Dynamic state in core Vulkan 1.0:
1170*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_VIEWPORT);
1171*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_SCISSOR_TEST_ENABLED);
1172*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_SCISSOR);
1173*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_LINE_WIDTH);
1174*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_POLYGON_OFFSET);
1175*8975f5c5SAndroid Build Coastguard Worker     mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_BLEND_COLOR);
1176*8975f5c5SAndroid Build Coastguard Worker     if (!getFeatures().useNonZeroStencilWriteMaskStaticState.enabled)
1177*8975f5c5SAndroid Build Coastguard Worker     {
1178*8975f5c5SAndroid Build Coastguard Worker         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
1179*8975f5c5SAndroid Build Coastguard Worker         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
1180*8975f5c5SAndroid Build Coastguard Worker     }
1181*8975f5c5SAndroid Build Coastguard Worker 
1182*8975f5c5SAndroid Build Coastguard Worker     // Dynamic state in VK_EXT_extended_dynamic_state:
1183*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useCullModeDynamicState.enabled)
1184*8975f5c5SAndroid Build Coastguard Worker     {
1185*8975f5c5SAndroid Build Coastguard Worker         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_CULL_FACE_ENABLED);
1186*8975f5c5SAndroid Build Coastguard Worker         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_CULL_FACE);
1187*8975f5c5SAndroid Build Coastguard Worker     }
1188*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useFrontFaceDynamicState.enabled)
1189*8975f5c5SAndroid Build Coastguard Worker     {
1190*8975f5c5SAndroid Build Coastguard Worker         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_FRONT_FACE);
1191*8975f5c5SAndroid Build Coastguard Worker     }
1192*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useDepthTestEnableDynamicState.enabled)
1193*8975f5c5SAndroid Build Coastguard Worker     {
1194*8975f5c5SAndroid Build Coastguard Worker         // Depth test affects depth write state too in GraphicsPipelineDesc, so the pipeline needs
1195*8975f5c5SAndroid Build Coastguard Worker         // to stay dirty if depth test changes while depth write state is static.
1196*8975f5c5SAndroid Build Coastguard Worker         if (mRenderer->getFeatures().useDepthWriteEnableDynamicState.enabled)
1197*8975f5c5SAndroid Build Coastguard Worker         {
1198*8975f5c5SAndroid Build Coastguard Worker             mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_DEPTH_TEST_ENABLED);
1199*8975f5c5SAndroid Build Coastguard Worker         }
1200*8975f5c5SAndroid Build Coastguard Worker     }
1201*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useDepthWriteEnableDynamicState.enabled)
1202*8975f5c5SAndroid Build Coastguard Worker     {
1203*8975f5c5SAndroid Build Coastguard Worker         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_DEPTH_MASK);
1204*8975f5c5SAndroid Build Coastguard Worker     }
1205*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useDepthCompareOpDynamicState.enabled)
1206*8975f5c5SAndroid Build Coastguard Worker     {
1207*8975f5c5SAndroid Build Coastguard Worker         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_DEPTH_FUNC);
1208*8975f5c5SAndroid Build Coastguard Worker     }
1209*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useStencilTestEnableDynamicState.enabled)
1210*8975f5c5SAndroid Build Coastguard Worker     {
1211*8975f5c5SAndroid Build Coastguard Worker         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_STENCIL_TEST_ENABLED);
1212*8975f5c5SAndroid Build Coastguard Worker     }
1213*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useStencilOpDynamicState.enabled)
1214*8975f5c5SAndroid Build Coastguard Worker     {
1215*8975f5c5SAndroid Build Coastguard Worker         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_STENCIL_FUNCS_FRONT);
1216*8975f5c5SAndroid Build Coastguard Worker         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_STENCIL_FUNCS_BACK);
1217*8975f5c5SAndroid Build Coastguard Worker         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_STENCIL_OPS_FRONT);
1218*8975f5c5SAndroid Build Coastguard Worker         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_STENCIL_OPS_BACK);
1219*8975f5c5SAndroid Build Coastguard Worker     }
1220*8975f5c5SAndroid Build Coastguard Worker     // Dynamic state in VK_EXT_extended_dynamic_state2:
1221*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().usePrimitiveRestartEnableDynamicState.enabled)
1222*8975f5c5SAndroid Build Coastguard Worker     {
1223*8975f5c5SAndroid Build Coastguard Worker         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
1224*8975f5c5SAndroid Build Coastguard Worker     }
1225*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useRasterizerDiscardEnableDynamicState.enabled)
1226*8975f5c5SAndroid Build Coastguard Worker     {
1227*8975f5c5SAndroid Build Coastguard Worker         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
1228*8975f5c5SAndroid Build Coastguard Worker     }
1229*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useDepthBiasEnableDynamicState.enabled)
1230*8975f5c5SAndroid Build Coastguard Worker     {
1231*8975f5c5SAndroid Build Coastguard Worker         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
1232*8975f5c5SAndroid Build Coastguard Worker     }
1233*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().supportsVertexInputDynamicState.enabled)
1234*8975f5c5SAndroid Build Coastguard Worker     {
1235*8975f5c5SAndroid Build Coastguard Worker         mPipelineDirtyBitsMask.reset(gl::state::DIRTY_BIT_VERTEX_ARRAY_BINDING);
1236*8975f5c5SAndroid Build Coastguard Worker     }
1237*8975f5c5SAndroid Build Coastguard Worker 
1238*8975f5c5SAndroid Build Coastguard Worker     // Stash the mRefCountedEventRecycler in vk::Context for ImageHelper to conveniently access
1239*8975f5c5SAndroid Build Coastguard Worker     mShareGroupRefCountedEventsGarbageRecycler =
1240*8975f5c5SAndroid Build Coastguard Worker         mShareGroupVk->getRefCountedEventsGarbageRecycler();
1241*8975f5c5SAndroid Build Coastguard Worker 
1242*8975f5c5SAndroid Build Coastguard Worker     mDeviceQueueIndex = renderer->getDeviceQueueIndex(mContextPriority);
1243*8975f5c5SAndroid Build Coastguard Worker 
1244*8975f5c5SAndroid Build Coastguard Worker     angle::PerfMonitorCounterGroup vulkanGroup;
1245*8975f5c5SAndroid Build Coastguard Worker     vulkanGroup.name = "vulkan";
1246*8975f5c5SAndroid Build Coastguard Worker 
1247*8975f5c5SAndroid Build Coastguard Worker #define ANGLE_ADD_PERF_MONITOR_COUNTER_GROUP(COUNTER) \
1248*8975f5c5SAndroid Build Coastguard Worker     {                                                 \
1249*8975f5c5SAndroid Build Coastguard Worker         angle::PerfMonitorCounter counter;            \
1250*8975f5c5SAndroid Build Coastguard Worker         counter.name  = #COUNTER;                     \
1251*8975f5c5SAndroid Build Coastguard Worker         counter.value = 0;                            \
1252*8975f5c5SAndroid Build Coastguard Worker         vulkanGroup.counters.push_back(counter);      \
1253*8975f5c5SAndroid Build Coastguard Worker     }
1254*8975f5c5SAndroid Build Coastguard Worker 
1255*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_PERF_COUNTERS_X(ANGLE_ADD_PERF_MONITOR_COUNTER_GROUP)
1256*8975f5c5SAndroid Build Coastguard Worker 
1257*8975f5c5SAndroid Build Coastguard Worker #undef ANGLE_ADD_PERF_MONITOR_COUNTER_GROUP
1258*8975f5c5SAndroid Build Coastguard Worker 
1259*8975f5c5SAndroid Build Coastguard Worker     mPerfMonitorCounters.push_back(vulkanGroup);
1260*8975f5c5SAndroid Build Coastguard Worker }
1261*8975f5c5SAndroid Build Coastguard Worker 
~ContextVk()1262*8975f5c5SAndroid Build Coastguard Worker ContextVk::~ContextVk() {}
1263*8975f5c5SAndroid Build Coastguard Worker 
onDestroy(const gl::Context * context)1264*8975f5c5SAndroid Build Coastguard Worker void ContextVk::onDestroy(const gl::Context *context)
1265*8975f5c5SAndroid Build Coastguard Worker {
1266*8975f5c5SAndroid Build Coastguard Worker     // If there is a context lost, destroy all the command buffers and resources regardless of
1267*8975f5c5SAndroid Build Coastguard Worker     // whether they finished execution on GPU.
1268*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->isDeviceLost())
1269*8975f5c5SAndroid Build Coastguard Worker     {
1270*8975f5c5SAndroid Build Coastguard Worker         mRenderer->handleDeviceLost();
1271*8975f5c5SAndroid Build Coastguard Worker     }
1272*8975f5c5SAndroid Build Coastguard Worker 
1273*8975f5c5SAndroid Build Coastguard Worker     // This will not destroy any resources. It will release them to be collected after finish.
1274*8975f5c5SAndroid Build Coastguard Worker     mIncompleteTextures.onDestroy(context);
1275*8975f5c5SAndroid Build Coastguard Worker 
1276*8975f5c5SAndroid Build Coastguard Worker     // Flush and complete current outstanding work before destruction.
1277*8975f5c5SAndroid Build Coastguard Worker     (void)finishImpl(RenderPassClosureReason::ContextDestruction);
1278*8975f5c5SAndroid Build Coastguard Worker 
1279*8975f5c5SAndroid Build Coastguard Worker     // The finish call could also generate device loss.
1280*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->isDeviceLost())
1281*8975f5c5SAndroid Build Coastguard Worker     {
1282*8975f5c5SAndroid Build Coastguard Worker         mRenderer->handleDeviceLost();
1283*8975f5c5SAndroid Build Coastguard Worker     }
1284*8975f5c5SAndroid Build Coastguard Worker 
1285*8975f5c5SAndroid Build Coastguard Worker     // Everything must be finished
1286*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mRenderer->hasResourceUseFinished(mSubmittedResourceUse));
1287*8975f5c5SAndroid Build Coastguard Worker 
1288*8975f5c5SAndroid Build Coastguard Worker     VkDevice device = getDevice();
1289*8975f5c5SAndroid Build Coastguard Worker 
1290*8975f5c5SAndroid Build Coastguard Worker     mShareGroupVk->cleanupRefCountedEventGarbage();
1291*8975f5c5SAndroid Build Coastguard Worker 
1292*8975f5c5SAndroid Build Coastguard Worker     mDefaultUniformStorage.release(mRenderer);
1293*8975f5c5SAndroid Build Coastguard Worker     mEmptyBuffer.release(mRenderer);
1294*8975f5c5SAndroid Build Coastguard Worker 
1295*8975f5c5SAndroid Build Coastguard Worker     for (vk::DynamicBuffer &defaultBuffer : mStreamedVertexBuffers)
1296*8975f5c5SAndroid Build Coastguard Worker     {
1297*8975f5c5SAndroid Build Coastguard Worker         defaultBuffer.destroy(mRenderer);
1298*8975f5c5SAndroid Build Coastguard Worker     }
1299*8975f5c5SAndroid Build Coastguard Worker 
1300*8975f5c5SAndroid Build Coastguard Worker     for (vk::DynamicQueryPool &queryPool : mQueryPools)
1301*8975f5c5SAndroid Build Coastguard Worker     {
1302*8975f5c5SAndroid Build Coastguard Worker         queryPool.destroy(device);
1303*8975f5c5SAndroid Build Coastguard Worker     }
1304*8975f5c5SAndroid Build Coastguard Worker 
1305*8975f5c5SAndroid Build Coastguard Worker     // Recycle current command buffers.
1306*8975f5c5SAndroid Build Coastguard Worker 
1307*8975f5c5SAndroid Build Coastguard Worker     // Release functions are only used for Vulkan secondary command buffers.
1308*8975f5c5SAndroid Build Coastguard Worker     mOutsideRenderPassCommands->releaseCommandPool();
1309*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommands->releaseCommandPool();
1310*8975f5c5SAndroid Build Coastguard Worker 
1311*8975f5c5SAndroid Build Coastguard Worker     // Detach functions are only used for ring buffer allocators.
1312*8975f5c5SAndroid Build Coastguard Worker     mOutsideRenderPassCommands->detachAllocator();
1313*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommands->detachAllocator();
1314*8975f5c5SAndroid Build Coastguard Worker 
1315*8975f5c5SAndroid Build Coastguard Worker     mRenderer->recycleOutsideRenderPassCommandBufferHelper(&mOutsideRenderPassCommands);
1316*8975f5c5SAndroid Build Coastguard Worker     mRenderer->recycleRenderPassCommandBufferHelper(&mRenderPassCommands);
1317*8975f5c5SAndroid Build Coastguard Worker 
1318*8975f5c5SAndroid Build Coastguard Worker     mInterfacePipelinesCache.destroy(device);
1319*8975f5c5SAndroid Build Coastguard Worker 
1320*8975f5c5SAndroid Build Coastguard Worker     mUtils.destroy(this);
1321*8975f5c5SAndroid Build Coastguard Worker 
1322*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCache.destroy(this);
1323*8975f5c5SAndroid Build Coastguard Worker     mShaderLibrary.destroy(device);
1324*8975f5c5SAndroid Build Coastguard Worker     mGpuEventQueryPool.destroy(device);
1325*8975f5c5SAndroid Build Coastguard Worker 
1326*8975f5c5SAndroid Build Coastguard Worker     // Must release all Vulkan secondary command buffers before destroying the pools.
1327*8975f5c5SAndroid Build Coastguard Worker     if ((!vk::OutsideRenderPassCommandBuffer::ExecutesInline() ||
1328*8975f5c5SAndroid Build Coastguard Worker          !vk::RenderPassCommandBuffer::ExecutesInline()) &&
1329*8975f5c5SAndroid Build Coastguard Worker         mRenderer->isAsyncCommandBufferResetAndGarbageCleanupEnabled())
1330*8975f5c5SAndroid Build Coastguard Worker     {
1331*8975f5c5SAndroid Build Coastguard Worker         // This will also reset Primary command buffers which is REQUIRED on some buggy Vulkan
1332*8975f5c5SAndroid Build Coastguard Worker         // implementations.
1333*8975f5c5SAndroid Build Coastguard Worker         (void)mRenderer->releaseFinishedCommands(this);
1334*8975f5c5SAndroid Build Coastguard Worker     }
1335*8975f5c5SAndroid Build Coastguard Worker 
1336*8975f5c5SAndroid Build Coastguard Worker     mCommandPools.outsideRenderPassPool.destroy(device);
1337*8975f5c5SAndroid Build Coastguard Worker     mCommandPools.renderPassPool.destroy(device);
1338*8975f5c5SAndroid Build Coastguard Worker 
1339*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mCurrentGarbage.empty());
1340*8975f5c5SAndroid Build Coastguard Worker 
1341*8975f5c5SAndroid Build Coastguard Worker     if (mCurrentQueueSerialIndex != kInvalidQueueSerialIndex)
1342*8975f5c5SAndroid Build Coastguard Worker     {
1343*8975f5c5SAndroid Build Coastguard Worker         releaseQueueSerialIndex();
1344*8975f5c5SAndroid Build Coastguard Worker     }
1345*8975f5c5SAndroid Build Coastguard Worker 
1346*8975f5c5SAndroid Build Coastguard Worker     mImageLoadContext = {};
1347*8975f5c5SAndroid Build Coastguard Worker }
1348*8975f5c5SAndroid Build Coastguard Worker 
getVertexArray() const1349*8975f5c5SAndroid Build Coastguard Worker VertexArrayVk *ContextVk::getVertexArray() const
1350*8975f5c5SAndroid Build Coastguard Worker {
1351*8975f5c5SAndroid Build Coastguard Worker     return vk::GetImpl(mState.getVertexArray());
1352*8975f5c5SAndroid Build Coastguard Worker }
1353*8975f5c5SAndroid Build Coastguard Worker 
getDrawFramebuffer() const1354*8975f5c5SAndroid Build Coastguard Worker FramebufferVk *ContextVk::getDrawFramebuffer() const
1355*8975f5c5SAndroid Build Coastguard Worker {
1356*8975f5c5SAndroid Build Coastguard Worker     return vk::GetImpl(mState.getDrawFramebuffer());
1357*8975f5c5SAndroid Build Coastguard Worker }
1358*8975f5c5SAndroid Build Coastguard Worker 
getIncompleteTexture(const gl::Context * context,gl::TextureType type,gl::SamplerFormat format,gl::Texture ** textureOut)1359*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::getIncompleteTexture(const gl::Context *context,
1360*8975f5c5SAndroid Build Coastguard Worker                                               gl::TextureType type,
1361*8975f5c5SAndroid Build Coastguard Worker                                               gl::SamplerFormat format,
1362*8975f5c5SAndroid Build Coastguard Worker                                               gl::Texture **textureOut)
1363*8975f5c5SAndroid Build Coastguard Worker {
1364*8975f5c5SAndroid Build Coastguard Worker     return mIncompleteTextures.getIncompleteTexture(context, type, format, this, textureOut);
1365*8975f5c5SAndroid Build Coastguard Worker }
1366*8975f5c5SAndroid Build Coastguard Worker 
initialize(const angle::ImageLoadContext & imageLoadContext)1367*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::initialize(const angle::ImageLoadContext &imageLoadContext)
1368*8975f5c5SAndroid Build Coastguard Worker {
1369*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::initialize");
1370*8975f5c5SAndroid Build Coastguard Worker 
1371*8975f5c5SAndroid Build Coastguard Worker     mImageLoadContext = imageLoadContext;
1372*8975f5c5SAndroid Build Coastguard Worker 
1373*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mShareGroupVk->unifyContextsPriority(this));
1374*8975f5c5SAndroid Build Coastguard Worker 
1375*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mQueryPools[gl::QueryType::AnySamples].init(this, VK_QUERY_TYPE_OCCLUSION,
1376*8975f5c5SAndroid Build Coastguard Worker                                                           vk::kDefaultOcclusionQueryPoolSize));
1377*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mQueryPools[gl::QueryType::AnySamplesConservative].init(
1378*8975f5c5SAndroid Build Coastguard Worker         this, VK_QUERY_TYPE_OCCLUSION, vk::kDefaultOcclusionQueryPoolSize));
1379*8975f5c5SAndroid Build Coastguard Worker 
1380*8975f5c5SAndroid Build Coastguard Worker     // Only initialize the timestamp query pools if the extension is available.
1381*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getQueueFamilyProperties().timestampValidBits > 0)
1382*8975f5c5SAndroid Build Coastguard Worker     {
1383*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mQueryPools[gl::QueryType::Timestamp].init(this, VK_QUERY_TYPE_TIMESTAMP,
1384*8975f5c5SAndroid Build Coastguard Worker                                                              vk::kDefaultTimestampQueryPoolSize));
1385*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mQueryPools[gl::QueryType::TimeElapsed].init(this, VK_QUERY_TYPE_TIMESTAMP,
1386*8975f5c5SAndroid Build Coastguard Worker                                                                vk::kDefaultTimestampQueryPoolSize));
1387*8975f5c5SAndroid Build Coastguard Worker     }
1388*8975f5c5SAndroid Build Coastguard Worker 
1389*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().supportsTransformFeedbackExtension.enabled)
1390*8975f5c5SAndroid Build Coastguard Worker     {
1391*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mQueryPools[gl::QueryType::TransformFeedbackPrimitivesWritten].init(
1392*8975f5c5SAndroid Build Coastguard Worker             this, VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT,
1393*8975f5c5SAndroid Build Coastguard Worker             vk::kDefaultTransformFeedbackQueryPoolSize));
1394*8975f5c5SAndroid Build Coastguard Worker     }
1395*8975f5c5SAndroid Build Coastguard Worker 
1396*8975f5c5SAndroid Build Coastguard Worker     // If VK_EXT_primitives_generated_query is supported, use that to implement the OpenGL query.
1397*8975f5c5SAndroid Build Coastguard Worker     // Otherwise, the primitives generated query is provided through the Vulkan pipeline statistics
1398*8975f5c5SAndroid Build Coastguard Worker     // query if supported.
1399*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().supportsPrimitivesGeneratedQuery.enabled)
1400*8975f5c5SAndroid Build Coastguard Worker     {
1401*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mQueryPools[gl::QueryType::PrimitivesGenerated].init(
1402*8975f5c5SAndroid Build Coastguard Worker             this, VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT,
1403*8975f5c5SAndroid Build Coastguard Worker             vk::kDefaultPrimitivesGeneratedQueryPoolSize));
1404*8975f5c5SAndroid Build Coastguard Worker     }
1405*8975f5c5SAndroid Build Coastguard Worker     else if (getFeatures().supportsPipelineStatisticsQuery.enabled)
1406*8975f5c5SAndroid Build Coastguard Worker     {
1407*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mQueryPools[gl::QueryType::PrimitivesGenerated].init(
1408*8975f5c5SAndroid Build Coastguard Worker             this, VK_QUERY_TYPE_PIPELINE_STATISTICS, vk::kDefaultPrimitivesGeneratedQueryPoolSize));
1409*8975f5c5SAndroid Build Coastguard Worker     }
1410*8975f5c5SAndroid Build Coastguard Worker 
1411*8975f5c5SAndroid Build Coastguard Worker     // Init GLES to Vulkan index type map.
1412*8975f5c5SAndroid Build Coastguard Worker     initIndexTypeMap();
1413*8975f5c5SAndroid Build Coastguard Worker 
1414*8975f5c5SAndroid Build Coastguard Worker     mGraphicsPipelineDesc.reset(new vk::GraphicsPipelineDesc());
1415*8975f5c5SAndroid Build Coastguard Worker     mGraphicsPipelineDesc->initDefaults(this, vk::GraphicsPipelineSubset::Complete,
1416*8975f5c5SAndroid Build Coastguard Worker                                         pipelineRobustness(), pipelineProtectedAccess());
1417*8975f5c5SAndroid Build Coastguard Worker 
1418*8975f5c5SAndroid Build Coastguard Worker     // Initialize current value/default attribute buffers.
1419*8975f5c5SAndroid Build Coastguard Worker     for (vk::DynamicBuffer &buffer : mStreamedVertexBuffers)
1420*8975f5c5SAndroid Build Coastguard Worker     {
1421*8975f5c5SAndroid Build Coastguard Worker         buffer.init(mRenderer, kVertexBufferUsage, vk::kVertexBufferAlignment,
1422*8975f5c5SAndroid Build Coastguard Worker                     kDynamicVertexDataSize, true);
1423*8975f5c5SAndroid Build Coastguard Worker     }
1424*8975f5c5SAndroid Build Coastguard Worker 
1425*8975f5c5SAndroid Build Coastguard Worker #if ANGLE_ENABLE_VULKAN_GPU_TRACE_EVENTS
1426*8975f5c5SAndroid Build Coastguard Worker     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
1427*8975f5c5SAndroid Build Coastguard Worker     ASSERT(platform);
1428*8975f5c5SAndroid Build Coastguard Worker 
1429*8975f5c5SAndroid Build Coastguard Worker     // GPU tracing workaround for anglebug.com/42261625.  The renderer should not emit gpu events
1430*8975f5c5SAndroid Build Coastguard Worker     // during platform discovery.
1431*8975f5c5SAndroid Build Coastguard Worker     const unsigned char *gpuEventsEnabled =
1432*8975f5c5SAndroid Build Coastguard Worker         platform->getTraceCategoryEnabledFlag(platform, "gpu.angle.gpu");
1433*8975f5c5SAndroid Build Coastguard Worker     mGpuEventsEnabled = gpuEventsEnabled && *gpuEventsEnabled;
1434*8975f5c5SAndroid Build Coastguard Worker #endif
1435*8975f5c5SAndroid Build Coastguard Worker 
1436*8975f5c5SAndroid Build Coastguard Worker     // Assign initial command buffers from queue
1437*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(vk::OutsideRenderPassCommandBuffer::InitializeCommandPool(
1438*8975f5c5SAndroid Build Coastguard Worker         this, &mCommandPools.outsideRenderPassPool, mRenderer->getQueueFamilyIndex(),
1439*8975f5c5SAndroid Build Coastguard Worker         getProtectionType()));
1440*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(vk::RenderPassCommandBuffer::InitializeCommandPool(
1441*8975f5c5SAndroid Build Coastguard Worker         this, &mCommandPools.renderPassPool, mRenderer->getQueueFamilyIndex(),
1442*8975f5c5SAndroid Build Coastguard Worker         getProtectionType()));
1443*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mRenderer->getOutsideRenderPassCommandBufferHelper(
1444*8975f5c5SAndroid Build Coastguard Worker         this, &mCommandPools.outsideRenderPassPool, &mOutsideRenderPassCommandsAllocator,
1445*8975f5c5SAndroid Build Coastguard Worker         &mOutsideRenderPassCommands));
1446*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mRenderer->getRenderPassCommandBufferHelper(
1447*8975f5c5SAndroid Build Coastguard Worker         this, &mCommandPools.renderPassPool, &mRenderPassCommandsAllocator, &mRenderPassCommands));
1448*8975f5c5SAndroid Build Coastguard Worker 
1449*8975f5c5SAndroid Build Coastguard Worker     // Allocate queueSerial index and generate queue serial for commands.
1450*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(allocateQueueSerialIndex());
1451*8975f5c5SAndroid Build Coastguard Worker 
1452*8975f5c5SAndroid Build Coastguard Worker     // Initialize serials to be valid but appear submitted and finished.
1453*8975f5c5SAndroid Build Coastguard Worker     mLastFlushedQueueSerial   = QueueSerial(mCurrentQueueSerialIndex, Serial());
1454*8975f5c5SAndroid Build Coastguard Worker     mLastSubmittedQueueSerial = mLastFlushedQueueSerial;
1455*8975f5c5SAndroid Build Coastguard Worker 
1456*8975f5c5SAndroid Build Coastguard Worker     if (mGpuEventsEnabled)
1457*8975f5c5SAndroid Build Coastguard Worker     {
1458*8975f5c5SAndroid Build Coastguard Worker         // GPU events should only be available if timestamp queries are available.
1459*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mRenderer->getQueueFamilyProperties().timestampValidBits > 0);
1460*8975f5c5SAndroid Build Coastguard Worker         // Calculate the difference between CPU and GPU clocks for GPU event reporting.
1461*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mGpuEventQueryPool.init(this, VK_QUERY_TYPE_TIMESTAMP,
1462*8975f5c5SAndroid Build Coastguard Worker                                           vk::kDefaultTimestampQueryPoolSize));
1463*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(synchronizeCpuGpuTime());
1464*8975f5c5SAndroid Build Coastguard Worker 
1465*8975f5c5SAndroid Build Coastguard Worker         EventName eventName = GetTraceEventName("Primary", mPrimaryBufferEventCounter);
1466*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
1467*8975f5c5SAndroid Build Coastguard Worker                                 TRACE_EVENT_PHASE_BEGIN, eventName));
1468*8975f5c5SAndroid Build Coastguard Worker     }
1469*8975f5c5SAndroid Build Coastguard Worker 
1470*8975f5c5SAndroid Build Coastguard Worker     size_t minAlignment = static_cast<size_t>(
1471*8975f5c5SAndroid Build Coastguard Worker         mRenderer->getPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment);
1472*8975f5c5SAndroid Build Coastguard Worker     mDefaultUniformStorage.init(mRenderer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, minAlignment,
1473*8975f5c5SAndroid Build Coastguard Worker                                 mRenderer->getDefaultUniformBufferSize(), true);
1474*8975f5c5SAndroid Build Coastguard Worker 
1475*8975f5c5SAndroid Build Coastguard Worker     // Initialize an "empty" buffer for use with default uniform blocks where there are no uniforms,
1476*8975f5c5SAndroid Build Coastguard Worker     // or atomic counter buffer array indices that are unused.
1477*8975f5c5SAndroid Build Coastguard Worker     constexpr VkBufferUsageFlags kEmptyBufferUsage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
1478*8975f5c5SAndroid Build Coastguard Worker                                                      VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
1479*8975f5c5SAndroid Build Coastguard Worker                                                      VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
1480*8975f5c5SAndroid Build Coastguard Worker     VkBufferCreateInfo emptyBufferInfo          = {};
1481*8975f5c5SAndroid Build Coastguard Worker     emptyBufferInfo.sType                       = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1482*8975f5c5SAndroid Build Coastguard Worker     emptyBufferInfo.flags                       = 0;
1483*8975f5c5SAndroid Build Coastguard Worker     emptyBufferInfo.size                        = 16;
1484*8975f5c5SAndroid Build Coastguard Worker     emptyBufferInfo.usage                       = kEmptyBufferUsage;
1485*8975f5c5SAndroid Build Coastguard Worker     emptyBufferInfo.sharingMode                 = VK_SHARING_MODE_EXCLUSIVE;
1486*8975f5c5SAndroid Build Coastguard Worker     emptyBufferInfo.queueFamilyIndexCount       = 0;
1487*8975f5c5SAndroid Build Coastguard Worker     emptyBufferInfo.pQueueFamilyIndices         = nullptr;
1488*8975f5c5SAndroid Build Coastguard Worker     constexpr VkMemoryPropertyFlags kMemoryType = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
1489*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mEmptyBuffer.init(this, emptyBufferInfo, kMemoryType));
1490*8975f5c5SAndroid Build Coastguard Worker 
1491*8975f5c5SAndroid Build Coastguard Worker     // If the share group has one context and is about to add the second one, the first context's
1492*8975f5c5SAndroid Build Coastguard Worker     // mutable textures should be flushed.
1493*8975f5c5SAndroid Build Coastguard Worker     if (isEligibleForMutableTextureFlush())
1494*8975f5c5SAndroid Build Coastguard Worker     {
1495*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mShareGroupVk->getContexts().size() == 1);
1496*8975f5c5SAndroid Build Coastguard Worker         for (auto context : mShareGroupVk->getContexts())
1497*8975f5c5SAndroid Build Coastguard Worker         {
1498*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(vk::GetImpl(context.second)->flushOutsideRenderPassCommands());
1499*8975f5c5SAndroid Build Coastguard Worker         }
1500*8975f5c5SAndroid Build Coastguard Worker     }
1501*8975f5c5SAndroid Build Coastguard Worker 
1502*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1503*8975f5c5SAndroid Build Coastguard Worker }
1504*8975f5c5SAndroid Build Coastguard Worker 
isSingleBufferedWindowCurrent() const1505*8975f5c5SAndroid Build Coastguard Worker bool ContextVk::isSingleBufferedWindowCurrent() const
1506*8975f5c5SAndroid Build Coastguard Worker {
1507*8975f5c5SAndroid Build Coastguard Worker     return (mCurrentWindowSurface != nullptr && mCurrentWindowSurface->isSharedPresentMode());
1508*8975f5c5SAndroid Build Coastguard Worker }
1509*8975f5c5SAndroid Build Coastguard Worker 
hasSomethingToFlush() const1510*8975f5c5SAndroid Build Coastguard Worker bool ContextVk::hasSomethingToFlush() const
1511*8975f5c5SAndroid Build Coastguard Worker {
1512*8975f5c5SAndroid Build Coastguard Worker     // Don't skip flushes for single-buffered windows with staged updates. It is expected that a
1513*8975f5c5SAndroid Build Coastguard Worker     // flush call on a single-buffered window ensures any pending updates reach the screen.
1514*8975f5c5SAndroid Build Coastguard Worker     const bool isSingleBufferedWindowWithStagedUpdates =
1515*8975f5c5SAndroid Build Coastguard Worker         isSingleBufferedWindowCurrent() && mCurrentWindowSurface->hasStagedUpdates();
1516*8975f5c5SAndroid Build Coastguard Worker 
1517*8975f5c5SAndroid Build Coastguard Worker     return (mHasAnyCommandsPendingSubmission || hasActiveRenderPass() ||
1518*8975f5c5SAndroid Build Coastguard Worker             !mOutsideRenderPassCommands->empty() || isSingleBufferedWindowWithStagedUpdates);
1519*8975f5c5SAndroid Build Coastguard Worker }
1520*8975f5c5SAndroid Build Coastguard Worker 
flushImpl(const gl::Context * context)1521*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::flushImpl(const gl::Context *context)
1522*8975f5c5SAndroid Build Coastguard Worker {
1523*8975f5c5SAndroid Build Coastguard Worker     // Skip if there's nothing to flush.
1524*8975f5c5SAndroid Build Coastguard Worker     if (!hasSomethingToFlush())
1525*8975f5c5SAndroid Build Coastguard Worker     {
1526*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
1527*8975f5c5SAndroid Build Coastguard Worker     }
1528*8975f5c5SAndroid Build Coastguard Worker 
1529*8975f5c5SAndroid Build Coastguard Worker     // Don't defer flushes when performing front buffer rendering. This can happen when -
1530*8975f5c5SAndroid Build Coastguard Worker     // 1. we have a single-buffered window, in this mode the application is not required to
1531*8975f5c5SAndroid Build Coastguard Worker     //    call eglSwapBuffers(), and glFlush() is expected to ensure that work is submitted.
1532*8975f5c5SAndroid Build Coastguard Worker     // 2. the framebuffer attachment has FRONT_BUFFER usage. Attachments being rendered to with such
1533*8975f5c5SAndroid Build Coastguard Worker     //    usage flags are expected to behave similar to a single-buffered window
1534*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
1535*8975f5c5SAndroid Build Coastguard Worker     ASSERT(drawFramebufferVk == vk::GetImpl(mState.getDrawFramebuffer()));
1536*8975f5c5SAndroid Build Coastguard Worker     const bool isSingleBufferedWindow = isSingleBufferedWindowCurrent();
1537*8975f5c5SAndroid Build Coastguard Worker     const bool frontBufferRenderingEnabled =
1538*8975f5c5SAndroid Build Coastguard Worker         isSingleBufferedWindow || drawFramebufferVk->hasFrontBufferUsage();
1539*8975f5c5SAndroid Build Coastguard Worker 
1540*8975f5c5SAndroid Build Coastguard Worker     if (hasActiveRenderPass() && !frontBufferRenderingEnabled)
1541*8975f5c5SAndroid Build Coastguard Worker     {
1542*8975f5c5SAndroid Build Coastguard Worker         mHasDeferredFlush = true;
1543*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
1544*8975f5c5SAndroid Build Coastguard Worker     }
1545*8975f5c5SAndroid Build Coastguard Worker 
1546*8975f5c5SAndroid Build Coastguard Worker     if (isSingleBufferedWindow &&
1547*8975f5c5SAndroid Build Coastguard Worker         mRenderer->getFeatures().swapbuffersOnFlushOrFinishWithSingleBuffer.enabled)
1548*8975f5c5SAndroid Build Coastguard Worker     {
1549*8975f5c5SAndroid Build Coastguard Worker         return mCurrentWindowSurface->onSharedPresentContextFlush(context);
1550*8975f5c5SAndroid Build Coastguard Worker     }
1551*8975f5c5SAndroid Build Coastguard Worker 
1552*8975f5c5SAndroid Build Coastguard Worker     return flushAndSubmitCommands(nullptr, nullptr, RenderPassClosureReason::GLFlush);
1553*8975f5c5SAndroid Build Coastguard Worker }
1554*8975f5c5SAndroid Build Coastguard Worker 
flush(const gl::Context * context)1555*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::flush(const gl::Context *context)
1556*8975f5c5SAndroid Build Coastguard Worker {
1557*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flushImpl(context));
1558*8975f5c5SAndroid Build Coastguard Worker 
1559*8975f5c5SAndroid Build Coastguard Worker     if (!mCurrentWindowSurface || isSingleBufferedWindowCurrent())
1560*8975f5c5SAndroid Build Coastguard Worker     {
1561*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(onFramebufferBoundary(context));
1562*8975f5c5SAndroid Build Coastguard Worker     }
1563*8975f5c5SAndroid Build Coastguard Worker 
1564*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1565*8975f5c5SAndroid Build Coastguard Worker }
1566*8975f5c5SAndroid Build Coastguard Worker 
finish(const gl::Context * context)1567*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::finish(const gl::Context *context)
1568*8975f5c5SAndroid Build Coastguard Worker {
1569*8975f5c5SAndroid Build Coastguard Worker     const bool singleBufferedFlush = isSingleBufferedWindowCurrent() && hasSomethingToFlush();
1570*8975f5c5SAndroid Build Coastguard Worker 
1571*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().swapbuffersOnFlushOrFinishWithSingleBuffer.enabled &&
1572*8975f5c5SAndroid Build Coastguard Worker         singleBufferedFlush)
1573*8975f5c5SAndroid Build Coastguard Worker     {
1574*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mCurrentWindowSurface->onSharedPresentContextFlush(context));
1575*8975f5c5SAndroid Build Coastguard Worker         // While call above performs implicit flush, don't skip |finishImpl| below, since we still
1576*8975f5c5SAndroid Build Coastguard Worker         // need to wait for submitted commands.
1577*8975f5c5SAndroid Build Coastguard Worker     }
1578*8975f5c5SAndroid Build Coastguard Worker 
1579*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(finishImpl(RenderPassClosureReason::GLFinish));
1580*8975f5c5SAndroid Build Coastguard Worker 
1581*8975f5c5SAndroid Build Coastguard Worker     syncObjectPerfCounters(mRenderer->getCommandQueuePerfCounters());
1582*8975f5c5SAndroid Build Coastguard Worker 
1583*8975f5c5SAndroid Build Coastguard Worker     if (!mCurrentWindowSurface || singleBufferedFlush)
1584*8975f5c5SAndroid Build Coastguard Worker     {
1585*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(onFramebufferBoundary(context));
1586*8975f5c5SAndroid Build Coastguard Worker     }
1587*8975f5c5SAndroid Build Coastguard Worker 
1588*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1589*8975f5c5SAndroid Build Coastguard Worker }
1590*8975f5c5SAndroid Build Coastguard Worker 
onFramebufferBoundary(const gl::Context * contextGL)1591*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::onFramebufferBoundary(const gl::Context *contextGL)
1592*8975f5c5SAndroid Build Coastguard Worker {
1593*8975f5c5SAndroid Build Coastguard Worker     mShareGroupVk->onFramebufferBoundary();
1594*8975f5c5SAndroid Build Coastguard Worker     return mRenderer->syncPipelineCacheVk(this, mRenderer->getGlobalOps(), contextGL);
1595*8975f5c5SAndroid Build Coastguard Worker }
1596*8975f5c5SAndroid Build Coastguard Worker 
setupDraw(const gl::Context * context,gl::PrimitiveMode mode,GLint firstVertexOrInvalid,GLsizei vertexOrIndexCount,GLsizei instanceCount,gl::DrawElementsType indexTypeOrInvalid,const void * indices,DirtyBits dirtyBitMask)1597*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::setupDraw(const gl::Context *context,
1598*8975f5c5SAndroid Build Coastguard Worker                                    gl::PrimitiveMode mode,
1599*8975f5c5SAndroid Build Coastguard Worker                                    GLint firstVertexOrInvalid,
1600*8975f5c5SAndroid Build Coastguard Worker                                    GLsizei vertexOrIndexCount,
1601*8975f5c5SAndroid Build Coastguard Worker                                    GLsizei instanceCount,
1602*8975f5c5SAndroid Build Coastguard Worker                                    gl::DrawElementsType indexTypeOrInvalid,
1603*8975f5c5SAndroid Build Coastguard Worker                                    const void *indices,
1604*8975f5c5SAndroid Build Coastguard Worker                                    DirtyBits dirtyBitMask)
1605*8975f5c5SAndroid Build Coastguard Worker {
1606*8975f5c5SAndroid Build Coastguard Worker     // Set any dirty bits that depend on draw call parameters or other objects.
1607*8975f5c5SAndroid Build Coastguard Worker     if (mode != mCurrentDrawMode)
1608*8975f5c5SAndroid Build Coastguard Worker     {
1609*8975f5c5SAndroid Build Coastguard Worker         invalidateCurrentGraphicsPipeline();
1610*8975f5c5SAndroid Build Coastguard Worker         mCurrentDrawMode = mode;
1611*8975f5c5SAndroid Build Coastguard Worker         mGraphicsPipelineDesc->updateTopology(&mGraphicsPipelineTransition, mCurrentDrawMode);
1612*8975f5c5SAndroid Build Coastguard Worker     }
1613*8975f5c5SAndroid Build Coastguard Worker 
1614*8975f5c5SAndroid Build Coastguard Worker     // Must be called before the command buffer is started. Can call finish.
1615*8975f5c5SAndroid Build Coastguard Worker     VertexArrayVk *vertexArrayVk = getVertexArray();
1616*8975f5c5SAndroid Build Coastguard Worker     if (vertexArrayVk->getStreamingVertexAttribsMask().any())
1617*8975f5c5SAndroid Build Coastguard Worker     {
1618*8975f5c5SAndroid Build Coastguard Worker         // All client attribs & any emulated buffered attribs will be updated
1619*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(vertexArrayVk->updateStreamedAttribs(context, firstVertexOrInvalid,
1620*8975f5c5SAndroid Build Coastguard Worker                                                        vertexOrIndexCount, instanceCount,
1621*8975f5c5SAndroid Build Coastguard Worker                                                        indexTypeOrInvalid, indices));
1622*8975f5c5SAndroid Build Coastguard Worker 
1623*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
1624*8975f5c5SAndroid Build Coastguard Worker     }
1625*8975f5c5SAndroid Build Coastguard Worker 
1626*8975f5c5SAndroid Build Coastguard Worker     ProgramExecutableVk *executableVk = vk::GetImpl(mState.getProgramExecutable());
1627*8975f5c5SAndroid Build Coastguard Worker     if (executableVk->updateAndCheckDirtyUniforms())
1628*8975f5c5SAndroid Build Coastguard Worker     {
1629*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_UNIFORMS);
1630*8975f5c5SAndroid Build Coastguard Worker     }
1631*8975f5c5SAndroid Build Coastguard Worker 
1632*8975f5c5SAndroid Build Coastguard Worker     // Update transform feedback offsets on every draw call when emulating transform feedback.  This
1633*8975f5c5SAndroid Build Coastguard Worker     // relies on the fact that no geometry/tessellation, indirect or indexed calls are supported in
1634*8975f5c5SAndroid Build Coastguard Worker     // ES3.1 (and emulation is not done for ES3.2).
1635*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().emulateTransformFeedback.enabled &&
1636*8975f5c5SAndroid Build Coastguard Worker         mState.isTransformFeedbackActiveUnpaused())
1637*8975f5c5SAndroid Build Coastguard Worker     {
1638*8975f5c5SAndroid Build Coastguard Worker         ASSERT(firstVertexOrInvalid != -1);
1639*8975f5c5SAndroid Build Coastguard Worker         mXfbBaseVertex             = firstVertexOrInvalid;
1640*8975f5c5SAndroid Build Coastguard Worker         mXfbVertexCountPerInstance = vertexOrIndexCount;
1641*8975f5c5SAndroid Build Coastguard Worker         invalidateGraphicsDriverUniforms();
1642*8975f5c5SAndroid Build Coastguard Worker     }
1643*8975f5c5SAndroid Build Coastguard Worker 
1644*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBits = mGraphicsDirtyBits & dirtyBitMask;
1645*8975f5c5SAndroid Build Coastguard Worker 
1646*8975f5c5SAndroid Build Coastguard Worker     if (dirtyBits.any())
1647*8975f5c5SAndroid Build Coastguard Worker     {
1648*8975f5c5SAndroid Build Coastguard Worker         // Flush any relevant dirty bits.
1649*8975f5c5SAndroid Build Coastguard Worker         for (DirtyBits::Iterator dirtyBitIter = dirtyBits.begin(); dirtyBitIter != dirtyBits.end();
1650*8975f5c5SAndroid Build Coastguard Worker              ++dirtyBitIter)
1651*8975f5c5SAndroid Build Coastguard Worker         {
1652*8975f5c5SAndroid Build Coastguard Worker             ASSERT(mGraphicsDirtyBitHandlers[*dirtyBitIter]);
1653*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(
1654*8975f5c5SAndroid Build Coastguard Worker                 (this->*mGraphicsDirtyBitHandlers[*dirtyBitIter])(&dirtyBitIter, dirtyBitMask));
1655*8975f5c5SAndroid Build Coastguard Worker         }
1656*8975f5c5SAndroid Build Coastguard Worker 
1657*8975f5c5SAndroid Build Coastguard Worker         // Reset the processed dirty bits, except for those that are expected to persist between
1658*8975f5c5SAndroid Build Coastguard Worker         // draw calls (such as the framebuffer fetch barrier which needs to be issued again and
1659*8975f5c5SAndroid Build Coastguard Worker         // again).
1660*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits &= (~dirtyBitMask | mPersistentGraphicsDirtyBits);
1661*8975f5c5SAndroid Build Coastguard Worker     }
1662*8975f5c5SAndroid Build Coastguard Worker 
1663*8975f5c5SAndroid Build Coastguard Worker     // Render pass must be always available at this point.
1664*8975f5c5SAndroid Build Coastguard Worker     ASSERT(hasActiveRenderPass());
1665*8975f5c5SAndroid Build Coastguard Worker 
1666*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.getAndResetDirtyUniformBlocks().none());
1667*8975f5c5SAndroid Build Coastguard Worker 
1668*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1669*8975f5c5SAndroid Build Coastguard Worker }
1670*8975f5c5SAndroid Build Coastguard Worker 
setupIndexedDraw(const gl::Context * context,gl::PrimitiveMode mode,GLsizei indexCount,GLsizei instanceCount,gl::DrawElementsType indexType,const void * indices)1671*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::setupIndexedDraw(const gl::Context *context,
1672*8975f5c5SAndroid Build Coastguard Worker                                           gl::PrimitiveMode mode,
1673*8975f5c5SAndroid Build Coastguard Worker                                           GLsizei indexCount,
1674*8975f5c5SAndroid Build Coastguard Worker                                           GLsizei instanceCount,
1675*8975f5c5SAndroid Build Coastguard Worker                                           gl::DrawElementsType indexType,
1676*8975f5c5SAndroid Build Coastguard Worker                                           const void *indices)
1677*8975f5c5SAndroid Build Coastguard Worker {
1678*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mode != gl::PrimitiveMode::LineLoop);
1679*8975f5c5SAndroid Build Coastguard Worker 
1680*8975f5c5SAndroid Build Coastguard Worker     if (indexType != mCurrentDrawElementsType)
1681*8975f5c5SAndroid Build Coastguard Worker     {
1682*8975f5c5SAndroid Build Coastguard Worker         mCurrentDrawElementsType = indexType;
1683*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(onIndexBufferChange(nullptr));
1684*8975f5c5SAndroid Build Coastguard Worker     }
1685*8975f5c5SAndroid Build Coastguard Worker 
1686*8975f5c5SAndroid Build Coastguard Worker     VertexArrayVk *vertexArrayVk         = getVertexArray();
1687*8975f5c5SAndroid Build Coastguard Worker     const gl::Buffer *elementArrayBuffer = vertexArrayVk->getState().getElementArrayBuffer();
1688*8975f5c5SAndroid Build Coastguard Worker     if (!elementArrayBuffer)
1689*8975f5c5SAndroid Build Coastguard Worker     {
1690*8975f5c5SAndroid Build Coastguard Worker         BufferBindingDirty bindingDirty;
1691*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(vertexArrayVk->convertIndexBufferCPU(this, indexType, indexCount, indices,
1692*8975f5c5SAndroid Build Coastguard Worker                                                        &bindingDirty));
1693*8975f5c5SAndroid Build Coastguard Worker         mCurrentIndexBufferOffset = 0;
1694*8975f5c5SAndroid Build Coastguard Worker 
1695*8975f5c5SAndroid Build Coastguard Worker         // We only set dirty bit when the bound buffer actually changed.
1696*8975f5c5SAndroid Build Coastguard Worker         if (bindingDirty == BufferBindingDirty::Yes)
1697*8975f5c5SAndroid Build Coastguard Worker         {
1698*8975f5c5SAndroid Build Coastguard Worker             mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
1699*8975f5c5SAndroid Build Coastguard Worker         }
1700*8975f5c5SAndroid Build Coastguard Worker     }
1701*8975f5c5SAndroid Build Coastguard Worker     else
1702*8975f5c5SAndroid Build Coastguard Worker     {
1703*8975f5c5SAndroid Build Coastguard Worker         mCurrentIndexBufferOffset = reinterpret_cast<VkDeviceSize>(indices);
1704*8975f5c5SAndroid Build Coastguard Worker 
1705*8975f5c5SAndroid Build Coastguard Worker         if (indices != mLastIndexBufferOffset)
1706*8975f5c5SAndroid Build Coastguard Worker         {
1707*8975f5c5SAndroid Build Coastguard Worker             mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
1708*8975f5c5SAndroid Build Coastguard Worker             mLastIndexBufferOffset = indices;
1709*8975f5c5SAndroid Build Coastguard Worker         }
1710*8975f5c5SAndroid Build Coastguard Worker 
1711*8975f5c5SAndroid Build Coastguard Worker         // When you draw with LineLoop mode or GL_UNSIGNED_BYTE type, we may allocate its own
1712*8975f5c5SAndroid Build Coastguard Worker         // element buffer and modify mCurrentElementArrayBuffer. When we switch out of that draw
1713*8975f5c5SAndroid Build Coastguard Worker         // mode, we must reset mCurrentElementArrayBuffer back to the vertexArray's element buffer.
1714*8975f5c5SAndroid Build Coastguard Worker         // Since in either case we set DIRTY_BIT_INDEX_BUFFER dirty bit, we use this bit to re-sync
1715*8975f5c5SAndroid Build Coastguard Worker         // mCurrentElementArrayBuffer.
1716*8975f5c5SAndroid Build Coastguard Worker         if (mGraphicsDirtyBits[DIRTY_BIT_INDEX_BUFFER])
1717*8975f5c5SAndroid Build Coastguard Worker         {
1718*8975f5c5SAndroid Build Coastguard Worker             vertexArrayVk->updateCurrentElementArrayBuffer();
1719*8975f5c5SAndroid Build Coastguard Worker         }
1720*8975f5c5SAndroid Build Coastguard Worker 
1721*8975f5c5SAndroid Build Coastguard Worker         if (shouldConvertUint8VkIndexType(indexType) && mGraphicsDirtyBits[DIRTY_BIT_INDEX_BUFFER])
1722*8975f5c5SAndroid Build Coastguard Worker         {
1723*8975f5c5SAndroid Build Coastguard Worker             ANGLE_VK_PERF_WARNING(this, GL_DEBUG_SEVERITY_LOW,
1724*8975f5c5SAndroid Build Coastguard Worker                                   "Potential inefficiency emulating uint8 vertex attributes due to "
1725*8975f5c5SAndroid Build Coastguard Worker                                   "lack of hardware support");
1726*8975f5c5SAndroid Build Coastguard Worker 
1727*8975f5c5SAndroid Build Coastguard Worker             BufferVk *bufferVk             = vk::GetImpl(elementArrayBuffer);
1728*8975f5c5SAndroid Build Coastguard Worker             vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
1729*8975f5c5SAndroid Build Coastguard Worker 
1730*8975f5c5SAndroid Build Coastguard Worker             if (bufferHelper.isHostVisible() &&
1731*8975f5c5SAndroid Build Coastguard Worker                 mRenderer->hasResourceUseFinished(bufferHelper.getResourceUse()))
1732*8975f5c5SAndroid Build Coastguard Worker             {
1733*8975f5c5SAndroid Build Coastguard Worker                 uint8_t *src = nullptr;
1734*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(
1735*8975f5c5SAndroid Build Coastguard Worker                     bufferVk->mapImpl(this, GL_MAP_READ_BIT, reinterpret_cast<void **>(&src)));
1736*8975f5c5SAndroid Build Coastguard Worker                 // Note: bufferOffset is not added here because mapImpl already adds it.
1737*8975f5c5SAndroid Build Coastguard Worker                 src += reinterpret_cast<uintptr_t>(indices);
1738*8975f5c5SAndroid Build Coastguard Worker                 const size_t byteCount = static_cast<size_t>(elementArrayBuffer->getSize()) -
1739*8975f5c5SAndroid Build Coastguard Worker                                          reinterpret_cast<uintptr_t>(indices);
1740*8975f5c5SAndroid Build Coastguard Worker                 BufferBindingDirty bindingDirty;
1741*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(vertexArrayVk->convertIndexBufferCPU(this, indexType, byteCount, src,
1742*8975f5c5SAndroid Build Coastguard Worker                                                                &bindingDirty));
1743*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(bufferVk->unmapImpl(this));
1744*8975f5c5SAndroid Build Coastguard Worker             }
1745*8975f5c5SAndroid Build Coastguard Worker             else
1746*8975f5c5SAndroid Build Coastguard Worker             {
1747*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(vertexArrayVk->convertIndexBufferGPU(this, bufferVk, indices));
1748*8975f5c5SAndroid Build Coastguard Worker             }
1749*8975f5c5SAndroid Build Coastguard Worker 
1750*8975f5c5SAndroid Build Coastguard Worker             mCurrentIndexBufferOffset = 0;
1751*8975f5c5SAndroid Build Coastguard Worker         }
1752*8975f5c5SAndroid Build Coastguard Worker     }
1753*8975f5c5SAndroid Build Coastguard Worker 
1754*8975f5c5SAndroid Build Coastguard Worker     mCurrentIndexBuffer = vertexArrayVk->getCurrentElementArrayBuffer();
1755*8975f5c5SAndroid Build Coastguard Worker     return setupDraw(context, mode, 0, indexCount, instanceCount, indexType, indices,
1756*8975f5c5SAndroid Build Coastguard Worker                      mIndexedDirtyBitsMask);
1757*8975f5c5SAndroid Build Coastguard Worker }
1758*8975f5c5SAndroid Build Coastguard Worker 
setupIndirectDraw(const gl::Context * context,gl::PrimitiveMode mode,DirtyBits dirtyBitMask,vk::BufferHelper * indirectBuffer)1759*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::setupIndirectDraw(const gl::Context *context,
1760*8975f5c5SAndroid Build Coastguard Worker                                            gl::PrimitiveMode mode,
1761*8975f5c5SAndroid Build Coastguard Worker                                            DirtyBits dirtyBitMask,
1762*8975f5c5SAndroid Build Coastguard Worker                                            vk::BufferHelper *indirectBuffer)
1763*8975f5c5SAndroid Build Coastguard Worker {
1764*8975f5c5SAndroid Build Coastguard Worker     GLint firstVertex     = -1;
1765*8975f5c5SAndroid Build Coastguard Worker     GLsizei vertexCount   = 0;
1766*8975f5c5SAndroid Build Coastguard Worker     GLsizei instanceCount = 1;
1767*8975f5c5SAndroid Build Coastguard Worker 
1768*8975f5c5SAndroid Build Coastguard Worker     // Break the render pass if the indirect buffer was previously used as the output from transform
1769*8975f5c5SAndroid Build Coastguard Worker     // feedback.
1770*8975f5c5SAndroid Build Coastguard Worker     if (mCurrentTransformFeedbackQueueSerial.valid() &&
1771*8975f5c5SAndroid Build Coastguard Worker         indirectBuffer->writtenByCommandBuffer(mCurrentTransformFeedbackQueueSerial))
1772*8975f5c5SAndroid Build Coastguard Worker     {
1773*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(
1774*8975f5c5SAndroid Build Coastguard Worker             flushCommandsAndEndRenderPass(RenderPassClosureReason::XfbWriteThenIndirectDrawBuffer));
1775*8975f5c5SAndroid Build Coastguard Worker     }
1776*8975f5c5SAndroid Build Coastguard Worker 
1777*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(setupDraw(context, mode, firstVertex, vertexCount, instanceCount,
1778*8975f5c5SAndroid Build Coastguard Worker                         gl::DrawElementsType::InvalidEnum, nullptr, dirtyBitMask));
1779*8975f5c5SAndroid Build Coastguard Worker 
1780*8975f5c5SAndroid Build Coastguard Worker     // Process indirect buffer after render pass has started.
1781*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommands->bufferRead(VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
1782*8975f5c5SAndroid Build Coastguard Worker                                     vk::PipelineStage::DrawIndirect, indirectBuffer);
1783*8975f5c5SAndroid Build Coastguard Worker 
1784*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1785*8975f5c5SAndroid Build Coastguard Worker }
1786*8975f5c5SAndroid Build Coastguard Worker 
setupIndexedIndirectDraw(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType indexType,vk::BufferHelper * indirectBuffer)1787*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::setupIndexedIndirectDraw(const gl::Context *context,
1788*8975f5c5SAndroid Build Coastguard Worker                                                   gl::PrimitiveMode mode,
1789*8975f5c5SAndroid Build Coastguard Worker                                                   gl::DrawElementsType indexType,
1790*8975f5c5SAndroid Build Coastguard Worker                                                   vk::BufferHelper *indirectBuffer)
1791*8975f5c5SAndroid Build Coastguard Worker {
1792*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mode != gl::PrimitiveMode::LineLoop);
1793*8975f5c5SAndroid Build Coastguard Worker 
1794*8975f5c5SAndroid Build Coastguard Worker     VertexArrayVk *vertexArrayVk = getVertexArray();
1795*8975f5c5SAndroid Build Coastguard Worker     mCurrentIndexBuffer          = vertexArrayVk->getCurrentElementArrayBuffer();
1796*8975f5c5SAndroid Build Coastguard Worker     if (indexType != mCurrentDrawElementsType)
1797*8975f5c5SAndroid Build Coastguard Worker     {
1798*8975f5c5SAndroid Build Coastguard Worker         mCurrentDrawElementsType = indexType;
1799*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(onIndexBufferChange(nullptr));
1800*8975f5c5SAndroid Build Coastguard Worker     }
1801*8975f5c5SAndroid Build Coastguard Worker 
1802*8975f5c5SAndroid Build Coastguard Worker     return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, indirectBuffer);
1803*8975f5c5SAndroid Build Coastguard Worker }
1804*8975f5c5SAndroid Build Coastguard Worker 
setupLineLoopIndexedIndirectDraw(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType indexType,vk::BufferHelper * srcIndexBuffer,vk::BufferHelper * srcIndirectBuffer,VkDeviceSize indirectBufferOffset,vk::BufferHelper ** indirectBufferOut)1805*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::setupLineLoopIndexedIndirectDraw(const gl::Context *context,
1806*8975f5c5SAndroid Build Coastguard Worker                                                           gl::PrimitiveMode mode,
1807*8975f5c5SAndroid Build Coastguard Worker                                                           gl::DrawElementsType indexType,
1808*8975f5c5SAndroid Build Coastguard Worker                                                           vk::BufferHelper *srcIndexBuffer,
1809*8975f5c5SAndroid Build Coastguard Worker                                                           vk::BufferHelper *srcIndirectBuffer,
1810*8975f5c5SAndroid Build Coastguard Worker                                                           VkDeviceSize indirectBufferOffset,
1811*8975f5c5SAndroid Build Coastguard Worker                                                           vk::BufferHelper **indirectBufferOut)
1812*8975f5c5SAndroid Build Coastguard Worker {
1813*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mode == gl::PrimitiveMode::LineLoop);
1814*8975f5c5SAndroid Build Coastguard Worker 
1815*8975f5c5SAndroid Build Coastguard Worker     vk::BufferHelper *dstIndexBuffer    = nullptr;
1816*8975f5c5SAndroid Build Coastguard Worker     vk::BufferHelper *dstIndirectBuffer = nullptr;
1817*8975f5c5SAndroid Build Coastguard Worker 
1818*8975f5c5SAndroid Build Coastguard Worker     VertexArrayVk *vertexArrayVk = getVertexArray();
1819*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(vertexArrayVk->handleLineLoopIndexIndirect(this, indexType, srcIndexBuffer,
1820*8975f5c5SAndroid Build Coastguard Worker                                                          srcIndirectBuffer, indirectBufferOffset,
1821*8975f5c5SAndroid Build Coastguard Worker                                                          &dstIndexBuffer, &dstIndirectBuffer));
1822*8975f5c5SAndroid Build Coastguard Worker 
1823*8975f5c5SAndroid Build Coastguard Worker     mCurrentIndexBuffer = dstIndexBuffer;
1824*8975f5c5SAndroid Build Coastguard Worker     *indirectBufferOut  = dstIndirectBuffer;
1825*8975f5c5SAndroid Build Coastguard Worker 
1826*8975f5c5SAndroid Build Coastguard Worker     if (indexType != mCurrentDrawElementsType)
1827*8975f5c5SAndroid Build Coastguard Worker     {
1828*8975f5c5SAndroid Build Coastguard Worker         mCurrentDrawElementsType = indexType;
1829*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(onIndexBufferChange(nullptr));
1830*8975f5c5SAndroid Build Coastguard Worker     }
1831*8975f5c5SAndroid Build Coastguard Worker 
1832*8975f5c5SAndroid Build Coastguard Worker     return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, dstIndirectBuffer);
1833*8975f5c5SAndroid Build Coastguard Worker }
1834*8975f5c5SAndroid Build Coastguard Worker 
setupLineLoopIndirectDraw(const gl::Context * context,gl::PrimitiveMode mode,vk::BufferHelper * indirectBuffer,VkDeviceSize indirectBufferOffset,vk::BufferHelper ** indirectBufferOut)1835*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::setupLineLoopIndirectDraw(const gl::Context *context,
1836*8975f5c5SAndroid Build Coastguard Worker                                                    gl::PrimitiveMode mode,
1837*8975f5c5SAndroid Build Coastguard Worker                                                    vk::BufferHelper *indirectBuffer,
1838*8975f5c5SAndroid Build Coastguard Worker                                                    VkDeviceSize indirectBufferOffset,
1839*8975f5c5SAndroid Build Coastguard Worker                                                    vk::BufferHelper **indirectBufferOut)
1840*8975f5c5SAndroid Build Coastguard Worker {
1841*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mode == gl::PrimitiveMode::LineLoop);
1842*8975f5c5SAndroid Build Coastguard Worker 
1843*8975f5c5SAndroid Build Coastguard Worker     vk::BufferHelper *indexBufferHelperOut    = nullptr;
1844*8975f5c5SAndroid Build Coastguard Worker     vk::BufferHelper *indirectBufferHelperOut = nullptr;
1845*8975f5c5SAndroid Build Coastguard Worker 
1846*8975f5c5SAndroid Build Coastguard Worker     VertexArrayVk *vertexArrayVk = getVertexArray();
1847*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(vertexArrayVk->handleLineLoopIndirectDraw(context, indirectBuffer,
1848*8975f5c5SAndroid Build Coastguard Worker                                                         indirectBufferOffset, &indexBufferHelperOut,
1849*8975f5c5SAndroid Build Coastguard Worker                                                         &indirectBufferHelperOut));
1850*8975f5c5SAndroid Build Coastguard Worker 
1851*8975f5c5SAndroid Build Coastguard Worker     *indirectBufferOut = indirectBufferHelperOut;
1852*8975f5c5SAndroid Build Coastguard Worker     mCurrentIndexBuffer = indexBufferHelperOut;
1853*8975f5c5SAndroid Build Coastguard Worker 
1854*8975f5c5SAndroid Build Coastguard Worker     if (gl::DrawElementsType::UnsignedInt != mCurrentDrawElementsType)
1855*8975f5c5SAndroid Build Coastguard Worker     {
1856*8975f5c5SAndroid Build Coastguard Worker         mCurrentDrawElementsType = gl::DrawElementsType::UnsignedInt;
1857*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(onIndexBufferChange(nullptr));
1858*8975f5c5SAndroid Build Coastguard Worker     }
1859*8975f5c5SAndroid Build Coastguard Worker 
1860*8975f5c5SAndroid Build Coastguard Worker     return setupIndirectDraw(context, mode, mIndexedDirtyBitsMask, indirectBufferHelperOut);
1861*8975f5c5SAndroid Build Coastguard Worker }
1862*8975f5c5SAndroid Build Coastguard Worker 
setupLineLoopDraw(const gl::Context * context,gl::PrimitiveMode mode,GLint firstVertex,GLsizei vertexOrIndexCount,gl::DrawElementsType indexTypeOrInvalid,const void * indices,uint32_t * numIndicesOut)1863*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
1864*8975f5c5SAndroid Build Coastguard Worker                                            gl::PrimitiveMode mode,
1865*8975f5c5SAndroid Build Coastguard Worker                                            GLint firstVertex,
1866*8975f5c5SAndroid Build Coastguard Worker                                            GLsizei vertexOrIndexCount,
1867*8975f5c5SAndroid Build Coastguard Worker                                            gl::DrawElementsType indexTypeOrInvalid,
1868*8975f5c5SAndroid Build Coastguard Worker                                            const void *indices,
1869*8975f5c5SAndroid Build Coastguard Worker                                            uint32_t *numIndicesOut)
1870*8975f5c5SAndroid Build Coastguard Worker {
1871*8975f5c5SAndroid Build Coastguard Worker     mCurrentIndexBufferOffset    = 0;
1872*8975f5c5SAndroid Build Coastguard Worker     vk::BufferHelper *dstIndexBuffer = mCurrentIndexBuffer;
1873*8975f5c5SAndroid Build Coastguard Worker 
1874*8975f5c5SAndroid Build Coastguard Worker     VertexArrayVk *vertexArrayVk = getVertexArray();
1875*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(vertexArrayVk->handleLineLoop(this, firstVertex, vertexOrIndexCount,
1876*8975f5c5SAndroid Build Coastguard Worker                                             indexTypeOrInvalid, indices, &dstIndexBuffer,
1877*8975f5c5SAndroid Build Coastguard Worker                                             numIndicesOut));
1878*8975f5c5SAndroid Build Coastguard Worker 
1879*8975f5c5SAndroid Build Coastguard Worker     mCurrentIndexBuffer = dstIndexBuffer;
1880*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(onIndexBufferChange(nullptr));
1881*8975f5c5SAndroid Build Coastguard Worker     mCurrentDrawElementsType = indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum
1882*8975f5c5SAndroid Build Coastguard Worker                                    ? indexTypeOrInvalid
1883*8975f5c5SAndroid Build Coastguard Worker                                    : gl::DrawElementsType::UnsignedInt;
1884*8975f5c5SAndroid Build Coastguard Worker     return setupDraw(context, mode, firstVertex, vertexOrIndexCount, 1, indexTypeOrInvalid, indices,
1885*8975f5c5SAndroid Build Coastguard Worker                      mIndexedDirtyBitsMask);
1886*8975f5c5SAndroid Build Coastguard Worker }
1887*8975f5c5SAndroid Build Coastguard Worker 
setupDispatch(const gl::Context * context)1888*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::setupDispatch(const gl::Context *context)
1889*8975f5c5SAndroid Build Coastguard Worker {
1890*8975f5c5SAndroid Build Coastguard Worker     // TODO: We don't currently check if this flush is necessary.  It serves to make sure the
1891*8975f5c5SAndroid Build Coastguard Worker     // barriers issued during dirty bit handling aren't reordered too early.
1892*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/382090958
1893*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flushOutsideRenderPassCommands());
1894*8975f5c5SAndroid Build Coastguard Worker 
1895*8975f5c5SAndroid Build Coastguard Worker     ProgramExecutableVk *executableVk = vk::GetImpl(mState.getProgramExecutable());
1896*8975f5c5SAndroid Build Coastguard Worker     if (executableVk->updateAndCheckDirtyUniforms())
1897*8975f5c5SAndroid Build Coastguard Worker     {
1898*8975f5c5SAndroid Build Coastguard Worker         mComputeDirtyBits.set(DIRTY_BIT_UNIFORMS);
1899*8975f5c5SAndroid Build Coastguard Worker     }
1900*8975f5c5SAndroid Build Coastguard Worker 
1901*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBits = mComputeDirtyBits;
1902*8975f5c5SAndroid Build Coastguard Worker 
1903*8975f5c5SAndroid Build Coastguard Worker     // Flush any relevant dirty bits.
1904*8975f5c5SAndroid Build Coastguard Worker     for (DirtyBits::Iterator dirtyBitIter = dirtyBits.begin(); dirtyBitIter != dirtyBits.end();
1905*8975f5c5SAndroid Build Coastguard Worker          ++dirtyBitIter)
1906*8975f5c5SAndroid Build Coastguard Worker     {
1907*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mComputeDirtyBitHandlers[*dirtyBitIter]);
1908*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY((this->*mComputeDirtyBitHandlers[*dirtyBitIter])(&dirtyBitIter));
1909*8975f5c5SAndroid Build Coastguard Worker     }
1910*8975f5c5SAndroid Build Coastguard Worker 
1911*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBits.reset();
1912*8975f5c5SAndroid Build Coastguard Worker 
1913*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.getAndResetDirtyUniformBlocks().none());
1914*8975f5c5SAndroid Build Coastguard Worker 
1915*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1916*8975f5c5SAndroid Build Coastguard Worker }
1917*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsMemoryBarrier(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)1918*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsMemoryBarrier(DirtyBits::Iterator *dirtyBitsIterator,
1919*8975f5c5SAndroid Build Coastguard Worker                                                           DirtyBits dirtyBitMask)
1920*8975f5c5SAndroid Build Coastguard Worker {
1921*8975f5c5SAndroid Build Coastguard Worker     return handleDirtyMemoryBarrierImpl(dirtyBitsIterator, dirtyBitMask);
1922*8975f5c5SAndroid Build Coastguard Worker }
1923*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyComputeMemoryBarrier(DirtyBits::Iterator * dirtyBitsIterator)1924*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyComputeMemoryBarrier(DirtyBits::Iterator *dirtyBitsIterator)
1925*8975f5c5SAndroid Build Coastguard Worker {
1926*8975f5c5SAndroid Build Coastguard Worker     return handleDirtyMemoryBarrierImpl(nullptr, {});
1927*8975f5c5SAndroid Build Coastguard Worker }
1928*8975f5c5SAndroid Build Coastguard Worker 
renderPassUsesStorageResources() const1929*8975f5c5SAndroid Build Coastguard Worker bool ContextVk::renderPassUsesStorageResources() const
1930*8975f5c5SAndroid Build Coastguard Worker {
1931*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
1932*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executable);
1933*8975f5c5SAndroid Build Coastguard Worker 
1934*8975f5c5SAndroid Build Coastguard Worker     if (!mRenderPassCommands->started())
1935*8975f5c5SAndroid Build Coastguard Worker     {
1936*8975f5c5SAndroid Build Coastguard Worker         return false;
1937*8975f5c5SAndroid Build Coastguard Worker     }
1938*8975f5c5SAndroid Build Coastguard Worker 
1939*8975f5c5SAndroid Build Coastguard Worker     // Storage images:
1940*8975f5c5SAndroid Build Coastguard Worker     for (size_t imageUnitIndex : executable->getActiveImagesMask())
1941*8975f5c5SAndroid Build Coastguard Worker     {
1942*8975f5c5SAndroid Build Coastguard Worker         const gl::Texture *texture = mState.getImageUnit(imageUnitIndex).texture.get();
1943*8975f5c5SAndroid Build Coastguard Worker         if (texture == nullptr)
1944*8975f5c5SAndroid Build Coastguard Worker         {
1945*8975f5c5SAndroid Build Coastguard Worker             continue;
1946*8975f5c5SAndroid Build Coastguard Worker         }
1947*8975f5c5SAndroid Build Coastguard Worker 
1948*8975f5c5SAndroid Build Coastguard Worker         TextureVk *textureVk = vk::GetImpl(texture);
1949*8975f5c5SAndroid Build Coastguard Worker 
1950*8975f5c5SAndroid Build Coastguard Worker         if (texture->getType() == gl::TextureType::Buffer)
1951*8975f5c5SAndroid Build Coastguard Worker         {
1952*8975f5c5SAndroid Build Coastguard Worker             vk::BufferHelper &buffer = vk::GetImpl(textureVk->getBuffer().get())->getBuffer();
1953*8975f5c5SAndroid Build Coastguard Worker             if (mRenderPassCommands->usesBuffer(buffer))
1954*8975f5c5SAndroid Build Coastguard Worker             {
1955*8975f5c5SAndroid Build Coastguard Worker                 return true;
1956*8975f5c5SAndroid Build Coastguard Worker             }
1957*8975f5c5SAndroid Build Coastguard Worker         }
1958*8975f5c5SAndroid Build Coastguard Worker         else
1959*8975f5c5SAndroid Build Coastguard Worker         {
1960*8975f5c5SAndroid Build Coastguard Worker             vk::ImageHelper &image = textureVk->getImage();
1961*8975f5c5SAndroid Build Coastguard Worker             // Images only need to close the render pass if they need a layout transition.  Outside
1962*8975f5c5SAndroid Build Coastguard Worker             // render pass command buffer doesn't need closing as the layout transition barriers are
1963*8975f5c5SAndroid Build Coastguard Worker             // recorded in sequence with the rest of the commands.
1964*8975f5c5SAndroid Build Coastguard Worker             if (mRenderPassCommands->usesImage(image))
1965*8975f5c5SAndroid Build Coastguard Worker             {
1966*8975f5c5SAndroid Build Coastguard Worker                 return true;
1967*8975f5c5SAndroid Build Coastguard Worker             }
1968*8975f5c5SAndroid Build Coastguard Worker         }
1969*8975f5c5SAndroid Build Coastguard Worker     }
1970*8975f5c5SAndroid Build Coastguard Worker 
1971*8975f5c5SAndroid Build Coastguard Worker     // Storage buffers:
1972*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::InterfaceBlock> &blocks = executable->getShaderStorageBlocks();
1973*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
1974*8975f5c5SAndroid Build Coastguard Worker     {
1975*8975f5c5SAndroid Build Coastguard Worker         const uint32_t binding = executable->getShaderStorageBlockBinding(bufferIndex);
1976*8975f5c5SAndroid Build Coastguard Worker         const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
1977*8975f5c5SAndroid Build Coastguard Worker             mState.getIndexedShaderStorageBuffer(binding);
1978*8975f5c5SAndroid Build Coastguard Worker 
1979*8975f5c5SAndroid Build Coastguard Worker         if (bufferBinding.get() == nullptr)
1980*8975f5c5SAndroid Build Coastguard Worker         {
1981*8975f5c5SAndroid Build Coastguard Worker             continue;
1982*8975f5c5SAndroid Build Coastguard Worker         }
1983*8975f5c5SAndroid Build Coastguard Worker 
1984*8975f5c5SAndroid Build Coastguard Worker         vk::BufferHelper &buffer = vk::GetImpl(bufferBinding.get())->getBuffer();
1985*8975f5c5SAndroid Build Coastguard Worker         if (mRenderPassCommands->usesBuffer(buffer))
1986*8975f5c5SAndroid Build Coastguard Worker         {
1987*8975f5c5SAndroid Build Coastguard Worker             return true;
1988*8975f5c5SAndroid Build Coastguard Worker         }
1989*8975f5c5SAndroid Build Coastguard Worker     }
1990*8975f5c5SAndroid Build Coastguard Worker 
1991*8975f5c5SAndroid Build Coastguard Worker     // Atomic counters:
1992*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers =
1993*8975f5c5SAndroid Build Coastguard Worker         executable->getAtomicCounterBuffers();
1994*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t bufferIndex = 0; bufferIndex < atomicCounterBuffers.size(); ++bufferIndex)
1995*8975f5c5SAndroid Build Coastguard Worker     {
1996*8975f5c5SAndroid Build Coastguard Worker         const uint32_t binding = executable->getAtomicCounterBufferBinding(bufferIndex);
1997*8975f5c5SAndroid Build Coastguard Worker         const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
1998*8975f5c5SAndroid Build Coastguard Worker             mState.getIndexedAtomicCounterBuffer(binding);
1999*8975f5c5SAndroid Build Coastguard Worker 
2000*8975f5c5SAndroid Build Coastguard Worker         if (bufferBinding.get() == nullptr)
2001*8975f5c5SAndroid Build Coastguard Worker         {
2002*8975f5c5SAndroid Build Coastguard Worker             continue;
2003*8975f5c5SAndroid Build Coastguard Worker         }
2004*8975f5c5SAndroid Build Coastguard Worker 
2005*8975f5c5SAndroid Build Coastguard Worker         vk::BufferHelper &buffer = vk::GetImpl(bufferBinding.get())->getBuffer();
2006*8975f5c5SAndroid Build Coastguard Worker         if (mRenderPassCommands->usesBuffer(buffer))
2007*8975f5c5SAndroid Build Coastguard Worker         {
2008*8975f5c5SAndroid Build Coastguard Worker             return true;
2009*8975f5c5SAndroid Build Coastguard Worker         }
2010*8975f5c5SAndroid Build Coastguard Worker     }
2011*8975f5c5SAndroid Build Coastguard Worker 
2012*8975f5c5SAndroid Build Coastguard Worker     return false;
2013*8975f5c5SAndroid Build Coastguard Worker }
2014*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyMemoryBarrierImpl(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2015*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyMemoryBarrierImpl(DirtyBits::Iterator *dirtyBitsIterator,
2016*8975f5c5SAndroid Build Coastguard Worker                                                       DirtyBits dirtyBitMask)
2017*8975f5c5SAndroid Build Coastguard Worker {
2018*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2019*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executable);
2020*8975f5c5SAndroid Build Coastguard Worker 
2021*8975f5c5SAndroid Build Coastguard Worker     const bool hasImages         = executable->hasImages();
2022*8975f5c5SAndroid Build Coastguard Worker     const bool hasStorageBuffers = executable->hasStorageBuffers();
2023*8975f5c5SAndroid Build Coastguard Worker     const bool hasAtomicCounters = executable->hasAtomicCounterBuffers();
2024*8975f5c5SAndroid Build Coastguard Worker 
2025*8975f5c5SAndroid Build Coastguard Worker     if (!hasImages && !hasStorageBuffers && !hasAtomicCounters)
2026*8975f5c5SAndroid Build Coastguard Worker     {
2027*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2028*8975f5c5SAndroid Build Coastguard Worker     }
2029*8975f5c5SAndroid Build Coastguard Worker 
2030*8975f5c5SAndroid Build Coastguard Worker     // Break the render pass if necessary.  This is only needed for write-after-read situations, and
2031*8975f5c5SAndroid Build Coastguard Worker     // is done by checking whether current storage buffers and images are used in the render pass.
2032*8975f5c5SAndroid Build Coastguard Worker     if (renderPassUsesStorageResources())
2033*8975f5c5SAndroid Build Coastguard Worker     {
2034*8975f5c5SAndroid Build Coastguard Worker         // Either set later bits (if called during handling of graphics dirty bits), or set the
2035*8975f5c5SAndroid Build Coastguard Worker         // dirty bits directly (if called during handling of compute dirty bits).
2036*8975f5c5SAndroid Build Coastguard Worker         if (dirtyBitsIterator)
2037*8975f5c5SAndroid Build Coastguard Worker         {
2038*8975f5c5SAndroid Build Coastguard Worker             return flushDirtyGraphicsRenderPass(
2039*8975f5c5SAndroid Build Coastguard Worker                 dirtyBitsIterator, dirtyBitMask,
2040*8975f5c5SAndroid Build Coastguard Worker                 RenderPassClosureReason::GLMemoryBarrierThenStorageResource);
2041*8975f5c5SAndroid Build Coastguard Worker         }
2042*8975f5c5SAndroid Build Coastguard Worker         else
2043*8975f5c5SAndroid Build Coastguard Worker         {
2044*8975f5c5SAndroid Build Coastguard Worker             return flushCommandsAndEndRenderPass(
2045*8975f5c5SAndroid Build Coastguard Worker                 RenderPassClosureReason::GLMemoryBarrierThenStorageResource);
2046*8975f5c5SAndroid Build Coastguard Worker         }
2047*8975f5c5SAndroid Build Coastguard Worker     }
2048*8975f5c5SAndroid Build Coastguard Worker 
2049*8975f5c5SAndroid Build Coastguard Worker     // Flushing outside render pass commands is cheap.  If a memory barrier has been issued in its
2050*8975f5c5SAndroid Build Coastguard Worker     // life time, just flush it instead of wasting time trying to figure out if it's necessary.
2051*8975f5c5SAndroid Build Coastguard Worker     if (mOutsideRenderPassCommands->hasGLMemoryBarrierIssued())
2052*8975f5c5SAndroid Build Coastguard Worker     {
2053*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushOutsideRenderPassCommands());
2054*8975f5c5SAndroid Build Coastguard Worker     }
2055*8975f5c5SAndroid Build Coastguard Worker 
2056*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2057*8975f5c5SAndroid Build Coastguard Worker }
2058*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsEventLog(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2059*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsEventLog(DirtyBits::Iterator *dirtyBitsIterator,
2060*8975f5c5SAndroid Build Coastguard Worker                                                      DirtyBits dirtyBitMask)
2061*8975f5c5SAndroid Build Coastguard Worker {
2062*8975f5c5SAndroid Build Coastguard Worker     return handleDirtyEventLogImpl(mRenderPassCommandBuffer);
2063*8975f5c5SAndroid Build Coastguard Worker }
2064*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyComputeEventLog(DirtyBits::Iterator * dirtyBitsIterator)2065*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyComputeEventLog(DirtyBits::Iterator *dirtyBitsIterator)
2066*8975f5c5SAndroid Build Coastguard Worker {
2067*8975f5c5SAndroid Build Coastguard Worker     return handleDirtyEventLogImpl(&mOutsideRenderPassCommands->getCommandBuffer());
2068*8975f5c5SAndroid Build Coastguard Worker }
2069*8975f5c5SAndroid Build Coastguard Worker 
2070*8975f5c5SAndroid Build Coastguard Worker template <typename CommandBufferT>
handleDirtyEventLogImpl(CommandBufferT * commandBuffer)2071*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyEventLogImpl(CommandBufferT *commandBuffer)
2072*8975f5c5SAndroid Build Coastguard Worker {
2073*8975f5c5SAndroid Build Coastguard Worker     // This method is called when a draw or dispatch command is being processed.  It's purpose is
2074*8975f5c5SAndroid Build Coastguard Worker     // to call the vkCmd*DebugUtilsLabelEXT functions in order to communicate to debuggers
2075*8975f5c5SAndroid Build Coastguard Worker     // (e.g. AGI) the OpenGL ES commands that the application uses.
2076*8975f5c5SAndroid Build Coastguard Worker 
2077*8975f5c5SAndroid Build Coastguard Worker     // Exit early if no OpenGL ES commands have been logged, or if no command buffer (for a no-op
2078*8975f5c5SAndroid Build Coastguard Worker     // draw), or if calling the vkCmd*DebugUtilsLabelEXT functions is not enabled.
2079*8975f5c5SAndroid Build Coastguard Worker     if (mEventLog.empty() || commandBuffer == nullptr || !mRenderer->angleDebuggerMode())
2080*8975f5c5SAndroid Build Coastguard Worker     {
2081*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2082*8975f5c5SAndroid Build Coastguard Worker     }
2083*8975f5c5SAndroid Build Coastguard Worker 
2084*8975f5c5SAndroid Build Coastguard Worker     // Insert OpenGL ES commands into debug label.  We create a 3-level cascade here for
2085*8975f5c5SAndroid Build Coastguard Worker     // OpenGL-ES-first debugging in AGI.  Here's the general outline of commands:
2086*8975f5c5SAndroid Build Coastguard Worker     // -glDrawCommand
2087*8975f5c5SAndroid Build Coastguard Worker     // --vkCmdBeginDebugUtilsLabelEXT() #1 for "glDrawCommand"
2088*8975f5c5SAndroid Build Coastguard Worker     // --OpenGL ES Commands
2089*8975f5c5SAndroid Build Coastguard Worker     // ---vkCmdBeginDebugUtilsLabelEXT() #2 for "OpenGL ES Commands"
2090*8975f5c5SAndroid Build Coastguard Worker     // ---Individual OpenGL ES Commands leading up to glDrawCommand
2091*8975f5c5SAndroid Build Coastguard Worker     // ----vkCmdBeginDebugUtilsLabelEXT() #3 for each individual OpenGL ES Command
2092*8975f5c5SAndroid Build Coastguard Worker     // ----vkCmdEndDebugUtilsLabelEXT() #3 for each individual OpenGL ES Command
2093*8975f5c5SAndroid Build Coastguard Worker     // ----...More Individual OGL Commands...
2094*8975f5c5SAndroid Build Coastguard Worker     // ----Final Individual OGL command will be the same glDrawCommand shown in #1 above
2095*8975f5c5SAndroid Build Coastguard Worker     // ---vkCmdEndDebugUtilsLabelEXT() #2 for "OpenGL ES Commands"
2096*8975f5c5SAndroid Build Coastguard Worker     // --VK SetupDraw & Draw-related commands will be embedded here under glDraw #1
2097*8975f5c5SAndroid Build Coastguard Worker     // --vkCmdEndDebugUtilsLabelEXT() #1 is called after each vkDraw* or vkDispatch* call
2098*8975f5c5SAndroid Build Coastguard Worker 
2099*8975f5c5SAndroid Build Coastguard Worker     // AGI desires no parameters on the top-level of the hierarchy.
2100*8975f5c5SAndroid Build Coastguard Worker     std::string topLevelCommand = mEventLog.back();
2101*8975f5c5SAndroid Build Coastguard Worker     size_t startOfParameters    = topLevelCommand.find("(");
2102*8975f5c5SAndroid Build Coastguard Worker     if (startOfParameters != std::string::npos)
2103*8975f5c5SAndroid Build Coastguard Worker     {
2104*8975f5c5SAndroid Build Coastguard Worker         topLevelCommand = topLevelCommand.substr(0, startOfParameters);
2105*8975f5c5SAndroid Build Coastguard Worker     }
2106*8975f5c5SAndroid Build Coastguard Worker     VkDebugUtilsLabelEXT label = {VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
2107*8975f5c5SAndroid Build Coastguard Worker                                   nullptr,
2108*8975f5c5SAndroid Build Coastguard Worker                                   topLevelCommand.c_str(),
2109*8975f5c5SAndroid Build Coastguard Worker                                   {0.0f, 0.0f, 0.0f, 0.0f}};
2110*8975f5c5SAndroid Build Coastguard Worker     // This is #1 from comment above
2111*8975f5c5SAndroid Build Coastguard Worker     commandBuffer->beginDebugUtilsLabelEXT(label);
2112*8975f5c5SAndroid Build Coastguard Worker     std::string oglCmds = "OpenGL ES Commands";
2113*8975f5c5SAndroid Build Coastguard Worker     label.pLabelName    = oglCmds.c_str();
2114*8975f5c5SAndroid Build Coastguard Worker     // This is #2 from comment above
2115*8975f5c5SAndroid Build Coastguard Worker     commandBuffer->beginDebugUtilsLabelEXT(label);
2116*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < mEventLog.size(); ++i)
2117*8975f5c5SAndroid Build Coastguard Worker     {
2118*8975f5c5SAndroid Build Coastguard Worker         label.pLabelName = mEventLog[i].c_str();
2119*8975f5c5SAndroid Build Coastguard Worker         // NOTE: We have to use a begin/end pair here because AGI does not promote the
2120*8975f5c5SAndroid Build Coastguard Worker         // pLabelName from an insertDebugUtilsLabelEXT() call to the Commands panel.
2121*8975f5c5SAndroid Build Coastguard Worker         // Internal bug b/169243237 is tracking this and once the insert* call shows the
2122*8975f5c5SAndroid Build Coastguard Worker         // pLabelName similar to begin* call, we can switch these to insert* calls instead.
2123*8975f5c5SAndroid Build Coastguard Worker         // This is #3 from comment above.
2124*8975f5c5SAndroid Build Coastguard Worker         commandBuffer->beginDebugUtilsLabelEXT(label);
2125*8975f5c5SAndroid Build Coastguard Worker         commandBuffer->endDebugUtilsLabelEXT();
2126*8975f5c5SAndroid Build Coastguard Worker     }
2127*8975f5c5SAndroid Build Coastguard Worker     commandBuffer->endDebugUtilsLabelEXT();
2128*8975f5c5SAndroid Build Coastguard Worker     // The final end* call for #1 above is made in the ContextVk::draw* or
2129*8975f5c5SAndroid Build Coastguard Worker     //  ContextVk::dispatch* function calls.
2130*8975f5c5SAndroid Build Coastguard Worker 
2131*8975f5c5SAndroid Build Coastguard Worker     mEventLog.clear();
2132*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2133*8975f5c5SAndroid Build Coastguard Worker }
2134*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDefaultAttribs(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2135*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDefaultAttribs(DirtyBits::Iterator *dirtyBitsIterator,
2136*8975f5c5SAndroid Build Coastguard Worker                                                            DirtyBits dirtyBitMask)
2137*8975f5c5SAndroid Build Coastguard Worker {
2138*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mDirtyDefaultAttribsMask.any());
2139*8975f5c5SAndroid Build Coastguard Worker 
2140*8975f5c5SAndroid Build Coastguard Worker     gl::AttributesMask attribsMask =
2141*8975f5c5SAndroid Build Coastguard Worker         mDirtyDefaultAttribsMask & mState.getProgramExecutable()->getAttributesMask();
2142*8975f5c5SAndroid Build Coastguard Worker     VertexArrayVk *vertexArrayVk = getVertexArray();
2143*8975f5c5SAndroid Build Coastguard Worker     for (size_t attribIndex : attribsMask)
2144*8975f5c5SAndroid Build Coastguard Worker     {
2145*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(vertexArrayVk->updateDefaultAttrib(this, attribIndex));
2146*8975f5c5SAndroid Build Coastguard Worker     }
2147*8975f5c5SAndroid Build Coastguard Worker 
2148*8975f5c5SAndroid Build Coastguard Worker     mDirtyDefaultAttribsMask.reset();
2149*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2150*8975f5c5SAndroid Build Coastguard Worker }
2151*8975f5c5SAndroid Build Coastguard Worker 
createGraphicsPipeline()2152*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::createGraphicsPipeline()
2153*8975f5c5SAndroid Build Coastguard Worker {
2154*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.getProgramExecutable() != nullptr);
2155*8975f5c5SAndroid Build Coastguard Worker     ProgramExecutableVk *executableVk = vk::GetImpl(mState.getProgramExecutable());
2156*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executableVk);
2157*8975f5c5SAndroid Build Coastguard Worker 
2158*8975f5c5SAndroid Build Coastguard Worker     // Wait for any warmup task if necessary
2159*8975f5c5SAndroid Build Coastguard Worker     executableVk->waitForGraphicsPostLinkTasks(this, *mGraphicsPipelineDesc);
2160*8975f5c5SAndroid Build Coastguard Worker 
2161*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineCacheAccess pipelineCache;
2162*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mRenderer->getPipelineCache(this, &pipelineCache));
2163*8975f5c5SAndroid Build Coastguard Worker 
2164*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineHelper *oldGraphicsPipeline = mCurrentGraphicsPipeline;
2165*8975f5c5SAndroid Build Coastguard Worker 
2166*8975f5c5SAndroid Build Coastguard Worker     // Attempt to use an existing pipeline.
2167*8975f5c5SAndroid Build Coastguard Worker     const vk::GraphicsPipelineDesc *descPtr = nullptr;
2168*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(executableVk->getGraphicsPipeline(this, vk::GraphicsPipelineSubset::Complete,
2169*8975f5c5SAndroid Build Coastguard Worker                                                 *mGraphicsPipelineDesc, &descPtr,
2170*8975f5c5SAndroid Build Coastguard Worker                                                 &mCurrentGraphicsPipeline));
2171*8975f5c5SAndroid Build Coastguard Worker 
2172*8975f5c5SAndroid Build Coastguard Worker     // If no such pipeline exists:
2173*8975f5c5SAndroid Build Coastguard Worker     //
2174*8975f5c5SAndroid Build Coastguard Worker     // - If VK_EXT_graphics_pipeline_library is not supported, create a new monolithic pipeline
2175*8975f5c5SAndroid Build Coastguard Worker     // - If VK_EXT_graphics_pipeline_library is supported:
2176*8975f5c5SAndroid Build Coastguard Worker     //   * Create the Shaders subset of the pipeline through the program executable
2177*8975f5c5SAndroid Build Coastguard Worker     //   * Create the VertexInput and FragmentOutput subsets
2178*8975f5c5SAndroid Build Coastguard Worker     //   * Link them together through the program executable
2179*8975f5c5SAndroid Build Coastguard Worker     if (mCurrentGraphicsPipeline == nullptr)
2180*8975f5c5SAndroid Build Coastguard Worker     {
2181*8975f5c5SAndroid Build Coastguard Worker         // Not found in cache
2182*8975f5c5SAndroid Build Coastguard Worker         ASSERT(descPtr == nullptr);
2183*8975f5c5SAndroid Build Coastguard Worker         if (!getFeatures().supportsGraphicsPipelineLibrary.enabled)
2184*8975f5c5SAndroid Build Coastguard Worker         {
2185*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(executableVk->createGraphicsPipeline(
2186*8975f5c5SAndroid Build Coastguard Worker                 this, vk::GraphicsPipelineSubset::Complete, &pipelineCache, PipelineSource::Draw,
2187*8975f5c5SAndroid Build Coastguard Worker                 *mGraphicsPipelineDesc, &descPtr, &mCurrentGraphicsPipeline));
2188*8975f5c5SAndroid Build Coastguard Worker         }
2189*8975f5c5SAndroid Build Coastguard Worker         else
2190*8975f5c5SAndroid Build Coastguard Worker         {
2191*8975f5c5SAndroid Build Coastguard Worker             const vk::GraphicsPipelineTransitionBits kShadersTransitionBitsMask =
2192*8975f5c5SAndroid Build Coastguard Worker                 vk::GetGraphicsPipelineTransitionBitsMask(vk::GraphicsPipelineSubset::Shaders);
2193*8975f5c5SAndroid Build Coastguard Worker             const vk::GraphicsPipelineTransitionBits kVertexInputTransitionBitsMask =
2194*8975f5c5SAndroid Build Coastguard Worker                 vk::GetGraphicsPipelineTransitionBitsMask(vk::GraphicsPipelineSubset::VertexInput);
2195*8975f5c5SAndroid Build Coastguard Worker             const vk::GraphicsPipelineTransitionBits kFragmentOutputTransitionBitsMask =
2196*8975f5c5SAndroid Build Coastguard Worker                 vk::GetGraphicsPipelineTransitionBitsMask(
2197*8975f5c5SAndroid Build Coastguard Worker                     vk::GraphicsPipelineSubset::FragmentOutput);
2198*8975f5c5SAndroid Build Coastguard Worker 
2199*8975f5c5SAndroid Build Coastguard Worker             // Recreate the shaders subset if necessary
2200*8975f5c5SAndroid Build Coastguard Worker             const vk::GraphicsPipelineTransitionBits shadersTransitionBits =
2201*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsPipelineLibraryTransition & kShadersTransitionBitsMask;
2202*8975f5c5SAndroid Build Coastguard Worker             if (mCurrentGraphicsPipelineShaders == nullptr || shadersTransitionBits.any())
2203*8975f5c5SAndroid Build Coastguard Worker             {
2204*8975f5c5SAndroid Build Coastguard Worker                 bool shouldRecreatePipeline = true;
2205*8975f5c5SAndroid Build Coastguard Worker                 if (mCurrentGraphicsPipelineShaders != nullptr)
2206*8975f5c5SAndroid Build Coastguard Worker                 {
2207*8975f5c5SAndroid Build Coastguard Worker                     ASSERT(mCurrentGraphicsPipelineShaders->valid());
2208*8975f5c5SAndroid Build Coastguard Worker                     shouldRecreatePipeline = !mCurrentGraphicsPipelineShaders->findTransition(
2209*8975f5c5SAndroid Build Coastguard Worker                         shadersTransitionBits, *mGraphicsPipelineDesc,
2210*8975f5c5SAndroid Build Coastguard Worker                         &mCurrentGraphicsPipelineShaders);
2211*8975f5c5SAndroid Build Coastguard Worker                 }
2212*8975f5c5SAndroid Build Coastguard Worker 
2213*8975f5c5SAndroid Build Coastguard Worker                 if (shouldRecreatePipeline)
2214*8975f5c5SAndroid Build Coastguard Worker                 {
2215*8975f5c5SAndroid Build Coastguard Worker                     vk::PipelineHelper *oldGraphicsPipelineShaders =
2216*8975f5c5SAndroid Build Coastguard Worker                         mCurrentGraphicsPipelineShaders;
2217*8975f5c5SAndroid Build Coastguard Worker 
2218*8975f5c5SAndroid Build Coastguard Worker                     const vk::GraphicsPipelineDesc *shadersDescPtr = nullptr;
2219*8975f5c5SAndroid Build Coastguard Worker                     ANGLE_TRY(executableVk->getGraphicsPipeline(
2220*8975f5c5SAndroid Build Coastguard Worker                         this, vk::GraphicsPipelineSubset::Shaders, *mGraphicsPipelineDesc,
2221*8975f5c5SAndroid Build Coastguard Worker                         &shadersDescPtr, &mCurrentGraphicsPipelineShaders));
2222*8975f5c5SAndroid Build Coastguard Worker                     if (shadersDescPtr == nullptr)
2223*8975f5c5SAndroid Build Coastguard Worker                     {
2224*8975f5c5SAndroid Build Coastguard Worker                         ANGLE_TRY(executableVk->createGraphicsPipeline(
2225*8975f5c5SAndroid Build Coastguard Worker                             this, vk::GraphicsPipelineSubset::Shaders, &pipelineCache,
2226*8975f5c5SAndroid Build Coastguard Worker                             PipelineSource::Draw, *mGraphicsPipelineDesc, &shadersDescPtr,
2227*8975f5c5SAndroid Build Coastguard Worker                             &mCurrentGraphicsPipelineShaders));
2228*8975f5c5SAndroid Build Coastguard Worker                     }
2229*8975f5c5SAndroid Build Coastguard Worker                     if (oldGraphicsPipelineShaders)
2230*8975f5c5SAndroid Build Coastguard Worker                     {
2231*8975f5c5SAndroid Build Coastguard Worker                         oldGraphicsPipelineShaders->addTransition(
2232*8975f5c5SAndroid Build Coastguard Worker                             shadersTransitionBits, shadersDescPtr, mCurrentGraphicsPipelineShaders);
2233*8975f5c5SAndroid Build Coastguard Worker                     }
2234*8975f5c5SAndroid Build Coastguard Worker                 }
2235*8975f5c5SAndroid Build Coastguard Worker             }
2236*8975f5c5SAndroid Build Coastguard Worker 
2237*8975f5c5SAndroid Build Coastguard Worker             // If blobs are reused between the pipeline libraries and the monolithic pipelines (so
2238*8975f5c5SAndroid Build Coastguard Worker             // |mergeProgramPipelineCachesToGlobalCache| would be enabled because merging the
2239*8975f5c5SAndroid Build Coastguard Worker             // pipelines would be beneficial), directly use the global cache for the vertex input
2240*8975f5c5SAndroid Build Coastguard Worker             // and fragment output pipelines.  This _may_ cause stalls as the worker thread that
2241*8975f5c5SAndroid Build Coastguard Worker             // creates pipelines is also holding the same lock.
2242*8975f5c5SAndroid Build Coastguard Worker             //
2243*8975f5c5SAndroid Build Coastguard Worker             // On the other hand, if there is not going to be any reuse of blobs, use a private
2244*8975f5c5SAndroid Build Coastguard Worker             // pipeline cache to avoid the aforementioned potential stall.
2245*8975f5c5SAndroid Build Coastguard Worker             vk::PipelineCacheAccess interfacePipelineCacheStorage;
2246*8975f5c5SAndroid Build Coastguard Worker             vk::PipelineCacheAccess *interfacePipelineCache = &pipelineCache;
2247*8975f5c5SAndroid Build Coastguard Worker             if (!getFeatures().mergeProgramPipelineCachesToGlobalCache.enabled)
2248*8975f5c5SAndroid Build Coastguard Worker             {
2249*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(ensureInterfacePipelineCache());
2250*8975f5c5SAndroid Build Coastguard Worker                 interfacePipelineCacheStorage.init(&mInterfacePipelinesCache, nullptr);
2251*8975f5c5SAndroid Build Coastguard Worker                 interfacePipelineCache = &interfacePipelineCacheStorage;
2252*8975f5c5SAndroid Build Coastguard Worker             }
2253*8975f5c5SAndroid Build Coastguard Worker 
2254*8975f5c5SAndroid Build Coastguard Worker             // Recreate the vertex input subset if necessary
2255*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(CreateGraphicsPipelineSubset(
2256*8975f5c5SAndroid Build Coastguard Worker                 this, *mGraphicsPipelineDesc,
2257*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsPipelineLibraryTransition & kVertexInputTransitionBitsMask,
2258*8975f5c5SAndroid Build Coastguard Worker                 GraphicsPipelineSubsetRenderPass::Unused,
2259*8975f5c5SAndroid Build Coastguard Worker                 mShareGroupVk->getVertexInputGraphicsPipelineCache(), interfacePipelineCache,
2260*8975f5c5SAndroid Build Coastguard Worker                 &mCurrentGraphicsPipelineVertexInput));
2261*8975f5c5SAndroid Build Coastguard Worker 
2262*8975f5c5SAndroid Build Coastguard Worker             // Recreate the fragment output subset if necessary
2263*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(CreateGraphicsPipelineSubset(
2264*8975f5c5SAndroid Build Coastguard Worker                 this, *mGraphicsPipelineDesc,
2265*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsPipelineLibraryTransition & kFragmentOutputTransitionBitsMask,
2266*8975f5c5SAndroid Build Coastguard Worker                 GraphicsPipelineSubsetRenderPass::Required,
2267*8975f5c5SAndroid Build Coastguard Worker                 mShareGroupVk->getFragmentOutputGraphicsPipelineCache(), interfacePipelineCache,
2268*8975f5c5SAndroid Build Coastguard Worker                 &mCurrentGraphicsPipelineFragmentOutput));
2269*8975f5c5SAndroid Build Coastguard Worker 
2270*8975f5c5SAndroid Build Coastguard Worker             // Link the three subsets into one pipeline.
2271*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(executableVk->linkGraphicsPipelineLibraries(
2272*8975f5c5SAndroid Build Coastguard Worker                 this, &pipelineCache, *mGraphicsPipelineDesc, mCurrentGraphicsPipelineVertexInput,
2273*8975f5c5SAndroid Build Coastguard Worker                 mCurrentGraphicsPipelineShaders, mCurrentGraphicsPipelineFragmentOutput, &descPtr,
2274*8975f5c5SAndroid Build Coastguard Worker                 &mCurrentGraphicsPipeline));
2275*8975f5c5SAndroid Build Coastguard Worker 
2276*8975f5c5SAndroid Build Coastguard Worker             // Reset the transition bits for pipeline libraries, they are only made to be up-to-date
2277*8975f5c5SAndroid Build Coastguard Worker             // here.
2278*8975f5c5SAndroid Build Coastguard Worker             mGraphicsPipelineLibraryTransition.reset();
2279*8975f5c5SAndroid Build Coastguard Worker         }
2280*8975f5c5SAndroid Build Coastguard Worker     }
2281*8975f5c5SAndroid Build Coastguard Worker 
2282*8975f5c5SAndroid Build Coastguard Worker     // Maintain the transition cache
2283*8975f5c5SAndroid Build Coastguard Worker     if (oldGraphicsPipeline)
2284*8975f5c5SAndroid Build Coastguard Worker     {
2285*8975f5c5SAndroid Build Coastguard Worker         oldGraphicsPipeline->addTransition(mGraphicsPipelineTransition, descPtr,
2286*8975f5c5SAndroid Build Coastguard Worker                                            mCurrentGraphicsPipeline);
2287*8975f5c5SAndroid Build Coastguard Worker     }
2288*8975f5c5SAndroid Build Coastguard Worker 
2289*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2290*8975f5c5SAndroid Build Coastguard Worker }
2291*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsPipelineDesc(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2292*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsPipelineDesc(DirtyBits::Iterator *dirtyBitsIterator,
2293*8975f5c5SAndroid Build Coastguard Worker                                                          DirtyBits dirtyBitMask)
2294*8975f5c5SAndroid Build Coastguard Worker {
2295*8975f5c5SAndroid Build Coastguard Worker     const VkPipeline previousPipeline = mCurrentGraphicsPipeline
2296*8975f5c5SAndroid Build Coastguard Worker                                             ? mCurrentGraphicsPipeline->getPipeline().getHandle()
2297*8975f5c5SAndroid Build Coastguard Worker                                             : VK_NULL_HANDLE;
2298*8975f5c5SAndroid Build Coastguard Worker 
2299*8975f5c5SAndroid Build Coastguard Worker     // Accumulate transition bits for the sake of pipeline libraries.  If a cache is hit in this
2300*8975f5c5SAndroid Build Coastguard Worker     // path, |mGraphicsPipelineTransition| is reset while the partial pipelines are left stale.  A
2301*8975f5c5SAndroid Build Coastguard Worker     // future partial library recreation would need to know the bits that have changed since.
2302*8975f5c5SAndroid Build Coastguard Worker     mGraphicsPipelineLibraryTransition |= mGraphicsPipelineTransition;
2303*8975f5c5SAndroid Build Coastguard Worker 
2304*8975f5c5SAndroid Build Coastguard Worker     // Recreate the pipeline if necessary.
2305*8975f5c5SAndroid Build Coastguard Worker     bool shouldRecreatePipeline =
2306*8975f5c5SAndroid Build Coastguard Worker         mCurrentGraphicsPipeline == nullptr || mGraphicsPipelineTransition.any();
2307*8975f5c5SAndroid Build Coastguard Worker 
2308*8975f5c5SAndroid Build Coastguard Worker     // If one can be found in the transition cache, recover it.
2309*8975f5c5SAndroid Build Coastguard Worker     if (mCurrentGraphicsPipeline != nullptr && mGraphicsPipelineTransition.any())
2310*8975f5c5SAndroid Build Coastguard Worker     {
2311*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mCurrentGraphicsPipeline->valid());
2312*8975f5c5SAndroid Build Coastguard Worker         shouldRecreatePipeline = !mCurrentGraphicsPipeline->findTransition(
2313*8975f5c5SAndroid Build Coastguard Worker             mGraphicsPipelineTransition, *mGraphicsPipelineDesc, &mCurrentGraphicsPipeline);
2314*8975f5c5SAndroid Build Coastguard Worker     }
2315*8975f5c5SAndroid Build Coastguard Worker 
2316*8975f5c5SAndroid Build Coastguard Worker     // Otherwise either retrieve the pipeline from the cache, or create a new one.
2317*8975f5c5SAndroid Build Coastguard Worker     if (shouldRecreatePipeline)
2318*8975f5c5SAndroid Build Coastguard Worker     {
2319*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(createGraphicsPipeline());
2320*8975f5c5SAndroid Build Coastguard Worker     }
2321*8975f5c5SAndroid Build Coastguard Worker 
2322*8975f5c5SAndroid Build Coastguard Worker     mGraphicsPipelineTransition.reset();
2323*8975f5c5SAndroid Build Coastguard Worker 
2324*8975f5c5SAndroid Build Coastguard Worker     // Update the queue serial for the pipeline object.
2325*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mCurrentGraphicsPipeline && mCurrentGraphicsPipeline->valid());
2326*8975f5c5SAndroid Build Coastguard Worker 
2327*8975f5c5SAndroid Build Coastguard Worker     const VkPipeline newPipeline = mCurrentGraphicsPipeline->getPipeline().getHandle();
2328*8975f5c5SAndroid Build Coastguard Worker 
2329*8975f5c5SAndroid Build Coastguard Worker     // If there's no change in pipeline, avoid rebinding it later.  If the rebind is due to a new
2330*8975f5c5SAndroid Build Coastguard Worker     // command buffer or UtilsVk, it will happen anyway with DIRTY_BIT_PIPELINE_BINDING.
2331*8975f5c5SAndroid Build Coastguard Worker     if (newPipeline == previousPipeline)
2332*8975f5c5SAndroid Build Coastguard Worker     {
2333*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2334*8975f5c5SAndroid Build Coastguard Worker     }
2335*8975f5c5SAndroid Build Coastguard Worker 
2336*8975f5c5SAndroid Build Coastguard Worker     // VK_EXT_transform_feedback disallows binding pipelines while transform feedback is active.
2337*8975f5c5SAndroid Build Coastguard Worker     // If a new pipeline needs to be bound, the render pass should necessarily be broken (which
2338*8975f5c5SAndroid Build Coastguard Worker     // implicitly pauses transform feedback), as resuming requires a barrier on the transform
2339*8975f5c5SAndroid Build Coastguard Worker     // feedback counter buffer.
2340*8975f5c5SAndroid Build Coastguard Worker     if (mRenderPassCommands->started())
2341*8975f5c5SAndroid Build Coastguard Worker     {
2342*8975f5c5SAndroid Build Coastguard Worker         mCurrentGraphicsPipeline->retainInRenderPass(mRenderPassCommands);
2343*8975f5c5SAndroid Build Coastguard Worker 
2344*8975f5c5SAndroid Build Coastguard Worker         if (mRenderPassCommands->isTransformFeedbackActiveUnpaused())
2345*8975f5c5SAndroid Build Coastguard Worker         {
2346*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(
2347*8975f5c5SAndroid Build Coastguard Worker                 flushDirtyGraphicsRenderPass(dirtyBitsIterator, dirtyBitMask,
2348*8975f5c5SAndroid Build Coastguard Worker                                              RenderPassClosureReason::PipelineBindWhileXfbActive));
2349*8975f5c5SAndroid Build Coastguard Worker 
2350*8975f5c5SAndroid Build Coastguard Worker             dirtyBitsIterator->setLaterBit(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
2351*8975f5c5SAndroid Build Coastguard Worker         }
2352*8975f5c5SAndroid Build Coastguard Worker     }
2353*8975f5c5SAndroid Build Coastguard Worker 
2354*8975f5c5SAndroid Build Coastguard Worker     // The pipeline needs to rebind because it's changed.
2355*8975f5c5SAndroid Build Coastguard Worker     dirtyBitsIterator->setLaterBit(DIRTY_BIT_PIPELINE_BINDING);
2356*8975f5c5SAndroid Build Coastguard Worker 
2357*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2358*8975f5c5SAndroid Build Coastguard Worker }
2359*8975f5c5SAndroid Build Coastguard Worker 
updateRenderPassDepthFeedbackLoopMode(UpdateDepthFeedbackLoopReason depthReason,UpdateDepthFeedbackLoopReason stencilReason)2360*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::updateRenderPassDepthFeedbackLoopMode(
2361*8975f5c5SAndroid Build Coastguard Worker     UpdateDepthFeedbackLoopReason depthReason,
2362*8975f5c5SAndroid Build Coastguard Worker     UpdateDepthFeedbackLoopReason stencilReason)
2363*8975f5c5SAndroid Build Coastguard Worker {
2364*8975f5c5SAndroid Build Coastguard Worker     return switchOutReadOnlyDepthStencilMode(nullptr, {}, depthReason, stencilReason);
2365*8975f5c5SAndroid Build Coastguard Worker }
2366*8975f5c5SAndroid Build Coastguard Worker 
switchOutReadOnlyDepthStencilMode(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask,UpdateDepthFeedbackLoopReason depthReason,UpdateDepthFeedbackLoopReason stencilReason)2367*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::switchOutReadOnlyDepthStencilMode(
2368*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
2369*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask,
2370*8975f5c5SAndroid Build Coastguard Worker     UpdateDepthFeedbackLoopReason depthReason,
2371*8975f5c5SAndroid Build Coastguard Worker     UpdateDepthFeedbackLoopReason stencilReason)
2372*8975f5c5SAndroid Build Coastguard Worker {
2373*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
2374*8975f5c5SAndroid Build Coastguard Worker     if (!hasActiveRenderPass() || drawFramebufferVk->getDepthStencilRenderTarget() == nullptr)
2375*8975f5c5SAndroid Build Coastguard Worker     {
2376*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2377*8975f5c5SAndroid Build Coastguard Worker     }
2378*8975f5c5SAndroid Build Coastguard Worker 
2379*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2380*8975f5c5SAndroid Build Coastguard Worker     const gl::DepthStencilState &dsState = mState.getDepthStencilState();
2381*8975f5c5SAndroid Build Coastguard Worker     vk::ResourceAccess depthAccess          = GetDepthAccess(dsState, executable, depthReason);
2382*8975f5c5SAndroid Build Coastguard Worker     vk::ResourceAccess stencilAccess        = GetStencilAccess(
2383*8975f5c5SAndroid Build Coastguard Worker         dsState, mState.getDrawFramebuffer()->getStencilBitCount(), executable, stencilReason);
2384*8975f5c5SAndroid Build Coastguard Worker 
2385*8975f5c5SAndroid Build Coastguard Worker     if ((HasResourceWriteAccess(depthAccess) &&
2386*8975f5c5SAndroid Build Coastguard Worker          mDepthStencilAttachmentFlags[vk::RenderPassUsage::DepthReadOnlyAttachment]) ||
2387*8975f5c5SAndroid Build Coastguard Worker         (HasResourceWriteAccess(stencilAccess) &&
2388*8975f5c5SAndroid Build Coastguard Worker          mDepthStencilAttachmentFlags[vk::RenderPassUsage::StencilReadOnlyAttachment]))
2389*8975f5c5SAndroid Build Coastguard Worker     {
2390*8975f5c5SAndroid Build Coastguard Worker         // We should not in the actual feedback mode
2391*8975f5c5SAndroid Build Coastguard Worker         ASSERT((mDepthStencilAttachmentFlags & vk::kDepthStencilFeedbackModeBits).none());
2392*8975f5c5SAndroid Build Coastguard Worker 
2393*8975f5c5SAndroid Build Coastguard Worker         // If we are switching out of read only mode and we are in feedback loop, we must end
2394*8975f5c5SAndroid Build Coastguard Worker         // render pass here. Otherwise, updating it to writeable layout will produce a writable
2395*8975f5c5SAndroid Build Coastguard Worker         // feedback loop that is illegal in vulkan and will trigger validation errors that depth
2396*8975f5c5SAndroid Build Coastguard Worker         // texture is using the writable layout.
2397*8975f5c5SAndroid Build Coastguard Worker         if (dirtyBitsIterator)
2398*8975f5c5SAndroid Build Coastguard Worker         {
2399*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(flushDirtyGraphicsRenderPass(
2400*8975f5c5SAndroid Build Coastguard Worker                 dirtyBitsIterator, dirtyBitMask,
2401*8975f5c5SAndroid Build Coastguard Worker                 RenderPassClosureReason::DepthStencilWriteAfterFeedbackLoop));
2402*8975f5c5SAndroid Build Coastguard Worker         }
2403*8975f5c5SAndroid Build Coastguard Worker         else
2404*8975f5c5SAndroid Build Coastguard Worker         {
2405*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(flushCommandsAndEndRenderPass(
2406*8975f5c5SAndroid Build Coastguard Worker                 RenderPassClosureReason::DepthStencilWriteAfterFeedbackLoop));
2407*8975f5c5SAndroid Build Coastguard Worker         }
2408*8975f5c5SAndroid Build Coastguard Worker         // Clear read-only depth/stencil feedback mode.
2409*8975f5c5SAndroid Build Coastguard Worker         mDepthStencilAttachmentFlags &= ~vk::kDepthStencilReadOnlyBits;
2410*8975f5c5SAndroid Build Coastguard Worker     }
2411*8975f5c5SAndroid Build Coastguard Worker 
2412*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2413*8975f5c5SAndroid Build Coastguard Worker }
2414*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsReadOnlyDepthFeedbackLoopMode(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2415*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsReadOnlyDepthFeedbackLoopMode(
2416*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
2417*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
2418*8975f5c5SAndroid Build Coastguard Worker {
2419*8975f5c5SAndroid Build Coastguard Worker     return switchOutReadOnlyDepthStencilMode(dirtyBitsIterator, dirtyBitMask,
2420*8975f5c5SAndroid Build Coastguard Worker                                              UpdateDepthFeedbackLoopReason::Draw,
2421*8975f5c5SAndroid Build Coastguard Worker                                              UpdateDepthFeedbackLoopReason::Draw);
2422*8975f5c5SAndroid Build Coastguard Worker }
2423*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyAnySamplePassedQueryEnd(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2424*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyAnySamplePassedQueryEnd(DirtyBits::Iterator *dirtyBitsIterator,
2425*8975f5c5SAndroid Build Coastguard Worker                                                             DirtyBits dirtyBitMask)
2426*8975f5c5SAndroid Build Coastguard Worker {
2427*8975f5c5SAndroid Build Coastguard Worker     if (mRenderPassCommands->started())
2428*8975f5c5SAndroid Build Coastguard Worker     {
2429*8975f5c5SAndroid Build Coastguard Worker         // When we switch from query enabled draw to query disabled draw, we do immediate flush to
2430*8975f5c5SAndroid Build Coastguard Worker         // ensure the query result will be ready early so that application thread calling
2431*8975f5c5SAndroid Build Coastguard Worker         // getQueryResult gets unblocked sooner.
2432*8975f5c5SAndroid Build Coastguard Worker         dirtyBitsIterator->setLaterBit(DIRTY_BIT_RENDER_PASS);
2433*8975f5c5SAndroid Build Coastguard Worker 
2434*8975f5c5SAndroid Build Coastguard Worker         // Don't let next render pass end up reactivate and reuse the current render pass, which
2435*8975f5c5SAndroid Build Coastguard Worker         // defeats the purpose of it.
2436*8975f5c5SAndroid Build Coastguard Worker         mAllowRenderPassToReactivate = false;
2437*8975f5c5SAndroid Build Coastguard Worker         mHasDeferredFlush            = true;
2438*8975f5c5SAndroid Build Coastguard Worker     }
2439*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2440*8975f5c5SAndroid Build Coastguard Worker }
2441*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsRenderPass(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2442*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsRenderPass(DirtyBits::Iterator *dirtyBitsIterator,
2443*8975f5c5SAndroid Build Coastguard Worker                                                        DirtyBits dirtyBitMask)
2444*8975f5c5SAndroid Build Coastguard Worker {
2445*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
2446*8975f5c5SAndroid Build Coastguard Worker 
2447*8975f5c5SAndroid Build Coastguard Worker     gl::Rectangle renderArea = drawFramebufferVk->getRenderArea(this);
2448*8975f5c5SAndroid Build Coastguard Worker     // Check to see if we can reactivate the current renderPass, if all arguments that we use to
2449*8975f5c5SAndroid Build Coastguard Worker     // start the render pass is the same. We don't need to check clear values since mid render pass
2450*8975f5c5SAndroid Build Coastguard Worker     // clear are handled differently.
2451*8975f5c5SAndroid Build Coastguard Worker     bool reactivateStartedRenderPass =
2452*8975f5c5SAndroid Build Coastguard Worker         hasStartedRenderPassWithQueueSerial(drawFramebufferVk->getLastRenderPassQueueSerial()) &&
2453*8975f5c5SAndroid Build Coastguard Worker         mAllowRenderPassToReactivate && renderArea == mRenderPassCommands->getRenderArea();
2454*8975f5c5SAndroid Build Coastguard Worker     if (reactivateStartedRenderPass)
2455*8975f5c5SAndroid Build Coastguard Worker     {
2456*8975f5c5SAndroid Build Coastguard Worker         INFO() << "Reactivate already started render pass on draw.";
2457*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommandBuffer = &mRenderPassCommands->getCommandBuffer();
2458*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!drawFramebufferVk->hasDeferredClears());
2459*8975f5c5SAndroid Build Coastguard Worker         ASSERT(hasActiveRenderPass());
2460*8975f5c5SAndroid Build Coastguard Worker 
2461*8975f5c5SAndroid Build Coastguard Worker         vk::RenderPassDesc framebufferRenderPassDesc = drawFramebufferVk->getRenderPassDesc();
2462*8975f5c5SAndroid Build Coastguard Worker         if (getFeatures().preferDynamicRendering.enabled)
2463*8975f5c5SAndroid Build Coastguard Worker         {
2464*8975f5c5SAndroid Build Coastguard Worker             // With dynamic rendering, drawFramebufferVk's render pass desc does not track
2465*8975f5c5SAndroid Build Coastguard Worker             // framebuffer fetch mode.  For the purposes of the following ASSERT, assume they are
2466*8975f5c5SAndroid Build Coastguard Worker             // the same.
2467*8975f5c5SAndroid Build Coastguard Worker             framebufferRenderPassDesc.setFramebufferFetchMode(
2468*8975f5c5SAndroid Build Coastguard Worker                 mRenderPassCommands->getRenderPassDesc().framebufferFetchMode());
2469*8975f5c5SAndroid Build Coastguard Worker         }
2470*8975f5c5SAndroid Build Coastguard Worker         ASSERT(framebufferRenderPassDesc == mRenderPassCommands->getRenderPassDesc());
2471*8975f5c5SAndroid Build Coastguard Worker 
2472*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2473*8975f5c5SAndroid Build Coastguard Worker     }
2474*8975f5c5SAndroid Build Coastguard Worker 
2475*8975f5c5SAndroid Build Coastguard Worker     // If the render pass needs to be recreated, close it using the special mid-dirty-bit-handling
2476*8975f5c5SAndroid Build Coastguard Worker     // function, so later dirty bits can be set.
2477*8975f5c5SAndroid Build Coastguard Worker     if (mRenderPassCommands->started())
2478*8975f5c5SAndroid Build Coastguard Worker     {
2479*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushDirtyGraphicsRenderPass(dirtyBitsIterator,
2480*8975f5c5SAndroid Build Coastguard Worker                                                dirtyBitMask & ~DirtyBits{DIRTY_BIT_RENDER_PASS},
2481*8975f5c5SAndroid Build Coastguard Worker                                                RenderPassClosureReason::AlreadySpecifiedElsewhere));
2482*8975f5c5SAndroid Build Coastguard Worker     }
2483*8975f5c5SAndroid Build Coastguard Worker 
2484*8975f5c5SAndroid Build Coastguard Worker     bool renderPassDescChanged = false;
2485*8975f5c5SAndroid Build Coastguard Worker 
2486*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(startRenderPass(renderArea, nullptr, &renderPassDescChanged));
2487*8975f5c5SAndroid Build Coastguard Worker 
2488*8975f5c5SAndroid Build Coastguard Worker     // The render pass desc can change when starting the render pass, for example due to
2489*8975f5c5SAndroid Build Coastguard Worker     // multisampled-render-to-texture needs based on loadOps.  In that case, recreate the graphics
2490*8975f5c5SAndroid Build Coastguard Worker     // pipeline.
2491*8975f5c5SAndroid Build Coastguard Worker     if (renderPassDescChanged)
2492*8975f5c5SAndroid Build Coastguard Worker     {
2493*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(handleDirtyGraphicsPipelineDesc(dirtyBitsIterator, dirtyBitMask));
2494*8975f5c5SAndroid Build Coastguard Worker     }
2495*8975f5c5SAndroid Build Coastguard Worker 
2496*8975f5c5SAndroid Build Coastguard Worker     // For dynamic rendering, the FramebufferVk's render pass desc does not track whether
2497*8975f5c5SAndroid Build Coastguard Worker     // framebuffer fetch is in use.  In that case, ContextVk updates the command buffer's (and
2498*8975f5c5SAndroid Build Coastguard Worker     // graphics pipeline's) render pass desc only:
2499*8975f5c5SAndroid Build Coastguard Worker     //
2500*8975f5c5SAndroid Build Coastguard Worker     // - When the render pass starts
2501*8975f5c5SAndroid Build Coastguard Worker     // - When the program binding changes (see |invalidateProgramExecutableHelper|)
2502*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().preferDynamicRendering.enabled)
2503*8975f5c5SAndroid Build Coastguard Worker     {
2504*8975f5c5SAndroid Build Coastguard Worker         vk::FramebufferFetchMode framebufferFetchMode =
2505*8975f5c5SAndroid Build Coastguard Worker             vk::GetProgramFramebufferFetchMode(mState.getProgramExecutable());
2506*8975f5c5SAndroid Build Coastguard Worker         if (framebufferFetchMode != vk::FramebufferFetchMode::None)
2507*8975f5c5SAndroid Build Coastguard Worker         {
2508*8975f5c5SAndroid Build Coastguard Worker             // Note: this function sets a dirty bit through onColorAccessChange() not through
2509*8975f5c5SAndroid Build Coastguard Worker             // |dirtyBitsIterator|, but that dirty bit is always set on new render passes, so it
2510*8975f5c5SAndroid Build Coastguard Worker             // won't be missed.
2511*8975f5c5SAndroid Build Coastguard Worker             onFramebufferFetchUse(framebufferFetchMode);
2512*8975f5c5SAndroid Build Coastguard Worker         }
2513*8975f5c5SAndroid Build Coastguard Worker         else
2514*8975f5c5SAndroid Build Coastguard Worker         {
2515*8975f5c5SAndroid Build Coastguard Worker             // Reset framebuffer fetch mode.  Note that |onFramebufferFetchUse| _accumulates_
2516*8975f5c5SAndroid Build Coastguard Worker             // framebuffer fetch mode.
2517*8975f5c5SAndroid Build Coastguard Worker             mRenderPassCommands->setFramebufferFetchMode(vk::FramebufferFetchMode::None);
2518*8975f5c5SAndroid Build Coastguard Worker         }
2519*8975f5c5SAndroid Build Coastguard Worker     }
2520*8975f5c5SAndroid Build Coastguard Worker 
2521*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2522*8975f5c5SAndroid Build Coastguard Worker }
2523*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsColorAccess(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2524*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsColorAccess(DirtyBits::Iterator *dirtyBitsIterator,
2525*8975f5c5SAndroid Build Coastguard Worker                                                         DirtyBits dirtyBitMask)
2526*8975f5c5SAndroid Build Coastguard Worker {
2527*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *drawFramebufferVk             = getDrawFramebuffer();
2528*8975f5c5SAndroid Build Coastguard Worker     const gl::FramebufferState &framebufferState = drawFramebufferVk->getState();
2529*8975f5c5SAndroid Build Coastguard Worker 
2530*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2531*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executable);
2532*8975f5c5SAndroid Build Coastguard Worker 
2533*8975f5c5SAndroid Build Coastguard Worker     // Update color attachment accesses
2534*8975f5c5SAndroid Build Coastguard Worker     vk::PackedAttachmentIndex colorIndexVk(0);
2535*8975f5c5SAndroid Build Coastguard Worker     for (size_t colorIndexGL : framebufferState.getColorAttachmentsMask())
2536*8975f5c5SAndroid Build Coastguard Worker     {
2537*8975f5c5SAndroid Build Coastguard Worker         if (framebufferState.getEnabledDrawBuffers().test(colorIndexGL))
2538*8975f5c5SAndroid Build Coastguard Worker         {
2539*8975f5c5SAndroid Build Coastguard Worker             vk::ResourceAccess colorAccess = GetColorAccess(
2540*8975f5c5SAndroid Build Coastguard Worker                 mState, framebufferState, drawFramebufferVk->getEmulatedAlphaAttachmentMask(),
2541*8975f5c5SAndroid Build Coastguard Worker                 executable, colorIndexGL);
2542*8975f5c5SAndroid Build Coastguard Worker             mRenderPassCommands->onColorAccess(colorIndexVk, colorAccess);
2543*8975f5c5SAndroid Build Coastguard Worker         }
2544*8975f5c5SAndroid Build Coastguard Worker         ++colorIndexVk;
2545*8975f5c5SAndroid Build Coastguard Worker     }
2546*8975f5c5SAndroid Build Coastguard Worker 
2547*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2548*8975f5c5SAndroid Build Coastguard Worker }
2549*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDepthStencilAccess(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2550*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDepthStencilAccess(
2551*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
2552*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
2553*8975f5c5SAndroid Build Coastguard Worker {
2554*8975f5c5SAndroid Build Coastguard Worker     const FramebufferVk &drawFramebufferVk = *getDrawFramebuffer();
2555*8975f5c5SAndroid Build Coastguard Worker     if (drawFramebufferVk.getDepthStencilRenderTarget() == nullptr)
2556*8975f5c5SAndroid Build Coastguard Worker     {
2557*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2558*8975f5c5SAndroid Build Coastguard Worker     }
2559*8975f5c5SAndroid Build Coastguard Worker 
2560*8975f5c5SAndroid Build Coastguard Worker     // Update depth/stencil attachment accesses
2561*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2562*8975f5c5SAndroid Build Coastguard Worker     const gl::DepthStencilState &dsState = mState.getDepthStencilState();
2563*8975f5c5SAndroid Build Coastguard Worker     vk::ResourceAccess depthAccess =
2564*8975f5c5SAndroid Build Coastguard Worker         GetDepthAccess(dsState, executable, UpdateDepthFeedbackLoopReason::Draw);
2565*8975f5c5SAndroid Build Coastguard Worker     vk::ResourceAccess stencilAccess =
2566*8975f5c5SAndroid Build Coastguard Worker         GetStencilAccess(dsState, mState.getDrawFramebuffer()->getStencilBitCount(), executable,
2567*8975f5c5SAndroid Build Coastguard Worker                          UpdateDepthFeedbackLoopReason::Draw);
2568*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommands->onDepthAccess(depthAccess);
2569*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommands->onStencilAccess(stencilAccess);
2570*8975f5c5SAndroid Build Coastguard Worker 
2571*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommands->updateDepthReadOnlyMode(mDepthStencilAttachmentFlags);
2572*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommands->updateStencilReadOnlyMode(mDepthStencilAttachmentFlags);
2573*8975f5c5SAndroid Build Coastguard Worker 
2574*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2575*8975f5c5SAndroid Build Coastguard Worker }
2576*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsPipelineBinding(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2577*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsPipelineBinding(DirtyBits::Iterator *dirtyBitsIterator,
2578*8975f5c5SAndroid Build Coastguard Worker                                                             DirtyBits dirtyBitMask)
2579*8975f5c5SAndroid Build Coastguard Worker {
2580*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mCurrentGraphicsPipeline);
2581*8975f5c5SAndroid Build Coastguard Worker 
2582*8975f5c5SAndroid Build Coastguard Worker     const vk::Pipeline *pipeline = nullptr;
2583*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mCurrentGraphicsPipeline->getPreferredPipeline(this, &pipeline));
2584*8975f5c5SAndroid Build Coastguard Worker 
2585*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->bindGraphicsPipeline(*pipeline);
2586*8975f5c5SAndroid Build Coastguard Worker 
2587*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2588*8975f5c5SAndroid Build Coastguard Worker }
2589*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyComputePipelineDesc(DirtyBits::Iterator * dirtyBitsIterator)2590*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyComputePipelineDesc(DirtyBits::Iterator *dirtyBitsIterator)
2591*8975f5c5SAndroid Build Coastguard Worker {
2592*8975f5c5SAndroid Build Coastguard Worker     if (mCurrentComputePipeline == nullptr)
2593*8975f5c5SAndroid Build Coastguard Worker     {
2594*8975f5c5SAndroid Build Coastguard Worker         vk::PipelineCacheAccess pipelineCache;
2595*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mRenderer->getPipelineCache(this, &pipelineCache));
2596*8975f5c5SAndroid Build Coastguard Worker 
2597*8975f5c5SAndroid Build Coastguard Worker         ProgramExecutableVk *executableVk = vk::GetImpl(mState.getProgramExecutable());
2598*8975f5c5SAndroid Build Coastguard Worker         ASSERT(executableVk);
2599*8975f5c5SAndroid Build Coastguard Worker 
2600*8975f5c5SAndroid Build Coastguard Worker         executableVk->waitForComputePostLinkTasks(this);
2601*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(executableVk->getOrCreateComputePipeline(
2602*8975f5c5SAndroid Build Coastguard Worker             this, &pipelineCache, PipelineSource::Draw, pipelineRobustness(),
2603*8975f5c5SAndroid Build Coastguard Worker             pipelineProtectedAccess(), &mCurrentComputePipeline));
2604*8975f5c5SAndroid Build Coastguard Worker     }
2605*8975f5c5SAndroid Build Coastguard Worker 
2606*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mComputeDirtyBits.test(DIRTY_BIT_PIPELINE_BINDING));
2607*8975f5c5SAndroid Build Coastguard Worker 
2608*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2609*8975f5c5SAndroid Build Coastguard Worker }
2610*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyComputePipelineBinding(DirtyBits::Iterator * dirtyBitsIterator)2611*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyComputePipelineBinding(DirtyBits::Iterator *dirtyBitsIterator)
2612*8975f5c5SAndroid Build Coastguard Worker {
2613*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mCurrentComputePipeline);
2614*8975f5c5SAndroid Build Coastguard Worker 
2615*8975f5c5SAndroid Build Coastguard Worker     mOutsideRenderPassCommands->getCommandBuffer().bindComputePipeline(
2616*8975f5c5SAndroid Build Coastguard Worker         mCurrentComputePipeline->getPipeline());
2617*8975f5c5SAndroid Build Coastguard Worker     mOutsideRenderPassCommands->retainResource(mCurrentComputePipeline);
2618*8975f5c5SAndroid Build Coastguard Worker 
2619*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2620*8975f5c5SAndroid Build Coastguard Worker }
2621*8975f5c5SAndroid Build Coastguard Worker 
2622*8975f5c5SAndroid Build Coastguard Worker template <typename CommandBufferHelperT>
handleDirtyTexturesImpl(CommandBufferHelperT * commandBufferHelper,PipelineType pipelineType)2623*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
2624*8975f5c5SAndroid Build Coastguard Worker     CommandBufferHelperT *commandBufferHelper,
2625*8975f5c5SAndroid Build Coastguard Worker     PipelineType pipelineType)
2626*8975f5c5SAndroid Build Coastguard Worker {
2627*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2628*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executable);
2629*8975f5c5SAndroid Build Coastguard Worker     const gl::ActiveTextureMask &activeTextures = executable->getActiveSamplersMask();
2630*8975f5c5SAndroid Build Coastguard Worker 
2631*8975f5c5SAndroid Build Coastguard Worker     for (size_t textureUnit : activeTextures)
2632*8975f5c5SAndroid Build Coastguard Worker     {
2633*8975f5c5SAndroid Build Coastguard Worker         TextureVk *textureVk = mActiveTextures[textureUnit];
2634*8975f5c5SAndroid Build Coastguard Worker 
2635*8975f5c5SAndroid Build Coastguard Worker         // If it's a texture buffer, get the attached buffer.
2636*8975f5c5SAndroid Build Coastguard Worker         if (textureVk->getBuffer().get() != nullptr)
2637*8975f5c5SAndroid Build Coastguard Worker         {
2638*8975f5c5SAndroid Build Coastguard Worker             vk::BufferHelper *buffer = textureVk->getPossiblyEmulatedTextureBuffer(this);
2639*8975f5c5SAndroid Build Coastguard Worker             const gl::ShaderBitSet stages =
2640*8975f5c5SAndroid Build Coastguard Worker                 executable->getSamplerShaderBitsForTextureUnitIndex(textureUnit);
2641*8975f5c5SAndroid Build Coastguard Worker 
2642*8975f5c5SAndroid Build Coastguard Worker             OnTextureBufferRead(buffer, stages, commandBufferHelper);
2643*8975f5c5SAndroid Build Coastguard Worker 
2644*8975f5c5SAndroid Build Coastguard Worker             textureVk->retainBufferViews(commandBufferHelper);
2645*8975f5c5SAndroid Build Coastguard Worker             continue;
2646*8975f5c5SAndroid Build Coastguard Worker         }
2647*8975f5c5SAndroid Build Coastguard Worker 
2648*8975f5c5SAndroid Build Coastguard Worker         // The image should be flushed and ready to use at this point. There may still be
2649*8975f5c5SAndroid Build Coastguard Worker         // lingering staged updates in its staging buffer for unused texture mip levels or
2650*8975f5c5SAndroid Build Coastguard Worker         // layers. Therefore we can't verify it has no staged updates right here.
2651*8975f5c5SAndroid Build Coastguard Worker         vk::ImageHelper &image = textureVk->getImage();
2652*8975f5c5SAndroid Build Coastguard Worker 
2653*8975f5c5SAndroid Build Coastguard Worker         const vk::ImageLayout imageLayout =
2654*8975f5c5SAndroid Build Coastguard Worker             GetImageReadLayout(textureVk, *executable, textureUnit, pipelineType);
2655*8975f5c5SAndroid Build Coastguard Worker 
2656*8975f5c5SAndroid Build Coastguard Worker         // Ensure the image is in the desired layout
2657*8975f5c5SAndroid Build Coastguard Worker         commandBufferHelper->imageRead(this, image.getAspectFlags(), imageLayout, &image);
2658*8975f5c5SAndroid Build Coastguard Worker     }
2659*8975f5c5SAndroid Build Coastguard Worker 
2660*8975f5c5SAndroid Build Coastguard Worker     if (executable->hasTextures())
2661*8975f5c5SAndroid Build Coastguard Worker     {
2662*8975f5c5SAndroid Build Coastguard Worker         ProgramExecutableVk *executableVk = vk::GetImpl(executable);
2663*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(executableVk->updateTexturesDescriptorSet(
2664*8975f5c5SAndroid Build Coastguard Worker             this, getCurrentFrameCount(), mActiveTextures, mState.getSamplers(), pipelineType,
2665*8975f5c5SAndroid Build Coastguard Worker             mShareGroupVk->getUpdateDescriptorSetsBuilder()));
2666*8975f5c5SAndroid Build Coastguard Worker     }
2667*8975f5c5SAndroid Build Coastguard Worker 
2668*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2669*8975f5c5SAndroid Build Coastguard Worker }
2670*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsTextures(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2671*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsTextures(DirtyBits::Iterator *dirtyBitsIterator,
2672*8975f5c5SAndroid Build Coastguard Worker                                                      DirtyBits dirtyBitMask)
2673*8975f5c5SAndroid Build Coastguard Worker {
2674*8975f5c5SAndroid Build Coastguard Worker     return handleDirtyTexturesImpl(mRenderPassCommands, PipelineType::Graphics);
2675*8975f5c5SAndroid Build Coastguard Worker }
2676*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyComputeTextures(DirtyBits::Iterator * dirtyBitsIterator)2677*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyComputeTextures(DirtyBits::Iterator *dirtyBitsIterator)
2678*8975f5c5SAndroid Build Coastguard Worker {
2679*8975f5c5SAndroid Build Coastguard Worker     return handleDirtyTexturesImpl(mOutsideRenderPassCommands, PipelineType::Compute);
2680*8975f5c5SAndroid Build Coastguard Worker }
2681*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsVertexBuffers(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2682*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(DirtyBits::Iterator *dirtyBitsIterator,
2683*8975f5c5SAndroid Build Coastguard Worker                                                           DirtyBits dirtyBitMask)
2684*8975f5c5SAndroid Build Coastguard Worker {
2685*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2686*8975f5c5SAndroid Build Coastguard Worker     VertexArrayVk *vertexArrayVk            = getVertexArray();
2687*8975f5c5SAndroid Build Coastguard Worker     uint32_t maxAttrib = mState.getProgramExecutable()->getMaxActiveAttribLocation();
2688*8975f5c5SAndroid Build Coastguard Worker     const gl::AttribArray<VkBuffer> &bufferHandles = vertexArrayVk->getCurrentArrayBufferHandles();
2689*8975f5c5SAndroid Build Coastguard Worker     const gl::AttribArray<VkDeviceSize> &bufferOffsets =
2690*8975f5c5SAndroid Build Coastguard Worker         vertexArrayVk->getCurrentArrayBufferOffsets();
2691*8975f5c5SAndroid Build Coastguard Worker 
2692*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useVertexInputBindingStrideDynamicState.enabled ||
2693*8975f5c5SAndroid Build Coastguard Worker         getFeatures().supportsVertexInputDynamicState.enabled)
2694*8975f5c5SAndroid Build Coastguard Worker     {
2695*8975f5c5SAndroid Build Coastguard Worker         const gl::AttribArray<GLuint> &bufferStrides =
2696*8975f5c5SAndroid Build Coastguard Worker             vertexArrayVk->getCurrentArrayBufferStrides();
2697*8975f5c5SAndroid Build Coastguard Worker         const gl::AttribArray<angle::FormatID> &bufferFormats =
2698*8975f5c5SAndroid Build Coastguard Worker             vertexArrayVk->getCurrentArrayBufferFormats();
2699*8975f5c5SAndroid Build Coastguard Worker         gl::AttribArray<VkDeviceSize> strides = {};
2700*8975f5c5SAndroid Build Coastguard Worker         const gl::AttribArray<GLuint> &bufferDivisors =
2701*8975f5c5SAndroid Build Coastguard Worker             vertexArrayVk->getCurrentArrayBufferDivisors();
2702*8975f5c5SAndroid Build Coastguard Worker         const gl::AttribArray<GLuint> &bufferRelativeOffsets =
2703*8975f5c5SAndroid Build Coastguard Worker             vertexArrayVk->getCurrentArrayBufferRelativeOffsets();
2704*8975f5c5SAndroid Build Coastguard Worker         const gl::AttributesMask &bufferCompressed =
2705*8975f5c5SAndroid Build Coastguard Worker             vertexArrayVk->getCurrentArrayBufferCompressed();
2706*8975f5c5SAndroid Build Coastguard Worker 
2707*8975f5c5SAndroid Build Coastguard Worker         gl::AttribVector<VkVertexInputBindingDescription2EXT> bindingDescs;
2708*8975f5c5SAndroid Build Coastguard Worker         gl::AttribVector<VkVertexInputAttributeDescription2EXT> attributeDescs;
2709*8975f5c5SAndroid Build Coastguard Worker 
2710*8975f5c5SAndroid Build Coastguard Worker         // Set stride to 0 for mismatching formats between the program's declared attribute and that
2711*8975f5c5SAndroid Build Coastguard Worker         // which is specified in glVertexAttribPointer.  See comment in vk_cache_utils.cpp
2712*8975f5c5SAndroid Build Coastguard Worker         // (initializePipeline) for more details.
2713*8975f5c5SAndroid Build Coastguard Worker         const gl::AttributesMask &activeAttribLocations =
2714*8975f5c5SAndroid Build Coastguard Worker             executable->getNonBuiltinAttribLocationsMask();
2715*8975f5c5SAndroid Build Coastguard Worker         const gl::ComponentTypeMask &programAttribsTypeMask = executable->getAttributesTypeMask();
2716*8975f5c5SAndroid Build Coastguard Worker 
2717*8975f5c5SAndroid Build Coastguard Worker         for (size_t attribIndex : activeAttribLocations)
2718*8975f5c5SAndroid Build Coastguard Worker         {
2719*8975f5c5SAndroid Build Coastguard Worker             const angle::Format &intendedFormat =
2720*8975f5c5SAndroid Build Coastguard Worker                 mRenderer->getFormat(bufferFormats[attribIndex]).getIntendedFormat();
2721*8975f5c5SAndroid Build Coastguard Worker 
2722*8975f5c5SAndroid Build Coastguard Worker             const gl::ComponentType attribType = GetVertexAttributeComponentType(
2723*8975f5c5SAndroid Build Coastguard Worker                 intendedFormat.isPureInt(), intendedFormat.vertexAttribType);
2724*8975f5c5SAndroid Build Coastguard Worker             const gl::ComponentType programAttribType =
2725*8975f5c5SAndroid Build Coastguard Worker                 gl::GetComponentTypeMask(programAttribsTypeMask, attribIndex);
2726*8975f5c5SAndroid Build Coastguard Worker 
2727*8975f5c5SAndroid Build Coastguard Worker             const bool mismatchingType =
2728*8975f5c5SAndroid Build Coastguard Worker                 attribType != programAttribType && (programAttribType == gl::ComponentType::Float ||
2729*8975f5c5SAndroid Build Coastguard Worker                                                     attribType == gl::ComponentType::Float);
2730*8975f5c5SAndroid Build Coastguard Worker             strides[attribIndex] = mismatchingType ? 0 : bufferStrides[attribIndex];
2731*8975f5c5SAndroid Build Coastguard Worker 
2732*8975f5c5SAndroid Build Coastguard Worker             if (getFeatures().supportsVertexInputDynamicState.enabled)
2733*8975f5c5SAndroid Build Coastguard Worker             {
2734*8975f5c5SAndroid Build Coastguard Worker                 VkVertexInputBindingDescription2EXT bindingDesc  = {};
2735*8975f5c5SAndroid Build Coastguard Worker                 VkVertexInputAttributeDescription2EXT attribDesc = {};
2736*8975f5c5SAndroid Build Coastguard Worker                 bindingDesc.sType   = VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT;
2737*8975f5c5SAndroid Build Coastguard Worker                 bindingDesc.binding = static_cast<uint32_t>(attribIndex);
2738*8975f5c5SAndroid Build Coastguard Worker                 bindingDesc.stride  = static_cast<uint32_t>(strides[attribIndex]);
2739*8975f5c5SAndroid Build Coastguard Worker                 bindingDesc.divisor =
2740*8975f5c5SAndroid Build Coastguard Worker                     bufferDivisors[attribIndex] > mRenderer->getMaxVertexAttribDivisor()
2741*8975f5c5SAndroid Build Coastguard Worker                         ? 1
2742*8975f5c5SAndroid Build Coastguard Worker                         : bufferDivisors[attribIndex];
2743*8975f5c5SAndroid Build Coastguard Worker                 if (bindingDesc.divisor != 0)
2744*8975f5c5SAndroid Build Coastguard Worker                 {
2745*8975f5c5SAndroid Build Coastguard Worker                     bindingDesc.inputRate =
2746*8975f5c5SAndroid Build Coastguard Worker                         static_cast<VkVertexInputRate>(VK_VERTEX_INPUT_RATE_INSTANCE);
2747*8975f5c5SAndroid Build Coastguard Worker                 }
2748*8975f5c5SAndroid Build Coastguard Worker                 else
2749*8975f5c5SAndroid Build Coastguard Worker                 {
2750*8975f5c5SAndroid Build Coastguard Worker                     bindingDesc.inputRate =
2751*8975f5c5SAndroid Build Coastguard Worker                         static_cast<VkVertexInputRate>(VK_VERTEX_INPUT_RATE_VERTEX);
2752*8975f5c5SAndroid Build Coastguard Worker                     // Divisor value is ignored by the implementation when using
2753*8975f5c5SAndroid Build Coastguard Worker                     // VK_VERTEX_INPUT_RATE_VERTEX, but it is set to 1 to avoid a validation error
2754*8975f5c5SAndroid Build Coastguard Worker                     // due to a validation layer issue.
2755*8975f5c5SAndroid Build Coastguard Worker                     bindingDesc.divisor = 1;
2756*8975f5c5SAndroid Build Coastguard Worker                 }
2757*8975f5c5SAndroid Build Coastguard Worker 
2758*8975f5c5SAndroid Build Coastguard Worker                 attribDesc.sType   = VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT;
2759*8975f5c5SAndroid Build Coastguard Worker                 attribDesc.binding = static_cast<uint32_t>(attribIndex);
2760*8975f5c5SAndroid Build Coastguard Worker                 attribDesc.format  = vk::GraphicsPipelineDesc::getPipelineVertexInputStateFormat(
2761*8975f5c5SAndroid Build Coastguard Worker                     this, bufferFormats[attribIndex], bufferCompressed[attribIndex],
2762*8975f5c5SAndroid Build Coastguard Worker                     programAttribType, static_cast<uint32_t>(attribIndex));
2763*8975f5c5SAndroid Build Coastguard Worker                 attribDesc.location = static_cast<uint32_t>(attribIndex);
2764*8975f5c5SAndroid Build Coastguard Worker                 attribDesc.offset   = bufferRelativeOffsets[attribIndex];
2765*8975f5c5SAndroid Build Coastguard Worker 
2766*8975f5c5SAndroid Build Coastguard Worker                 bindingDescs.push_back(bindingDesc);
2767*8975f5c5SAndroid Build Coastguard Worker                 attributeDescs.push_back(attribDesc);
2768*8975f5c5SAndroid Build Coastguard Worker             }
2769*8975f5c5SAndroid Build Coastguard Worker         }
2770*8975f5c5SAndroid Build Coastguard Worker 
2771*8975f5c5SAndroid Build Coastguard Worker         if (getFeatures().supportsVertexInputDynamicState.enabled)
2772*8975f5c5SAndroid Build Coastguard Worker         {
2773*8975f5c5SAndroid Build Coastguard Worker             mRenderPassCommandBuffer->setVertexInput(
2774*8975f5c5SAndroid Build Coastguard Worker                 static_cast<uint32_t>(bindingDescs.size()), bindingDescs.data(),
2775*8975f5c5SAndroid Build Coastguard Worker                 static_cast<uint32_t>(attributeDescs.size()), attributeDescs.data());
2776*8975f5c5SAndroid Build Coastguard Worker             if (bindingDescs.size() != 0)
2777*8975f5c5SAndroid Build Coastguard Worker             {
2778*8975f5c5SAndroid Build Coastguard Worker 
2779*8975f5c5SAndroid Build Coastguard Worker                 mRenderPassCommandBuffer->bindVertexBuffers(0, maxAttrib, bufferHandles.data(),
2780*8975f5c5SAndroid Build Coastguard Worker                                                             bufferOffsets.data());
2781*8975f5c5SAndroid Build Coastguard Worker             }
2782*8975f5c5SAndroid Build Coastguard Worker         }
2783*8975f5c5SAndroid Build Coastguard Worker         else
2784*8975f5c5SAndroid Build Coastguard Worker         {
2785*8975f5c5SAndroid Build Coastguard Worker             // TODO: Use the sizes parameters here to fix the robustness issue worked around in
2786*8975f5c5SAndroid Build Coastguard Worker             // crbug.com/1310038
2787*8975f5c5SAndroid Build Coastguard Worker             mRenderPassCommandBuffer->bindVertexBuffers2(
2788*8975f5c5SAndroid Build Coastguard Worker                 0, maxAttrib, bufferHandles.data(), bufferOffsets.data(), nullptr, strides.data());
2789*8975f5c5SAndroid Build Coastguard Worker         }
2790*8975f5c5SAndroid Build Coastguard Worker     }
2791*8975f5c5SAndroid Build Coastguard Worker     else
2792*8975f5c5SAndroid Build Coastguard Worker     {
2793*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommandBuffer->bindVertexBuffers(0, maxAttrib, bufferHandles.data(),
2794*8975f5c5SAndroid Build Coastguard Worker                                                     bufferOffsets.data());
2795*8975f5c5SAndroid Build Coastguard Worker     }
2796*8975f5c5SAndroid Build Coastguard Worker 
2797*8975f5c5SAndroid Build Coastguard Worker     const gl::AttribArray<vk::BufferHelper *> &arrayBufferResources =
2798*8975f5c5SAndroid Build Coastguard Worker         vertexArrayVk->getCurrentArrayBuffers();
2799*8975f5c5SAndroid Build Coastguard Worker 
2800*8975f5c5SAndroid Build Coastguard Worker     // Mark all active vertex buffers as accessed.
2801*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t attribIndex = 0; attribIndex < maxAttrib; ++attribIndex)
2802*8975f5c5SAndroid Build Coastguard Worker     {
2803*8975f5c5SAndroid Build Coastguard Worker         vk::BufferHelper *arrayBuffer = arrayBufferResources[attribIndex];
2804*8975f5c5SAndroid Build Coastguard Worker         if (arrayBuffer)
2805*8975f5c5SAndroid Build Coastguard Worker         {
2806*8975f5c5SAndroid Build Coastguard Worker             mRenderPassCommands->bufferRead(VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
2807*8975f5c5SAndroid Build Coastguard Worker                                             vk::PipelineStage::VertexInput, arrayBuffer);
2808*8975f5c5SAndroid Build Coastguard Worker         }
2809*8975f5c5SAndroid Build Coastguard Worker     }
2810*8975f5c5SAndroid Build Coastguard Worker 
2811*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2812*8975f5c5SAndroid Build Coastguard Worker }
2813*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsIndexBuffer(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2814*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsIndexBuffer(DirtyBits::Iterator *dirtyBitsIterator,
2815*8975f5c5SAndroid Build Coastguard Worker                                                         DirtyBits dirtyBitMask)
2816*8975f5c5SAndroid Build Coastguard Worker {
2817*8975f5c5SAndroid Build Coastguard Worker     vk::BufferHelper *elementArrayBuffer = mCurrentIndexBuffer;
2818*8975f5c5SAndroid Build Coastguard Worker     ASSERT(elementArrayBuffer != nullptr);
2819*8975f5c5SAndroid Build Coastguard Worker 
2820*8975f5c5SAndroid Build Coastguard Worker     VkDeviceSize bufferOffset;
2821*8975f5c5SAndroid Build Coastguard Worker     const vk::Buffer &buffer = elementArrayBuffer->getBufferForVertexArray(
2822*8975f5c5SAndroid Build Coastguard Worker         this, elementArrayBuffer->getSize(), &bufferOffset);
2823*8975f5c5SAndroid Build Coastguard Worker 
2824*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->bindIndexBuffer(buffer, bufferOffset + mCurrentIndexBufferOffset,
2825*8975f5c5SAndroid Build Coastguard Worker                                               getVkIndexType(mCurrentDrawElementsType));
2826*8975f5c5SAndroid Build Coastguard Worker 
2827*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommands->bufferRead(VK_ACCESS_INDEX_READ_BIT, vk::PipelineStage::VertexInput,
2828*8975f5c5SAndroid Build Coastguard Worker                                     elementArrayBuffer);
2829*8975f5c5SAndroid Build Coastguard Worker 
2830*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2831*8975f5c5SAndroid Build Coastguard Worker }
2832*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsFramebufferFetchBarrier(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2833*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsFramebufferFetchBarrier(
2834*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
2835*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
2836*8975f5c5SAndroid Build Coastguard Worker {
2837*8975f5c5SAndroid Build Coastguard Worker     VkMemoryBarrier memoryBarrier = {};
2838*8975f5c5SAndroid Build Coastguard Worker     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2839*8975f5c5SAndroid Build Coastguard Worker     memoryBarrier.srcAccessMask   = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
2840*8975f5c5SAndroid Build Coastguard Worker     memoryBarrier.dstAccessMask   = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
2841*8975f5c5SAndroid Build Coastguard Worker 
2842*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->pipelineBarrier(
2843*8975f5c5SAndroid Build Coastguard Worker         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
2844*8975f5c5SAndroid Build Coastguard Worker         GetLocalDependencyFlags(this), 1, &memoryBarrier, 0, nullptr, 0, nullptr);
2845*8975f5c5SAndroid Build Coastguard Worker 
2846*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2847*8975f5c5SAndroid Build Coastguard Worker }
2848*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsBlendBarrier(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2849*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsBlendBarrier(DirtyBits::Iterator *dirtyBitsIterator,
2850*8975f5c5SAndroid Build Coastguard Worker                                                          DirtyBits dirtyBitMask)
2851*8975f5c5SAndroid Build Coastguard Worker {
2852*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().supportsBlendOperationAdvancedCoherent.enabled)
2853*8975f5c5SAndroid Build Coastguard Worker     {
2854*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2855*8975f5c5SAndroid Build Coastguard Worker     }
2856*8975f5c5SAndroid Build Coastguard Worker 
2857*8975f5c5SAndroid Build Coastguard Worker     VkMemoryBarrier memoryBarrier = {};
2858*8975f5c5SAndroid Build Coastguard Worker     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2859*8975f5c5SAndroid Build Coastguard Worker     memoryBarrier.srcAccessMask   = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
2860*8975f5c5SAndroid Build Coastguard Worker     memoryBarrier.dstAccessMask   = VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT;
2861*8975f5c5SAndroid Build Coastguard Worker 
2862*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2863*8975f5c5SAndroid Build Coastguard Worker                                               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2864*8975f5c5SAndroid Build Coastguard Worker                                               GetLocalDependencyFlags(this), 1, &memoryBarrier, 0,
2865*8975f5c5SAndroid Build Coastguard Worker                                               nullptr, 0, nullptr);
2866*8975f5c5SAndroid Build Coastguard Worker 
2867*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2868*8975f5c5SAndroid Build Coastguard Worker }
2869*8975f5c5SAndroid Build Coastguard Worker 
2870*8975f5c5SAndroid Build Coastguard Worker template <typename CommandBufferHelperT>
handleDirtyShaderResourcesImpl(CommandBufferHelperT * commandBufferHelper,PipelineType pipelineType,DirtyBits::Iterator * dirtyBitsIterator)2871*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyShaderResourcesImpl(CommandBufferHelperT *commandBufferHelper,
2872*8975f5c5SAndroid Build Coastguard Worker                                                         PipelineType pipelineType,
2873*8975f5c5SAndroid Build Coastguard Worker                                                         DirtyBits::Iterator *dirtyBitsIterator)
2874*8975f5c5SAndroid Build Coastguard Worker {
2875*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
2876*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executable);
2877*8975f5c5SAndroid Build Coastguard Worker 
2878*8975f5c5SAndroid Build Coastguard Worker     // DIRTY_BIT_UNIFORM_BUFFERS is set when uniform buffer bindings change.
2879*8975f5c5SAndroid Build Coastguard Worker     // DIRTY_BIT_SHADER_RESOURCES gets set when the program executable has changed. In that case,
2880*8975f5c5SAndroid Build Coastguard Worker     // this function will update entire the shader resource descriptorSet.  This means there is no
2881*8975f5c5SAndroid Build Coastguard Worker     // need to process uniform buffer bindings again.
2882*8975f5c5SAndroid Build Coastguard Worker     dirtyBitsIterator->resetLaterBit(DIRTY_BIT_UNIFORM_BUFFERS);
2883*8975f5c5SAndroid Build Coastguard Worker 
2884*8975f5c5SAndroid Build Coastguard Worker     // This function processes uniform buffers, so it doesn't matter which are dirty.  The following
2885*8975f5c5SAndroid Build Coastguard Worker     // makes sure the dirty bits are reset.
2886*8975f5c5SAndroid Build Coastguard Worker     mState.getAndResetDirtyUniformBlocks();
2887*8975f5c5SAndroid Build Coastguard Worker 
2888*8975f5c5SAndroid Build Coastguard Worker     const bool hasImages               = executable->hasImages();
2889*8975f5c5SAndroid Build Coastguard Worker     const bool hasStorageBuffers       = executable->hasStorageBuffers();
2890*8975f5c5SAndroid Build Coastguard Worker     const bool hasAtomicCounterBuffers = executable->hasAtomicCounterBuffers();
2891*8975f5c5SAndroid Build Coastguard Worker     const bool hasUniformBuffers       = executable->hasUniformBuffers();
2892*8975f5c5SAndroid Build Coastguard Worker     const bool hasFramebufferFetch     = executable->usesColorFramebufferFetch() ||
2893*8975f5c5SAndroid Build Coastguard Worker                                      executable->usesDepthFramebufferFetch() ||
2894*8975f5c5SAndroid Build Coastguard Worker                                      executable->usesStencilFramebufferFetch();
2895*8975f5c5SAndroid Build Coastguard Worker 
2896*8975f5c5SAndroid Build Coastguard Worker     if (!hasUniformBuffers && !hasStorageBuffers && !hasAtomicCounterBuffers && !hasImages &&
2897*8975f5c5SAndroid Build Coastguard Worker         !hasFramebufferFetch)
2898*8975f5c5SAndroid Build Coastguard Worker     {
2899*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2900*8975f5c5SAndroid Build Coastguard Worker     }
2901*8975f5c5SAndroid Build Coastguard Worker 
2902*8975f5c5SAndroid Build Coastguard Worker     const VkPhysicalDeviceLimits &limits = mRenderer->getPhysicalDeviceProperties().limits;
2903*8975f5c5SAndroid Build Coastguard Worker     ProgramExecutableVk *executableVk    = vk::GetImpl(executable);
2904*8975f5c5SAndroid Build Coastguard Worker     const ShaderInterfaceVariableInfoMap &variableInfoMap = executableVk->getVariableInfoMap();
2905*8975f5c5SAndroid Build Coastguard Worker 
2906*8975f5c5SAndroid Build Coastguard Worker     mShaderBufferWriteDescriptorDescs = executableVk->getShaderResourceWriteDescriptorDescs();
2907*8975f5c5SAndroid Build Coastguard Worker     // Update writeDescriptorDescs with inputAttachments
2908*8975f5c5SAndroid Build Coastguard Worker     mShaderBufferWriteDescriptorDescs.updateInputAttachments(
2909*8975f5c5SAndroid Build Coastguard Worker         *executable, variableInfoMap, vk::GetImpl(mState.getDrawFramebuffer()));
2910*8975f5c5SAndroid Build Coastguard Worker 
2911*8975f5c5SAndroid Build Coastguard Worker     mShaderBuffersDescriptorDesc.resize(
2912*8975f5c5SAndroid Build Coastguard Worker         mShaderBufferWriteDescriptorDescs.getTotalDescriptorCount());
2913*8975f5c5SAndroid Build Coastguard Worker     if (hasUniformBuffers)
2914*8975f5c5SAndroid Build Coastguard Worker     {
2915*8975f5c5SAndroid Build Coastguard Worker         mShaderBuffersDescriptorDesc.updateShaderBuffers(
2916*8975f5c5SAndroid Build Coastguard Worker             commandBufferHelper, *executable, variableInfoMap,
2917*8975f5c5SAndroid Build Coastguard Worker             mState.getOffsetBindingPointerUniformBuffers(), executable->getUniformBlocks(),
2918*8975f5c5SAndroid Build Coastguard Worker             executableVk->getUniformBufferDescriptorType(), limits.maxUniformBufferRange,
2919*8975f5c5SAndroid Build Coastguard Worker             mEmptyBuffer, mShaderBufferWriteDescriptorDescs, mDeferredMemoryBarriers);
2920*8975f5c5SAndroid Build Coastguard Worker     }
2921*8975f5c5SAndroid Build Coastguard Worker     if (hasStorageBuffers)
2922*8975f5c5SAndroid Build Coastguard Worker     {
2923*8975f5c5SAndroid Build Coastguard Worker         mShaderBuffersDescriptorDesc.updateShaderBuffers(
2924*8975f5c5SAndroid Build Coastguard Worker             commandBufferHelper, *executable, variableInfoMap,
2925*8975f5c5SAndroid Build Coastguard Worker             mState.getOffsetBindingPointerShaderStorageBuffers(),
2926*8975f5c5SAndroid Build Coastguard Worker             executable->getShaderStorageBlocks(), executableVk->getStorageBufferDescriptorType(),
2927*8975f5c5SAndroid Build Coastguard Worker             limits.maxStorageBufferRange, mEmptyBuffer, mShaderBufferWriteDescriptorDescs,
2928*8975f5c5SAndroid Build Coastguard Worker             mDeferredMemoryBarriers);
2929*8975f5c5SAndroid Build Coastguard Worker     }
2930*8975f5c5SAndroid Build Coastguard Worker     if (hasAtomicCounterBuffers)
2931*8975f5c5SAndroid Build Coastguard Worker     {
2932*8975f5c5SAndroid Build Coastguard Worker         mShaderBuffersDescriptorDesc.updateAtomicCounters(
2933*8975f5c5SAndroid Build Coastguard Worker             commandBufferHelper, *executable, variableInfoMap,
2934*8975f5c5SAndroid Build Coastguard Worker             mState.getOffsetBindingPointerAtomicCounterBuffers(),
2935*8975f5c5SAndroid Build Coastguard Worker             executable->getAtomicCounterBuffers(), limits.minStorageBufferOffsetAlignment,
2936*8975f5c5SAndroid Build Coastguard Worker             mEmptyBuffer, mShaderBufferWriteDescriptorDescs);
2937*8975f5c5SAndroid Build Coastguard Worker     }
2938*8975f5c5SAndroid Build Coastguard Worker     if (hasImages)
2939*8975f5c5SAndroid Build Coastguard Worker     {
2940*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(updateActiveImages(commandBufferHelper));
2941*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mShaderBuffersDescriptorDesc.updateImages(this, *executable, variableInfoMap,
2942*8975f5c5SAndroid Build Coastguard Worker                                                             mActiveImages, mState.getImageUnits(),
2943*8975f5c5SAndroid Build Coastguard Worker                                                             mShaderBufferWriteDescriptorDescs));
2944*8975f5c5SAndroid Build Coastguard Worker     }
2945*8975f5c5SAndroid Build Coastguard Worker     if (hasFramebufferFetch)
2946*8975f5c5SAndroid Build Coastguard Worker     {
2947*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mShaderBuffersDescriptorDesc.updateInputAttachments(
2948*8975f5c5SAndroid Build Coastguard Worker             this, *executable, variableInfoMap, vk::GetImpl(mState.getDrawFramebuffer()),
2949*8975f5c5SAndroid Build Coastguard Worker             mShaderBufferWriteDescriptorDescs));
2950*8975f5c5SAndroid Build Coastguard Worker     }
2951*8975f5c5SAndroid Build Coastguard Worker 
2952*8975f5c5SAndroid Build Coastguard Worker     mDeferredMemoryBarriers = 0;
2953*8975f5c5SAndroid Build Coastguard Worker 
2954*8975f5c5SAndroid Build Coastguard Worker     vk::SharedDescriptorSetCacheKey newSharedCacheKey;
2955*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(executableVk->updateShaderResourcesDescriptorSet(
2956*8975f5c5SAndroid Build Coastguard Worker         this, getCurrentFrameCount(), mShareGroupVk->getUpdateDescriptorSetsBuilder(),
2957*8975f5c5SAndroid Build Coastguard Worker         mShaderBufferWriteDescriptorDescs, mShaderBuffersDescriptorDesc, &newSharedCacheKey));
2958*8975f5c5SAndroid Build Coastguard Worker 
2959*8975f5c5SAndroid Build Coastguard Worker     if (newSharedCacheKey)
2960*8975f5c5SAndroid Build Coastguard Worker     {
2961*8975f5c5SAndroid Build Coastguard Worker         // A new cache entry has been created. We record this cache key in the images and buffers so
2962*8975f5c5SAndroid Build Coastguard Worker         // that the descriptorSet cache can be destroyed when buffer/image is destroyed.
2963*8975f5c5SAndroid Build Coastguard Worker         updateShaderResourcesWithSharedCacheKey(newSharedCacheKey);
2964*8975f5c5SAndroid Build Coastguard Worker     }
2965*8975f5c5SAndroid Build Coastguard Worker 
2966*8975f5c5SAndroid Build Coastguard Worker     // Record usage of storage buffers and images in the command buffer to aid handling of
2967*8975f5c5SAndroid Build Coastguard Worker     // glMemoryBarrier.
2968*8975f5c5SAndroid Build Coastguard Worker     if (hasImages || hasStorageBuffers || hasAtomicCounterBuffers)
2969*8975f5c5SAndroid Build Coastguard Worker     {
2970*8975f5c5SAndroid Build Coastguard Worker         commandBufferHelper->setHasShaderStorageOutput();
2971*8975f5c5SAndroid Build Coastguard Worker     }
2972*8975f5c5SAndroid Build Coastguard Worker 
2973*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2974*8975f5c5SAndroid Build Coastguard Worker }
2975*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsShaderResources(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)2976*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsShaderResources(DirtyBits::Iterator *dirtyBitsIterator,
2977*8975f5c5SAndroid Build Coastguard Worker                                                             DirtyBits dirtyBitMask)
2978*8975f5c5SAndroid Build Coastguard Worker {
2979*8975f5c5SAndroid Build Coastguard Worker     return handleDirtyShaderResourcesImpl(mRenderPassCommands, PipelineType::Graphics,
2980*8975f5c5SAndroid Build Coastguard Worker                                           dirtyBitsIterator);
2981*8975f5c5SAndroid Build Coastguard Worker }
2982*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyComputeShaderResources(DirtyBits::Iterator * dirtyBitsIterator)2983*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyComputeShaderResources(DirtyBits::Iterator *dirtyBitsIterator)
2984*8975f5c5SAndroid Build Coastguard Worker {
2985*8975f5c5SAndroid Build Coastguard Worker     return handleDirtyShaderResourcesImpl(mOutsideRenderPassCommands, PipelineType::Compute,
2986*8975f5c5SAndroid Build Coastguard Worker                                           dirtyBitsIterator);
2987*8975f5c5SAndroid Build Coastguard Worker }
2988*8975f5c5SAndroid Build Coastguard Worker 
2989*8975f5c5SAndroid Build Coastguard Worker template <typename CommandBufferT>
handleDirtyUniformBuffersImpl(CommandBufferT * commandBufferHelper)2990*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyUniformBuffersImpl(CommandBufferT *commandBufferHelper)
2991*8975f5c5SAndroid Build Coastguard Worker {
2992*8975f5c5SAndroid Build Coastguard Worker     gl::ProgramExecutable *executable = mState.getProgramExecutable();
2993*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executable);
2994*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executable->hasUniformBuffers());
2995*8975f5c5SAndroid Build Coastguard Worker 
2996*8975f5c5SAndroid Build Coastguard Worker     const VkPhysicalDeviceLimits &limits = mRenderer->getPhysicalDeviceProperties().limits;
2997*8975f5c5SAndroid Build Coastguard Worker     ProgramExecutableVk *executableVk    = vk::GetImpl(executable);
2998*8975f5c5SAndroid Build Coastguard Worker     const ShaderInterfaceVariableInfoMap &variableInfoMap = executableVk->getVariableInfoMap();
2999*8975f5c5SAndroid Build Coastguard Worker 
3000*8975f5c5SAndroid Build Coastguard Worker     gl::ProgramUniformBlockMask dirtyBits = mState.getAndResetDirtyUniformBlocks();
3001*8975f5c5SAndroid Build Coastguard Worker     for (size_t blockIndex : dirtyBits)
3002*8975f5c5SAndroid Build Coastguard Worker     {
3003*8975f5c5SAndroid Build Coastguard Worker         const GLuint binding = executable->getUniformBlockBinding(blockIndex);
3004*8975f5c5SAndroid Build Coastguard Worker         mShaderBuffersDescriptorDesc.updateOneShaderBuffer(
3005*8975f5c5SAndroid Build Coastguard Worker             commandBufferHelper, variableInfoMap, mState.getOffsetBindingPointerUniformBuffers(),
3006*8975f5c5SAndroid Build Coastguard Worker             executable->getUniformBlocks()[blockIndex], binding,
3007*8975f5c5SAndroid Build Coastguard Worker             executableVk->getUniformBufferDescriptorType(), limits.maxUniformBufferRange,
3008*8975f5c5SAndroid Build Coastguard Worker             mEmptyBuffer, mShaderBufferWriteDescriptorDescs, mDeferredMemoryBarriers);
3009*8975f5c5SAndroid Build Coastguard Worker     }
3010*8975f5c5SAndroid Build Coastguard Worker 
3011*8975f5c5SAndroid Build Coastguard Worker     vk::SharedDescriptorSetCacheKey newSharedCacheKey;
3012*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(executableVk->updateShaderResourcesDescriptorSet(
3013*8975f5c5SAndroid Build Coastguard Worker         this, getCurrentFrameCount(), mShareGroupVk->getUpdateDescriptorSetsBuilder(),
3014*8975f5c5SAndroid Build Coastguard Worker         mShaderBufferWriteDescriptorDescs, mShaderBuffersDescriptorDesc, &newSharedCacheKey));
3015*8975f5c5SAndroid Build Coastguard Worker 
3016*8975f5c5SAndroid Build Coastguard Worker     if (newSharedCacheKey)
3017*8975f5c5SAndroid Build Coastguard Worker     {
3018*8975f5c5SAndroid Build Coastguard Worker         // A new cache entry has been created. We record this cache key in the images and
3019*8975f5c5SAndroid Build Coastguard Worker         // buffers so that the descriptorSet cache can be destroyed when buffer/image is
3020*8975f5c5SAndroid Build Coastguard Worker         // destroyed.
3021*8975f5c5SAndroid Build Coastguard Worker         updateShaderResourcesWithSharedCacheKey(newSharedCacheKey);
3022*8975f5c5SAndroid Build Coastguard Worker     }
3023*8975f5c5SAndroid Build Coastguard Worker 
3024*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3025*8975f5c5SAndroid Build Coastguard Worker }
3026*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsUniformBuffers(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3027*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsUniformBuffers(DirtyBits::Iterator *dirtyBitsIterator,
3028*8975f5c5SAndroid Build Coastguard Worker                                                            DirtyBits dirtyBitMask)
3029*8975f5c5SAndroid Build Coastguard Worker {
3030*8975f5c5SAndroid Build Coastguard Worker     return handleDirtyUniformBuffersImpl(mRenderPassCommands);
3031*8975f5c5SAndroid Build Coastguard Worker }
3032*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyComputeUniformBuffers(DirtyBits::Iterator * dirtyBitsIterator)3033*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyComputeUniformBuffers(DirtyBits::Iterator *dirtyBitsIterator)
3034*8975f5c5SAndroid Build Coastguard Worker {
3035*8975f5c5SAndroid Build Coastguard Worker     return handleDirtyUniformBuffersImpl(mOutsideRenderPassCommands);
3036*8975f5c5SAndroid Build Coastguard Worker }
3037*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsTransformFeedbackBuffersEmulation(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3038*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation(
3039*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
3040*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
3041*8975f5c5SAndroid Build Coastguard Worker {
3042*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
3043*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executable);
3044*8975f5c5SAndroid Build Coastguard Worker 
3045*8975f5c5SAndroid Build Coastguard Worker     if (!executable->hasTransformFeedbackOutput())
3046*8975f5c5SAndroid Build Coastguard Worker     {
3047*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
3048*8975f5c5SAndroid Build Coastguard Worker     }
3049*8975f5c5SAndroid Build Coastguard Worker 
3050*8975f5c5SAndroid Build Coastguard Worker     TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(mState.getCurrentTransformFeedback());
3051*8975f5c5SAndroid Build Coastguard Worker 
3052*8975f5c5SAndroid Build Coastguard Worker     if (mState.isTransformFeedbackActiveUnpaused())
3053*8975f5c5SAndroid Build Coastguard Worker     {
3054*8975f5c5SAndroid Build Coastguard Worker         size_t bufferCount = executable->getTransformFeedbackBufferCount();
3055*8975f5c5SAndroid Build Coastguard Worker         const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &bufferHelpers =
3056*8975f5c5SAndroid Build Coastguard Worker             transformFeedbackVk->getBufferHelpers();
3057*8975f5c5SAndroid Build Coastguard Worker 
3058*8975f5c5SAndroid Build Coastguard Worker         for (size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
3059*8975f5c5SAndroid Build Coastguard Worker         {
3060*8975f5c5SAndroid Build Coastguard Worker             vk::BufferHelper *bufferHelper = bufferHelpers[bufferIndex];
3061*8975f5c5SAndroid Build Coastguard Worker             ASSERT(bufferHelper);
3062*8975f5c5SAndroid Build Coastguard Worker             mRenderPassCommands->bufferWrite(VK_ACCESS_SHADER_WRITE_BIT,
3063*8975f5c5SAndroid Build Coastguard Worker                                              vk::PipelineStage::VertexShader, bufferHelper);
3064*8975f5c5SAndroid Build Coastguard Worker         }
3065*8975f5c5SAndroid Build Coastguard Worker 
3066*8975f5c5SAndroid Build Coastguard Worker         mCurrentTransformFeedbackQueueSerial = mRenderPassCommands->getQueueSerial();
3067*8975f5c5SAndroid Build Coastguard Worker     }
3068*8975f5c5SAndroid Build Coastguard Worker 
3069*8975f5c5SAndroid Build Coastguard Worker     ProgramExecutableVk *executableVk      = vk::GetImpl(executable);
3070*8975f5c5SAndroid Build Coastguard Worker     vk::BufferHelper *currentUniformBuffer = mDefaultUniformStorage.getCurrentBuffer();
3071*8975f5c5SAndroid Build Coastguard Worker 
3072*8975f5c5SAndroid Build Coastguard Worker     const vk::WriteDescriptorDescs &writeDescriptorDescs =
3073*8975f5c5SAndroid Build Coastguard Worker         executableVk->getDefaultUniformWriteDescriptorDescs(transformFeedbackVk);
3074*8975f5c5SAndroid Build Coastguard Worker 
3075*8975f5c5SAndroid Build Coastguard Worker     vk::DescriptorSetDescBuilder uniformsAndXfbDesc(writeDescriptorDescs.getTotalDescriptorCount());
3076*8975f5c5SAndroid Build Coastguard Worker     uniformsAndXfbDesc.updateUniformsAndXfb(
3077*8975f5c5SAndroid Build Coastguard Worker         this, *executable, writeDescriptorDescs, currentUniformBuffer, mEmptyBuffer,
3078*8975f5c5SAndroid Build Coastguard Worker         mState.isTransformFeedbackActiveUnpaused(), transformFeedbackVk);
3079*8975f5c5SAndroid Build Coastguard Worker 
3080*8975f5c5SAndroid Build Coastguard Worker     vk::SharedDescriptorSetCacheKey newSharedCacheKey;
3081*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(executableVk->updateUniformsAndXfbDescriptorSet(
3082*8975f5c5SAndroid Build Coastguard Worker         this, getCurrentFrameCount(), mShareGroupVk->getUpdateDescriptorSetsBuilder(),
3083*8975f5c5SAndroid Build Coastguard Worker         writeDescriptorDescs, currentUniformBuffer, &uniformsAndXfbDesc, &newSharedCacheKey));
3084*8975f5c5SAndroid Build Coastguard Worker 
3085*8975f5c5SAndroid Build Coastguard Worker     if (newSharedCacheKey)
3086*8975f5c5SAndroid Build Coastguard Worker     {
3087*8975f5c5SAndroid Build Coastguard Worker         if (currentUniformBuffer)
3088*8975f5c5SAndroid Build Coastguard Worker         {
3089*8975f5c5SAndroid Build Coastguard Worker             currentUniformBuffer->getBufferBlock()->onNewDescriptorSet(newSharedCacheKey);
3090*8975f5c5SAndroid Build Coastguard Worker         }
3091*8975f5c5SAndroid Build Coastguard Worker         transformFeedbackVk->onNewDescriptorSet(*executable, newSharedCacheKey);
3092*8975f5c5SAndroid Build Coastguard Worker     }
3093*8975f5c5SAndroid Build Coastguard Worker 
3094*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3095*8975f5c5SAndroid Build Coastguard Worker }
3096*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsTransformFeedbackBuffersExtension(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3097*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension(
3098*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
3099*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
3100*8975f5c5SAndroid Build Coastguard Worker {
3101*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
3102*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executable);
3103*8975f5c5SAndroid Build Coastguard Worker 
3104*8975f5c5SAndroid Build Coastguard Worker     if (!executable->hasTransformFeedbackOutput() || !mState.isTransformFeedbackActive())
3105*8975f5c5SAndroid Build Coastguard Worker     {
3106*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
3107*8975f5c5SAndroid Build Coastguard Worker     }
3108*8975f5c5SAndroid Build Coastguard Worker 
3109*8975f5c5SAndroid Build Coastguard Worker     TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(mState.getCurrentTransformFeedback());
3110*8975f5c5SAndroid Build Coastguard Worker     size_t bufferCount                       = executable->getTransformFeedbackBufferCount();
3111*8975f5c5SAndroid Build Coastguard Worker 
3112*8975f5c5SAndroid Build Coastguard Worker     const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &buffers =
3113*8975f5c5SAndroid Build Coastguard Worker         transformFeedbackVk->getBufferHelpers();
3114*8975f5c5SAndroid Build Coastguard Worker     gl::TransformFeedbackBuffersArray<vk::BufferHelper> &counterBuffers =
3115*8975f5c5SAndroid Build Coastguard Worker         transformFeedbackVk->getCounterBufferHelpers();
3116*8975f5c5SAndroid Build Coastguard Worker 
3117*8975f5c5SAndroid Build Coastguard Worker     // Issue necessary barriers for the transform feedback buffers.
3118*8975f5c5SAndroid Build Coastguard Worker     for (size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
3119*8975f5c5SAndroid Build Coastguard Worker     {
3120*8975f5c5SAndroid Build Coastguard Worker         vk::BufferHelper *bufferHelper = buffers[bufferIndex];
3121*8975f5c5SAndroid Build Coastguard Worker         ASSERT(bufferHelper);
3122*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommands->bufferWrite(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT,
3123*8975f5c5SAndroid Build Coastguard Worker                                          vk::PipelineStage::TransformFeedback, bufferHelper);
3124*8975f5c5SAndroid Build Coastguard Worker     }
3125*8975f5c5SAndroid Build Coastguard Worker 
3126*8975f5c5SAndroid Build Coastguard Worker     // Issue necessary barriers for the transform feedback counter buffer.  Note that the barrier is
3127*8975f5c5SAndroid Build Coastguard Worker     // issued only on the first buffer (which uses a global memory barrier), as all the counter
3128*8975f5c5SAndroid Build Coastguard Worker     // buffers of the transform feedback object are used together.  The rest of the buffers are
3129*8975f5c5SAndroid Build Coastguard Worker     // simply retained so they don't get deleted too early.
3130*8975f5c5SAndroid Build Coastguard Worker     ASSERT(counterBuffers[0].valid());
3131*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommands->bufferWrite(VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT |
3132*8975f5c5SAndroid Build Coastguard Worker                                          VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT,
3133*8975f5c5SAndroid Build Coastguard Worker                                      vk::PipelineStage::TransformFeedback, &counterBuffers[0]);
3134*8975f5c5SAndroid Build Coastguard Worker     for (size_t bufferIndex = 1; bufferIndex < bufferCount; ++bufferIndex)
3135*8975f5c5SAndroid Build Coastguard Worker     {
3136*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommands->retainResourceForWrite(&counterBuffers[bufferIndex]);
3137*8975f5c5SAndroid Build Coastguard Worker     }
3138*8975f5c5SAndroid Build Coastguard Worker 
3139*8975f5c5SAndroid Build Coastguard Worker     const gl::TransformFeedbackBuffersArray<VkBuffer> &bufferHandles =
3140*8975f5c5SAndroid Build Coastguard Worker         transformFeedbackVk->getBufferHandles();
3141*8975f5c5SAndroid Build Coastguard Worker     const gl::TransformFeedbackBuffersArray<VkDeviceSize> &bufferOffsets =
3142*8975f5c5SAndroid Build Coastguard Worker         transformFeedbackVk->getBufferOffsets();
3143*8975f5c5SAndroid Build Coastguard Worker     const gl::TransformFeedbackBuffersArray<VkDeviceSize> &bufferSizes =
3144*8975f5c5SAndroid Build Coastguard Worker         transformFeedbackVk->getBufferSizes();
3145*8975f5c5SAndroid Build Coastguard Worker 
3146*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->bindTransformFeedbackBuffers(
3147*8975f5c5SAndroid Build Coastguard Worker         0, static_cast<uint32_t>(bufferCount), bufferHandles.data(), bufferOffsets.data(),
3148*8975f5c5SAndroid Build Coastguard Worker         bufferSizes.data());
3149*8975f5c5SAndroid Build Coastguard Worker 
3150*8975f5c5SAndroid Build Coastguard Worker     if (!mState.isTransformFeedbackActiveUnpaused())
3151*8975f5c5SAndroid Build Coastguard Worker     {
3152*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
3153*8975f5c5SAndroid Build Coastguard Worker     }
3154*8975f5c5SAndroid Build Coastguard Worker 
3155*8975f5c5SAndroid Build Coastguard Worker     // We should have same number of counter buffers as xfb buffers have
3156*8975f5c5SAndroid Build Coastguard Worker     const gl::TransformFeedbackBuffersArray<VkBuffer> &counterBufferHandles =
3157*8975f5c5SAndroid Build Coastguard Worker         transformFeedbackVk->getCounterBufferHandles();
3158*8975f5c5SAndroid Build Coastguard Worker     const gl::TransformFeedbackBuffersArray<VkDeviceSize> &counterBufferOffsets =
3159*8975f5c5SAndroid Build Coastguard Worker         transformFeedbackVk->getCounterBufferOffsets();
3160*8975f5c5SAndroid Build Coastguard Worker 
3161*8975f5c5SAndroid Build Coastguard Worker     bool rebindBuffers = transformFeedbackVk->getAndResetBufferRebindState();
3162*8975f5c5SAndroid Build Coastguard Worker 
3163*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommands->beginTransformFeedback(bufferCount, counterBufferHandles.data(),
3164*8975f5c5SAndroid Build Coastguard Worker                                                 counterBufferOffsets.data(), rebindBuffers);
3165*8975f5c5SAndroid Build Coastguard Worker 
3166*8975f5c5SAndroid Build Coastguard Worker     mCurrentTransformFeedbackQueueSerial = mRenderPassCommands->getQueueSerial();
3167*8975f5c5SAndroid Build Coastguard Worker 
3168*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3169*8975f5c5SAndroid Build Coastguard Worker }
3170*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsTransformFeedbackResume(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3171*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackResume(
3172*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
3173*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
3174*8975f5c5SAndroid Build Coastguard Worker {
3175*8975f5c5SAndroid Build Coastguard Worker     if (mRenderPassCommands->isTransformFeedbackStarted())
3176*8975f5c5SAndroid Build Coastguard Worker     {
3177*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommands->resumeTransformFeedback();
3178*8975f5c5SAndroid Build Coastguard Worker     }
3179*8975f5c5SAndroid Build Coastguard Worker 
3180*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(resumeXfbRenderPassQueriesIfActive());
3181*8975f5c5SAndroid Build Coastguard Worker 
3182*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3183*8975f5c5SAndroid Build Coastguard Worker }
3184*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDescriptorSets(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3185*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDescriptorSets(DirtyBits::Iterator *dirtyBitsIterator,
3186*8975f5c5SAndroid Build Coastguard Worker                                                            DirtyBits dirtyBitMask)
3187*8975f5c5SAndroid Build Coastguard Worker {
3188*8975f5c5SAndroid Build Coastguard Worker     return handleDirtyDescriptorSetsImpl(mRenderPassCommands, PipelineType::Graphics);
3189*8975f5c5SAndroid Build Coastguard Worker }
3190*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsUniforms(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3191*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsUniforms(DirtyBits::Iterator *dirtyBitsIterator,
3192*8975f5c5SAndroid Build Coastguard Worker                                                      DirtyBits dirtyBitMask)
3193*8975f5c5SAndroid Build Coastguard Worker {
3194*8975f5c5SAndroid Build Coastguard Worker     return handleDirtyUniformsImpl(dirtyBitsIterator);
3195*8975f5c5SAndroid Build Coastguard Worker }
3196*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyComputeUniforms(DirtyBits::Iterator * dirtyBitsIterator)3197*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyComputeUniforms(DirtyBits::Iterator *dirtyBitsIterator)
3198*8975f5c5SAndroid Build Coastguard Worker {
3199*8975f5c5SAndroid Build Coastguard Worker     return handleDirtyUniformsImpl(dirtyBitsIterator);
3200*8975f5c5SAndroid Build Coastguard Worker }
3201*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyUniformsImpl(DirtyBits::Iterator * dirtyBitsIterator)3202*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyUniformsImpl(DirtyBits::Iterator *dirtyBitsIterator)
3203*8975f5c5SAndroid Build Coastguard Worker {
3204*8975f5c5SAndroid Build Coastguard Worker     dirtyBitsIterator->setLaterBit(DIRTY_BIT_DESCRIPTOR_SETS);
3205*8975f5c5SAndroid Build Coastguard Worker 
3206*8975f5c5SAndroid Build Coastguard Worker     ProgramExecutableVk *executableVk = vk::GetImpl(mState.getProgramExecutable());
3207*8975f5c5SAndroid Build Coastguard Worker     TransformFeedbackVk *transformFeedbackVk =
3208*8975f5c5SAndroid Build Coastguard Worker         vk::SafeGetImpl(mState.getCurrentTransformFeedback());
3209*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(executableVk->updateUniforms(
3210*8975f5c5SAndroid Build Coastguard Worker         this, getCurrentFrameCount(), mShareGroupVk->getUpdateDescriptorSetsBuilder(),
3211*8975f5c5SAndroid Build Coastguard Worker         &mEmptyBuffer, &mDefaultUniformStorage, mState.isTransformFeedbackActiveUnpaused(),
3212*8975f5c5SAndroid Build Coastguard Worker         transformFeedbackVk));
3213*8975f5c5SAndroid Build Coastguard Worker 
3214*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3215*8975f5c5SAndroid Build Coastguard Worker }
3216*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicViewport(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3217*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicViewport(DirtyBits::Iterator *dirtyBitsIterator,
3218*8975f5c5SAndroid Build Coastguard Worker                                                             DirtyBits dirtyBitMask)
3219*8975f5c5SAndroid Build Coastguard Worker {
3220*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setViewport(0, 1, &mViewport);
3221*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3222*8975f5c5SAndroid Build Coastguard Worker }
3223*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicScissor(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3224*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicScissor(DirtyBits::Iterator *dirtyBitsIterator,
3225*8975f5c5SAndroid Build Coastguard Worker                                                            DirtyBits dirtyBitMask)
3226*8975f5c5SAndroid Build Coastguard Worker {
3227*8975f5c5SAndroid Build Coastguard Worker     handleDirtyGraphicsDynamicScissorImpl(mState.isQueryActive(gl::QueryType::PrimitivesGenerated));
3228*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3229*8975f5c5SAndroid Build Coastguard Worker }
3230*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicLineWidth(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3231*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicLineWidth(DirtyBits::Iterator *dirtyBitsIterator,
3232*8975f5c5SAndroid Build Coastguard Worker                                                              DirtyBits dirtyBitMask)
3233*8975f5c5SAndroid Build Coastguard Worker {
3234*8975f5c5SAndroid Build Coastguard Worker     // Clamp line width to min/max allowed values. It's not invalid GL to
3235*8975f5c5SAndroid Build Coastguard Worker     // provide out-of-range line widths, but it _is_ invalid Vulkan.
3236*8975f5c5SAndroid Build Coastguard Worker     const float lineWidth = gl::clamp(mState.getLineWidth(), mState.getCaps().minAliasedLineWidth,
3237*8975f5c5SAndroid Build Coastguard Worker                                       mState.getCaps().maxAliasedLineWidth);
3238*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setLineWidth(lineWidth);
3239*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3240*8975f5c5SAndroid Build Coastguard Worker }
3241*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicDepthBias(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3242*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicDepthBias(DirtyBits::Iterator *dirtyBitsIterator,
3243*8975f5c5SAndroid Build Coastguard Worker                                                              DirtyBits dirtyBitMask)
3244*8975f5c5SAndroid Build Coastguard Worker {
3245*8975f5c5SAndroid Build Coastguard Worker     const gl::RasterizerState &rasterState = mState.getRasterizerState();
3246*8975f5c5SAndroid Build Coastguard Worker 
3247*8975f5c5SAndroid Build Coastguard Worker     float depthBiasConstantFactor = rasterState.polygonOffsetUnits;
3248*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().doubleDepthBiasConstantFactor.enabled)
3249*8975f5c5SAndroid Build Coastguard Worker     {
3250*8975f5c5SAndroid Build Coastguard Worker         depthBiasConstantFactor *= 2.0f;
3251*8975f5c5SAndroid Build Coastguard Worker     }
3252*8975f5c5SAndroid Build Coastguard Worker 
3253*8975f5c5SAndroid Build Coastguard Worker     // Note: depth bias clamp is only exposed in EXT_polygon_offset_clamp.
3254*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setDepthBias(depthBiasConstantFactor, rasterState.polygonOffsetClamp,
3255*8975f5c5SAndroid Build Coastguard Worker                                            rasterState.polygonOffsetFactor);
3256*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3257*8975f5c5SAndroid Build Coastguard Worker }
3258*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicBlendConstants(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3259*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicBlendConstants(
3260*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
3261*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
3262*8975f5c5SAndroid Build Coastguard Worker {
3263*8975f5c5SAndroid Build Coastguard Worker     const gl::ColorF &color = mState.getBlendColor();
3264*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setBlendConstants(color.data());
3265*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3266*8975f5c5SAndroid Build Coastguard Worker }
3267*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicStencilCompareMask(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3268*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicStencilCompareMask(
3269*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
3270*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
3271*8975f5c5SAndroid Build Coastguard Worker {
3272*8975f5c5SAndroid Build Coastguard Worker     const gl::DepthStencilState &depthStencilState = mState.getDepthStencilState();
3273*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setStencilCompareMask(depthStencilState.stencilMask,
3274*8975f5c5SAndroid Build Coastguard Worker                                                     depthStencilState.stencilBackMask);
3275*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3276*8975f5c5SAndroid Build Coastguard Worker }
3277*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicStencilWriteMask(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3278*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicStencilWriteMask(
3279*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
3280*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
3281*8975f5c5SAndroid Build Coastguard Worker {
3282*8975f5c5SAndroid Build Coastguard Worker     const gl::DepthStencilState &depthStencilState = mState.getDepthStencilState();
3283*8975f5c5SAndroid Build Coastguard Worker     const gl::Framebuffer *drawFramebuffer         = mState.getDrawFramebuffer();
3284*8975f5c5SAndroid Build Coastguard Worker     uint32_t frontWritemask                        = 0;
3285*8975f5c5SAndroid Build Coastguard Worker     uint32_t backWritemask                         = 0;
3286*8975f5c5SAndroid Build Coastguard Worker     // Don't write to stencil buffers that should not exist
3287*8975f5c5SAndroid Build Coastguard Worker     if (drawFramebuffer->hasStencil())
3288*8975f5c5SAndroid Build Coastguard Worker     {
3289*8975f5c5SAndroid Build Coastguard Worker         frontWritemask = depthStencilState.stencilWritemask;
3290*8975f5c5SAndroid Build Coastguard Worker         backWritemask  = depthStencilState.stencilBackWritemask;
3291*8975f5c5SAndroid Build Coastguard Worker     }
3292*8975f5c5SAndroid Build Coastguard Worker 
3293*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setStencilWriteMask(frontWritemask, backWritemask);
3294*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3295*8975f5c5SAndroid Build Coastguard Worker }
3296*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicStencilReference(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3297*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicStencilReference(
3298*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
3299*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
3300*8975f5c5SAndroid Build Coastguard Worker {
3301*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setStencilReference(mState.getStencilRef(),
3302*8975f5c5SAndroid Build Coastguard Worker                                                   mState.getStencilBackRef());
3303*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3304*8975f5c5SAndroid Build Coastguard Worker }
3305*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicCullMode(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3306*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicCullMode(DirtyBits::Iterator *dirtyBitsIterator,
3307*8975f5c5SAndroid Build Coastguard Worker                                                             DirtyBits dirtyBitMask)
3308*8975f5c5SAndroid Build Coastguard Worker {
3309*8975f5c5SAndroid Build Coastguard Worker     const gl::RasterizerState &rasterState = mState.getRasterizerState();
3310*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setCullMode(gl_vk::GetCullMode(rasterState));
3311*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3312*8975f5c5SAndroid Build Coastguard Worker }
3313*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicFrontFace(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3314*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicFrontFace(DirtyBits::Iterator *dirtyBitsIterator,
3315*8975f5c5SAndroid Build Coastguard Worker                                                              DirtyBits dirtyBitMask)
3316*8975f5c5SAndroid Build Coastguard Worker {
3317*8975f5c5SAndroid Build Coastguard Worker     const gl::RasterizerState &rasterState = mState.getRasterizerState();
3318*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setFrontFace(
3319*8975f5c5SAndroid Build Coastguard Worker         gl_vk::GetFrontFace(rasterState.frontFace, isYFlipEnabledForDrawFBO()));
3320*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3321*8975f5c5SAndroid Build Coastguard Worker }
3322*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicDepthTestEnable(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3323*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicDepthTestEnable(
3324*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
3325*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
3326*8975f5c5SAndroid Build Coastguard Worker {
3327*8975f5c5SAndroid Build Coastguard Worker     const gl::DepthStencilState depthStencilState = mState.getDepthStencilState();
3328*8975f5c5SAndroid Build Coastguard Worker     gl::Framebuffer *drawFramebuffer              = mState.getDrawFramebuffer();
3329*8975f5c5SAndroid Build Coastguard Worker 
3330*8975f5c5SAndroid Build Coastguard Worker     // Only enable the depth test if the draw framebuffer has a depth buffer.
3331*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setDepthTestEnable(depthStencilState.depthTest &&
3332*8975f5c5SAndroid Build Coastguard Worker                                                  drawFramebuffer->hasDepth());
3333*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3334*8975f5c5SAndroid Build Coastguard Worker }
3335*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicDepthWriteEnable(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3336*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicDepthWriteEnable(
3337*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
3338*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
3339*8975f5c5SAndroid Build Coastguard Worker {
3340*8975f5c5SAndroid Build Coastguard Worker     const gl::DepthStencilState depthStencilState = mState.getDepthStencilState();
3341*8975f5c5SAndroid Build Coastguard Worker     gl::Framebuffer *drawFramebuffer              = mState.getDrawFramebuffer();
3342*8975f5c5SAndroid Build Coastguard Worker 
3343*8975f5c5SAndroid Build Coastguard Worker     // Only enable the depth write if the draw framebuffer has a depth buffer.
3344*8975f5c5SAndroid Build Coastguard Worker     const bool depthWriteEnabled =
3345*8975f5c5SAndroid Build Coastguard Worker         drawFramebuffer->hasDepth() && depthStencilState.depthTest && depthStencilState.depthMask;
3346*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setDepthWriteEnable(depthWriteEnabled);
3347*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3348*8975f5c5SAndroid Build Coastguard Worker }
3349*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicDepthCompareOp(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3350*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicDepthCompareOp(
3351*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
3352*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
3353*8975f5c5SAndroid Build Coastguard Worker {
3354*8975f5c5SAndroid Build Coastguard Worker     const gl::DepthStencilState depthStencilState = mState.getDepthStencilState();
3355*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setDepthCompareOp(gl_vk::GetCompareOp(depthStencilState.depthFunc));
3356*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3357*8975f5c5SAndroid Build Coastguard Worker }
3358*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicStencilTestEnable(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3359*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicStencilTestEnable(
3360*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
3361*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
3362*8975f5c5SAndroid Build Coastguard Worker {
3363*8975f5c5SAndroid Build Coastguard Worker     const gl::DepthStencilState depthStencilState = mState.getDepthStencilState();
3364*8975f5c5SAndroid Build Coastguard Worker     gl::Framebuffer *drawFramebuffer              = mState.getDrawFramebuffer();
3365*8975f5c5SAndroid Build Coastguard Worker 
3366*8975f5c5SAndroid Build Coastguard Worker     // Only enable the stencil test if the draw framebuffer has a stencil buffer.
3367*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setStencilTestEnable(depthStencilState.stencilTest &&
3368*8975f5c5SAndroid Build Coastguard Worker                                                    drawFramebuffer->hasStencil());
3369*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3370*8975f5c5SAndroid Build Coastguard Worker }
3371*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicStencilOp(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3372*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicStencilOp(DirtyBits::Iterator *dirtyBitsIterator,
3373*8975f5c5SAndroid Build Coastguard Worker                                                              DirtyBits dirtyBitMask)
3374*8975f5c5SAndroid Build Coastguard Worker {
3375*8975f5c5SAndroid Build Coastguard Worker     const gl::DepthStencilState depthStencilState = mState.getDepthStencilState();
3376*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setStencilOp(
3377*8975f5c5SAndroid Build Coastguard Worker         VK_STENCIL_FACE_FRONT_BIT, gl_vk::GetStencilOp(depthStencilState.stencilFail),
3378*8975f5c5SAndroid Build Coastguard Worker         gl_vk::GetStencilOp(depthStencilState.stencilPassDepthPass),
3379*8975f5c5SAndroid Build Coastguard Worker         gl_vk::GetStencilOp(depthStencilState.stencilPassDepthFail),
3380*8975f5c5SAndroid Build Coastguard Worker         gl_vk::GetCompareOp(depthStencilState.stencilFunc));
3381*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setStencilOp(
3382*8975f5c5SAndroid Build Coastguard Worker         VK_STENCIL_FACE_BACK_BIT, gl_vk::GetStencilOp(depthStencilState.stencilBackFail),
3383*8975f5c5SAndroid Build Coastguard Worker         gl_vk::GetStencilOp(depthStencilState.stencilBackPassDepthPass),
3384*8975f5c5SAndroid Build Coastguard Worker         gl_vk::GetStencilOp(depthStencilState.stencilBackPassDepthFail),
3385*8975f5c5SAndroid Build Coastguard Worker         gl_vk::GetCompareOp(depthStencilState.stencilBackFunc));
3386*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3387*8975f5c5SAndroid Build Coastguard Worker }
3388*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicRasterizerDiscardEnable(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3389*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicRasterizerDiscardEnable(
3390*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
3391*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
3392*8975f5c5SAndroid Build Coastguard Worker {
3393*8975f5c5SAndroid Build Coastguard Worker     const bool isEmulatingRasterizerDiscard =
3394*8975f5c5SAndroid Build Coastguard Worker         isEmulatingRasterizerDiscardDuringPrimitivesGeneratedQuery(
3395*8975f5c5SAndroid Build Coastguard Worker             mState.isQueryActive(gl::QueryType::PrimitivesGenerated));
3396*8975f5c5SAndroid Build Coastguard Worker     const bool isRasterizerDiscardEnabled = mState.isRasterizerDiscardEnabled();
3397*8975f5c5SAndroid Build Coastguard Worker 
3398*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setRasterizerDiscardEnable(isRasterizerDiscardEnabled &&
3399*8975f5c5SAndroid Build Coastguard Worker                                                          !isEmulatingRasterizerDiscard);
3400*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3401*8975f5c5SAndroid Build Coastguard Worker }
3402*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicDepthBiasEnable(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3403*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicDepthBiasEnable(
3404*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
3405*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
3406*8975f5c5SAndroid Build Coastguard Worker {
3407*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setDepthBiasEnable(mState.isPolygonOffsetEnabled());
3408*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3409*8975f5c5SAndroid Build Coastguard Worker }
3410*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicLogicOp(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3411*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicLogicOp(DirtyBits::Iterator *dirtyBitsIterator,
3412*8975f5c5SAndroid Build Coastguard Worker                                                            DirtyBits dirtyBitMask)
3413*8975f5c5SAndroid Build Coastguard Worker {
3414*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setLogicOp(gl_vk::GetLogicOp(gl::ToGLenum(mState.getLogicOp())));
3415*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3416*8975f5c5SAndroid Build Coastguard Worker }
3417*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicPrimitiveRestartEnable(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3418*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicPrimitiveRestartEnable(
3419*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
3420*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
3421*8975f5c5SAndroid Build Coastguard Worker {
3422*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setPrimitiveRestartEnable(mState.isPrimitiveRestartEnabled());
3423*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3424*8975f5c5SAndroid Build Coastguard Worker }
3425*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicFragmentShadingRate(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)3426*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDynamicFragmentShadingRate(
3427*8975f5c5SAndroid Build Coastguard Worker     DirtyBits::Iterator *dirtyBitsIterator,
3428*8975f5c5SAndroid Build Coastguard Worker     DirtyBits dirtyBitMask)
3429*8975f5c5SAndroid Build Coastguard Worker {
3430*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *drawFramebufferVk = vk::GetImpl(mState.getDrawFramebuffer());
3431*8975f5c5SAndroid Build Coastguard Worker     const bool isFoveationEnabled    = drawFramebufferVk->isFoveationEnabled();
3432*8975f5c5SAndroid Build Coastguard Worker 
3433*8975f5c5SAndroid Build Coastguard Worker     gl::ShadingRate shadingRate =
3434*8975f5c5SAndroid Build Coastguard Worker         isFoveationEnabled ? gl::ShadingRate::_1x1 : getState().getShadingRate();
3435*8975f5c5SAndroid Build Coastguard Worker     if (shadingRate == gl::ShadingRate::Undefined)
3436*8975f5c5SAndroid Build Coastguard Worker     {
3437*8975f5c5SAndroid Build Coastguard Worker         // Shading rate has not been set. Since this is dynamic state, set it to 1x1
3438*8975f5c5SAndroid Build Coastguard Worker         shadingRate = gl::ShadingRate::_1x1;
3439*8975f5c5SAndroid Build Coastguard Worker     }
3440*8975f5c5SAndroid Build Coastguard Worker 
3441*8975f5c5SAndroid Build Coastguard Worker     const bool shadingRateSupported = mRenderer->isShadingRateSupported(shadingRate);
3442*8975f5c5SAndroid Build Coastguard Worker     VkExtent2D fragmentSize         = {};
3443*8975f5c5SAndroid Build Coastguard Worker 
3444*8975f5c5SAndroid Build Coastguard Worker     switch (shadingRate)
3445*8975f5c5SAndroid Build Coastguard Worker     {
3446*8975f5c5SAndroid Build Coastguard Worker         case gl::ShadingRate::_1x1:
3447*8975f5c5SAndroid Build Coastguard Worker             ASSERT(shadingRateSupported);
3448*8975f5c5SAndroid Build Coastguard Worker             fragmentSize.width  = 1;
3449*8975f5c5SAndroid Build Coastguard Worker             fragmentSize.height = 1;
3450*8975f5c5SAndroid Build Coastguard Worker             break;
3451*8975f5c5SAndroid Build Coastguard Worker         case gl::ShadingRate::_1x2:
3452*8975f5c5SAndroid Build Coastguard Worker             ASSERT(shadingRateSupported);
3453*8975f5c5SAndroid Build Coastguard Worker             fragmentSize.width  = 1;
3454*8975f5c5SAndroid Build Coastguard Worker             fragmentSize.height = 2;
3455*8975f5c5SAndroid Build Coastguard Worker             break;
3456*8975f5c5SAndroid Build Coastguard Worker         case gl::ShadingRate::_2x1:
3457*8975f5c5SAndroid Build Coastguard Worker             ASSERT(shadingRateSupported);
3458*8975f5c5SAndroid Build Coastguard Worker             fragmentSize.width  = 2;
3459*8975f5c5SAndroid Build Coastguard Worker             fragmentSize.height = 1;
3460*8975f5c5SAndroid Build Coastguard Worker             break;
3461*8975f5c5SAndroid Build Coastguard Worker         case gl::ShadingRate::_2x2:
3462*8975f5c5SAndroid Build Coastguard Worker             ASSERT(shadingRateSupported);
3463*8975f5c5SAndroid Build Coastguard Worker             fragmentSize.width  = 2;
3464*8975f5c5SAndroid Build Coastguard Worker             fragmentSize.height = 2;
3465*8975f5c5SAndroid Build Coastguard Worker             break;
3466*8975f5c5SAndroid Build Coastguard Worker         case gl::ShadingRate::_4x2:
3467*8975f5c5SAndroid Build Coastguard Worker             if (shadingRateSupported)
3468*8975f5c5SAndroid Build Coastguard Worker             {
3469*8975f5c5SAndroid Build Coastguard Worker                 fragmentSize.width  = 4;
3470*8975f5c5SAndroid Build Coastguard Worker                 fragmentSize.height = 2;
3471*8975f5c5SAndroid Build Coastguard Worker             }
3472*8975f5c5SAndroid Build Coastguard Worker             else
3473*8975f5c5SAndroid Build Coastguard Worker             {
3474*8975f5c5SAndroid Build Coastguard Worker                 // Fallback to shading rate that preserves aspect ratio
3475*8975f5c5SAndroid Build Coastguard Worker                 fragmentSize.width  = 2;
3476*8975f5c5SAndroid Build Coastguard Worker                 fragmentSize.height = 1;
3477*8975f5c5SAndroid Build Coastguard Worker             }
3478*8975f5c5SAndroid Build Coastguard Worker             break;
3479*8975f5c5SAndroid Build Coastguard Worker         case gl::ShadingRate::_4x4:
3480*8975f5c5SAndroid Build Coastguard Worker             if (shadingRateSupported)
3481*8975f5c5SAndroid Build Coastguard Worker             {
3482*8975f5c5SAndroid Build Coastguard Worker                 fragmentSize.width  = 4;
3483*8975f5c5SAndroid Build Coastguard Worker                 fragmentSize.height = 4;
3484*8975f5c5SAndroid Build Coastguard Worker             }
3485*8975f5c5SAndroid Build Coastguard Worker             else
3486*8975f5c5SAndroid Build Coastguard Worker             {
3487*8975f5c5SAndroid Build Coastguard Worker                 // Fallback to shading rate that preserves aspect ratio
3488*8975f5c5SAndroid Build Coastguard Worker                 fragmentSize.width  = 2;
3489*8975f5c5SAndroid Build Coastguard Worker                 fragmentSize.height = 2;
3490*8975f5c5SAndroid Build Coastguard Worker             }
3491*8975f5c5SAndroid Build Coastguard Worker             break;
3492*8975f5c5SAndroid Build Coastguard Worker         default:
3493*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
3494*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
3495*8975f5c5SAndroid Build Coastguard Worker     }
3496*8975f5c5SAndroid Build Coastguard Worker 
3497*8975f5c5SAndroid Build Coastguard Worker     VkFragmentShadingRateCombinerOpKHR shadingRateCombinerOp[2] = {
3498*8975f5c5SAndroid Build Coastguard Worker         VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
3499*8975f5c5SAndroid Build Coastguard Worker         VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR};
3500*8975f5c5SAndroid Build Coastguard Worker 
3501*8975f5c5SAndroid Build Coastguard Worker     // If foveated rendering is enabled update combiner op
3502*8975f5c5SAndroid Build Coastguard Worker     if (isFoveationEnabled)
3503*8975f5c5SAndroid Build Coastguard Worker     {
3504*8975f5c5SAndroid Build Coastguard Worker         shadingRateCombinerOp[1] = VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR;
3505*8975f5c5SAndroid Build Coastguard Worker     }
3506*8975f5c5SAndroid Build Coastguard Worker 
3507*8975f5c5SAndroid Build Coastguard Worker     ASSERT(hasActiveRenderPass());
3508*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->setFragmentShadingRate(&fragmentSize, shadingRateCombinerOp);
3509*8975f5c5SAndroid Build Coastguard Worker 
3510*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3511*8975f5c5SAndroid Build Coastguard Worker }
3512*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDynamicScissorImpl(bool isPrimitivesGeneratedQueryActive)3513*8975f5c5SAndroid Build Coastguard Worker void ContextVk::handleDirtyGraphicsDynamicScissorImpl(bool isPrimitivesGeneratedQueryActive)
3514*8975f5c5SAndroid Build Coastguard Worker {
3515*8975f5c5SAndroid Build Coastguard Worker     // If primitives generated query and rasterizer discard are both active, but the Vulkan
3516*8975f5c5SAndroid Build Coastguard Worker     // implementation of the query does not support rasterizer discard, use an empty scissor to
3517*8975f5c5SAndroid Build Coastguard Worker     // emulate it.
3518*8975f5c5SAndroid Build Coastguard Worker     if (isEmulatingRasterizerDiscardDuringPrimitivesGeneratedQuery(
3519*8975f5c5SAndroid Build Coastguard Worker             isPrimitivesGeneratedQueryActive))
3520*8975f5c5SAndroid Build Coastguard Worker     {
3521*8975f5c5SAndroid Build Coastguard Worker         VkRect2D emptyScissor = {};
3522*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommandBuffer->setScissor(0, 1, &emptyScissor);
3523*8975f5c5SAndroid Build Coastguard Worker     }
3524*8975f5c5SAndroid Build Coastguard Worker     else
3525*8975f5c5SAndroid Build Coastguard Worker     {
3526*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommandBuffer->setScissor(0, 1, &mScissor);
3527*8975f5c5SAndroid Build Coastguard Worker     }
3528*8975f5c5SAndroid Build Coastguard Worker }
3529*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyComputeDescriptorSets(DirtyBits::Iterator * dirtyBitsIterator)3530*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyComputeDescriptorSets(DirtyBits::Iterator *dirtyBitsIterator)
3531*8975f5c5SAndroid Build Coastguard Worker {
3532*8975f5c5SAndroid Build Coastguard Worker     return handleDirtyDescriptorSetsImpl(mOutsideRenderPassCommands, PipelineType::Compute);
3533*8975f5c5SAndroid Build Coastguard Worker }
3534*8975f5c5SAndroid Build Coastguard Worker 
3535*8975f5c5SAndroid Build Coastguard Worker template <typename CommandBufferHelperT>
handleDirtyDescriptorSetsImpl(CommandBufferHelperT * commandBufferHelper,PipelineType pipelineType)3536*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyDescriptorSetsImpl(CommandBufferHelperT *commandBufferHelper,
3537*8975f5c5SAndroid Build Coastguard Worker                                                        PipelineType pipelineType)
3538*8975f5c5SAndroid Build Coastguard Worker {
3539*8975f5c5SAndroid Build Coastguard Worker     // When using Vulkan secondary command buffers, the descriptor sets need to be updated before
3540*8975f5c5SAndroid Build Coastguard Worker     // they are bound.
3541*8975f5c5SAndroid Build Coastguard Worker     if (!CommandBufferHelperT::ExecutesInline())
3542*8975f5c5SAndroid Build Coastguard Worker     {
3543*8975f5c5SAndroid Build Coastguard Worker         flushDescriptorSetUpdates();
3544*8975f5c5SAndroid Build Coastguard Worker     }
3545*8975f5c5SAndroid Build Coastguard Worker 
3546*8975f5c5SAndroid Build Coastguard Worker     ProgramExecutableVk *executableVk = vk::GetImpl(mState.getProgramExecutable());
3547*8975f5c5SAndroid Build Coastguard Worker     return executableVk->bindDescriptorSets(this, getCurrentFrameCount(), commandBufferHelper,
3548*8975f5c5SAndroid Build Coastguard Worker                                             &commandBufferHelper->getCommandBuffer(), pipelineType);
3549*8975f5c5SAndroid Build Coastguard Worker }
3550*8975f5c5SAndroid Build Coastguard Worker 
syncObjectPerfCounters(const angle::VulkanPerfCounters & commandQueuePerfCounters)3551*8975f5c5SAndroid Build Coastguard Worker void ContextVk::syncObjectPerfCounters(const angle::VulkanPerfCounters &commandQueuePerfCounters)
3552*8975f5c5SAndroid Build Coastguard Worker {
3553*8975f5c5SAndroid Build Coastguard Worker     if (!mState.isPerfMonitorActive())
3554*8975f5c5SAndroid Build Coastguard Worker     {
3555*8975f5c5SAndroid Build Coastguard Worker         return;
3556*8975f5c5SAndroid Build Coastguard Worker     }
3557*8975f5c5SAndroid Build Coastguard Worker 
3558*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.descriptorSetCacheTotalSize                = 0;
3559*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.descriptorSetCacheKeySizeBytes             = 0;
3560*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.uniformsAndXfbDescriptorSetCacheHits       = 0;
3561*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.uniformsAndXfbDescriptorSetCacheMisses     = 0;
3562*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.uniformsAndXfbDescriptorSetCacheTotalSize  = 0;
3563*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.textureDescriptorSetCacheHits              = 0;
3564*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.textureDescriptorSetCacheMisses            = 0;
3565*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.textureDescriptorSetCacheTotalSize         = 0;
3566*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.shaderResourcesDescriptorSetCacheHits      = 0;
3567*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.shaderResourcesDescriptorSetCacheMisses    = 0;
3568*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.shaderResourcesDescriptorSetCacheTotalSize = 0;
3569*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.dynamicBufferAllocations                   = 0;
3570*8975f5c5SAndroid Build Coastguard Worker 
3571*8975f5c5SAndroid Build Coastguard Worker     // Share group descriptor set allocations and caching stats.
3572*8975f5c5SAndroid Build Coastguard Worker     memset(mVulkanCacheStats.data(), 0, sizeof(CacheStats) * mVulkanCacheStats.size());
3573*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().descriptorSetCache.enabled)
3574*8975f5c5SAndroid Build Coastguard Worker     {
3575*8975f5c5SAndroid Build Coastguard Worker         mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::UniformsAndXfb]
3576*8975f5c5SAndroid Build Coastguard Worker             .accumulateDescriptorCacheStats(VulkanCacheType::UniformsAndXfbDescriptors, this);
3577*8975f5c5SAndroid Build Coastguard Worker         mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::Texture]
3578*8975f5c5SAndroid Build Coastguard Worker             .accumulateDescriptorCacheStats(VulkanCacheType::TextureDescriptors, this);
3579*8975f5c5SAndroid Build Coastguard Worker         mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::ShaderResource]
3580*8975f5c5SAndroid Build Coastguard Worker             .accumulateDescriptorCacheStats(VulkanCacheType::ShaderResourcesDescriptors, this);
3581*8975f5c5SAndroid Build Coastguard Worker 
3582*8975f5c5SAndroid Build Coastguard Worker         const CacheStats &uniCacheStats =
3583*8975f5c5SAndroid Build Coastguard Worker             mVulkanCacheStats[VulkanCacheType::UniformsAndXfbDescriptors];
3584*8975f5c5SAndroid Build Coastguard Worker         mPerfCounters.uniformsAndXfbDescriptorSetCacheHits      = uniCacheStats.getHitCount();
3585*8975f5c5SAndroid Build Coastguard Worker         mPerfCounters.uniformsAndXfbDescriptorSetCacheMisses    = uniCacheStats.getMissCount();
3586*8975f5c5SAndroid Build Coastguard Worker         mPerfCounters.uniformsAndXfbDescriptorSetCacheTotalSize = uniCacheStats.getSize();
3587*8975f5c5SAndroid Build Coastguard Worker 
3588*8975f5c5SAndroid Build Coastguard Worker         const CacheStats &texCacheStats = mVulkanCacheStats[VulkanCacheType::TextureDescriptors];
3589*8975f5c5SAndroid Build Coastguard Worker         mPerfCounters.textureDescriptorSetCacheHits      = texCacheStats.getHitCount();
3590*8975f5c5SAndroid Build Coastguard Worker         mPerfCounters.textureDescriptorSetCacheMisses    = texCacheStats.getMissCount();
3591*8975f5c5SAndroid Build Coastguard Worker         mPerfCounters.textureDescriptorSetCacheTotalSize = texCacheStats.getSize();
3592*8975f5c5SAndroid Build Coastguard Worker 
3593*8975f5c5SAndroid Build Coastguard Worker         const CacheStats &resCacheStats =
3594*8975f5c5SAndroid Build Coastguard Worker             mVulkanCacheStats[VulkanCacheType::ShaderResourcesDescriptors];
3595*8975f5c5SAndroid Build Coastguard Worker         mPerfCounters.shaderResourcesDescriptorSetCacheHits      = resCacheStats.getHitCount();
3596*8975f5c5SAndroid Build Coastguard Worker         mPerfCounters.shaderResourcesDescriptorSetCacheMisses    = resCacheStats.getMissCount();
3597*8975f5c5SAndroid Build Coastguard Worker         mPerfCounters.shaderResourcesDescriptorSetCacheTotalSize = resCacheStats.getSize();
3598*8975f5c5SAndroid Build Coastguard Worker 
3599*8975f5c5SAndroid Build Coastguard Worker         mPerfCounters.descriptorSetCacheTotalSize =
3600*8975f5c5SAndroid Build Coastguard Worker             uniCacheStats.getSize() + texCacheStats.getSize() + resCacheStats.getSize() +
3601*8975f5c5SAndroid Build Coastguard Worker             mVulkanCacheStats[VulkanCacheType::DriverUniformsDescriptors].getSize();
3602*8975f5c5SAndroid Build Coastguard Worker 
3603*8975f5c5SAndroid Build Coastguard Worker         mPerfCounters.descriptorSetCacheKeySizeBytes = 0;
3604*8975f5c5SAndroid Build Coastguard Worker 
3605*8975f5c5SAndroid Build Coastguard Worker         for (DescriptorSetIndex descriptorSetIndex : angle::AllEnums<DescriptorSetIndex>())
3606*8975f5c5SAndroid Build Coastguard Worker         {
3607*8975f5c5SAndroid Build Coastguard Worker             vk::MetaDescriptorPool &descriptorPool =
3608*8975f5c5SAndroid Build Coastguard Worker                 mShareGroupVk->getMetaDescriptorPools()[descriptorSetIndex];
3609*8975f5c5SAndroid Build Coastguard Worker             mPerfCounters.descriptorSetCacheKeySizeBytes +=
3610*8975f5c5SAndroid Build Coastguard Worker                 descriptorPool.getTotalCacheKeySizeBytes();
3611*8975f5c5SAndroid Build Coastguard Worker         }
3612*8975f5c5SAndroid Build Coastguard Worker     }
3613*8975f5c5SAndroid Build Coastguard Worker 
3614*8975f5c5SAndroid Build Coastguard Worker     // Update perf counters from the renderer as well
3615*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.commandQueueSubmitCallsTotal =
3616*8975f5c5SAndroid Build Coastguard Worker         commandQueuePerfCounters.commandQueueSubmitCallsTotal;
3617*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.commandQueueSubmitCallsPerFrame =
3618*8975f5c5SAndroid Build Coastguard Worker         commandQueuePerfCounters.commandQueueSubmitCallsPerFrame;
3619*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.vkQueueSubmitCallsTotal    = commandQueuePerfCounters.vkQueueSubmitCallsTotal;
3620*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.vkQueueSubmitCallsPerFrame = commandQueuePerfCounters.vkQueueSubmitCallsPerFrame;
3621*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.commandQueueWaitSemaphoresTotal =
3622*8975f5c5SAndroid Build Coastguard Worker         commandQueuePerfCounters.commandQueueWaitSemaphoresTotal;
3623*8975f5c5SAndroid Build Coastguard Worker 
3624*8975f5c5SAndroid Build Coastguard Worker     // Return current drawFramebuffer's cache stats
3625*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.framebufferCacheSize = mShareGroupVk->getFramebufferCache().getSize();
3626*8975f5c5SAndroid Build Coastguard Worker 
3627*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.pendingSubmissionGarbageObjects =
3628*8975f5c5SAndroid Build Coastguard Worker         static_cast<uint64_t>(mRenderer->getPendingSubmissionGarbageSize());
3629*8975f5c5SAndroid Build Coastguard Worker }
3630*8975f5c5SAndroid Build Coastguard Worker 
updateOverlayOnPresent()3631*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateOverlayOnPresent()
3632*8975f5c5SAndroid Build Coastguard Worker {
3633*8975f5c5SAndroid Build Coastguard Worker     const gl::OverlayType *overlay = mState.getOverlay();
3634*8975f5c5SAndroid Build Coastguard Worker     ASSERT(overlay->isEnabled());
3635*8975f5c5SAndroid Build Coastguard Worker 
3636*8975f5c5SAndroid Build Coastguard Worker     angle::VulkanPerfCounters commandQueuePerfCounters = mRenderer->getCommandQueuePerfCounters();
3637*8975f5c5SAndroid Build Coastguard Worker     syncObjectPerfCounters(commandQueuePerfCounters);
3638*8975f5c5SAndroid Build Coastguard Worker 
3639*8975f5c5SAndroid Build Coastguard Worker     // Update overlay if active.
3640*8975f5c5SAndroid Build Coastguard Worker     {
3641*8975f5c5SAndroid Build Coastguard Worker         gl::RunningGraphWidget *renderPassCount =
3642*8975f5c5SAndroid Build Coastguard Worker             overlay->getRunningGraphWidget(gl::WidgetId::VulkanRenderPassCount);
3643*8975f5c5SAndroid Build Coastguard Worker         renderPassCount->add(mRenderPassCommands->getAndResetCounter());
3644*8975f5c5SAndroid Build Coastguard Worker         renderPassCount->next();
3645*8975f5c5SAndroid Build Coastguard Worker     }
3646*8975f5c5SAndroid Build Coastguard Worker 
3647*8975f5c5SAndroid Build Coastguard Worker     {
3648*8975f5c5SAndroid Build Coastguard Worker         gl::RunningGraphWidget *writeDescriptorSetCount =
3649*8975f5c5SAndroid Build Coastguard Worker             overlay->getRunningGraphWidget(gl::WidgetId::VulkanWriteDescriptorSetCount);
3650*8975f5c5SAndroid Build Coastguard Worker         writeDescriptorSetCount->add(mPerfCounters.writeDescriptorSets);
3651*8975f5c5SAndroid Build Coastguard Worker         writeDescriptorSetCount->next();
3652*8975f5c5SAndroid Build Coastguard Worker     }
3653*8975f5c5SAndroid Build Coastguard Worker 
3654*8975f5c5SAndroid Build Coastguard Worker     {
3655*8975f5c5SAndroid Build Coastguard Worker         gl::RunningGraphWidget *descriptorSetAllocationCount =
3656*8975f5c5SAndroid Build Coastguard Worker             overlay->getRunningGraphWidget(gl::WidgetId::VulkanDescriptorSetAllocations);
3657*8975f5c5SAndroid Build Coastguard Worker         descriptorSetAllocationCount->add(mPerfCounters.descriptorSetAllocations);
3658*8975f5c5SAndroid Build Coastguard Worker         descriptorSetAllocationCount->next();
3659*8975f5c5SAndroid Build Coastguard Worker     }
3660*8975f5c5SAndroid Build Coastguard Worker 
3661*8975f5c5SAndroid Build Coastguard Worker     {
3662*8975f5c5SAndroid Build Coastguard Worker         gl::RunningGraphWidget *shaderResourceHitRate =
3663*8975f5c5SAndroid Build Coastguard Worker             overlay->getRunningGraphWidget(gl::WidgetId::VulkanShaderResourceDSHitRate);
3664*8975f5c5SAndroid Build Coastguard Worker         uint64_t numCacheAccesses = mPerfCounters.shaderResourcesDescriptorSetCacheHits +
3665*8975f5c5SAndroid Build Coastguard Worker                                     mPerfCounters.shaderResourcesDescriptorSetCacheMisses;
3666*8975f5c5SAndroid Build Coastguard Worker         if (numCacheAccesses > 0)
3667*8975f5c5SAndroid Build Coastguard Worker         {
3668*8975f5c5SAndroid Build Coastguard Worker             float hitRateFloat =
3669*8975f5c5SAndroid Build Coastguard Worker                 static_cast<float>(mPerfCounters.shaderResourcesDescriptorSetCacheHits) /
3670*8975f5c5SAndroid Build Coastguard Worker                 static_cast<float>(numCacheAccesses);
3671*8975f5c5SAndroid Build Coastguard Worker             size_t hitRate = static_cast<size_t>(hitRateFloat * 100.0f);
3672*8975f5c5SAndroid Build Coastguard Worker             shaderResourceHitRate->add(hitRate);
3673*8975f5c5SAndroid Build Coastguard Worker             shaderResourceHitRate->next();
3674*8975f5c5SAndroid Build Coastguard Worker         }
3675*8975f5c5SAndroid Build Coastguard Worker     }
3676*8975f5c5SAndroid Build Coastguard Worker 
3677*8975f5c5SAndroid Build Coastguard Worker     {
3678*8975f5c5SAndroid Build Coastguard Worker         gl::RunningGraphWidget *dynamicBufferAllocations =
3679*8975f5c5SAndroid Build Coastguard Worker             overlay->getRunningGraphWidget(gl::WidgetId::VulkanDynamicBufferAllocations);
3680*8975f5c5SAndroid Build Coastguard Worker         dynamicBufferAllocations->next();
3681*8975f5c5SAndroid Build Coastguard Worker     }
3682*8975f5c5SAndroid Build Coastguard Worker 
3683*8975f5c5SAndroid Build Coastguard Worker     {
3684*8975f5c5SAndroid Build Coastguard Worker         gl::CountWidget *cacheKeySize =
3685*8975f5c5SAndroid Build Coastguard Worker             overlay->getCountWidget(gl::WidgetId::VulkanDescriptorCacheKeySize);
3686*8975f5c5SAndroid Build Coastguard Worker         cacheKeySize->reset();
3687*8975f5c5SAndroid Build Coastguard Worker         cacheKeySize->add(mPerfCounters.descriptorSetCacheKeySizeBytes);
3688*8975f5c5SAndroid Build Coastguard Worker     }
3689*8975f5c5SAndroid Build Coastguard Worker 
3690*8975f5c5SAndroid Build Coastguard Worker     {
3691*8975f5c5SAndroid Build Coastguard Worker         gl::RunningGraphWidget *dynamicBufferAllocations =
3692*8975f5c5SAndroid Build Coastguard Worker             overlay->getRunningGraphWidget(gl::WidgetId::VulkanDynamicBufferAllocations);
3693*8975f5c5SAndroid Build Coastguard Worker         dynamicBufferAllocations->add(mPerfCounters.dynamicBufferAllocations);
3694*8975f5c5SAndroid Build Coastguard Worker     }
3695*8975f5c5SAndroid Build Coastguard Worker 
3696*8975f5c5SAndroid Build Coastguard Worker     {
3697*8975f5c5SAndroid Build Coastguard Worker         gl::RunningGraphWidget *attemptedSubmissionsWidget =
3698*8975f5c5SAndroid Build Coastguard Worker             overlay->getRunningGraphWidget(gl::WidgetId::VulkanAttemptedSubmissions);
3699*8975f5c5SAndroid Build Coastguard Worker         attemptedSubmissionsWidget->add(commandQueuePerfCounters.commandQueueSubmitCallsPerFrame);
3700*8975f5c5SAndroid Build Coastguard Worker         attemptedSubmissionsWidget->next();
3701*8975f5c5SAndroid Build Coastguard Worker 
3702*8975f5c5SAndroid Build Coastguard Worker         gl::RunningGraphWidget *actualSubmissionsWidget =
3703*8975f5c5SAndroid Build Coastguard Worker             overlay->getRunningGraphWidget(gl::WidgetId::VulkanActualSubmissions);
3704*8975f5c5SAndroid Build Coastguard Worker         actualSubmissionsWidget->add(commandQueuePerfCounters.vkQueueSubmitCallsPerFrame);
3705*8975f5c5SAndroid Build Coastguard Worker         actualSubmissionsWidget->next();
3706*8975f5c5SAndroid Build Coastguard Worker     }
3707*8975f5c5SAndroid Build Coastguard Worker 
3708*8975f5c5SAndroid Build Coastguard Worker     {
3709*8975f5c5SAndroid Build Coastguard Worker         gl::RunningGraphWidget *cacheLookupsWidget =
3710*8975f5c5SAndroid Build Coastguard Worker             overlay->getRunningGraphWidget(gl::WidgetId::VulkanPipelineCacheLookups);
3711*8975f5c5SAndroid Build Coastguard Worker         cacheLookupsWidget->add(mPerfCounters.pipelineCreationCacheHits +
3712*8975f5c5SAndroid Build Coastguard Worker                                 mPerfCounters.pipelineCreationCacheMisses);
3713*8975f5c5SAndroid Build Coastguard Worker         cacheLookupsWidget->next();
3714*8975f5c5SAndroid Build Coastguard Worker 
3715*8975f5c5SAndroid Build Coastguard Worker         gl::RunningGraphWidget *cacheMissesWidget =
3716*8975f5c5SAndroid Build Coastguard Worker             overlay->getRunningGraphWidget(gl::WidgetId::VulkanPipelineCacheMisses);
3717*8975f5c5SAndroid Build Coastguard Worker         cacheMissesWidget->add(mPerfCounters.pipelineCreationCacheMisses);
3718*8975f5c5SAndroid Build Coastguard Worker         cacheMissesWidget->next();
3719*8975f5c5SAndroid Build Coastguard Worker 
3720*8975f5c5SAndroid Build Coastguard Worker         overlay->getCountWidget(gl::WidgetId::VulkanTotalPipelineCacheHitTimeMs)
3721*8975f5c5SAndroid Build Coastguard Worker             ->set(mPerfCounters.pipelineCreationTotalCacheHitsDurationNs / 1000'000);
3722*8975f5c5SAndroid Build Coastguard Worker         overlay->getCountWidget(gl::WidgetId::VulkanTotalPipelineCacheMissTimeMs)
3723*8975f5c5SAndroid Build Coastguard Worker             ->set(mPerfCounters.pipelineCreationTotalCacheMissesDurationNs / 1000'000);
3724*8975f5c5SAndroid Build Coastguard Worker     }
3725*8975f5c5SAndroid Build Coastguard Worker }
3726*8975f5c5SAndroid Build Coastguard Worker 
addOverlayUsedBuffersCount(vk::CommandBufferHelperCommon * commandBuffer)3727*8975f5c5SAndroid Build Coastguard Worker void ContextVk::addOverlayUsedBuffersCount(vk::CommandBufferHelperCommon *commandBuffer)
3728*8975f5c5SAndroid Build Coastguard Worker {
3729*8975f5c5SAndroid Build Coastguard Worker     const gl::OverlayType *overlay = mState.getOverlay();
3730*8975f5c5SAndroid Build Coastguard Worker     if (!overlay->isEnabled())
3731*8975f5c5SAndroid Build Coastguard Worker     {
3732*8975f5c5SAndroid Build Coastguard Worker         return;
3733*8975f5c5SAndroid Build Coastguard Worker     }
3734*8975f5c5SAndroid Build Coastguard Worker 
3735*8975f5c5SAndroid Build Coastguard Worker     {
3736*8975f5c5SAndroid Build Coastguard Worker         gl::RunningGraphWidget *textureDescriptorCacheSize =
3737*8975f5c5SAndroid Build Coastguard Worker             overlay->getRunningGraphWidget(gl::WidgetId::VulkanTextureDescriptorCacheSize);
3738*8975f5c5SAndroid Build Coastguard Worker         textureDescriptorCacheSize->add(mPerfCounters.textureDescriptorSetCacheTotalSize);
3739*8975f5c5SAndroid Build Coastguard Worker         textureDescriptorCacheSize->next();
3740*8975f5c5SAndroid Build Coastguard Worker     }
3741*8975f5c5SAndroid Build Coastguard Worker 
3742*8975f5c5SAndroid Build Coastguard Worker     {
3743*8975f5c5SAndroid Build Coastguard Worker         gl::RunningGraphWidget *uniformDescriptorCacheSize =
3744*8975f5c5SAndroid Build Coastguard Worker             overlay->getRunningGraphWidget(gl::WidgetId::VulkanUniformDescriptorCacheSize);
3745*8975f5c5SAndroid Build Coastguard Worker         uniformDescriptorCacheSize->add(mPerfCounters.uniformsAndXfbDescriptorSetCacheTotalSize);
3746*8975f5c5SAndroid Build Coastguard Worker         uniformDescriptorCacheSize->next();
3747*8975f5c5SAndroid Build Coastguard Worker     }
3748*8975f5c5SAndroid Build Coastguard Worker 
3749*8975f5c5SAndroid Build Coastguard Worker     {
3750*8975f5c5SAndroid Build Coastguard Worker         gl::RunningGraphWidget *descriptorCacheSize =
3751*8975f5c5SAndroid Build Coastguard Worker             overlay->getRunningGraphWidget(gl::WidgetId::VulkanDescriptorCacheSize);
3752*8975f5c5SAndroid Build Coastguard Worker         descriptorCacheSize->add(mPerfCounters.descriptorSetCacheTotalSize);
3753*8975f5c5SAndroid Build Coastguard Worker         descriptorCacheSize->next();
3754*8975f5c5SAndroid Build Coastguard Worker     }
3755*8975f5c5SAndroid Build Coastguard Worker }
3756*8975f5c5SAndroid Build Coastguard Worker 
submitCommands(const vk::Semaphore * signalSemaphore,const vk::SharedExternalFence * externalFence,Submit submission)3757*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::submitCommands(const vk::Semaphore *signalSemaphore,
3758*8975f5c5SAndroid Build Coastguard Worker                                         const vk::SharedExternalFence *externalFence,
3759*8975f5c5SAndroid Build Coastguard Worker                                         Submit submission)
3760*8975f5c5SAndroid Build Coastguard Worker {
3761*8975f5c5SAndroid Build Coastguard Worker     if (kEnableCommandStreamDiagnostics)
3762*8975f5c5SAndroid Build Coastguard Worker     {
3763*8975f5c5SAndroid Build Coastguard Worker         dumpCommandStreamDiagnostics();
3764*8975f5c5SAndroid Build Coastguard Worker     }
3765*8975f5c5SAndroid Build Coastguard Worker 
3766*8975f5c5SAndroid Build Coastguard Worker     if (!mCurrentGarbage.empty() && submission == Submit::AllCommands)
3767*8975f5c5SAndroid Build Coastguard Worker     {
3768*8975f5c5SAndroid Build Coastguard Worker         // Clean up garbage.
3769*8975f5c5SAndroid Build Coastguard Worker         vk::ResourceUse use(mLastFlushedQueueSerial);
3770*8975f5c5SAndroid Build Coastguard Worker         mRenderer->collectGarbage(use, std::move(mCurrentGarbage));
3771*8975f5c5SAndroid Build Coastguard Worker     }
3772*8975f5c5SAndroid Build Coastguard Worker 
3773*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mLastFlushedQueueSerial.valid());
3774*8975f5c5SAndroid Build Coastguard Worker     ASSERT(QueueSerialsHaveDifferentIndexOrSmaller(mLastSubmittedQueueSerial,
3775*8975f5c5SAndroid Build Coastguard Worker                                                    mLastFlushedQueueSerial));
3776*8975f5c5SAndroid Build Coastguard Worker 
3777*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mRenderer->submitCommands(this, getProtectionType(), mContextPriority,
3778*8975f5c5SAndroid Build Coastguard Worker                                         signalSemaphore, externalFence, mLastFlushedQueueSerial));
3779*8975f5c5SAndroid Build Coastguard Worker 
3780*8975f5c5SAndroid Build Coastguard Worker     mLastSubmittedQueueSerial = mLastFlushedQueueSerial;
3781*8975f5c5SAndroid Build Coastguard Worker     mSubmittedResourceUse.setQueueSerial(mLastSubmittedQueueSerial);
3782*8975f5c5SAndroid Build Coastguard Worker 
3783*8975f5c5SAndroid Build Coastguard Worker     // Now that we have submitted commands, some of pending garbage may no longer pending
3784*8975f5c5SAndroid Build Coastguard Worker     // and should be moved to garbage list.
3785*8975f5c5SAndroid Build Coastguard Worker     mRenderer->cleanupPendingSubmissionGarbage();
3786*8975f5c5SAndroid Build Coastguard Worker     // In case of big amount of render/submission within one frame, if we accumulate excessive
3787*8975f5c5SAndroid Build Coastguard Worker     // amount of garbage, also trigger the cleanup.
3788*8975f5c5SAndroid Build Coastguard Worker     mShareGroupVk->cleanupExcessiveRefCountedEventGarbage();
3789*8975f5c5SAndroid Build Coastguard Worker 
3790*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBits |= mNewComputeCommandBufferDirtyBits;
3791*8975f5c5SAndroid Build Coastguard Worker 
3792*8975f5c5SAndroid Build Coastguard Worker     if (mGpuEventsEnabled)
3793*8975f5c5SAndroid Build Coastguard Worker     {
3794*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(checkCompletedGpuEvents());
3795*8975f5c5SAndroid Build Coastguard Worker     }
3796*8975f5c5SAndroid Build Coastguard Worker 
3797*8975f5c5SAndroid Build Coastguard Worker     mTotalBufferToImageCopySize       = 0;
3798*8975f5c5SAndroid Build Coastguard Worker     mEstimatedPendingImageGarbageSize = 0;
3799*8975f5c5SAndroid Build Coastguard Worker 
3800*8975f5c5SAndroid Build Coastguard Worker     // If we have destroyed a lot of memory, also prune to ensure memory gets freed as soon as
3801*8975f5c5SAndroid Build Coastguard Worker     // possible. For example we may end here when game launches and uploads a lot of textures before
3802*8975f5c5SAndroid Build Coastguard Worker     // draw the first frame.
3803*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getSuballocationDestroyedSize() >= kMaxTotalEmptyBufferBytes)
3804*8975f5c5SAndroid Build Coastguard Worker     {
3805*8975f5c5SAndroid Build Coastguard Worker         mShareGroupVk->pruneDefaultBufferPools();
3806*8975f5c5SAndroid Build Coastguard Worker     }
3807*8975f5c5SAndroid Build Coastguard Worker 
3808*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3809*8975f5c5SAndroid Build Coastguard Worker }
3810*8975f5c5SAndroid Build Coastguard Worker 
onCopyUpdate(VkDeviceSize size,bool * commandBufferWasFlushedOut)3811*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::onCopyUpdate(VkDeviceSize size, bool *commandBufferWasFlushedOut)
3812*8975f5c5SAndroid Build Coastguard Worker {
3813*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::onCopyUpdate");
3814*8975f5c5SAndroid Build Coastguard Worker     *commandBufferWasFlushedOut = false;
3815*8975f5c5SAndroid Build Coastguard Worker 
3816*8975f5c5SAndroid Build Coastguard Worker     mTotalBufferToImageCopySize += size;
3817*8975f5c5SAndroid Build Coastguard Worker     // If the copy size exceeds the specified threshold, submit the outside command buffer.
3818*8975f5c5SAndroid Build Coastguard Worker     if (mTotalBufferToImageCopySize >= kMaxBufferToImageCopySize)
3819*8975f5c5SAndroid Build Coastguard Worker     {
3820*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushAndSubmitOutsideRenderPassCommands());
3821*8975f5c5SAndroid Build Coastguard Worker         *commandBufferWasFlushedOut = true;
3822*8975f5c5SAndroid Build Coastguard Worker     }
3823*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
3824*8975f5c5SAndroid Build Coastguard Worker }
3825*8975f5c5SAndroid Build Coastguard Worker 
addToPendingImageGarbage(vk::ResourceUse use,VkDeviceSize size)3826*8975f5c5SAndroid Build Coastguard Worker void ContextVk::addToPendingImageGarbage(vk::ResourceUse use, VkDeviceSize size)
3827*8975f5c5SAndroid Build Coastguard Worker {
3828*8975f5c5SAndroid Build Coastguard Worker     if (!mRenderer->hasResourceUseFinished(use))
3829*8975f5c5SAndroid Build Coastguard Worker     {
3830*8975f5c5SAndroid Build Coastguard Worker         mEstimatedPendingImageGarbageSize += size;
3831*8975f5c5SAndroid Build Coastguard Worker     }
3832*8975f5c5SAndroid Build Coastguard Worker }
3833*8975f5c5SAndroid Build Coastguard Worker 
hasExcessPendingGarbage() const3834*8975f5c5SAndroid Build Coastguard Worker bool ContextVk::hasExcessPendingGarbage() const
3835*8975f5c5SAndroid Build Coastguard Worker {
3836*8975f5c5SAndroid Build Coastguard Worker     VkDeviceSize trackedPendingGarbage =
3837*8975f5c5SAndroid Build Coastguard Worker         mRenderer->getPendingSuballocationGarbageSize() + mEstimatedPendingImageGarbageSize;
3838*8975f5c5SAndroid Build Coastguard Worker     return trackedPendingGarbage >= mRenderer->getPendingGarbageSizeLimit();
3839*8975f5c5SAndroid Build Coastguard Worker }
3840*8975f5c5SAndroid Build Coastguard Worker 
synchronizeCpuGpuTime()3841*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::synchronizeCpuGpuTime()
3842*8975f5c5SAndroid Build Coastguard Worker {
3843*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mGpuEventsEnabled);
3844*8975f5c5SAndroid Build Coastguard Worker 
3845*8975f5c5SAndroid Build Coastguard Worker     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
3846*8975f5c5SAndroid Build Coastguard Worker     ASSERT(platform);
3847*8975f5c5SAndroid Build Coastguard Worker 
3848*8975f5c5SAndroid Build Coastguard Worker     // To synchronize CPU and GPU times, we need to get the CPU timestamp as close as possible
3849*8975f5c5SAndroid Build Coastguard Worker     // to the GPU timestamp.  The process of getting the GPU timestamp is as follows:
3850*8975f5c5SAndroid Build Coastguard Worker     //
3851*8975f5c5SAndroid Build Coastguard Worker     //             CPU                            GPU
3852*8975f5c5SAndroid Build Coastguard Worker     //
3853*8975f5c5SAndroid Build Coastguard Worker     //     Record command buffer
3854*8975f5c5SAndroid Build Coastguard Worker     //     with timestamp query
3855*8975f5c5SAndroid Build Coastguard Worker     //
3856*8975f5c5SAndroid Build Coastguard Worker     //     Submit command buffer
3857*8975f5c5SAndroid Build Coastguard Worker     //
3858*8975f5c5SAndroid Build Coastguard Worker     //     Post-submission work             Begin execution
3859*8975f5c5SAndroid Build Coastguard Worker     //
3860*8975f5c5SAndroid Build Coastguard Worker     //            ????                    Write timestamp Tgpu
3861*8975f5c5SAndroid Build Coastguard Worker     //
3862*8975f5c5SAndroid Build Coastguard Worker     //            ????                       End execution
3863*8975f5c5SAndroid Build Coastguard Worker     //
3864*8975f5c5SAndroid Build Coastguard Worker     //            ????                    Return query results
3865*8975f5c5SAndroid Build Coastguard Worker     //
3866*8975f5c5SAndroid Build Coastguard Worker     //            ????
3867*8975f5c5SAndroid Build Coastguard Worker     //
3868*8975f5c5SAndroid Build Coastguard Worker     //       Get query results
3869*8975f5c5SAndroid Build Coastguard Worker     //
3870*8975f5c5SAndroid Build Coastguard Worker     // The areas of unknown work (????) on the CPU indicate that the CPU may or may not have
3871*8975f5c5SAndroid Build Coastguard Worker     // finished post-submission work while the GPU is executing in parallel. With no further
3872*8975f5c5SAndroid Build Coastguard Worker     // work, querying CPU timestamps before submission and after getting query results give the
3873*8975f5c5SAndroid Build Coastguard Worker     // bounds to Tgpu, which could be quite large.
3874*8975f5c5SAndroid Build Coastguard Worker     //
3875*8975f5c5SAndroid Build Coastguard Worker     // Using VkEvents, the GPU can be made to wait for the CPU and vice versa, in an effort to
3876*8975f5c5SAndroid Build Coastguard Worker     // reduce this range. This function implements the following procedure:
3877*8975f5c5SAndroid Build Coastguard Worker     //
3878*8975f5c5SAndroid Build Coastguard Worker     //             CPU                            GPU
3879*8975f5c5SAndroid Build Coastguard Worker     //
3880*8975f5c5SAndroid Build Coastguard Worker     //     Record command buffer
3881*8975f5c5SAndroid Build Coastguard Worker     //     with timestamp query
3882*8975f5c5SAndroid Build Coastguard Worker     //
3883*8975f5c5SAndroid Build Coastguard Worker     //     Submit command buffer
3884*8975f5c5SAndroid Build Coastguard Worker     //
3885*8975f5c5SAndroid Build Coastguard Worker     //     Post-submission work             Begin execution
3886*8975f5c5SAndroid Build Coastguard Worker     //
3887*8975f5c5SAndroid Build Coastguard Worker     //            ????                    Set Event GPUReady
3888*8975f5c5SAndroid Build Coastguard Worker     //
3889*8975f5c5SAndroid Build Coastguard Worker     //    Wait on Event GPUReady         Wait on Event CPUReady
3890*8975f5c5SAndroid Build Coastguard Worker     //
3891*8975f5c5SAndroid Build Coastguard Worker     //       Get CPU Time Ts             Wait on Event CPUReady
3892*8975f5c5SAndroid Build Coastguard Worker     //
3893*8975f5c5SAndroid Build Coastguard Worker     //      Set Event CPUReady           Wait on Event CPUReady
3894*8975f5c5SAndroid Build Coastguard Worker     //
3895*8975f5c5SAndroid Build Coastguard Worker     //      Get CPU Time Tcpu              Get GPU Time Tgpu
3896*8975f5c5SAndroid Build Coastguard Worker     //
3897*8975f5c5SAndroid Build Coastguard Worker     //    Wait on Event GPUDone            Set Event GPUDone
3898*8975f5c5SAndroid Build Coastguard Worker     //
3899*8975f5c5SAndroid Build Coastguard Worker     //       Get CPU Time Te                 End Execution
3900*8975f5c5SAndroid Build Coastguard Worker     //
3901*8975f5c5SAndroid Build Coastguard Worker     //            Idle                    Return query results
3902*8975f5c5SAndroid Build Coastguard Worker     //
3903*8975f5c5SAndroid Build Coastguard Worker     //      Get query results
3904*8975f5c5SAndroid Build Coastguard Worker     //
3905*8975f5c5SAndroid Build Coastguard Worker     // If Te-Ts > epsilon, a GPU or CPU interruption can be assumed and the operation can be
3906*8975f5c5SAndroid Build Coastguard Worker     // retried.  Once Te-Ts < epsilon, Tcpu can be taken to presumably match Tgpu.  Finding an
3907*8975f5c5SAndroid Build Coastguard Worker     // epsilon that's valid for all devices may be difficult, so the loop can be performed only
3908*8975f5c5SAndroid Build Coastguard Worker     // a limited number of times and the Tcpu,Tgpu pair corresponding to smallest Te-Ts used for
3909*8975f5c5SAndroid Build Coastguard Worker     // calibration.
3910*8975f5c5SAndroid Build Coastguard Worker     //
3911*8975f5c5SAndroid Build Coastguard Worker     // Note: Once VK_EXT_calibrated_timestamps is ubiquitous, this should be redone.
3912*8975f5c5SAndroid Build Coastguard Worker 
3913*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::synchronizeCpuGpuTime");
3914*8975f5c5SAndroid Build Coastguard Worker 
3915*8975f5c5SAndroid Build Coastguard Worker     // Create a query used to receive the GPU timestamp
3916*8975f5c5SAndroid Build Coastguard Worker     vk::QueryHelper timestampQuery;
3917*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, &timestampQuery, 1));
3918*8975f5c5SAndroid Build Coastguard Worker 
3919*8975f5c5SAndroid Build Coastguard Worker     // Create the three events
3920*8975f5c5SAndroid Build Coastguard Worker     VkEventCreateInfo eventCreateInfo = {};
3921*8975f5c5SAndroid Build Coastguard Worker     eventCreateInfo.sType             = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
3922*8975f5c5SAndroid Build Coastguard Worker     eventCreateInfo.flags             = 0;
3923*8975f5c5SAndroid Build Coastguard Worker 
3924*8975f5c5SAndroid Build Coastguard Worker     VkDevice device = getDevice();
3925*8975f5c5SAndroid Build Coastguard Worker     vk::DeviceScoped<vk::Event> cpuReady(device), gpuReady(device), gpuDone(device);
3926*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_TRY(this, cpuReady.get().init(device, eventCreateInfo));
3927*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_TRY(this, gpuReady.get().init(device, eventCreateInfo));
3928*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_TRY(this, gpuDone.get().init(device, eventCreateInfo));
3929*8975f5c5SAndroid Build Coastguard Worker 
3930*8975f5c5SAndroid Build Coastguard Worker     constexpr uint32_t kRetries = 10;
3931*8975f5c5SAndroid Build Coastguard Worker 
3932*8975f5c5SAndroid Build Coastguard Worker     // Time suffixes used are S for seconds and Cycles for cycles
3933*8975f5c5SAndroid Build Coastguard Worker     double tightestRangeS = 1e6f;
3934*8975f5c5SAndroid Build Coastguard Worker     double TcpuS          = 0;
3935*8975f5c5SAndroid Build Coastguard Worker     uint64_t TgpuCycles   = 0;
3936*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kRetries; ++i)
3937*8975f5c5SAndroid Build Coastguard Worker     {
3938*8975f5c5SAndroid Build Coastguard Worker         // Reset the events
3939*8975f5c5SAndroid Build Coastguard Worker         ANGLE_VK_TRY(this, cpuReady.get().reset(device));
3940*8975f5c5SAndroid Build Coastguard Worker         ANGLE_VK_TRY(this, gpuReady.get().reset(device));
3941*8975f5c5SAndroid Build Coastguard Worker         ANGLE_VK_TRY(this, gpuDone.get().reset(device));
3942*8975f5c5SAndroid Build Coastguard Worker 
3943*8975f5c5SAndroid Build Coastguard Worker         // Record the command buffer
3944*8975f5c5SAndroid Build Coastguard Worker         vk::DeviceScoped<vk::PrimaryCommandBuffer> commandBatch(device);
3945*8975f5c5SAndroid Build Coastguard Worker         vk::PrimaryCommandBuffer &commandBuffer = commandBatch.get();
3946*8975f5c5SAndroid Build Coastguard Worker 
3947*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mRenderer->getCommandBufferOneOff(this, getProtectionType(), &commandBuffer));
3948*8975f5c5SAndroid Build Coastguard Worker 
3949*8975f5c5SAndroid Build Coastguard Worker         commandBuffer.setEvent(gpuReady.get().getHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
3950*8975f5c5SAndroid Build Coastguard Worker         commandBuffer.waitEvents(1, cpuReady.get().ptr(), VK_PIPELINE_STAGE_HOST_BIT,
3951*8975f5c5SAndroid Build Coastguard Worker                                  VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, nullptr, 0, nullptr, 0,
3952*8975f5c5SAndroid Build Coastguard Worker                                  nullptr);
3953*8975f5c5SAndroid Build Coastguard Worker         timestampQuery.writeTimestampToPrimary(this, &commandBuffer);
3954*8975f5c5SAndroid Build Coastguard Worker 
3955*8975f5c5SAndroid Build Coastguard Worker         commandBuffer.setEvent(gpuDone.get().getHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
3956*8975f5c5SAndroid Build Coastguard Worker 
3957*8975f5c5SAndroid Build Coastguard Worker         ANGLE_VK_TRY(this, commandBuffer.end());
3958*8975f5c5SAndroid Build Coastguard Worker 
3959*8975f5c5SAndroid Build Coastguard Worker         QueueSerial submitSerial;
3960*8975f5c5SAndroid Build Coastguard Worker         // vkEvent's are externally synchronized, therefore need work to be submitted before calling
3961*8975f5c5SAndroid Build Coastguard Worker         // vkGetEventStatus
3962*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mRenderer->queueSubmitOneOff(this, std::move(commandBuffer), getProtectionType(),
3963*8975f5c5SAndroid Build Coastguard Worker                                                mContextPriority, VK_NULL_HANDLE, 0,
3964*8975f5c5SAndroid Build Coastguard Worker                                                vk::SubmitPolicy::EnsureSubmitted, &submitSerial));
3965*8975f5c5SAndroid Build Coastguard Worker 
3966*8975f5c5SAndroid Build Coastguard Worker         // Track it with the submitSerial.
3967*8975f5c5SAndroid Build Coastguard Worker         timestampQuery.setQueueSerial(submitSerial);
3968*8975f5c5SAndroid Build Coastguard Worker 
3969*8975f5c5SAndroid Build Coastguard Worker         // Wait for GPU to be ready.  This is a short busy wait.
3970*8975f5c5SAndroid Build Coastguard Worker         VkResult result = VK_EVENT_RESET;
3971*8975f5c5SAndroid Build Coastguard Worker         do
3972*8975f5c5SAndroid Build Coastguard Worker         {
3973*8975f5c5SAndroid Build Coastguard Worker             result = gpuReady.get().getStatus(device);
3974*8975f5c5SAndroid Build Coastguard Worker             if (result != VK_EVENT_SET && result != VK_EVENT_RESET)
3975*8975f5c5SAndroid Build Coastguard Worker             {
3976*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_VK_TRY(this, result);
3977*8975f5c5SAndroid Build Coastguard Worker             }
3978*8975f5c5SAndroid Build Coastguard Worker         } while (result == VK_EVENT_RESET);
3979*8975f5c5SAndroid Build Coastguard Worker 
3980*8975f5c5SAndroid Build Coastguard Worker         double TsS = platform->monotonicallyIncreasingTime(platform);
3981*8975f5c5SAndroid Build Coastguard Worker 
3982*8975f5c5SAndroid Build Coastguard Worker         // Tell the GPU to go ahead with the timestamp query.
3983*8975f5c5SAndroid Build Coastguard Worker         ANGLE_VK_TRY(this, cpuReady.get().set(device));
3984*8975f5c5SAndroid Build Coastguard Worker         double cpuTimestampS = platform->monotonicallyIncreasingTime(platform);
3985*8975f5c5SAndroid Build Coastguard Worker 
3986*8975f5c5SAndroid Build Coastguard Worker         // Wait for GPU to be done.  Another short busy wait.
3987*8975f5c5SAndroid Build Coastguard Worker         do
3988*8975f5c5SAndroid Build Coastguard Worker         {
3989*8975f5c5SAndroid Build Coastguard Worker             result = gpuDone.get().getStatus(device);
3990*8975f5c5SAndroid Build Coastguard Worker             if (result != VK_EVENT_SET && result != VK_EVENT_RESET)
3991*8975f5c5SAndroid Build Coastguard Worker             {
3992*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_VK_TRY(this, result);
3993*8975f5c5SAndroid Build Coastguard Worker             }
3994*8975f5c5SAndroid Build Coastguard Worker         } while (result == VK_EVENT_RESET);
3995*8975f5c5SAndroid Build Coastguard Worker 
3996*8975f5c5SAndroid Build Coastguard Worker         double TeS = platform->monotonicallyIncreasingTime(platform);
3997*8975f5c5SAndroid Build Coastguard Worker 
3998*8975f5c5SAndroid Build Coastguard Worker         // Get the query results
3999*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mRenderer->finishQueueSerial(this, submitSerial));
4000*8975f5c5SAndroid Build Coastguard Worker 
4001*8975f5c5SAndroid Build Coastguard Worker         vk::QueryResult gpuTimestampCycles(1);
4002*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(timestampQuery.getUint64Result(this, &gpuTimestampCycles));
4003*8975f5c5SAndroid Build Coastguard Worker 
4004*8975f5c5SAndroid Build Coastguard Worker         // Use the first timestamp queried as origin.
4005*8975f5c5SAndroid Build Coastguard Worker         if (mGpuEventTimestampOrigin == 0)
4006*8975f5c5SAndroid Build Coastguard Worker         {
4007*8975f5c5SAndroid Build Coastguard Worker             mGpuEventTimestampOrigin =
4008*8975f5c5SAndroid Build Coastguard Worker                 gpuTimestampCycles.getResult(vk::QueryResult::kDefaultResultIndex);
4009*8975f5c5SAndroid Build Coastguard Worker         }
4010*8975f5c5SAndroid Build Coastguard Worker 
4011*8975f5c5SAndroid Build Coastguard Worker         // Take these CPU and GPU timestamps if there is better confidence.
4012*8975f5c5SAndroid Build Coastguard Worker         double confidenceRangeS = TeS - TsS;
4013*8975f5c5SAndroid Build Coastguard Worker         if (confidenceRangeS < tightestRangeS)
4014*8975f5c5SAndroid Build Coastguard Worker         {
4015*8975f5c5SAndroid Build Coastguard Worker             tightestRangeS = confidenceRangeS;
4016*8975f5c5SAndroid Build Coastguard Worker             TcpuS          = cpuTimestampS;
4017*8975f5c5SAndroid Build Coastguard Worker             TgpuCycles     = gpuTimestampCycles.getResult(vk::QueryResult::kDefaultResultIndex);
4018*8975f5c5SAndroid Build Coastguard Worker         }
4019*8975f5c5SAndroid Build Coastguard Worker     }
4020*8975f5c5SAndroid Build Coastguard Worker 
4021*8975f5c5SAndroid Build Coastguard Worker     mGpuEventQueryPool.freeQuery(this, &timestampQuery);
4022*8975f5c5SAndroid Build Coastguard Worker 
4023*8975f5c5SAndroid Build Coastguard Worker     // timestampPeriod gives nanoseconds/cycle.
4024*8975f5c5SAndroid Build Coastguard Worker     double TgpuS =
4025*8975f5c5SAndroid Build Coastguard Worker         (TgpuCycles - mGpuEventTimestampOrigin) *
4026*8975f5c5SAndroid Build Coastguard Worker         static_cast<double>(getRenderer()->getPhysicalDeviceProperties().limits.timestampPeriod) /
4027*8975f5c5SAndroid Build Coastguard Worker         1'000'000'000.0;
4028*8975f5c5SAndroid Build Coastguard Worker 
4029*8975f5c5SAndroid Build Coastguard Worker     flushGpuEvents(TgpuS, TcpuS);
4030*8975f5c5SAndroid Build Coastguard Worker 
4031*8975f5c5SAndroid Build Coastguard Worker     mGpuClockSync.gpuTimestampS = TgpuS;
4032*8975f5c5SAndroid Build Coastguard Worker     mGpuClockSync.cpuTimestampS = TcpuS;
4033*8975f5c5SAndroid Build Coastguard Worker 
4034*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4035*8975f5c5SAndroid Build Coastguard Worker }
4036*8975f5c5SAndroid Build Coastguard Worker 
traceGpuEventImpl(vk::OutsideRenderPassCommandBuffer * commandBuffer,char phase,const EventName & name)4037*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::traceGpuEventImpl(vk::OutsideRenderPassCommandBuffer *commandBuffer,
4038*8975f5c5SAndroid Build Coastguard Worker                                            char phase,
4039*8975f5c5SAndroid Build Coastguard Worker                                            const EventName &name)
4040*8975f5c5SAndroid Build Coastguard Worker {
4041*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mGpuEventsEnabled);
4042*8975f5c5SAndroid Build Coastguard Worker 
4043*8975f5c5SAndroid Build Coastguard Worker     GpuEventQuery gpuEvent;
4044*8975f5c5SAndroid Build Coastguard Worker     gpuEvent.name  = name;
4045*8975f5c5SAndroid Build Coastguard Worker     gpuEvent.phase = phase;
4046*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, &gpuEvent.queryHelper, 1));
4047*8975f5c5SAndroid Build Coastguard Worker 
4048*8975f5c5SAndroid Build Coastguard Worker     gpuEvent.queryHelper.writeTimestamp(this, commandBuffer);
4049*8975f5c5SAndroid Build Coastguard Worker 
4050*8975f5c5SAndroid Build Coastguard Worker     mInFlightGpuEventQueries.push_back(std::move(gpuEvent));
4051*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4052*8975f5c5SAndroid Build Coastguard Worker }
4053*8975f5c5SAndroid Build Coastguard Worker 
checkCompletedGpuEvents()4054*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::checkCompletedGpuEvents()
4055*8975f5c5SAndroid Build Coastguard Worker {
4056*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mGpuEventsEnabled);
4057*8975f5c5SAndroid Build Coastguard Worker 
4058*8975f5c5SAndroid Build Coastguard Worker     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
4059*8975f5c5SAndroid Build Coastguard Worker     ASSERT(platform);
4060*8975f5c5SAndroid Build Coastguard Worker 
4061*8975f5c5SAndroid Build Coastguard Worker     int finishedCount = 0;
4062*8975f5c5SAndroid Build Coastguard Worker 
4063*8975f5c5SAndroid Build Coastguard Worker     for (GpuEventQuery &eventQuery : mInFlightGpuEventQueries)
4064*8975f5c5SAndroid Build Coastguard Worker     {
4065*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mRenderer->hasResourceUseSubmitted(eventQuery.queryHelper.getResourceUse()));
4066*8975f5c5SAndroid Build Coastguard Worker         // Only check the timestamp query if the submission has finished.
4067*8975f5c5SAndroid Build Coastguard Worker         if (!mRenderer->hasResourceUseFinished(eventQuery.queryHelper.getResourceUse()))
4068*8975f5c5SAndroid Build Coastguard Worker         {
4069*8975f5c5SAndroid Build Coastguard Worker             break;
4070*8975f5c5SAndroid Build Coastguard Worker         }
4071*8975f5c5SAndroid Build Coastguard Worker 
4072*8975f5c5SAndroid Build Coastguard Worker         // See if the results are available.
4073*8975f5c5SAndroid Build Coastguard Worker         vk::QueryResult gpuTimestampCycles(1);
4074*8975f5c5SAndroid Build Coastguard Worker         bool available = false;
4075*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(eventQuery.queryHelper.getUint64ResultNonBlocking(this, &gpuTimestampCycles,
4076*8975f5c5SAndroid Build Coastguard Worker                                                                     &available));
4077*8975f5c5SAndroid Build Coastguard Worker         if (!available)
4078*8975f5c5SAndroid Build Coastguard Worker         {
4079*8975f5c5SAndroid Build Coastguard Worker             break;
4080*8975f5c5SAndroid Build Coastguard Worker         }
4081*8975f5c5SAndroid Build Coastguard Worker 
4082*8975f5c5SAndroid Build Coastguard Worker         mGpuEventQueryPool.freeQuery(this, &eventQuery.queryHelper);
4083*8975f5c5SAndroid Build Coastguard Worker 
4084*8975f5c5SAndroid Build Coastguard Worker         GpuEvent gpuEvent;
4085*8975f5c5SAndroid Build Coastguard Worker         gpuEvent.gpuTimestampCycles =
4086*8975f5c5SAndroid Build Coastguard Worker             gpuTimestampCycles.getResult(vk::QueryResult::kDefaultResultIndex);
4087*8975f5c5SAndroid Build Coastguard Worker         gpuEvent.name  = eventQuery.name;
4088*8975f5c5SAndroid Build Coastguard Worker         gpuEvent.phase = eventQuery.phase;
4089*8975f5c5SAndroid Build Coastguard Worker 
4090*8975f5c5SAndroid Build Coastguard Worker         mGpuEvents.emplace_back(gpuEvent);
4091*8975f5c5SAndroid Build Coastguard Worker 
4092*8975f5c5SAndroid Build Coastguard Worker         ++finishedCount;
4093*8975f5c5SAndroid Build Coastguard Worker     }
4094*8975f5c5SAndroid Build Coastguard Worker 
4095*8975f5c5SAndroid Build Coastguard Worker     mInFlightGpuEventQueries.erase(mInFlightGpuEventQueries.begin(),
4096*8975f5c5SAndroid Build Coastguard Worker                                    mInFlightGpuEventQueries.begin() + finishedCount);
4097*8975f5c5SAndroid Build Coastguard Worker 
4098*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4099*8975f5c5SAndroid Build Coastguard Worker }
4100*8975f5c5SAndroid Build Coastguard Worker 
flushGpuEvents(double nextSyncGpuTimestampS,double nextSyncCpuTimestampS)4101*8975f5c5SAndroid Build Coastguard Worker void ContextVk::flushGpuEvents(double nextSyncGpuTimestampS, double nextSyncCpuTimestampS)
4102*8975f5c5SAndroid Build Coastguard Worker {
4103*8975f5c5SAndroid Build Coastguard Worker     if (mGpuEvents.empty())
4104*8975f5c5SAndroid Build Coastguard Worker     {
4105*8975f5c5SAndroid Build Coastguard Worker         return;
4106*8975f5c5SAndroid Build Coastguard Worker     }
4107*8975f5c5SAndroid Build Coastguard Worker 
4108*8975f5c5SAndroid Build Coastguard Worker     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
4109*8975f5c5SAndroid Build Coastguard Worker     ASSERT(platform);
4110*8975f5c5SAndroid Build Coastguard Worker 
4111*8975f5c5SAndroid Build Coastguard Worker     // Find the slope of the clock drift for adjustment
4112*8975f5c5SAndroid Build Coastguard Worker     double lastGpuSyncTimeS  = mGpuClockSync.gpuTimestampS;
4113*8975f5c5SAndroid Build Coastguard Worker     double lastGpuSyncDiffS  = mGpuClockSync.cpuTimestampS - mGpuClockSync.gpuTimestampS;
4114*8975f5c5SAndroid Build Coastguard Worker     double gpuSyncDriftSlope = 0;
4115*8975f5c5SAndroid Build Coastguard Worker 
4116*8975f5c5SAndroid Build Coastguard Worker     double nextGpuSyncTimeS = nextSyncGpuTimestampS;
4117*8975f5c5SAndroid Build Coastguard Worker     double nextGpuSyncDiffS = nextSyncCpuTimestampS - nextSyncGpuTimestampS;
4118*8975f5c5SAndroid Build Coastguard Worker 
4119*8975f5c5SAndroid Build Coastguard Worker     // No gpu trace events should have been generated before the clock sync, so if there is no
4120*8975f5c5SAndroid Build Coastguard Worker     // "previous" clock sync, there should be no gpu events (i.e. the function early-outs
4121*8975f5c5SAndroid Build Coastguard Worker     // above).
4122*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mGpuClockSync.gpuTimestampS != std::numeric_limits<double>::max() &&
4123*8975f5c5SAndroid Build Coastguard Worker            mGpuClockSync.cpuTimestampS != std::numeric_limits<double>::max());
4124*8975f5c5SAndroid Build Coastguard Worker 
4125*8975f5c5SAndroid Build Coastguard Worker     gpuSyncDriftSlope =
4126*8975f5c5SAndroid Build Coastguard Worker         (nextGpuSyncDiffS - lastGpuSyncDiffS) / (nextGpuSyncTimeS - lastGpuSyncTimeS);
4127*8975f5c5SAndroid Build Coastguard Worker 
4128*8975f5c5SAndroid Build Coastguard Worker     for (const GpuEvent &gpuEvent : mGpuEvents)
4129*8975f5c5SAndroid Build Coastguard Worker     {
4130*8975f5c5SAndroid Build Coastguard Worker         double gpuTimestampS =
4131*8975f5c5SAndroid Build Coastguard Worker             (gpuEvent.gpuTimestampCycles - mGpuEventTimestampOrigin) *
4132*8975f5c5SAndroid Build Coastguard Worker             static_cast<double>(
4133*8975f5c5SAndroid Build Coastguard Worker                 getRenderer()->getPhysicalDeviceProperties().limits.timestampPeriod) *
4134*8975f5c5SAndroid Build Coastguard Worker             1e-9;
4135*8975f5c5SAndroid Build Coastguard Worker 
4136*8975f5c5SAndroid Build Coastguard Worker         // Account for clock drift.
4137*8975f5c5SAndroid Build Coastguard Worker         gpuTimestampS += lastGpuSyncDiffS + gpuSyncDriftSlope * (gpuTimestampS - lastGpuSyncTimeS);
4138*8975f5c5SAndroid Build Coastguard Worker 
4139*8975f5c5SAndroid Build Coastguard Worker         // Generate the trace now that the GPU timestamp is available and clock drifts are
4140*8975f5c5SAndroid Build Coastguard Worker         // accounted for.
4141*8975f5c5SAndroid Build Coastguard Worker         static long long eventId = 1;
4142*8975f5c5SAndroid Build Coastguard Worker         static const unsigned char *categoryEnabled =
4143*8975f5c5SAndroid Build Coastguard Worker             TRACE_EVENT_API_GET_CATEGORY_ENABLED(platform, "gpu.angle.gpu");
4144*8975f5c5SAndroid Build Coastguard Worker         platform->addTraceEvent(platform, gpuEvent.phase, categoryEnabled, gpuEvent.name.data(),
4145*8975f5c5SAndroid Build Coastguard Worker                                 eventId++, gpuTimestampS, 0, nullptr, nullptr, nullptr,
4146*8975f5c5SAndroid Build Coastguard Worker                                 TRACE_EVENT_FLAG_NONE);
4147*8975f5c5SAndroid Build Coastguard Worker     }
4148*8975f5c5SAndroid Build Coastguard Worker 
4149*8975f5c5SAndroid Build Coastguard Worker     mGpuEvents.clear();
4150*8975f5c5SAndroid Build Coastguard Worker }
4151*8975f5c5SAndroid Build Coastguard Worker 
clearAllGarbage()4152*8975f5c5SAndroid Build Coastguard Worker void ContextVk::clearAllGarbage()
4153*8975f5c5SAndroid Build Coastguard Worker {
4154*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::clearAllGarbage");
4155*8975f5c5SAndroid Build Coastguard Worker 
4156*8975f5c5SAndroid Build Coastguard Worker     // The VMA virtual allocator code has assertion to ensure all sub-ranges are freed before
4157*8975f5c5SAndroid Build Coastguard Worker     // virtual block gets freed. We need to ensure all completed garbage objects are actually freed
4158*8975f5c5SAndroid Build Coastguard Worker     // to avoid hitting that assertion.
4159*8975f5c5SAndroid Build Coastguard Worker     mRenderer->cleanupGarbage(nullptr);
4160*8975f5c5SAndroid Build Coastguard Worker 
4161*8975f5c5SAndroid Build Coastguard Worker     for (vk::GarbageObject &garbage : mCurrentGarbage)
4162*8975f5c5SAndroid Build Coastguard Worker     {
4163*8975f5c5SAndroid Build Coastguard Worker         garbage.destroy(mRenderer);
4164*8975f5c5SAndroid Build Coastguard Worker     }
4165*8975f5c5SAndroid Build Coastguard Worker     mCurrentGarbage.clear();
4166*8975f5c5SAndroid Build Coastguard Worker }
4167*8975f5c5SAndroid Build Coastguard Worker 
handleDeviceLost()4168*8975f5c5SAndroid Build Coastguard Worker void ContextVk::handleDeviceLost()
4169*8975f5c5SAndroid Build Coastguard Worker {
4170*8975f5c5SAndroid Build Coastguard Worker     vk::SecondaryCommandBufferCollector collector;
4171*8975f5c5SAndroid Build Coastguard Worker     (void)mOutsideRenderPassCommands->reset(this, &collector);
4172*8975f5c5SAndroid Build Coastguard Worker     (void)mRenderPassCommands->reset(this, &collector);
4173*8975f5c5SAndroid Build Coastguard Worker     collector.releaseCommandBuffers();
4174*8975f5c5SAndroid Build Coastguard Worker 
4175*8975f5c5SAndroid Build Coastguard Worker     mRenderer->notifyDeviceLost();
4176*8975f5c5SAndroid Build Coastguard Worker }
4177*8975f5c5SAndroid Build Coastguard Worker 
drawArrays(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count)4178*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::drawArrays(const gl::Context *context,
4179*8975f5c5SAndroid Build Coastguard Worker                                     gl::PrimitiveMode mode,
4180*8975f5c5SAndroid Build Coastguard Worker                                     GLint first,
4181*8975f5c5SAndroid Build Coastguard Worker                                     GLsizei count)
4182*8975f5c5SAndroid Build Coastguard Worker {
4183*8975f5c5SAndroid Build Coastguard Worker     uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
4184*8975f5c5SAndroid Build Coastguard Worker 
4185*8975f5c5SAndroid Build Coastguard Worker     if (mode == gl::PrimitiveMode::LineLoop)
4186*8975f5c5SAndroid Build Coastguard Worker     {
4187*8975f5c5SAndroid Build Coastguard Worker         uint32_t numIndices;
4188*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupLineLoopDraw(context, mode, first, count, gl::DrawElementsType::InvalidEnum,
4189*8975f5c5SAndroid Build Coastguard Worker                                     nullptr, &numIndices));
4190*8975f5c5SAndroid Build Coastguard Worker         LineLoopHelper::Draw(numIndices, 0, mRenderPassCommandBuffer);
4191*8975f5c5SAndroid Build Coastguard Worker     }
4192*8975f5c5SAndroid Build Coastguard Worker     else
4193*8975f5c5SAndroid Build Coastguard Worker     {
4194*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum,
4195*8975f5c5SAndroid Build Coastguard Worker                             nullptr, mNonIndexedDirtyBitsMask));
4196*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommandBuffer->draw(clampedVertexCount, first);
4197*8975f5c5SAndroid Build Coastguard Worker     }
4198*8975f5c5SAndroid Build Coastguard Worker 
4199*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4200*8975f5c5SAndroid Build Coastguard Worker }
4201*8975f5c5SAndroid Build Coastguard Worker 
drawArraysInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instances)4202*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::drawArraysInstanced(const gl::Context *context,
4203*8975f5c5SAndroid Build Coastguard Worker                                              gl::PrimitiveMode mode,
4204*8975f5c5SAndroid Build Coastguard Worker                                              GLint first,
4205*8975f5c5SAndroid Build Coastguard Worker                                              GLsizei count,
4206*8975f5c5SAndroid Build Coastguard Worker                                              GLsizei instances)
4207*8975f5c5SAndroid Build Coastguard Worker {
4208*8975f5c5SAndroid Build Coastguard Worker     if (mode == gl::PrimitiveMode::LineLoop)
4209*8975f5c5SAndroid Build Coastguard Worker     {
4210*8975f5c5SAndroid Build Coastguard Worker         uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
4211*8975f5c5SAndroid Build Coastguard Worker         uint32_t numIndices;
4212*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupLineLoopDraw(context, mode, first, clampedVertexCount,
4213*8975f5c5SAndroid Build Coastguard Worker                                     gl::DrawElementsType::InvalidEnum, nullptr, &numIndices));
4214*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommandBuffer->drawIndexedInstanced(numIndices, instances);
4215*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
4216*8975f5c5SAndroid Build Coastguard Worker     }
4217*8975f5c5SAndroid Build Coastguard Worker 
4218*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
4219*8975f5c5SAndroid Build Coastguard Worker                         nullptr, mNonIndexedDirtyBitsMask));
4220*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->drawInstanced(gl::GetClampedVertexCount<uint32_t>(count), instances,
4221*8975f5c5SAndroid Build Coastguard Worker                                             first);
4222*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4223*8975f5c5SAndroid Build Coastguard Worker }
4224*8975f5c5SAndroid Build Coastguard Worker 
drawArraysInstancedBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instances,GLuint baseInstance)4225*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::drawArraysInstancedBaseInstance(const gl::Context *context,
4226*8975f5c5SAndroid Build Coastguard Worker                                                          gl::PrimitiveMode mode,
4227*8975f5c5SAndroid Build Coastguard Worker                                                          GLint first,
4228*8975f5c5SAndroid Build Coastguard Worker                                                          GLsizei count,
4229*8975f5c5SAndroid Build Coastguard Worker                                                          GLsizei instances,
4230*8975f5c5SAndroid Build Coastguard Worker                                                          GLuint baseInstance)
4231*8975f5c5SAndroid Build Coastguard Worker {
4232*8975f5c5SAndroid Build Coastguard Worker     if (mode == gl::PrimitiveMode::LineLoop)
4233*8975f5c5SAndroid Build Coastguard Worker     {
4234*8975f5c5SAndroid Build Coastguard Worker         uint32_t clampedVertexCount = gl::GetClampedVertexCount<uint32_t>(count);
4235*8975f5c5SAndroid Build Coastguard Worker         uint32_t numIndices;
4236*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupLineLoopDraw(context, mode, first, clampedVertexCount,
4237*8975f5c5SAndroid Build Coastguard Worker                                     gl::DrawElementsType::InvalidEnum, nullptr, &numIndices));
4238*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommandBuffer->drawIndexedInstancedBaseVertexBaseInstance(numIndices, instances,
4239*8975f5c5SAndroid Build Coastguard Worker                                                                              0, 0, baseInstance);
4240*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
4241*8975f5c5SAndroid Build Coastguard Worker     }
4242*8975f5c5SAndroid Build Coastguard Worker 
4243*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
4244*8975f5c5SAndroid Build Coastguard Worker                         nullptr, mNonIndexedDirtyBitsMask));
4245*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->drawInstancedBaseInstance(gl::GetClampedVertexCount<uint32_t>(count),
4246*8975f5c5SAndroid Build Coastguard Worker                                                         instances, first, baseInstance);
4247*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4248*8975f5c5SAndroid Build Coastguard Worker }
4249*8975f5c5SAndroid Build Coastguard Worker 
drawElements(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices)4250*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::drawElements(const gl::Context *context,
4251*8975f5c5SAndroid Build Coastguard Worker                                       gl::PrimitiveMode mode,
4252*8975f5c5SAndroid Build Coastguard Worker                                       GLsizei count,
4253*8975f5c5SAndroid Build Coastguard Worker                                       gl::DrawElementsType type,
4254*8975f5c5SAndroid Build Coastguard Worker                                       const void *indices)
4255*8975f5c5SAndroid Build Coastguard Worker {
4256*8975f5c5SAndroid Build Coastguard Worker     if (mode == gl::PrimitiveMode::LineLoop)
4257*8975f5c5SAndroid Build Coastguard Worker     {
4258*8975f5c5SAndroid Build Coastguard Worker         uint32_t indexCount;
4259*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
4260*8975f5c5SAndroid Build Coastguard Worker         LineLoopHelper::Draw(indexCount, 0, mRenderPassCommandBuffer);
4261*8975f5c5SAndroid Build Coastguard Worker     }
4262*8975f5c5SAndroid Build Coastguard Worker     else
4263*8975f5c5SAndroid Build Coastguard Worker     {
4264*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices));
4265*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommandBuffer->drawIndexed(count);
4266*8975f5c5SAndroid Build Coastguard Worker     }
4267*8975f5c5SAndroid Build Coastguard Worker 
4268*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4269*8975f5c5SAndroid Build Coastguard Worker }
4270*8975f5c5SAndroid Build Coastguard Worker 
drawElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)4271*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::drawElementsBaseVertex(const gl::Context *context,
4272*8975f5c5SAndroid Build Coastguard Worker                                                 gl::PrimitiveMode mode,
4273*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei count,
4274*8975f5c5SAndroid Build Coastguard Worker                                                 gl::DrawElementsType type,
4275*8975f5c5SAndroid Build Coastguard Worker                                                 const void *indices,
4276*8975f5c5SAndroid Build Coastguard Worker                                                 GLint baseVertex)
4277*8975f5c5SAndroid Build Coastguard Worker {
4278*8975f5c5SAndroid Build Coastguard Worker     if (mode == gl::PrimitiveMode::LineLoop)
4279*8975f5c5SAndroid Build Coastguard Worker     {
4280*8975f5c5SAndroid Build Coastguard Worker         uint32_t indexCount;
4281*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
4282*8975f5c5SAndroid Build Coastguard Worker         LineLoopHelper::Draw(indexCount, baseVertex, mRenderPassCommandBuffer);
4283*8975f5c5SAndroid Build Coastguard Worker     }
4284*8975f5c5SAndroid Build Coastguard Worker     else
4285*8975f5c5SAndroid Build Coastguard Worker     {
4286*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices));
4287*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommandBuffer->drawIndexedBaseVertex(count, baseVertex);
4288*8975f5c5SAndroid Build Coastguard Worker     }
4289*8975f5c5SAndroid Build Coastguard Worker 
4290*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4291*8975f5c5SAndroid Build Coastguard Worker }
4292*8975f5c5SAndroid Build Coastguard Worker 
drawElementsInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances)4293*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::drawElementsInstanced(const gl::Context *context,
4294*8975f5c5SAndroid Build Coastguard Worker                                                gl::PrimitiveMode mode,
4295*8975f5c5SAndroid Build Coastguard Worker                                                GLsizei count,
4296*8975f5c5SAndroid Build Coastguard Worker                                                gl::DrawElementsType type,
4297*8975f5c5SAndroid Build Coastguard Worker                                                const void *indices,
4298*8975f5c5SAndroid Build Coastguard Worker                                                GLsizei instances)
4299*8975f5c5SAndroid Build Coastguard Worker {
4300*8975f5c5SAndroid Build Coastguard Worker     if (mode == gl::PrimitiveMode::LineLoop)
4301*8975f5c5SAndroid Build Coastguard Worker     {
4302*8975f5c5SAndroid Build Coastguard Worker         uint32_t indexCount;
4303*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
4304*8975f5c5SAndroid Build Coastguard Worker         count = indexCount;
4305*8975f5c5SAndroid Build Coastguard Worker     }
4306*8975f5c5SAndroid Build Coastguard Worker     else
4307*8975f5c5SAndroid Build Coastguard Worker     {
4308*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices));
4309*8975f5c5SAndroid Build Coastguard Worker     }
4310*8975f5c5SAndroid Build Coastguard Worker 
4311*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->drawIndexedInstanced(count, instances);
4312*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4313*8975f5c5SAndroid Build Coastguard Worker }
4314*8975f5c5SAndroid Build Coastguard Worker 
drawElementsInstancedBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex)4315*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::drawElementsInstancedBaseVertex(const gl::Context *context,
4316*8975f5c5SAndroid Build Coastguard Worker                                                          gl::PrimitiveMode mode,
4317*8975f5c5SAndroid Build Coastguard Worker                                                          GLsizei count,
4318*8975f5c5SAndroid Build Coastguard Worker                                                          gl::DrawElementsType type,
4319*8975f5c5SAndroid Build Coastguard Worker                                                          const void *indices,
4320*8975f5c5SAndroid Build Coastguard Worker                                                          GLsizei instances,
4321*8975f5c5SAndroid Build Coastguard Worker                                                          GLint baseVertex)
4322*8975f5c5SAndroid Build Coastguard Worker {
4323*8975f5c5SAndroid Build Coastguard Worker     if (mode == gl::PrimitiveMode::LineLoop)
4324*8975f5c5SAndroid Build Coastguard Worker     {
4325*8975f5c5SAndroid Build Coastguard Worker         uint32_t indexCount;
4326*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
4327*8975f5c5SAndroid Build Coastguard Worker         count = indexCount;
4328*8975f5c5SAndroid Build Coastguard Worker     }
4329*8975f5c5SAndroid Build Coastguard Worker     else
4330*8975f5c5SAndroid Build Coastguard Worker     {
4331*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices));
4332*8975f5c5SAndroid Build Coastguard Worker     }
4333*8975f5c5SAndroid Build Coastguard Worker 
4334*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->drawIndexedInstancedBaseVertex(count, instances, baseVertex);
4335*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4336*8975f5c5SAndroid Build Coastguard Worker }
4337*8975f5c5SAndroid Build Coastguard Worker 
drawElementsInstancedBaseVertexBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex,GLuint baseInstance)4338*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
4339*8975f5c5SAndroid Build Coastguard Worker                                                                      gl::PrimitiveMode mode,
4340*8975f5c5SAndroid Build Coastguard Worker                                                                      GLsizei count,
4341*8975f5c5SAndroid Build Coastguard Worker                                                                      gl::DrawElementsType type,
4342*8975f5c5SAndroid Build Coastguard Worker                                                                      const void *indices,
4343*8975f5c5SAndroid Build Coastguard Worker                                                                      GLsizei instances,
4344*8975f5c5SAndroid Build Coastguard Worker                                                                      GLint baseVertex,
4345*8975f5c5SAndroid Build Coastguard Worker                                                                      GLuint baseInstance)
4346*8975f5c5SAndroid Build Coastguard Worker {
4347*8975f5c5SAndroid Build Coastguard Worker     if (mode == gl::PrimitiveMode::LineLoop)
4348*8975f5c5SAndroid Build Coastguard Worker     {
4349*8975f5c5SAndroid Build Coastguard Worker         uint32_t indexCount;
4350*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupLineLoopDraw(context, mode, 0, count, type, indices, &indexCount));
4351*8975f5c5SAndroid Build Coastguard Worker         count = indexCount;
4352*8975f5c5SAndroid Build Coastguard Worker     }
4353*8975f5c5SAndroid Build Coastguard Worker     else
4354*8975f5c5SAndroid Build Coastguard Worker     {
4355*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices));
4356*8975f5c5SAndroid Build Coastguard Worker     }
4357*8975f5c5SAndroid Build Coastguard Worker 
4358*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->drawIndexedInstancedBaseVertexBaseInstance(count, instances, 0,
4359*8975f5c5SAndroid Build Coastguard Worker                                                                          baseVertex, baseInstance);
4360*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4361*8975f5c5SAndroid Build Coastguard Worker }
4362*8975f5c5SAndroid Build Coastguard Worker 
drawRangeElements(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices)4363*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::drawRangeElements(const gl::Context *context,
4364*8975f5c5SAndroid Build Coastguard Worker                                            gl::PrimitiveMode mode,
4365*8975f5c5SAndroid Build Coastguard Worker                                            GLuint start,
4366*8975f5c5SAndroid Build Coastguard Worker                                            GLuint end,
4367*8975f5c5SAndroid Build Coastguard Worker                                            GLsizei count,
4368*8975f5c5SAndroid Build Coastguard Worker                                            gl::DrawElementsType type,
4369*8975f5c5SAndroid Build Coastguard Worker                                            const void *indices)
4370*8975f5c5SAndroid Build Coastguard Worker {
4371*8975f5c5SAndroid Build Coastguard Worker     return drawElements(context, mode, count, type, indices);
4372*8975f5c5SAndroid Build Coastguard Worker }
4373*8975f5c5SAndroid Build Coastguard Worker 
drawRangeElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)4374*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::drawRangeElementsBaseVertex(const gl::Context *context,
4375*8975f5c5SAndroid Build Coastguard Worker                                                      gl::PrimitiveMode mode,
4376*8975f5c5SAndroid Build Coastguard Worker                                                      GLuint start,
4377*8975f5c5SAndroid Build Coastguard Worker                                                      GLuint end,
4378*8975f5c5SAndroid Build Coastguard Worker                                                      GLsizei count,
4379*8975f5c5SAndroid Build Coastguard Worker                                                      gl::DrawElementsType type,
4380*8975f5c5SAndroid Build Coastguard Worker                                                      const void *indices,
4381*8975f5c5SAndroid Build Coastguard Worker                                                      GLint baseVertex)
4382*8975f5c5SAndroid Build Coastguard Worker {
4383*8975f5c5SAndroid Build Coastguard Worker     return drawElementsBaseVertex(context, mode, count, type, indices, baseVertex);
4384*8975f5c5SAndroid Build Coastguard Worker }
4385*8975f5c5SAndroid Build Coastguard Worker 
getDevice() const4386*8975f5c5SAndroid Build Coastguard Worker VkDevice ContextVk::getDevice() const
4387*8975f5c5SAndroid Build Coastguard Worker {
4388*8975f5c5SAndroid Build Coastguard Worker     return mRenderer->getDevice();
4389*8975f5c5SAndroid Build Coastguard Worker }
4390*8975f5c5SAndroid Build Coastguard Worker 
drawArraysIndirect(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect)4391*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::drawArraysIndirect(const gl::Context *context,
4392*8975f5c5SAndroid Build Coastguard Worker                                             gl::PrimitiveMode mode,
4393*8975f5c5SAndroid Build Coastguard Worker                                             const void *indirect)
4394*8975f5c5SAndroid Build Coastguard Worker {
4395*8975f5c5SAndroid Build Coastguard Worker     return multiDrawArraysIndirectHelper(context, mode, indirect, 1, 0);
4396*8975f5c5SAndroid Build Coastguard Worker }
4397*8975f5c5SAndroid Build Coastguard Worker 
drawElementsIndirect(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect)4398*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::drawElementsIndirect(const gl::Context *context,
4399*8975f5c5SAndroid Build Coastguard Worker                                               gl::PrimitiveMode mode,
4400*8975f5c5SAndroid Build Coastguard Worker                                               gl::DrawElementsType type,
4401*8975f5c5SAndroid Build Coastguard Worker                                               const void *indirect)
4402*8975f5c5SAndroid Build Coastguard Worker {
4403*8975f5c5SAndroid Build Coastguard Worker     return multiDrawElementsIndirectHelper(context, mode, type, indirect, 1, 0);
4404*8975f5c5SAndroid Build Coastguard Worker }
4405*8975f5c5SAndroid Build Coastguard Worker 
multiDrawArrays(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,GLsizei drawcount)4406*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::multiDrawArrays(const gl::Context *context,
4407*8975f5c5SAndroid Build Coastguard Worker                                          gl::PrimitiveMode mode,
4408*8975f5c5SAndroid Build Coastguard Worker                                          const GLint *firsts,
4409*8975f5c5SAndroid Build Coastguard Worker                                          const GLsizei *counts,
4410*8975f5c5SAndroid Build Coastguard Worker                                          GLsizei drawcount)
4411*8975f5c5SAndroid Build Coastguard Worker {
4412*8975f5c5SAndroid Build Coastguard Worker     return rx::MultiDrawArraysGeneral(this, context, mode, firsts, counts, drawcount);
4413*8975f5c5SAndroid Build Coastguard Worker }
4414*8975f5c5SAndroid Build Coastguard Worker 
multiDrawArraysInstanced(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,GLsizei drawcount)4415*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::multiDrawArraysInstanced(const gl::Context *context,
4416*8975f5c5SAndroid Build Coastguard Worker                                                   gl::PrimitiveMode mode,
4417*8975f5c5SAndroid Build Coastguard Worker                                                   const GLint *firsts,
4418*8975f5c5SAndroid Build Coastguard Worker                                                   const GLsizei *counts,
4419*8975f5c5SAndroid Build Coastguard Worker                                                   const GLsizei *instanceCounts,
4420*8975f5c5SAndroid Build Coastguard Worker                                                   GLsizei drawcount)
4421*8975f5c5SAndroid Build Coastguard Worker {
4422*8975f5c5SAndroid Build Coastguard Worker     return rx::MultiDrawArraysInstancedGeneral(this, context, mode, firsts, counts, instanceCounts,
4423*8975f5c5SAndroid Build Coastguard Worker                                                drawcount);
4424*8975f5c5SAndroid Build Coastguard Worker }
4425*8975f5c5SAndroid Build Coastguard Worker 
multiDrawArraysIndirect(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect,GLsizei drawcount,GLsizei stride)4426*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::multiDrawArraysIndirect(const gl::Context *context,
4427*8975f5c5SAndroid Build Coastguard Worker                                                  gl::PrimitiveMode mode,
4428*8975f5c5SAndroid Build Coastguard Worker                                                  const void *indirect,
4429*8975f5c5SAndroid Build Coastguard Worker                                                  GLsizei drawcount,
4430*8975f5c5SAndroid Build Coastguard Worker                                                  GLsizei stride)
4431*8975f5c5SAndroid Build Coastguard Worker {
4432*8975f5c5SAndroid Build Coastguard Worker     return multiDrawArraysIndirectHelper(context, mode, indirect, drawcount, stride);
4433*8975f5c5SAndroid Build Coastguard Worker }
4434*8975f5c5SAndroid Build Coastguard Worker 
multiDrawArraysIndirectHelper(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect,GLsizei drawcount,GLsizei stride)4435*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::multiDrawArraysIndirectHelper(const gl::Context *context,
4436*8975f5c5SAndroid Build Coastguard Worker                                                        gl::PrimitiveMode mode,
4437*8975f5c5SAndroid Build Coastguard Worker                                                        const void *indirect,
4438*8975f5c5SAndroid Build Coastguard Worker                                                        GLsizei drawcount,
4439*8975f5c5SAndroid Build Coastguard Worker                                                        GLsizei stride)
4440*8975f5c5SAndroid Build Coastguard Worker {
4441*8975f5c5SAndroid Build Coastguard Worker     VertexArrayVk *vertexArrayVk = getVertexArray();
4442*8975f5c5SAndroid Build Coastguard Worker     if (drawcount > 1 && !CanMultiDrawIndirectUseCmd(this, vertexArrayVk, mode, drawcount, stride))
4443*8975f5c5SAndroid Build Coastguard Worker     {
4444*8975f5c5SAndroid Build Coastguard Worker         return rx::MultiDrawArraysIndirectGeneral(this, context, mode, indirect, drawcount, stride);
4445*8975f5c5SAndroid Build Coastguard Worker     }
4446*8975f5c5SAndroid Build Coastguard Worker 
4447*8975f5c5SAndroid Build Coastguard Worker     // Stride must be a multiple of the size of VkDrawIndirectCommand (stride = 0 is invalid when
4448*8975f5c5SAndroid Build Coastguard Worker     // drawcount > 1).
4449*8975f5c5SAndroid Build Coastguard Worker     uint32_t vkStride = (stride == 0 && drawcount > 1) ? sizeof(VkDrawIndirectCommand) : stride;
4450*8975f5c5SAndroid Build Coastguard Worker 
4451*8975f5c5SAndroid Build Coastguard Worker     gl::Buffer *indirectBuffer            = mState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
4452*8975f5c5SAndroid Build Coastguard Worker     vk::BufferHelper *currentIndirectBuf  = &vk::GetImpl(indirectBuffer)->getBuffer();
4453*8975f5c5SAndroid Build Coastguard Worker     VkDeviceSize currentIndirectBufOffset = reinterpret_cast<VkDeviceSize>(indirect);
4454*8975f5c5SAndroid Build Coastguard Worker 
4455*8975f5c5SAndroid Build Coastguard Worker     if (vertexArrayVk->getStreamingVertexAttribsMask().any())
4456*8975f5c5SAndroid Build Coastguard Worker     {
4457*8975f5c5SAndroid Build Coastguard Worker         // Handling instanced vertex attributes is not covered for drawcount > 1.
4458*8975f5c5SAndroid Build Coastguard Worker         ASSERT(drawcount <= 1);
4459*8975f5c5SAndroid Build Coastguard Worker 
4460*8975f5c5SAndroid Build Coastguard Worker         // We have instanced vertex attributes that need to be emulated for Vulkan.
4461*8975f5c5SAndroid Build Coastguard Worker         // invalidate any cache and map the buffer so that we can read the indirect data.
4462*8975f5c5SAndroid Build Coastguard Worker         // Mapping the buffer will cause a flush.
4463*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(currentIndirectBuf->invalidate(mRenderer, 0, sizeof(VkDrawIndirectCommand)));
4464*8975f5c5SAndroid Build Coastguard Worker         uint8_t *buffPtr;
4465*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(currentIndirectBuf->map(this, &buffPtr));
4466*8975f5c5SAndroid Build Coastguard Worker         const VkDrawIndirectCommand *indirectData =
4467*8975f5c5SAndroid Build Coastguard Worker             reinterpret_cast<VkDrawIndirectCommand *>(buffPtr + currentIndirectBufOffset);
4468*8975f5c5SAndroid Build Coastguard Worker 
4469*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(drawArraysInstanced(context, mode, indirectData->firstVertex,
4470*8975f5c5SAndroid Build Coastguard Worker                                       indirectData->vertexCount, indirectData->instanceCount));
4471*8975f5c5SAndroid Build Coastguard Worker 
4472*8975f5c5SAndroid Build Coastguard Worker         currentIndirectBuf->unmap(mRenderer);
4473*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
4474*8975f5c5SAndroid Build Coastguard Worker     }
4475*8975f5c5SAndroid Build Coastguard Worker 
4476*8975f5c5SAndroid Build Coastguard Worker     if (mode == gl::PrimitiveMode::LineLoop)
4477*8975f5c5SAndroid Build Coastguard Worker     {
4478*8975f5c5SAndroid Build Coastguard Worker         // Line loop only supports handling at most one indirect parameter.
4479*8975f5c5SAndroid Build Coastguard Worker         ASSERT(drawcount <= 1);
4480*8975f5c5SAndroid Build Coastguard Worker 
4481*8975f5c5SAndroid Build Coastguard Worker         ASSERT(indirectBuffer);
4482*8975f5c5SAndroid Build Coastguard Worker         vk::BufferHelper *dstIndirectBuf = nullptr;
4483*8975f5c5SAndroid Build Coastguard Worker 
4484*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupLineLoopIndirectDraw(context, mode, currentIndirectBuf,
4485*8975f5c5SAndroid Build Coastguard Worker                                             currentIndirectBufOffset, &dstIndirectBuf));
4486*8975f5c5SAndroid Build Coastguard Worker 
4487*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommandBuffer->drawIndexedIndirect(
4488*8975f5c5SAndroid Build Coastguard Worker             dstIndirectBuf->getBuffer(), dstIndirectBuf->getOffset(), drawcount, vkStride);
4489*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
4490*8975f5c5SAndroid Build Coastguard Worker     }
4491*8975f5c5SAndroid Build Coastguard Worker 
4492*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(setupIndirectDraw(context, mode, mNonIndexedDirtyBitsMask, currentIndirectBuf));
4493*8975f5c5SAndroid Build Coastguard Worker 
4494*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->drawIndirect(
4495*8975f5c5SAndroid Build Coastguard Worker         currentIndirectBuf->getBuffer(), currentIndirectBuf->getOffset() + currentIndirectBufOffset,
4496*8975f5c5SAndroid Build Coastguard Worker         drawcount, vkStride);
4497*8975f5c5SAndroid Build Coastguard Worker 
4498*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4499*8975f5c5SAndroid Build Coastguard Worker }
4500*8975f5c5SAndroid Build Coastguard Worker 
multiDrawElements(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,GLsizei drawcount)4501*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::multiDrawElements(const gl::Context *context,
4502*8975f5c5SAndroid Build Coastguard Worker                                            gl::PrimitiveMode mode,
4503*8975f5c5SAndroid Build Coastguard Worker                                            const GLsizei *counts,
4504*8975f5c5SAndroid Build Coastguard Worker                                            gl::DrawElementsType type,
4505*8975f5c5SAndroid Build Coastguard Worker                                            const GLvoid *const *indices,
4506*8975f5c5SAndroid Build Coastguard Worker                                            GLsizei drawcount)
4507*8975f5c5SAndroid Build Coastguard Worker {
4508*8975f5c5SAndroid Build Coastguard Worker     return rx::MultiDrawElementsGeneral(this, context, mode, counts, type, indices, drawcount);
4509*8975f5c5SAndroid Build Coastguard Worker }
4510*8975f5c5SAndroid Build Coastguard Worker 
multiDrawElementsInstanced(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,GLsizei drawcount)4511*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::multiDrawElementsInstanced(const gl::Context *context,
4512*8975f5c5SAndroid Build Coastguard Worker                                                     gl::PrimitiveMode mode,
4513*8975f5c5SAndroid Build Coastguard Worker                                                     const GLsizei *counts,
4514*8975f5c5SAndroid Build Coastguard Worker                                                     gl::DrawElementsType type,
4515*8975f5c5SAndroid Build Coastguard Worker                                                     const GLvoid *const *indices,
4516*8975f5c5SAndroid Build Coastguard Worker                                                     const GLsizei *instanceCounts,
4517*8975f5c5SAndroid Build Coastguard Worker                                                     GLsizei drawcount)
4518*8975f5c5SAndroid Build Coastguard Worker {
4519*8975f5c5SAndroid Build Coastguard Worker     return rx::MultiDrawElementsInstancedGeneral(this, context, mode, counts, type, indices,
4520*8975f5c5SAndroid Build Coastguard Worker                                                  instanceCounts, drawcount);
4521*8975f5c5SAndroid Build Coastguard Worker }
4522*8975f5c5SAndroid Build Coastguard Worker 
multiDrawElementsIndirect(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect,GLsizei drawcount,GLsizei stride)4523*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::multiDrawElementsIndirect(const gl::Context *context,
4524*8975f5c5SAndroid Build Coastguard Worker                                                    gl::PrimitiveMode mode,
4525*8975f5c5SAndroid Build Coastguard Worker                                                    gl::DrawElementsType type,
4526*8975f5c5SAndroid Build Coastguard Worker                                                    const void *indirect,
4527*8975f5c5SAndroid Build Coastguard Worker                                                    GLsizei drawcount,
4528*8975f5c5SAndroid Build Coastguard Worker                                                    GLsizei stride)
4529*8975f5c5SAndroid Build Coastguard Worker {
4530*8975f5c5SAndroid Build Coastguard Worker     return multiDrawElementsIndirectHelper(context, mode, type, indirect, drawcount, stride);
4531*8975f5c5SAndroid Build Coastguard Worker }
4532*8975f5c5SAndroid Build Coastguard Worker 
multiDrawElementsIndirectHelper(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect,GLsizei drawcount,GLsizei stride)4533*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::multiDrawElementsIndirectHelper(const gl::Context *context,
4534*8975f5c5SAndroid Build Coastguard Worker                                                          gl::PrimitiveMode mode,
4535*8975f5c5SAndroid Build Coastguard Worker                                                          gl::DrawElementsType type,
4536*8975f5c5SAndroid Build Coastguard Worker                                                          const void *indirect,
4537*8975f5c5SAndroid Build Coastguard Worker                                                          GLsizei drawcount,
4538*8975f5c5SAndroid Build Coastguard Worker                                                          GLsizei stride)
4539*8975f5c5SAndroid Build Coastguard Worker {
4540*8975f5c5SAndroid Build Coastguard Worker     VertexArrayVk *vertexArrayVk = getVertexArray();
4541*8975f5c5SAndroid Build Coastguard Worker     if (drawcount > 1 && !CanMultiDrawIndirectUseCmd(this, vertexArrayVk, mode, drawcount, stride))
4542*8975f5c5SAndroid Build Coastguard Worker     {
4543*8975f5c5SAndroid Build Coastguard Worker         return rx::MultiDrawElementsIndirectGeneral(this, context, mode, type, indirect, drawcount,
4544*8975f5c5SAndroid Build Coastguard Worker                                                     stride);
4545*8975f5c5SAndroid Build Coastguard Worker     }
4546*8975f5c5SAndroid Build Coastguard Worker 
4547*8975f5c5SAndroid Build Coastguard Worker     // Stride must be a multiple of the size of VkDrawIndexedIndirectCommand (stride = 0 is invalid
4548*8975f5c5SAndroid Build Coastguard Worker     // when drawcount > 1).
4549*8975f5c5SAndroid Build Coastguard Worker     uint32_t vkStride =
4550*8975f5c5SAndroid Build Coastguard Worker         (stride == 0 && drawcount > 1) ? sizeof(VkDrawIndexedIndirectCommand) : stride;
4551*8975f5c5SAndroid Build Coastguard Worker 
4552*8975f5c5SAndroid Build Coastguard Worker     gl::Buffer *indirectBuffer = mState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
4553*8975f5c5SAndroid Build Coastguard Worker     ASSERT(indirectBuffer);
4554*8975f5c5SAndroid Build Coastguard Worker     vk::BufferHelper *currentIndirectBuf  = &vk::GetImpl(indirectBuffer)->getBuffer();
4555*8975f5c5SAndroid Build Coastguard Worker     VkDeviceSize currentIndirectBufOffset = reinterpret_cast<VkDeviceSize>(indirect);
4556*8975f5c5SAndroid Build Coastguard Worker 
4557*8975f5c5SAndroid Build Coastguard Worker     // Reset the index buffer offset
4558*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
4559*8975f5c5SAndroid Build Coastguard Worker     mCurrentIndexBufferOffset = 0;
4560*8975f5c5SAndroid Build Coastguard Worker 
4561*8975f5c5SAndroid Build Coastguard Worker     if (vertexArrayVk->getStreamingVertexAttribsMask().any())
4562*8975f5c5SAndroid Build Coastguard Worker     {
4563*8975f5c5SAndroid Build Coastguard Worker         // Handling instanced vertex attributes is not covered for drawcount > 1.
4564*8975f5c5SAndroid Build Coastguard Worker         ASSERT(drawcount <= 1);
4565*8975f5c5SAndroid Build Coastguard Worker 
4566*8975f5c5SAndroid Build Coastguard Worker         // We have instanced vertex attributes that need to be emulated for Vulkan.
4567*8975f5c5SAndroid Build Coastguard Worker         // invalidate any cache and map the buffer so that we can read the indirect data.
4568*8975f5c5SAndroid Build Coastguard Worker         // Mapping the buffer will cause a flush.
4569*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(
4570*8975f5c5SAndroid Build Coastguard Worker             currentIndirectBuf->invalidate(mRenderer, 0, sizeof(VkDrawIndexedIndirectCommand)));
4571*8975f5c5SAndroid Build Coastguard Worker         uint8_t *buffPtr;
4572*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(currentIndirectBuf->map(this, &buffPtr));
4573*8975f5c5SAndroid Build Coastguard Worker         const VkDrawIndexedIndirectCommand *indirectData =
4574*8975f5c5SAndroid Build Coastguard Worker             reinterpret_cast<VkDrawIndexedIndirectCommand *>(buffPtr + currentIndirectBufOffset);
4575*8975f5c5SAndroid Build Coastguard Worker 
4576*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(drawElementsInstanced(context, mode, indirectData->indexCount, type, nullptr,
4577*8975f5c5SAndroid Build Coastguard Worker                                         indirectData->instanceCount));
4578*8975f5c5SAndroid Build Coastguard Worker 
4579*8975f5c5SAndroid Build Coastguard Worker         currentIndirectBuf->unmap(mRenderer);
4580*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
4581*8975f5c5SAndroid Build Coastguard Worker     }
4582*8975f5c5SAndroid Build Coastguard Worker 
4583*8975f5c5SAndroid Build Coastguard Worker     if (shouldConvertUint8VkIndexType(type) && mGraphicsDirtyBits[DIRTY_BIT_INDEX_BUFFER])
4584*8975f5c5SAndroid Build Coastguard Worker     {
4585*8975f5c5SAndroid Build Coastguard Worker         ANGLE_VK_PERF_WARNING(
4586*8975f5c5SAndroid Build Coastguard Worker             this, GL_DEBUG_SEVERITY_LOW,
4587*8975f5c5SAndroid Build Coastguard Worker             "Potential inefficiency emulating uint8 vertex attributes due to lack "
4588*8975f5c5SAndroid Build Coastguard Worker             "of hardware support");
4589*8975f5c5SAndroid Build Coastguard Worker 
4590*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(vertexArrayVk->convertIndexBufferIndirectGPU(
4591*8975f5c5SAndroid Build Coastguard Worker             this, currentIndirectBuf, currentIndirectBufOffset, &currentIndirectBuf));
4592*8975f5c5SAndroid Build Coastguard Worker         currentIndirectBufOffset = 0;
4593*8975f5c5SAndroid Build Coastguard Worker     }
4594*8975f5c5SAndroid Build Coastguard Worker 
4595*8975f5c5SAndroid Build Coastguard Worker     // If the line-loop handling function modifies the element array buffer in the vertex array,
4596*8975f5c5SAndroid Build Coastguard Worker     // there is a possibility that the modified version is used as a source for the next line-loop
4597*8975f5c5SAndroid Build Coastguard Worker     // draw, which can lead to errors. To avoid this, a local index buffer pointer is used to pass
4598*8975f5c5SAndroid Build Coastguard Worker     // the current index buffer (after translation, in case it is needed) and use the resulting
4599*8975f5c5SAndroid Build Coastguard Worker     // index buffer for draw.
4600*8975f5c5SAndroid Build Coastguard Worker     vk::BufferHelper *currentIndexBuf = vertexArrayVk->getCurrentElementArrayBuffer();
4601*8975f5c5SAndroid Build Coastguard Worker     if (mode == gl::PrimitiveMode::LineLoop)
4602*8975f5c5SAndroid Build Coastguard Worker     {
4603*8975f5c5SAndroid Build Coastguard Worker         // Line loop only supports handling at most one indirect parameter.
4604*8975f5c5SAndroid Build Coastguard Worker         ASSERT(drawcount <= 1);
4605*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupLineLoopIndexedIndirectDraw(context, mode, type, currentIndexBuf,
4606*8975f5c5SAndroid Build Coastguard Worker                                                    currentIndirectBuf, currentIndirectBufOffset,
4607*8975f5c5SAndroid Build Coastguard Worker                                                    &currentIndirectBuf));
4608*8975f5c5SAndroid Build Coastguard Worker         currentIndirectBufOffset = 0;
4609*8975f5c5SAndroid Build Coastguard Worker     }
4610*8975f5c5SAndroid Build Coastguard Worker     else
4611*8975f5c5SAndroid Build Coastguard Worker     {
4612*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(setupIndexedIndirectDraw(context, mode, type, currentIndirectBuf));
4613*8975f5c5SAndroid Build Coastguard Worker     }
4614*8975f5c5SAndroid Build Coastguard Worker 
4615*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommandBuffer->drawIndexedIndirect(
4616*8975f5c5SAndroid Build Coastguard Worker         currentIndirectBuf->getBuffer(), currentIndirectBuf->getOffset() + currentIndirectBufOffset,
4617*8975f5c5SAndroid Build Coastguard Worker         drawcount, vkStride);
4618*8975f5c5SAndroid Build Coastguard Worker 
4619*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4620*8975f5c5SAndroid Build Coastguard Worker }
4621*8975f5c5SAndroid Build Coastguard Worker 
multiDrawArraysInstancedBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,const GLuint * baseInstances,GLsizei drawcount)4622*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::multiDrawArraysInstancedBaseInstance(const gl::Context *context,
4623*8975f5c5SAndroid Build Coastguard Worker                                                               gl::PrimitiveMode mode,
4624*8975f5c5SAndroid Build Coastguard Worker                                                               const GLint *firsts,
4625*8975f5c5SAndroid Build Coastguard Worker                                                               const GLsizei *counts,
4626*8975f5c5SAndroid Build Coastguard Worker                                                               const GLsizei *instanceCounts,
4627*8975f5c5SAndroid Build Coastguard Worker                                                               const GLuint *baseInstances,
4628*8975f5c5SAndroid Build Coastguard Worker                                                               GLsizei drawcount)
4629*8975f5c5SAndroid Build Coastguard Worker {
4630*8975f5c5SAndroid Build Coastguard Worker     return rx::MultiDrawArraysInstancedBaseInstanceGeneral(
4631*8975f5c5SAndroid Build Coastguard Worker         this, context, mode, firsts, counts, instanceCounts, baseInstances, drawcount);
4632*8975f5c5SAndroid Build Coastguard Worker }
4633*8975f5c5SAndroid Build Coastguard Worker 
multiDrawElementsInstancedBaseVertexBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,const GLint * baseVertices,const GLuint * baseInstances,GLsizei drawcount)4634*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::multiDrawElementsInstancedBaseVertexBaseInstance(
4635*8975f5c5SAndroid Build Coastguard Worker     const gl::Context *context,
4636*8975f5c5SAndroid Build Coastguard Worker     gl::PrimitiveMode mode,
4637*8975f5c5SAndroid Build Coastguard Worker     const GLsizei *counts,
4638*8975f5c5SAndroid Build Coastguard Worker     gl::DrawElementsType type,
4639*8975f5c5SAndroid Build Coastguard Worker     const GLvoid *const *indices,
4640*8975f5c5SAndroid Build Coastguard Worker     const GLsizei *instanceCounts,
4641*8975f5c5SAndroid Build Coastguard Worker     const GLint *baseVertices,
4642*8975f5c5SAndroid Build Coastguard Worker     const GLuint *baseInstances,
4643*8975f5c5SAndroid Build Coastguard Worker     GLsizei drawcount)
4644*8975f5c5SAndroid Build Coastguard Worker {
4645*8975f5c5SAndroid Build Coastguard Worker     return rx::MultiDrawElementsInstancedBaseVertexBaseInstanceGeneral(
4646*8975f5c5SAndroid Build Coastguard Worker         this, context, mode, counts, type, indices, instanceCounts, baseVertices, baseInstances,
4647*8975f5c5SAndroid Build Coastguard Worker         drawcount);
4648*8975f5c5SAndroid Build Coastguard Worker }
4649*8975f5c5SAndroid Build Coastguard Worker 
optimizeRenderPassForPresent(vk::ImageViewHelper * colorImageView,vk::ImageHelper * colorImage,vk::ImageHelper * colorImageMS,vk::PresentMode presentMode,bool * imageResolved)4650*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::optimizeRenderPassForPresent(vk::ImageViewHelper *colorImageView,
4651*8975f5c5SAndroid Build Coastguard Worker                                                       vk::ImageHelper *colorImage,
4652*8975f5c5SAndroid Build Coastguard Worker                                                       vk::ImageHelper *colorImageMS,
4653*8975f5c5SAndroid Build Coastguard Worker                                                       vk::PresentMode presentMode,
4654*8975f5c5SAndroid Build Coastguard Worker                                                       bool *imageResolved)
4655*8975f5c5SAndroid Build Coastguard Worker {
4656*8975f5c5SAndroid Build Coastguard Worker     // Note: mRenderPassCommandBuffer may be nullptr because the render pass is marked for closure.
4657*8975f5c5SAndroid Build Coastguard Worker     // That doesn't matter and the render pass can continue to be modified.  This function shouldn't
4658*8975f5c5SAndroid Build Coastguard Worker     // rely on mRenderPassCommandBuffer.
4659*8975f5c5SAndroid Build Coastguard Worker 
4660*8975f5c5SAndroid Build Coastguard Worker     // The caller must have verified this is the right render pass by calling
4661*8975f5c5SAndroid Build Coastguard Worker     // |hasStartedRenderPassWithSwapchainFramebuffer()|.
4662*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mRenderPassCommands->started());
4663*8975f5c5SAndroid Build Coastguard Worker 
4664*8975f5c5SAndroid Build Coastguard Worker     // EGL1.5 spec: The contents of ancillary buffers are always undefined after calling
4665*8975f5c5SAndroid Build Coastguard Worker     // eglSwapBuffers
4666*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *drawFramebufferVk         = getDrawFramebuffer();
4667*8975f5c5SAndroid Build Coastguard Worker     RenderTargetVk *depthStencilRenderTarget = drawFramebufferVk->getDepthStencilRenderTarget();
4668*8975f5c5SAndroid Build Coastguard Worker     if (depthStencilRenderTarget != nullptr)
4669*8975f5c5SAndroid Build Coastguard Worker     {
4670*8975f5c5SAndroid Build Coastguard Worker         // Change depth/stencil attachment storeOp to DONT_CARE
4671*8975f5c5SAndroid Build Coastguard Worker         const gl::DepthStencilState &dsState = mState.getDepthStencilState();
4672*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommands->invalidateRenderPassDepthAttachment(
4673*8975f5c5SAndroid Build Coastguard Worker             dsState, mRenderPassCommands->getRenderArea());
4674*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommands->invalidateRenderPassStencilAttachment(
4675*8975f5c5SAndroid Build Coastguard Worker             dsState, mState.getDrawFramebuffer()->getStencilBitCount(),
4676*8975f5c5SAndroid Build Coastguard Worker             mRenderPassCommands->getRenderArea());
4677*8975f5c5SAndroid Build Coastguard Worker     }
4678*8975f5c5SAndroid Build Coastguard Worker 
4679*8975f5c5SAndroid Build Coastguard Worker     // Use finalLayout instead of extra barrier for layout change to present
4680*8975f5c5SAndroid Build Coastguard Worker     if (colorImage != nullptr && getFeatures().supportsPresentation.enabled)
4681*8975f5c5SAndroid Build Coastguard Worker     {
4682*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommands->setImageOptimizeForPresent(colorImage);
4683*8975f5c5SAndroid Build Coastguard Worker     }
4684*8975f5c5SAndroid Build Coastguard Worker 
4685*8975f5c5SAndroid Build Coastguard Worker     // Resolve the multisample image
4686*8975f5c5SAndroid Build Coastguard Worker     vk::RenderPassCommandBufferHelper &commandBufferHelper = getStartedRenderPassCommands();
4687*8975f5c5SAndroid Build Coastguard Worker     gl::Rectangle renderArea                               = commandBufferHelper.getRenderArea();
4688*8975f5c5SAndroid Build Coastguard Worker     const gl::Rectangle invalidateArea(0, 0, colorImageMS->getRotatedExtents().width,
4689*8975f5c5SAndroid Build Coastguard Worker                                        colorImageMS->getRotatedExtents().height);
4690*8975f5c5SAndroid Build Coastguard Worker     if (colorImageMS->valid() && renderArea == invalidateArea)
4691*8975f5c5SAndroid Build Coastguard Worker     {
4692*8975f5c5SAndroid Build Coastguard Worker         // Due to lack of support for GL_MESA_framebuffer_flip_y, it is currently impossible for the
4693*8975f5c5SAndroid Build Coastguard Worker         // application to resolve the default framebuffer into an FBO with a resolve attachment.  If
4694*8975f5c5SAndroid Build Coastguard Worker         // that is ever supported, the path that adds the resolve attachment would invalidate the
4695*8975f5c5SAndroid Build Coastguard Worker         // framebuffer that the render pass holds on to, in which case this function is not called.
4696*8975f5c5SAndroid Build Coastguard Worker         // Either way, there cannot be a resolve attachment here already.
4697*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!mRenderPassCommands->getFramebuffer().hasColorResolveAttachment(0));
4698*8975f5c5SAndroid Build Coastguard Worker 
4699*8975f5c5SAndroid Build Coastguard Worker         // Add the resolve attachment to the render pass
4700*8975f5c5SAndroid Build Coastguard Worker         const vk::ImageView *resolveImageView = nullptr;
4701*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(colorImageView->getLevelLayerDrawImageView(this, *colorImage, vk::LevelIndex(0),
4702*8975f5c5SAndroid Build Coastguard Worker                                                              0, &resolveImageView));
4703*8975f5c5SAndroid Build Coastguard Worker 
4704*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommands->addColorResolveAttachment(0, colorImage, resolveImageView->getHandle(),
4705*8975f5c5SAndroid Build Coastguard Worker                                                        gl::LevelIndex(0), 0, 1, {});
4706*8975f5c5SAndroid Build Coastguard Worker         onImageRenderPassWrite(gl::LevelIndex(0), 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
4707*8975f5c5SAndroid Build Coastguard Worker                                vk::ImageLayout::ColorWrite, colorImage);
4708*8975f5c5SAndroid Build Coastguard Worker 
4709*8975f5c5SAndroid Build Coastguard Worker         // Invalidate the surface.  See comment in WindowSurfaceVk::doDeferredAcquireNextImage on
4710*8975f5c5SAndroid Build Coastguard Worker         // why this is not done when in DEMAND_REFRESH mode.
4711*8975f5c5SAndroid Build Coastguard Worker         if (presentMode != vk::PresentMode::SharedDemandRefreshKHR)
4712*8975f5c5SAndroid Build Coastguard Worker         {
4713*8975f5c5SAndroid Build Coastguard Worker             commandBufferHelper.invalidateRenderPassColorAttachment(
4714*8975f5c5SAndroid Build Coastguard Worker                 mState, 0, vk::PackedAttachmentIndex(0), invalidateArea);
4715*8975f5c5SAndroid Build Coastguard Worker         }
4716*8975f5c5SAndroid Build Coastguard Worker 
4717*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(
4718*8975f5c5SAndroid Build Coastguard Worker             flushCommandsAndEndRenderPass(RenderPassClosureReason::AlreadySpecifiedElsewhere));
4719*8975f5c5SAndroid Build Coastguard Worker 
4720*8975f5c5SAndroid Build Coastguard Worker         *imageResolved = true;
4721*8975f5c5SAndroid Build Coastguard Worker 
4722*8975f5c5SAndroid Build Coastguard Worker         mPerfCounters.swapchainResolveInSubpass++;
4723*8975f5c5SAndroid Build Coastguard Worker     }
4724*8975f5c5SAndroid Build Coastguard Worker 
4725*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4726*8975f5c5SAndroid Build Coastguard Worker }
4727*8975f5c5SAndroid Build Coastguard Worker 
getResetStatus()4728*8975f5c5SAndroid Build Coastguard Worker gl::GraphicsResetStatus ContextVk::getResetStatus()
4729*8975f5c5SAndroid Build Coastguard Worker {
4730*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->isDeviceLost())
4731*8975f5c5SAndroid Build Coastguard Worker     {
4732*8975f5c5SAndroid Build Coastguard Worker         // TODO(geofflang): It may be possible to track which context caused the device lost and
4733*8975f5c5SAndroid Build Coastguard Worker         // return either GL_GUILTY_CONTEXT_RESET or GL_INNOCENT_CONTEXT_RESET.
4734*8975f5c5SAndroid Build Coastguard Worker         // http://anglebug.com/42261488
4735*8975f5c5SAndroid Build Coastguard Worker         return gl::GraphicsResetStatus::UnknownContextReset;
4736*8975f5c5SAndroid Build Coastguard Worker     }
4737*8975f5c5SAndroid Build Coastguard Worker 
4738*8975f5c5SAndroid Build Coastguard Worker     return gl::GraphicsResetStatus::NoError;
4739*8975f5c5SAndroid Build Coastguard Worker }
4740*8975f5c5SAndroid Build Coastguard Worker 
insertEventMarker(GLsizei length,const char * marker)4741*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::insertEventMarker(GLsizei length, const char *marker)
4742*8975f5c5SAndroid Build Coastguard Worker {
4743*8975f5c5SAndroid Build Coastguard Worker     insertEventMarkerImpl(GL_DEBUG_SOURCE_APPLICATION, marker);
4744*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4745*8975f5c5SAndroid Build Coastguard Worker }
4746*8975f5c5SAndroid Build Coastguard Worker 
insertEventMarkerImpl(GLenum source,const char * marker)4747*8975f5c5SAndroid Build Coastguard Worker void ContextVk::insertEventMarkerImpl(GLenum source, const char *marker)
4748*8975f5c5SAndroid Build Coastguard Worker {
4749*8975f5c5SAndroid Build Coastguard Worker     if (!isDebugEnabled())
4750*8975f5c5SAndroid Build Coastguard Worker     {
4751*8975f5c5SAndroid Build Coastguard Worker         return;
4752*8975f5c5SAndroid Build Coastguard Worker     }
4753*8975f5c5SAndroid Build Coastguard Worker 
4754*8975f5c5SAndroid Build Coastguard Worker     VkDebugUtilsLabelEXT label;
4755*8975f5c5SAndroid Build Coastguard Worker     vk::MakeDebugUtilsLabel(source, marker, &label);
4756*8975f5c5SAndroid Build Coastguard Worker 
4757*8975f5c5SAndroid Build Coastguard Worker     if (hasActiveRenderPass())
4758*8975f5c5SAndroid Build Coastguard Worker     {
4759*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommandBuffer->insertDebugUtilsLabelEXT(label);
4760*8975f5c5SAndroid Build Coastguard Worker     }
4761*8975f5c5SAndroid Build Coastguard Worker     else
4762*8975f5c5SAndroid Build Coastguard Worker     {
4763*8975f5c5SAndroid Build Coastguard Worker         mOutsideRenderPassCommands->getCommandBuffer().insertDebugUtilsLabelEXT(label);
4764*8975f5c5SAndroid Build Coastguard Worker     }
4765*8975f5c5SAndroid Build Coastguard Worker }
4766*8975f5c5SAndroid Build Coastguard Worker 
pushGroupMarker(GLsizei length,const char * marker)4767*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::pushGroupMarker(GLsizei length, const char *marker)
4768*8975f5c5SAndroid Build Coastguard Worker {
4769*8975f5c5SAndroid Build Coastguard Worker     return pushDebugGroupImpl(GL_DEBUG_SOURCE_APPLICATION, 0, marker);
4770*8975f5c5SAndroid Build Coastguard Worker }
4771*8975f5c5SAndroid Build Coastguard Worker 
popGroupMarker()4772*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::popGroupMarker()
4773*8975f5c5SAndroid Build Coastguard Worker {
4774*8975f5c5SAndroid Build Coastguard Worker     return popDebugGroupImpl();
4775*8975f5c5SAndroid Build Coastguard Worker }
4776*8975f5c5SAndroid Build Coastguard Worker 
pushDebugGroup(const gl::Context * context,GLenum source,GLuint id,const std::string & message)4777*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::pushDebugGroup(const gl::Context *context,
4778*8975f5c5SAndroid Build Coastguard Worker                                         GLenum source,
4779*8975f5c5SAndroid Build Coastguard Worker                                         GLuint id,
4780*8975f5c5SAndroid Build Coastguard Worker                                         const std::string &message)
4781*8975f5c5SAndroid Build Coastguard Worker {
4782*8975f5c5SAndroid Build Coastguard Worker     return pushDebugGroupImpl(source, id, message.c_str());
4783*8975f5c5SAndroid Build Coastguard Worker }
4784*8975f5c5SAndroid Build Coastguard Worker 
popDebugGroup(const gl::Context * context)4785*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::popDebugGroup(const gl::Context *context)
4786*8975f5c5SAndroid Build Coastguard Worker {
4787*8975f5c5SAndroid Build Coastguard Worker     return popDebugGroupImpl();
4788*8975f5c5SAndroid Build Coastguard Worker }
4789*8975f5c5SAndroid Build Coastguard Worker 
pushDebugGroupImpl(GLenum source,GLuint id,const char * message)4790*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::pushDebugGroupImpl(GLenum source, GLuint id, const char *message)
4791*8975f5c5SAndroid Build Coastguard Worker {
4792*8975f5c5SAndroid Build Coastguard Worker     if (!isDebugEnabled())
4793*8975f5c5SAndroid Build Coastguard Worker     {
4794*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
4795*8975f5c5SAndroid Build Coastguard Worker     }
4796*8975f5c5SAndroid Build Coastguard Worker 
4797*8975f5c5SAndroid Build Coastguard Worker     VkDebugUtilsLabelEXT label;
4798*8975f5c5SAndroid Build Coastguard Worker     vk::MakeDebugUtilsLabel(source, message, &label);
4799*8975f5c5SAndroid Build Coastguard Worker 
4800*8975f5c5SAndroid Build Coastguard Worker     if (hasActiveRenderPass())
4801*8975f5c5SAndroid Build Coastguard Worker     {
4802*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommandBuffer->beginDebugUtilsLabelEXT(label);
4803*8975f5c5SAndroid Build Coastguard Worker     }
4804*8975f5c5SAndroid Build Coastguard Worker     else
4805*8975f5c5SAndroid Build Coastguard Worker     {
4806*8975f5c5SAndroid Build Coastguard Worker         mOutsideRenderPassCommands->getCommandBuffer().beginDebugUtilsLabelEXT(label);
4807*8975f5c5SAndroid Build Coastguard Worker     }
4808*8975f5c5SAndroid Build Coastguard Worker 
4809*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4810*8975f5c5SAndroid Build Coastguard Worker }
4811*8975f5c5SAndroid Build Coastguard Worker 
popDebugGroupImpl()4812*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::popDebugGroupImpl()
4813*8975f5c5SAndroid Build Coastguard Worker {
4814*8975f5c5SAndroid Build Coastguard Worker     if (!isDebugEnabled())
4815*8975f5c5SAndroid Build Coastguard Worker     {
4816*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
4817*8975f5c5SAndroid Build Coastguard Worker     }
4818*8975f5c5SAndroid Build Coastguard Worker 
4819*8975f5c5SAndroid Build Coastguard Worker     if (hasActiveRenderPass())
4820*8975f5c5SAndroid Build Coastguard Worker     {
4821*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommandBuffer->endDebugUtilsLabelEXT();
4822*8975f5c5SAndroid Build Coastguard Worker     }
4823*8975f5c5SAndroid Build Coastguard Worker     else
4824*8975f5c5SAndroid Build Coastguard Worker     {
4825*8975f5c5SAndroid Build Coastguard Worker         mOutsideRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
4826*8975f5c5SAndroid Build Coastguard Worker     }
4827*8975f5c5SAndroid Build Coastguard Worker 
4828*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
4829*8975f5c5SAndroid Build Coastguard Worker }
4830*8975f5c5SAndroid Build Coastguard Worker 
logEvent(const char * eventString)4831*8975f5c5SAndroid Build Coastguard Worker void ContextVk::logEvent(const char *eventString)
4832*8975f5c5SAndroid Build Coastguard Worker {
4833*8975f5c5SAndroid Build Coastguard Worker     if (!mRenderer->angleDebuggerMode())
4834*8975f5c5SAndroid Build Coastguard Worker     {
4835*8975f5c5SAndroid Build Coastguard Worker         return;
4836*8975f5c5SAndroid Build Coastguard Worker     }
4837*8975f5c5SAndroid Build Coastguard Worker 
4838*8975f5c5SAndroid Build Coastguard Worker     // Save this event (about an OpenGL ES command being called).
4839*8975f5c5SAndroid Build Coastguard Worker     mEventLog.push_back(eventString);
4840*8975f5c5SAndroid Build Coastguard Worker 
4841*8975f5c5SAndroid Build Coastguard Worker     // Set a dirty bit in order to stay off the "hot path" for when not logging.
4842*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits.set(DIRTY_BIT_EVENT_LOG);
4843*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBits.set(DIRTY_BIT_EVENT_LOG);
4844*8975f5c5SAndroid Build Coastguard Worker }
4845*8975f5c5SAndroid Build Coastguard Worker 
endEventLog(angle::EntryPoint entryPoint,PipelineType pipelineType)4846*8975f5c5SAndroid Build Coastguard Worker void ContextVk::endEventLog(angle::EntryPoint entryPoint, PipelineType pipelineType)
4847*8975f5c5SAndroid Build Coastguard Worker {
4848*8975f5c5SAndroid Build Coastguard Worker     if (!mRenderer->angleDebuggerMode())
4849*8975f5c5SAndroid Build Coastguard Worker     {
4850*8975f5c5SAndroid Build Coastguard Worker         return;
4851*8975f5c5SAndroid Build Coastguard Worker     }
4852*8975f5c5SAndroid Build Coastguard Worker 
4853*8975f5c5SAndroid Build Coastguard Worker     if (pipelineType == PipelineType::Graphics)
4854*8975f5c5SAndroid Build Coastguard Worker     {
4855*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mRenderPassCommands);
4856*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
4857*8975f5c5SAndroid Build Coastguard Worker     }
4858*8975f5c5SAndroid Build Coastguard Worker     else
4859*8975f5c5SAndroid Build Coastguard Worker     {
4860*8975f5c5SAndroid Build Coastguard Worker         ASSERT(pipelineType == PipelineType::Compute);
4861*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mOutsideRenderPassCommands);
4862*8975f5c5SAndroid Build Coastguard Worker         mOutsideRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
4863*8975f5c5SAndroid Build Coastguard Worker     }
4864*8975f5c5SAndroid Build Coastguard Worker }
endEventLogForClearOrQuery()4865*8975f5c5SAndroid Build Coastguard Worker void ContextVk::endEventLogForClearOrQuery()
4866*8975f5c5SAndroid Build Coastguard Worker {
4867*8975f5c5SAndroid Build Coastguard Worker     if (!mRenderer->angleDebuggerMode())
4868*8975f5c5SAndroid Build Coastguard Worker     {
4869*8975f5c5SAndroid Build Coastguard Worker         return;
4870*8975f5c5SAndroid Build Coastguard Worker     }
4871*8975f5c5SAndroid Build Coastguard Worker 
4872*8975f5c5SAndroid Build Coastguard Worker     switch (mQueryEventType)
4873*8975f5c5SAndroid Build Coastguard Worker     {
4874*8975f5c5SAndroid Build Coastguard Worker         case GraphicsEventCmdBuf::InOutsideCmdBufQueryCmd:
4875*8975f5c5SAndroid Build Coastguard Worker             ASSERT(mOutsideRenderPassCommands);
4876*8975f5c5SAndroid Build Coastguard Worker             mOutsideRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
4877*8975f5c5SAndroid Build Coastguard Worker             break;
4878*8975f5c5SAndroid Build Coastguard Worker         case GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd:
4879*8975f5c5SAndroid Build Coastguard Worker             ASSERT(mRenderPassCommands);
4880*8975f5c5SAndroid Build Coastguard Worker             mRenderPassCommands->getCommandBuffer().endDebugUtilsLabelEXT();
4881*8975f5c5SAndroid Build Coastguard Worker             break;
4882*8975f5c5SAndroid Build Coastguard Worker         case GraphicsEventCmdBuf::NotInQueryCmd:
4883*8975f5c5SAndroid Build Coastguard Worker             // The glClear* or gl*Query* command was noop'd or otherwise ended early.  We could
4884*8975f5c5SAndroid Build Coastguard Worker             // call handleDirtyEventLogImpl() to start the hierarchy, but it isn't clear which (if
4885*8975f5c5SAndroid Build Coastguard Worker             // any) command buffer to use.  We'll just skip processing this command (other than to
4886*8975f5c5SAndroid Build Coastguard Worker             // let it stay queued for the next time handleDirtyEventLogImpl() is called.
4887*8975f5c5SAndroid Build Coastguard Worker             return;
4888*8975f5c5SAndroid Build Coastguard Worker         default:
4889*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
4890*8975f5c5SAndroid Build Coastguard Worker     }
4891*8975f5c5SAndroid Build Coastguard Worker 
4892*8975f5c5SAndroid Build Coastguard Worker     mQueryEventType = GraphicsEventCmdBuf::NotInQueryCmd;
4893*8975f5c5SAndroid Build Coastguard Worker }
4894*8975f5c5SAndroid Build Coastguard Worker 
handleNoopDrawEvent()4895*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleNoopDrawEvent()
4896*8975f5c5SAndroid Build Coastguard Worker {
4897*8975f5c5SAndroid Build Coastguard Worker     // Even though this draw call is being no-op'd, we still must handle the dirty event log
4898*8975f5c5SAndroid Build Coastguard Worker     return handleDirtyEventLogImpl(mRenderPassCommandBuffer);
4899*8975f5c5SAndroid Build Coastguard Worker }
4900*8975f5c5SAndroid Build Coastguard Worker 
handleGraphicsEventLog(GraphicsEventCmdBuf queryEventType)4901*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleGraphicsEventLog(GraphicsEventCmdBuf queryEventType)
4902*8975f5c5SAndroid Build Coastguard Worker {
4903*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mQueryEventType == GraphicsEventCmdBuf::NotInQueryCmd || mEventLog.empty());
4904*8975f5c5SAndroid Build Coastguard Worker     if (!mRenderer->angleDebuggerMode())
4905*8975f5c5SAndroid Build Coastguard Worker     {
4906*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
4907*8975f5c5SAndroid Build Coastguard Worker     }
4908*8975f5c5SAndroid Build Coastguard Worker 
4909*8975f5c5SAndroid Build Coastguard Worker     mQueryEventType = queryEventType;
4910*8975f5c5SAndroid Build Coastguard Worker 
4911*8975f5c5SAndroid Build Coastguard Worker     switch (mQueryEventType)
4912*8975f5c5SAndroid Build Coastguard Worker     {
4913*8975f5c5SAndroid Build Coastguard Worker         case GraphicsEventCmdBuf::InOutsideCmdBufQueryCmd:
4914*8975f5c5SAndroid Build Coastguard Worker             ASSERT(mOutsideRenderPassCommands);
4915*8975f5c5SAndroid Build Coastguard Worker             return handleDirtyEventLogImpl(&mOutsideRenderPassCommands->getCommandBuffer());
4916*8975f5c5SAndroid Build Coastguard Worker         case GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd:
4917*8975f5c5SAndroid Build Coastguard Worker             ASSERT(mRenderPassCommands);
4918*8975f5c5SAndroid Build Coastguard Worker             return handleDirtyEventLogImpl(&mRenderPassCommands->getCommandBuffer());
4919*8975f5c5SAndroid Build Coastguard Worker         default:
4920*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
4921*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
4922*8975f5c5SAndroid Build Coastguard Worker     }
4923*8975f5c5SAndroid Build Coastguard Worker }
4924*8975f5c5SAndroid Build Coastguard Worker 
isViewportFlipEnabledForDrawFBO() const4925*8975f5c5SAndroid Build Coastguard Worker bool ContextVk::isViewportFlipEnabledForDrawFBO() const
4926*8975f5c5SAndroid Build Coastguard Worker {
4927*8975f5c5SAndroid Build Coastguard Worker     return mFlipViewportForDrawFramebuffer && mFlipYForCurrentSurface;
4928*8975f5c5SAndroid Build Coastguard Worker }
4929*8975f5c5SAndroid Build Coastguard Worker 
isViewportFlipEnabledForReadFBO() const4930*8975f5c5SAndroid Build Coastguard Worker bool ContextVk::isViewportFlipEnabledForReadFBO() const
4931*8975f5c5SAndroid Build Coastguard Worker {
4932*8975f5c5SAndroid Build Coastguard Worker     return mFlipViewportForReadFramebuffer;
4933*8975f5c5SAndroid Build Coastguard Worker }
4934*8975f5c5SAndroid Build Coastguard Worker 
isRotatedAspectRatioForDrawFBO() const4935*8975f5c5SAndroid Build Coastguard Worker bool ContextVk::isRotatedAspectRatioForDrawFBO() const
4936*8975f5c5SAndroid Build Coastguard Worker {
4937*8975f5c5SAndroid Build Coastguard Worker     return IsRotatedAspectRatio(mCurrentRotationDrawFramebuffer);
4938*8975f5c5SAndroid Build Coastguard Worker }
4939*8975f5c5SAndroid Build Coastguard Worker 
isRotatedAspectRatioForReadFBO() const4940*8975f5c5SAndroid Build Coastguard Worker bool ContextVk::isRotatedAspectRatioForReadFBO() const
4941*8975f5c5SAndroid Build Coastguard Worker {
4942*8975f5c5SAndroid Build Coastguard Worker     return IsRotatedAspectRatio(mCurrentRotationReadFramebuffer);
4943*8975f5c5SAndroid Build Coastguard Worker }
4944*8975f5c5SAndroid Build Coastguard Worker 
getRotationDrawFramebuffer() const4945*8975f5c5SAndroid Build Coastguard Worker SurfaceRotation ContextVk::getRotationDrawFramebuffer() const
4946*8975f5c5SAndroid Build Coastguard Worker {
4947*8975f5c5SAndroid Build Coastguard Worker     return mCurrentRotationDrawFramebuffer;
4948*8975f5c5SAndroid Build Coastguard Worker }
4949*8975f5c5SAndroid Build Coastguard Worker 
getRotationReadFramebuffer() const4950*8975f5c5SAndroid Build Coastguard Worker SurfaceRotation ContextVk::getRotationReadFramebuffer() const
4951*8975f5c5SAndroid Build Coastguard Worker {
4952*8975f5c5SAndroid Build Coastguard Worker     return mCurrentRotationReadFramebuffer;
4953*8975f5c5SAndroid Build Coastguard Worker }
4954*8975f5c5SAndroid Build Coastguard Worker 
getSurfaceRotationImpl(const gl::Framebuffer * framebuffer,const egl::Surface * surface)4955*8975f5c5SAndroid Build Coastguard Worker SurfaceRotation ContextVk::getSurfaceRotationImpl(const gl::Framebuffer *framebuffer,
4956*8975f5c5SAndroid Build Coastguard Worker                                                   const egl::Surface *surface)
4957*8975f5c5SAndroid Build Coastguard Worker {
4958*8975f5c5SAndroid Build Coastguard Worker     SurfaceRotation surfaceRotation = SurfaceRotation::Identity;
4959*8975f5c5SAndroid Build Coastguard Worker     if (surface && surface->getType() == EGL_WINDOW_BIT)
4960*8975f5c5SAndroid Build Coastguard Worker     {
4961*8975f5c5SAndroid Build Coastguard Worker         const WindowSurfaceVk *windowSurface = GetImplAs<WindowSurfaceVk>(surface);
4962*8975f5c5SAndroid Build Coastguard Worker         surfaceRotation                      = DetermineSurfaceRotation(framebuffer, windowSurface);
4963*8975f5c5SAndroid Build Coastguard Worker     }
4964*8975f5c5SAndroid Build Coastguard Worker     return surfaceRotation;
4965*8975f5c5SAndroid Build Coastguard Worker }
4966*8975f5c5SAndroid Build Coastguard Worker 
updateColorMasks()4967*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateColorMasks()
4968*8975f5c5SAndroid Build Coastguard Worker {
4969*8975f5c5SAndroid Build Coastguard Worker     const gl::BlendStateExt &blendStateExt = mState.getBlendStateExt();
4970*8975f5c5SAndroid Build Coastguard Worker 
4971*8975f5c5SAndroid Build Coastguard Worker     mClearColorMasks = blendStateExt.getColorMaskBits();
4972*8975f5c5SAndroid Build Coastguard Worker 
4973*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *framebufferVk = vk::GetImpl(mState.getDrawFramebuffer());
4974*8975f5c5SAndroid Build Coastguard Worker     mGraphicsPipelineDesc->updateColorWriteMasks(&mGraphicsPipelineTransition, mClearColorMasks,
4975*8975f5c5SAndroid Build Coastguard Worker                                                  framebufferVk->getEmulatedAlphaAttachmentMask(),
4976*8975f5c5SAndroid Build Coastguard Worker                                                  framebufferVk->getState().getEnabledDrawBuffers());
4977*8975f5c5SAndroid Build Coastguard Worker 
4978*8975f5c5SAndroid Build Coastguard Worker     // This function may be called outside of ContextVk::syncState, and so invalidates the graphics
4979*8975f5c5SAndroid Build Coastguard Worker     // pipeline.
4980*8975f5c5SAndroid Build Coastguard Worker     invalidateCurrentGraphicsPipeline();
4981*8975f5c5SAndroid Build Coastguard Worker 
4982*8975f5c5SAndroid Build Coastguard Worker     onColorAccessChange();
4983*8975f5c5SAndroid Build Coastguard Worker }
4984*8975f5c5SAndroid Build Coastguard Worker 
updateMissingOutputsMask()4985*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateMissingOutputsMask()
4986*8975f5c5SAndroid Build Coastguard Worker {
4987*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
4988*8975f5c5SAndroid Build Coastguard Worker     if (executable == nullptr)
4989*8975f5c5SAndroid Build Coastguard Worker     {
4990*8975f5c5SAndroid Build Coastguard Worker         return;
4991*8975f5c5SAndroid Build Coastguard Worker     }
4992*8975f5c5SAndroid Build Coastguard Worker 
4993*8975f5c5SAndroid Build Coastguard Worker     const gl::DrawBufferMask framebufferMask    = mState.getDrawFramebuffer()->getDrawBufferMask();
4994*8975f5c5SAndroid Build Coastguard Worker     const gl::DrawBufferMask shaderOutMask      = executable->getActiveOutputVariablesMask();
4995*8975f5c5SAndroid Build Coastguard Worker     const gl::DrawBufferMask missingOutputsMask = ~shaderOutMask & framebufferMask;
4996*8975f5c5SAndroid Build Coastguard Worker 
4997*8975f5c5SAndroid Build Coastguard Worker     mGraphicsPipelineDesc->updateMissingOutputsMask(&mGraphicsPipelineTransition,
4998*8975f5c5SAndroid Build Coastguard Worker                                                     missingOutputsMask);
4999*8975f5c5SAndroid Build Coastguard Worker }
5000*8975f5c5SAndroid Build Coastguard Worker 
updateBlendFuncsAndEquations()5001*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateBlendFuncsAndEquations()
5002*8975f5c5SAndroid Build Coastguard Worker {
5003*8975f5c5SAndroid Build Coastguard Worker     const gl::BlendStateExt &blendStateExt = mState.getBlendStateExt();
5004*8975f5c5SAndroid Build Coastguard Worker 
5005*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *framebufferVk              = vk::GetImpl(mState.getDrawFramebuffer());
5006*8975f5c5SAndroid Build Coastguard Worker     mCachedDrawFramebufferColorAttachmentMask = framebufferVk->getState().getEnabledDrawBuffers();
5007*8975f5c5SAndroid Build Coastguard Worker 
5008*8975f5c5SAndroid Build Coastguard Worker     mGraphicsPipelineDesc->updateBlendFuncs(&mGraphicsPipelineTransition, blendStateExt,
5009*8975f5c5SAndroid Build Coastguard Worker                                             mCachedDrawFramebufferColorAttachmentMask);
5010*8975f5c5SAndroid Build Coastguard Worker 
5011*8975f5c5SAndroid Build Coastguard Worker     mGraphicsPipelineDesc->updateBlendEquations(&mGraphicsPipelineTransition, blendStateExt,
5012*8975f5c5SAndroid Build Coastguard Worker                                                 mCachedDrawFramebufferColorAttachmentMask);
5013*8975f5c5SAndroid Build Coastguard Worker 
5014*8975f5c5SAndroid Build Coastguard Worker     // This function may be called outside of ContextVk::syncState, and so invalidates the graphics
5015*8975f5c5SAndroid Build Coastguard Worker     // pipeline.
5016*8975f5c5SAndroid Build Coastguard Worker     invalidateCurrentGraphicsPipeline();
5017*8975f5c5SAndroid Build Coastguard Worker }
5018*8975f5c5SAndroid Build Coastguard Worker 
updateSampleMaskWithRasterizationSamples(const uint32_t rasterizationSamples)5019*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateSampleMaskWithRasterizationSamples(const uint32_t rasterizationSamples)
5020*8975f5c5SAndroid Build Coastguard Worker {
5021*8975f5c5SAndroid Build Coastguard Worker     static_assert(sizeof(uint32_t) == sizeof(GLbitfield), "Vulkan assumes 32-bit sample masks");
5022*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.getMaxSampleMaskWords() == 1);
5023*8975f5c5SAndroid Build Coastguard Worker 
5024*8975f5c5SAndroid Build Coastguard Worker     uint32_t mask = std::numeric_limits<uint16_t>::max();
5025*8975f5c5SAndroid Build Coastguard Worker 
5026*8975f5c5SAndroid Build Coastguard Worker     // The following assumes that supported sample counts for multisampled
5027*8975f5c5SAndroid Build Coastguard Worker     // rendering does not include 1. This is true in the Vulkan backend,
5028*8975f5c5SAndroid Build Coastguard Worker     // where 1x multisampling is disallowed.
5029*8975f5c5SAndroid Build Coastguard Worker     if (rasterizationSamples > 1)
5030*8975f5c5SAndroid Build Coastguard Worker     {
5031*8975f5c5SAndroid Build Coastguard Worker         if (mState.isSampleMaskEnabled())
5032*8975f5c5SAndroid Build Coastguard Worker         {
5033*8975f5c5SAndroid Build Coastguard Worker             mask = mState.getSampleMaskWord(0) & angle::BitMask<uint32_t>(rasterizationSamples);
5034*8975f5c5SAndroid Build Coastguard Worker         }
5035*8975f5c5SAndroid Build Coastguard Worker 
5036*8975f5c5SAndroid Build Coastguard Worker         // If sample coverage is enabled, emulate it by generating and applying a mask on top of the
5037*8975f5c5SAndroid Build Coastguard Worker         // sample mask.
5038*8975f5c5SAndroid Build Coastguard Worker         if (mState.isSampleCoverageEnabled())
5039*8975f5c5SAndroid Build Coastguard Worker         {
5040*8975f5c5SAndroid Build Coastguard Worker             ApplySampleCoverage(mState, GetCoverageSampleCount(mState, rasterizationSamples),
5041*8975f5c5SAndroid Build Coastguard Worker                                 &mask);
5042*8975f5c5SAndroid Build Coastguard Worker         }
5043*8975f5c5SAndroid Build Coastguard Worker     }
5044*8975f5c5SAndroid Build Coastguard Worker 
5045*8975f5c5SAndroid Build Coastguard Worker     mGraphicsPipelineDesc->updateSampleMask(&mGraphicsPipelineTransition, 0, mask);
5046*8975f5c5SAndroid Build Coastguard Worker }
5047*8975f5c5SAndroid Build Coastguard Worker 
updateAlphaToCoverageWithRasterizationSamples(const uint32_t rasterizationSamples)5048*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateAlphaToCoverageWithRasterizationSamples(const uint32_t rasterizationSamples)
5049*8975f5c5SAndroid Build Coastguard Worker {
5050*8975f5c5SAndroid Build Coastguard Worker     // The following assumes that supported sample counts for multisampled
5051*8975f5c5SAndroid Build Coastguard Worker     // rendering does not include 1. This is true in the Vulkan backend,
5052*8975f5c5SAndroid Build Coastguard Worker     // where 1x multisampling is disallowed.
5053*8975f5c5SAndroid Build Coastguard Worker     mGraphicsPipelineDesc->updateAlphaToCoverageEnable(
5054*8975f5c5SAndroid Build Coastguard Worker         &mGraphicsPipelineTransition,
5055*8975f5c5SAndroid Build Coastguard Worker         mState.isSampleAlphaToCoverageEnabled() && rasterizationSamples > 1);
5056*8975f5c5SAndroid Build Coastguard Worker }
5057*8975f5c5SAndroid Build Coastguard Worker 
updateFrameBufferFetchSamples(const uint32_t prevSamples,const uint32_t curSamples)5058*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateFrameBufferFetchSamples(const uint32_t prevSamples, const uint32_t curSamples)
5059*8975f5c5SAndroid Build Coastguard Worker {
5060*8975f5c5SAndroid Build Coastguard Worker     const bool isPrevMultisampled = prevSamples > 1;
5061*8975f5c5SAndroid Build Coastguard Worker     const bool isCurMultisampled  = curSamples > 1;
5062*8975f5c5SAndroid Build Coastguard Worker     if (isPrevMultisampled != isCurMultisampled)
5063*8975f5c5SAndroid Build Coastguard Worker     {
5064*8975f5c5SAndroid Build Coastguard Worker         // If we change from single sample to multisample, we need to use the Shader Program with
5065*8975f5c5SAndroid Build Coastguard Worker         // ProgramTransformOptions.multisampleFramebufferFetch == true. Invalidate the graphics
5066*8975f5c5SAndroid Build Coastguard Worker         // pipeline so that we can fetch the shader with the correct permutation option in
5067*8975f5c5SAndroid Build Coastguard Worker         // handleDirtyGraphicsPipelineDesc()
5068*8975f5c5SAndroid Build Coastguard Worker         invalidateCurrentGraphicsPipeline();
5069*8975f5c5SAndroid Build Coastguard Worker     }
5070*8975f5c5SAndroid Build Coastguard Worker }
5071*8975f5c5SAndroid Build Coastguard Worker 
getCorrectedViewport(const gl::Rectangle & viewport) const5072*8975f5c5SAndroid Build Coastguard Worker gl::Rectangle ContextVk::getCorrectedViewport(const gl::Rectangle &viewport) const
5073*8975f5c5SAndroid Build Coastguard Worker {
5074*8975f5c5SAndroid Build Coastguard Worker     const gl::Caps &caps                   = getCaps();
5075*8975f5c5SAndroid Build Coastguard Worker     const VkPhysicalDeviceLimits &limitsVk = mRenderer->getPhysicalDeviceProperties().limits;
5076*8975f5c5SAndroid Build Coastguard Worker     const int viewportBoundsRangeLow       = static_cast<int>(limitsVk.viewportBoundsRange[0]);
5077*8975f5c5SAndroid Build Coastguard Worker     const int viewportBoundsRangeHigh      = static_cast<int>(limitsVk.viewportBoundsRange[1]);
5078*8975f5c5SAndroid Build Coastguard Worker 
5079*8975f5c5SAndroid Build Coastguard Worker     // Clamp the viewport values to what Vulkan specifies
5080*8975f5c5SAndroid Build Coastguard Worker 
5081*8975f5c5SAndroid Build Coastguard Worker     // width must be greater than 0.0 and less than or equal to
5082*8975f5c5SAndroid Build Coastguard Worker     // VkPhysicalDeviceLimits::maxViewportDimensions[0]
5083*8975f5c5SAndroid Build Coastguard Worker     int correctedWidth = std::min<int>(viewport.width, caps.maxViewportWidth);
5084*8975f5c5SAndroid Build Coastguard Worker     correctedWidth     = std::max<int>(correctedWidth, 0);
5085*8975f5c5SAndroid Build Coastguard Worker     // height must be greater than 0.0 and less than or equal to
5086*8975f5c5SAndroid Build Coastguard Worker     // VkPhysicalDeviceLimits::maxViewportDimensions[1]
5087*8975f5c5SAndroid Build Coastguard Worker     int correctedHeight = std::min<int>(viewport.height, caps.maxViewportHeight);
5088*8975f5c5SAndroid Build Coastguard Worker     correctedHeight     = std::max<int>(correctedHeight, 0);
5089*8975f5c5SAndroid Build Coastguard Worker     // x and y must each be between viewportBoundsRange[0] and viewportBoundsRange[1], inclusive.
5090*8975f5c5SAndroid Build Coastguard Worker     // Viewport size cannot be 0 so ensure there is always size for a 1x1 viewport
5091*8975f5c5SAndroid Build Coastguard Worker     int correctedX = std::min<int>(viewport.x, viewportBoundsRangeHigh - 1);
5092*8975f5c5SAndroid Build Coastguard Worker     correctedX     = std::max<int>(correctedX, viewportBoundsRangeLow);
5093*8975f5c5SAndroid Build Coastguard Worker     int correctedY = std::min<int>(viewport.y, viewportBoundsRangeHigh - 1);
5094*8975f5c5SAndroid Build Coastguard Worker     correctedY     = std::max<int>(correctedY, viewportBoundsRangeLow);
5095*8975f5c5SAndroid Build Coastguard Worker     // x + width must be less than or equal to viewportBoundsRange[1]
5096*8975f5c5SAndroid Build Coastguard Worker     if ((correctedX + correctedWidth) > viewportBoundsRangeHigh)
5097*8975f5c5SAndroid Build Coastguard Worker     {
5098*8975f5c5SAndroid Build Coastguard Worker         correctedWidth = viewportBoundsRangeHigh - correctedX;
5099*8975f5c5SAndroid Build Coastguard Worker     }
5100*8975f5c5SAndroid Build Coastguard Worker     // y + height must be less than or equal to viewportBoundsRange[1]
5101*8975f5c5SAndroid Build Coastguard Worker     if ((correctedY + correctedHeight) > viewportBoundsRangeHigh)
5102*8975f5c5SAndroid Build Coastguard Worker     {
5103*8975f5c5SAndroid Build Coastguard Worker         correctedHeight = viewportBoundsRangeHigh - correctedY;
5104*8975f5c5SAndroid Build Coastguard Worker     }
5105*8975f5c5SAndroid Build Coastguard Worker 
5106*8975f5c5SAndroid Build Coastguard Worker     return gl::Rectangle(correctedX, correctedY, correctedWidth, correctedHeight);
5107*8975f5c5SAndroid Build Coastguard Worker }
5108*8975f5c5SAndroid Build Coastguard Worker 
updateViewport(FramebufferVk * framebufferVk,const gl::Rectangle & viewport,float nearPlane,float farPlane)5109*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateViewport(FramebufferVk *framebufferVk,
5110*8975f5c5SAndroid Build Coastguard Worker                                const gl::Rectangle &viewport,
5111*8975f5c5SAndroid Build Coastguard Worker                                float nearPlane,
5112*8975f5c5SAndroid Build Coastguard Worker                                float farPlane)
5113*8975f5c5SAndroid Build Coastguard Worker {
5114*8975f5c5SAndroid Build Coastguard Worker 
5115*8975f5c5SAndroid Build Coastguard Worker     gl::Box fbDimensions        = framebufferVk->getState().getDimensions();
5116*8975f5c5SAndroid Build Coastguard Worker     gl::Rectangle correctedRect = getCorrectedViewport(viewport);
5117*8975f5c5SAndroid Build Coastguard Worker     gl::Rectangle rotatedRect;
5118*8975f5c5SAndroid Build Coastguard Worker     RotateRectangle(getRotationDrawFramebuffer(), false, fbDimensions.width, fbDimensions.height,
5119*8975f5c5SAndroid Build Coastguard Worker                     correctedRect, &rotatedRect);
5120*8975f5c5SAndroid Build Coastguard Worker 
5121*8975f5c5SAndroid Build Coastguard Worker     const bool invertViewport = isViewportFlipEnabledForDrawFBO();
5122*8975f5c5SAndroid Build Coastguard Worker 
5123*8975f5c5SAndroid Build Coastguard Worker     gl_vk::GetViewport(
5124*8975f5c5SAndroid Build Coastguard Worker         rotatedRect, nearPlane, farPlane, invertViewport,
5125*8975f5c5SAndroid Build Coastguard Worker         // If clip space origin is upper left, viewport origin's y value will be offset by the
5126*8975f5c5SAndroid Build Coastguard Worker         // height of the viewport when clip space is mapped into screen space.
5127*8975f5c5SAndroid Build Coastguard Worker         mState.getClipOrigin() == gl::ClipOrigin::UpperLeft,
5128*8975f5c5SAndroid Build Coastguard Worker         // If the surface is rotated 90/270 degrees, use the framebuffer's width instead of the
5129*8975f5c5SAndroid Build Coastguard Worker         // height for calculating the final viewport.
5130*8975f5c5SAndroid Build Coastguard Worker         isRotatedAspectRatioForDrawFBO() ? fbDimensions.width : fbDimensions.height, &mViewport);
5131*8975f5c5SAndroid Build Coastguard Worker 
5132*8975f5c5SAndroid Build Coastguard Worker     // Ensure viewport is within Vulkan requirements
5133*8975f5c5SAndroid Build Coastguard Worker     vk::ClampViewport(&mViewport);
5134*8975f5c5SAndroid Build Coastguard Worker 
5135*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_VIEWPORT);
5136*8975f5c5SAndroid Build Coastguard Worker }
5137*8975f5c5SAndroid Build Coastguard Worker 
updateFrontFace()5138*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateFrontFace()
5139*8975f5c5SAndroid Build Coastguard Worker {
5140*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useFrontFaceDynamicState.enabled)
5141*8975f5c5SAndroid Build Coastguard Worker     {
5142*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_FRONT_FACE);
5143*8975f5c5SAndroid Build Coastguard Worker     }
5144*8975f5c5SAndroid Build Coastguard Worker     else
5145*8975f5c5SAndroid Build Coastguard Worker     {
5146*8975f5c5SAndroid Build Coastguard Worker         mGraphicsPipelineDesc->updateFrontFace(
5147*8975f5c5SAndroid Build Coastguard Worker             &mGraphicsPipelineTransition, mState.getRasterizerState(), isYFlipEnabledForDrawFBO());
5148*8975f5c5SAndroid Build Coastguard Worker     }
5149*8975f5c5SAndroid Build Coastguard Worker }
5150*8975f5c5SAndroid Build Coastguard Worker 
updateDepthRange(float nearPlane,float farPlane)5151*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateDepthRange(float nearPlane, float farPlane)
5152*8975f5c5SAndroid Build Coastguard Worker {
5153*8975f5c5SAndroid Build Coastguard Worker     // GLES2.0 Section 2.12.1: Each of n and f are clamped to lie within [0, 1], as are all
5154*8975f5c5SAndroid Build Coastguard Worker     // arguments of type clampf.
5155*8975f5c5SAndroid Build Coastguard Worker     ASSERT(nearPlane >= 0.0f && nearPlane <= 1.0f);
5156*8975f5c5SAndroid Build Coastguard Worker     ASSERT(farPlane >= 0.0f && farPlane <= 1.0f);
5157*8975f5c5SAndroid Build Coastguard Worker     mViewport.minDepth = nearPlane;
5158*8975f5c5SAndroid Build Coastguard Worker     mViewport.maxDepth = farPlane;
5159*8975f5c5SAndroid Build Coastguard Worker 
5160*8975f5c5SAndroid Build Coastguard Worker     invalidateGraphicsDriverUniforms();
5161*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_VIEWPORT);
5162*8975f5c5SAndroid Build Coastguard Worker }
5163*8975f5c5SAndroid Build Coastguard Worker 
updateScissor(const gl::State & glState)5164*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateScissor(const gl::State &glState)
5165*8975f5c5SAndroid Build Coastguard Worker {
5166*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer());
5167*8975f5c5SAndroid Build Coastguard Worker     gl::Rectangle renderArea     = framebufferVk->getNonRotatedCompleteRenderArea();
5168*8975f5c5SAndroid Build Coastguard Worker 
5169*8975f5c5SAndroid Build Coastguard Worker     // Clip the render area to the viewport.
5170*8975f5c5SAndroid Build Coastguard Worker     gl::Rectangle viewportClippedRenderArea;
5171*8975f5c5SAndroid Build Coastguard Worker     if (!gl::ClipRectangle(renderArea, getCorrectedViewport(glState.getViewport()),
5172*8975f5c5SAndroid Build Coastguard Worker                            &viewportClippedRenderArea))
5173*8975f5c5SAndroid Build Coastguard Worker     {
5174*8975f5c5SAndroid Build Coastguard Worker         viewportClippedRenderArea = gl::Rectangle();
5175*8975f5c5SAndroid Build Coastguard Worker     }
5176*8975f5c5SAndroid Build Coastguard Worker 
5177*8975f5c5SAndroid Build Coastguard Worker     gl::Rectangle scissoredArea = ClipRectToScissor(getState(), viewportClippedRenderArea, false);
5178*8975f5c5SAndroid Build Coastguard Worker     gl::Rectangle rotatedScissoredArea;
5179*8975f5c5SAndroid Build Coastguard Worker     RotateRectangle(getRotationDrawFramebuffer(), isViewportFlipEnabledForDrawFBO(),
5180*8975f5c5SAndroid Build Coastguard Worker                     renderArea.width, renderArea.height, scissoredArea, &rotatedScissoredArea);
5181*8975f5c5SAndroid Build Coastguard Worker     mScissor = gl_vk::GetRect(rotatedScissoredArea);
5182*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_SCISSOR);
5183*8975f5c5SAndroid Build Coastguard Worker 
5184*8975f5c5SAndroid Build Coastguard Worker     // If the scissor has grown beyond the previous scissoredRenderArea, grow the render pass render
5185*8975f5c5SAndroid Build Coastguard Worker     // area.  The only undesirable effect this may have is that if the render area does not cover a
5186*8975f5c5SAndroid Build Coastguard Worker     // previously invalidated area, that invalidate will have to be discarded.
5187*8975f5c5SAndroid Build Coastguard Worker     if (mRenderPassCommandBuffer &&
5188*8975f5c5SAndroid Build Coastguard Worker         !mRenderPassCommands->getRenderArea().encloses(rotatedScissoredArea))
5189*8975f5c5SAndroid Build Coastguard Worker     {
5190*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mRenderPassCommands->started());
5191*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommands->growRenderArea(this, rotatedScissoredArea);
5192*8975f5c5SAndroid Build Coastguard Worker     }
5193*8975f5c5SAndroid Build Coastguard Worker }
5194*8975f5c5SAndroid Build Coastguard Worker 
updateDepthStencil(const gl::State & glState)5195*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateDepthStencil(const gl::State &glState)
5196*8975f5c5SAndroid Build Coastguard Worker {
5197*8975f5c5SAndroid Build Coastguard Worker     updateDepthTestEnabled(glState);
5198*8975f5c5SAndroid Build Coastguard Worker     updateDepthWriteEnabled(glState);
5199*8975f5c5SAndroid Build Coastguard Worker     updateStencilTestEnabled(glState);
5200*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_WRITE_MASK);
5201*8975f5c5SAndroid Build Coastguard Worker }
5202*8975f5c5SAndroid Build Coastguard Worker 
updateDepthTestEnabled(const gl::State & glState)5203*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateDepthTestEnabled(const gl::State &glState)
5204*8975f5c5SAndroid Build Coastguard Worker {
5205*8975f5c5SAndroid Build Coastguard Worker     const gl::DepthStencilState depthStencilState = glState.getDepthStencilState();
5206*8975f5c5SAndroid Build Coastguard Worker     gl::Framebuffer *drawFramebuffer              = glState.getDrawFramebuffer();
5207*8975f5c5SAndroid Build Coastguard Worker 
5208*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useDepthTestEnableDynamicState.enabled)
5209*8975f5c5SAndroid Build Coastguard Worker     {
5210*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_TEST_ENABLE);
5211*8975f5c5SAndroid Build Coastguard Worker     }
5212*8975f5c5SAndroid Build Coastguard Worker     else
5213*8975f5c5SAndroid Build Coastguard Worker     {
5214*8975f5c5SAndroid Build Coastguard Worker         mGraphicsPipelineDesc->updateDepthTestEnabled(&mGraphicsPipelineTransition,
5215*8975f5c5SAndroid Build Coastguard Worker                                                       depthStencilState, drawFramebuffer);
5216*8975f5c5SAndroid Build Coastguard Worker     }
5217*8975f5c5SAndroid Build Coastguard Worker }
5218*8975f5c5SAndroid Build Coastguard Worker 
updateDepthWriteEnabled(const gl::State & glState)5219*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateDepthWriteEnabled(const gl::State &glState)
5220*8975f5c5SAndroid Build Coastguard Worker {
5221*8975f5c5SAndroid Build Coastguard Worker     const gl::DepthStencilState depthStencilState = glState.getDepthStencilState();
5222*8975f5c5SAndroid Build Coastguard Worker     gl::Framebuffer *drawFramebuffer              = glState.getDrawFramebuffer();
5223*8975f5c5SAndroid Build Coastguard Worker 
5224*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useDepthWriteEnableDynamicState.enabled)
5225*8975f5c5SAndroid Build Coastguard Worker     {
5226*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_WRITE_ENABLE);
5227*8975f5c5SAndroid Build Coastguard Worker     }
5228*8975f5c5SAndroid Build Coastguard Worker     else
5229*8975f5c5SAndroid Build Coastguard Worker     {
5230*8975f5c5SAndroid Build Coastguard Worker         mGraphicsPipelineDesc->updateDepthWriteEnabled(&mGraphicsPipelineTransition,
5231*8975f5c5SAndroid Build Coastguard Worker                                                        depthStencilState, drawFramebuffer);
5232*8975f5c5SAndroid Build Coastguard Worker     }
5233*8975f5c5SAndroid Build Coastguard Worker }
5234*8975f5c5SAndroid Build Coastguard Worker 
updateDepthFunc(const gl::State & glState)5235*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateDepthFunc(const gl::State &glState)
5236*8975f5c5SAndroid Build Coastguard Worker {
5237*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useDepthCompareOpDynamicState.enabled)
5238*8975f5c5SAndroid Build Coastguard Worker     {
5239*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_COMPARE_OP);
5240*8975f5c5SAndroid Build Coastguard Worker     }
5241*8975f5c5SAndroid Build Coastguard Worker     else
5242*8975f5c5SAndroid Build Coastguard Worker     {
5243*8975f5c5SAndroid Build Coastguard Worker         mGraphicsPipelineDesc->updateDepthFunc(&mGraphicsPipelineTransition,
5244*8975f5c5SAndroid Build Coastguard Worker                                                glState.getDepthStencilState());
5245*8975f5c5SAndroid Build Coastguard Worker     }
5246*8975f5c5SAndroid Build Coastguard Worker }
5247*8975f5c5SAndroid Build Coastguard Worker 
updateStencilTestEnabled(const gl::State & glState)5248*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateStencilTestEnabled(const gl::State &glState)
5249*8975f5c5SAndroid Build Coastguard Worker {
5250*8975f5c5SAndroid Build Coastguard Worker     const gl::DepthStencilState depthStencilState = glState.getDepthStencilState();
5251*8975f5c5SAndroid Build Coastguard Worker     gl::Framebuffer *drawFramebuffer              = glState.getDrawFramebuffer();
5252*8975f5c5SAndroid Build Coastguard Worker 
5253*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useStencilTestEnableDynamicState.enabled)
5254*8975f5c5SAndroid Build Coastguard Worker     {
5255*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_TEST_ENABLE);
5256*8975f5c5SAndroid Build Coastguard Worker     }
5257*8975f5c5SAndroid Build Coastguard Worker     else
5258*8975f5c5SAndroid Build Coastguard Worker     {
5259*8975f5c5SAndroid Build Coastguard Worker         mGraphicsPipelineDesc->updateStencilTestEnabled(&mGraphicsPipelineTransition,
5260*8975f5c5SAndroid Build Coastguard Worker                                                         depthStencilState, drawFramebuffer);
5261*8975f5c5SAndroid Build Coastguard Worker     }
5262*8975f5c5SAndroid Build Coastguard Worker }
5263*8975f5c5SAndroid Build Coastguard Worker 
5264*8975f5c5SAndroid Build Coastguard Worker // If the target is a single-sampled target, sampleShading should be disabled, to use Bresenham line
5265*8975f5c5SAndroid Build Coastguard Worker // rasterization feature.
updateSampleShadingWithRasterizationSamples(const uint32_t rasterizationSamples)5266*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateSampleShadingWithRasterizationSamples(const uint32_t rasterizationSamples)
5267*8975f5c5SAndroid Build Coastguard Worker {
5268*8975f5c5SAndroid Build Coastguard Worker     bool sampleShadingEnable =
5269*8975f5c5SAndroid Build Coastguard Worker         (rasterizationSamples <= 1 ? false : mState.isSampleShadingEnabled());
5270*8975f5c5SAndroid Build Coastguard Worker     float minSampleShading = mState.getMinSampleShading();
5271*8975f5c5SAndroid Build Coastguard Worker 
5272*8975f5c5SAndroid Build Coastguard Worker     // If sample shading is not enabled, check if it should be implicitly enabled according to the
5273*8975f5c5SAndroid Build Coastguard Worker     // program.  Normally the driver should do this, but some drivers don't.
5274*8975f5c5SAndroid Build Coastguard Worker     if (rasterizationSamples > 1 && !sampleShadingEnable &&
5275*8975f5c5SAndroid Build Coastguard Worker         getFeatures().explicitlyEnablePerSampleShading.enabled)
5276*8975f5c5SAndroid Build Coastguard Worker     {
5277*8975f5c5SAndroid Build Coastguard Worker         const gl::ProgramExecutable *executable = mState.getProgramExecutable();
5278*8975f5c5SAndroid Build Coastguard Worker         if (executable && executable->enablesPerSampleShading())
5279*8975f5c5SAndroid Build Coastguard Worker         {
5280*8975f5c5SAndroid Build Coastguard Worker             sampleShadingEnable = true;
5281*8975f5c5SAndroid Build Coastguard Worker             minSampleShading    = 1.0;
5282*8975f5c5SAndroid Build Coastguard Worker         }
5283*8975f5c5SAndroid Build Coastguard Worker     }
5284*8975f5c5SAndroid Build Coastguard Worker 
5285*8975f5c5SAndroid Build Coastguard Worker     mGraphicsPipelineDesc->updateSampleShading(&mGraphicsPipelineTransition, sampleShadingEnable,
5286*8975f5c5SAndroid Build Coastguard Worker                                                minSampleShading);
5287*8975f5c5SAndroid Build Coastguard Worker }
5288*8975f5c5SAndroid Build Coastguard Worker 
5289*8975f5c5SAndroid Build Coastguard Worker // If the target is switched between a single-sampled and multisample, the dependency related to the
5290*8975f5c5SAndroid Build Coastguard Worker // rasterization sample should be updated.
updateRasterizationSamples(const uint32_t rasterizationSamples)5291*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateRasterizationSamples(const uint32_t rasterizationSamples)
5292*8975f5c5SAndroid Build Coastguard Worker {
5293*8975f5c5SAndroid Build Coastguard Worker     uint32_t prevSampleCount = mGraphicsPipelineDesc->getRasterizationSamples();
5294*8975f5c5SAndroid Build Coastguard Worker     updateFrameBufferFetchSamples(prevSampleCount, rasterizationSamples);
5295*8975f5c5SAndroid Build Coastguard Worker     mGraphicsPipelineDesc->updateRasterizationSamples(&mGraphicsPipelineTransition,
5296*8975f5c5SAndroid Build Coastguard Worker                                                       rasterizationSamples);
5297*8975f5c5SAndroid Build Coastguard Worker     updateSampleShadingWithRasterizationSamples(rasterizationSamples);
5298*8975f5c5SAndroid Build Coastguard Worker     updateSampleMaskWithRasterizationSamples(rasterizationSamples);
5299*8975f5c5SAndroid Build Coastguard Worker     updateAlphaToCoverageWithRasterizationSamples(rasterizationSamples);
5300*8975f5c5SAndroid Build Coastguard Worker }
5301*8975f5c5SAndroid Build Coastguard Worker 
updateRasterizerDiscardEnabled(bool isPrimitivesGeneratedQueryActive)5302*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateRasterizerDiscardEnabled(bool isPrimitivesGeneratedQueryActive)
5303*8975f5c5SAndroid Build Coastguard Worker {
5304*8975f5c5SAndroid Build Coastguard Worker     // On some devices, when rasterizerDiscardEnable is enabled, the
5305*8975f5c5SAndroid Build Coastguard Worker     // VK_EXT_primitives_generated_query as well as the pipeline statistics query used to emulate it
5306*8975f5c5SAndroid Build Coastguard Worker     // are non-functional.  For VK_EXT_primitives_generated_query there's a feature bit but not for
5307*8975f5c5SAndroid Build Coastguard Worker     // pipeline statistics query.  If the primitives generated query is active (and rasterizer
5308*8975f5c5SAndroid Build Coastguard Worker     // discard is not supported), rasterizerDiscardEnable is set to false and the functionality
5309*8975f5c5SAndroid Build Coastguard Worker     // is otherwise emulated (by using an empty scissor).
5310*8975f5c5SAndroid Build Coastguard Worker 
5311*8975f5c5SAndroid Build Coastguard Worker     // If the primitives generated query implementation supports rasterizer discard, just set
5312*8975f5c5SAndroid Build Coastguard Worker     // rasterizer discard as requested.  Otherwise disable it.
5313*8975f5c5SAndroid Build Coastguard Worker     const bool isEmulatingRasterizerDiscard =
5314*8975f5c5SAndroid Build Coastguard Worker         isEmulatingRasterizerDiscardDuringPrimitivesGeneratedQuery(
5315*8975f5c5SAndroid Build Coastguard Worker             isPrimitivesGeneratedQueryActive);
5316*8975f5c5SAndroid Build Coastguard Worker 
5317*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().useRasterizerDiscardEnableDynamicState.enabled)
5318*8975f5c5SAndroid Build Coastguard Worker     {
5319*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_RASTERIZER_DISCARD_ENABLE);
5320*8975f5c5SAndroid Build Coastguard Worker     }
5321*8975f5c5SAndroid Build Coastguard Worker     else
5322*8975f5c5SAndroid Build Coastguard Worker     {
5323*8975f5c5SAndroid Build Coastguard Worker         const bool isRasterizerDiscardEnabled = mState.isRasterizerDiscardEnabled();
5324*8975f5c5SAndroid Build Coastguard Worker 
5325*8975f5c5SAndroid Build Coastguard Worker         mGraphicsPipelineDesc->updateRasterizerDiscardEnabled(
5326*8975f5c5SAndroid Build Coastguard Worker             &mGraphicsPipelineTransition,
5327*8975f5c5SAndroid Build Coastguard Worker             isRasterizerDiscardEnabled && !isEmulatingRasterizerDiscard);
5328*8975f5c5SAndroid Build Coastguard Worker 
5329*8975f5c5SAndroid Build Coastguard Worker         invalidateCurrentGraphicsPipeline();
5330*8975f5c5SAndroid Build Coastguard Worker     }
5331*8975f5c5SAndroid Build Coastguard Worker 
5332*8975f5c5SAndroid Build Coastguard Worker     if (isEmulatingRasterizerDiscard)
5333*8975f5c5SAndroid Build Coastguard Worker     {
5334*8975f5c5SAndroid Build Coastguard Worker         // If we are emulating rasterizer discard, update the scissor to use an empty one if
5335*8975f5c5SAndroid Build Coastguard Worker         // rasterizer discard is enabled.
5336*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_SCISSOR);
5337*8975f5c5SAndroid Build Coastguard Worker     }
5338*8975f5c5SAndroid Build Coastguard Worker }
5339*8975f5c5SAndroid Build Coastguard Worker 
updateAdvancedBlendEquations(const gl::ProgramExecutable * executable)5340*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateAdvancedBlendEquations(const gl::ProgramExecutable *executable)
5341*8975f5c5SAndroid Build Coastguard Worker {
5342*8975f5c5SAndroid Build Coastguard Worker     if (!getFeatures().emulateAdvancedBlendEquations.enabled || executable == nullptr)
5343*8975f5c5SAndroid Build Coastguard Worker     {
5344*8975f5c5SAndroid Build Coastguard Worker         return;
5345*8975f5c5SAndroid Build Coastguard Worker     }
5346*8975f5c5SAndroid Build Coastguard Worker 
5347*8975f5c5SAndroid Build Coastguard Worker     // If advanced blend equations is emulated and the program uses advanced equations, update the
5348*8975f5c5SAndroid Build Coastguard Worker     // driver uniforms to pass the equation to the shader.
5349*8975f5c5SAndroid Build Coastguard Worker     if (executable->getAdvancedBlendEquations().any())
5350*8975f5c5SAndroid Build Coastguard Worker     {
5351*8975f5c5SAndroid Build Coastguard Worker         invalidateGraphicsDriverUniforms();
5352*8975f5c5SAndroid Build Coastguard Worker     }
5353*8975f5c5SAndroid Build Coastguard Worker }
5354*8975f5c5SAndroid Build Coastguard Worker 
updateDither()5355*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateDither()
5356*8975f5c5SAndroid Build Coastguard Worker {
5357*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().supportsLegacyDithering.enabled)
5358*8975f5c5SAndroid Build Coastguard Worker     {
5359*8975f5c5SAndroid Build Coastguard Worker         FramebufferVk *framebufferVk = vk::GetImpl(mState.getDrawFramebuffer());
5360*8975f5c5SAndroid Build Coastguard Worker         if (framebufferVk->updateLegacyDither(this))
5361*8975f5c5SAndroid Build Coastguard Worker         {
5362*8975f5c5SAndroid Build Coastguard Worker             // Can't reactivate: same framebuffer but the render pass desc has changed.
5363*8975f5c5SAndroid Build Coastguard Worker             mAllowRenderPassToReactivate = false;
5364*8975f5c5SAndroid Build Coastguard Worker 
5365*8975f5c5SAndroid Build Coastguard Worker             onRenderPassFinished(RenderPassClosureReason::LegacyDithering);
5366*8975f5c5SAndroid Build Coastguard Worker         }
5367*8975f5c5SAndroid Build Coastguard Worker 
5368*8975f5c5SAndroid Build Coastguard Worker         // update GraphicsPipelineDesc renderpass legacy dithering bit
5369*8975f5c5SAndroid Build Coastguard Worker         if (isDitherEnabled() != mGraphicsPipelineDesc->isLegacyDitherEnabled())
5370*8975f5c5SAndroid Build Coastguard Worker         {
5371*8975f5c5SAndroid Build Coastguard Worker             const vk::FramebufferFetchMode framebufferFetchMode =
5372*8975f5c5SAndroid Build Coastguard Worker                 vk::GetProgramFramebufferFetchMode(mState.getProgramExecutable());
5373*8975f5c5SAndroid Build Coastguard Worker             mGraphicsPipelineDesc->updateRenderPassDesc(&mGraphicsPipelineTransition, getFeatures(),
5374*8975f5c5SAndroid Build Coastguard Worker                                                         framebufferVk->getRenderPassDesc(),
5375*8975f5c5SAndroid Build Coastguard Worker                                                         framebufferFetchMode);
5376*8975f5c5SAndroid Build Coastguard Worker             invalidateCurrentGraphicsPipeline();
5377*8975f5c5SAndroid Build Coastguard Worker         }
5378*8975f5c5SAndroid Build Coastguard Worker     }
5379*8975f5c5SAndroid Build Coastguard Worker 
5380*8975f5c5SAndroid Build Coastguard Worker     if (!getFeatures().emulateDithering.enabled)
5381*8975f5c5SAndroid Build Coastguard Worker     {
5382*8975f5c5SAndroid Build Coastguard Worker         return;
5383*8975f5c5SAndroid Build Coastguard Worker     }
5384*8975f5c5SAndroid Build Coastguard Worker 
5385*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *framebufferVk = vk::GetImpl(mState.getDrawFramebuffer());
5386*8975f5c5SAndroid Build Coastguard Worker 
5387*8975f5c5SAndroid Build Coastguard Worker     // Dithering in OpenGL is vaguely defined, to the extent that no dithering is also a valid
5388*8975f5c5SAndroid Build Coastguard Worker     // dithering algorithm.  Dithering is enabled by default, but emulating it has a non-negligible
5389*8975f5c5SAndroid Build Coastguard Worker     // cost.  Similarly to some other GLES drivers, ANGLE enables dithering only on low-bit formats
5390*8975f5c5SAndroid Build Coastguard Worker     // where visual banding is particularly common; namely RGBA4444, RGBA5551 and RGB565.
5391*8975f5c5SAndroid Build Coastguard Worker     //
5392*8975f5c5SAndroid Build Coastguard Worker     // Dithering is emulated in the fragment shader and is controlled by a spec constant.  Every 2
5393*8975f5c5SAndroid Build Coastguard Worker     // bits of the spec constant correspond to one attachment, with the value indicating:
5394*8975f5c5SAndroid Build Coastguard Worker     //
5395*8975f5c5SAndroid Build Coastguard Worker     // - 00: No dithering
5396*8975f5c5SAndroid Build Coastguard Worker     // - 01: Dither for RGBA4444
5397*8975f5c5SAndroid Build Coastguard Worker     // - 10: Dither for RGBA5551
5398*8975f5c5SAndroid Build Coastguard Worker     // - 11: Dither for RGB565
5399*8975f5c5SAndroid Build Coastguard Worker     //
5400*8975f5c5SAndroid Build Coastguard Worker     uint16_t ditherControl = 0;
5401*8975f5c5SAndroid Build Coastguard Worker     if (mState.isDitherEnabled())
5402*8975f5c5SAndroid Build Coastguard Worker     {
5403*8975f5c5SAndroid Build Coastguard Worker         const gl::DrawBufferMask attachmentMask =
5404*8975f5c5SAndroid Build Coastguard Worker             framebufferVk->getState().getColorAttachmentsMask();
5405*8975f5c5SAndroid Build Coastguard Worker 
5406*8975f5c5SAndroid Build Coastguard Worker         for (size_t colorIndex : attachmentMask)
5407*8975f5c5SAndroid Build Coastguard Worker         {
5408*8975f5c5SAndroid Build Coastguard Worker             // As dithering is emulated in the fragment shader itself, there are a number of
5409*8975f5c5SAndroid Build Coastguard Worker             // situations that can lead to incorrect blending.  We only allow blending with specific
5410*8975f5c5SAndroid Build Coastguard Worker             // combinations know to not interfere with dithering.
5411*8975f5c5SAndroid Build Coastguard Worker             if (mState.isBlendEnabledIndexed(static_cast<GLuint>(colorIndex)) &&
5412*8975f5c5SAndroid Build Coastguard Worker                 !BlendModeSupportsDither(this, colorIndex))
5413*8975f5c5SAndroid Build Coastguard Worker             {
5414*8975f5c5SAndroid Build Coastguard Worker                 continue;
5415*8975f5c5SAndroid Build Coastguard Worker             }
5416*8975f5c5SAndroid Build Coastguard Worker 
5417*8975f5c5SAndroid Build Coastguard Worker             RenderTargetVk *attachment = framebufferVk->getColorDrawRenderTarget(colorIndex);
5418*8975f5c5SAndroid Build Coastguard Worker 
5419*8975f5c5SAndroid Build Coastguard Worker             const angle::FormatID format = attachment->getImageActualFormatID();
5420*8975f5c5SAndroid Build Coastguard Worker 
5421*8975f5c5SAndroid Build Coastguard Worker             uint16_t attachmentDitherControl = sh::vk::kDitherControlNoDither;
5422*8975f5c5SAndroid Build Coastguard Worker             switch (format)
5423*8975f5c5SAndroid Build Coastguard Worker             {
5424*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R4G4B4A4_UNORM:
5425*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::B4G4R4A4_UNORM:
5426*8975f5c5SAndroid Build Coastguard Worker                     attachmentDitherControl = sh::vk::kDitherControlDither4444;
5427*8975f5c5SAndroid Build Coastguard Worker                     break;
5428*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R5G5B5A1_UNORM:
5429*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::B5G5R5A1_UNORM:
5430*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::A1R5G5B5_UNORM:
5431*8975f5c5SAndroid Build Coastguard Worker                     attachmentDitherControl = sh::vk::kDitherControlDither5551;
5432*8975f5c5SAndroid Build Coastguard Worker                     break;
5433*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::R5G6B5_UNORM:
5434*8975f5c5SAndroid Build Coastguard Worker                 case angle::FormatID::B5G6R5_UNORM:
5435*8975f5c5SAndroid Build Coastguard Worker                     attachmentDitherControl = sh::vk::kDitherControlDither565;
5436*8975f5c5SAndroid Build Coastguard Worker                     break;
5437*8975f5c5SAndroid Build Coastguard Worker                 default:
5438*8975f5c5SAndroid Build Coastguard Worker                     break;
5439*8975f5c5SAndroid Build Coastguard Worker             }
5440*8975f5c5SAndroid Build Coastguard Worker 
5441*8975f5c5SAndroid Build Coastguard Worker             ditherControl |= static_cast<uint16_t>(attachmentDitherControl << 2 * colorIndex);
5442*8975f5c5SAndroid Build Coastguard Worker         }
5443*8975f5c5SAndroid Build Coastguard Worker     }
5444*8975f5c5SAndroid Build Coastguard Worker 
5445*8975f5c5SAndroid Build Coastguard Worker     if (ditherControl != mGraphicsPipelineDesc->getEmulatedDitherControl())
5446*8975f5c5SAndroid Build Coastguard Worker     {
5447*8975f5c5SAndroid Build Coastguard Worker         mGraphicsPipelineDesc->updateEmulatedDitherControl(&mGraphicsPipelineTransition,
5448*8975f5c5SAndroid Build Coastguard Worker                                                            ditherControl);
5449*8975f5c5SAndroid Build Coastguard Worker         invalidateCurrentGraphicsPipeline();
5450*8975f5c5SAndroid Build Coastguard Worker     }
5451*8975f5c5SAndroid Build Coastguard Worker }
5452*8975f5c5SAndroid Build Coastguard Worker 
updateStencilWriteWorkaround()5453*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateStencilWriteWorkaround()
5454*8975f5c5SAndroid Build Coastguard Worker {
5455*8975f5c5SAndroid Build Coastguard Worker     if (!getFeatures().useNonZeroStencilWriteMaskStaticState.enabled)
5456*8975f5c5SAndroid Build Coastguard Worker     {
5457*8975f5c5SAndroid Build Coastguard Worker         return;
5458*8975f5c5SAndroid Build Coastguard Worker     }
5459*8975f5c5SAndroid Build Coastguard Worker 
5460*8975f5c5SAndroid Build Coastguard Worker     // On certain drivers, having a stencil write mask of 0 in static state enables optimizations
5461*8975f5c5SAndroid Build Coastguard Worker     // that make the interaction of the stencil write mask dynamic state with discard and alpha to
5462*8975f5c5SAndroid Build Coastguard Worker     // coverage broken.  When the program has discard, or when alpha to coverage is enabled, these
5463*8975f5c5SAndroid Build Coastguard Worker     // optimizations are disabled by specifying a non-zero static state for stencil write mask.
5464*8975f5c5SAndroid Build Coastguard Worker     const bool programHasDiscard        = mState.getProgramExecutable()->hasDiscard();
5465*8975f5c5SAndroid Build Coastguard Worker     const bool isAlphaToCoverageEnabled = mState.isSampleAlphaToCoverageEnabled();
5466*8975f5c5SAndroid Build Coastguard Worker 
5467*8975f5c5SAndroid Build Coastguard Worker     mGraphicsPipelineDesc->updateNonZeroStencilWriteMaskWorkaround(
5468*8975f5c5SAndroid Build Coastguard Worker         &mGraphicsPipelineTransition, programHasDiscard || isAlphaToCoverageEnabled);
5469*8975f5c5SAndroid Build Coastguard Worker }
5470*8975f5c5SAndroid Build Coastguard Worker 
invalidateProgramExecutableHelper(const gl::Context * context)5471*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::invalidateProgramExecutableHelper(const gl::Context *context)
5472*8975f5c5SAndroid Build Coastguard Worker {
5473*8975f5c5SAndroid Build Coastguard Worker     const gl::State &glState                = context->getState();
5474*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = glState.getProgramExecutable();
5475*8975f5c5SAndroid Build Coastguard Worker 
5476*8975f5c5SAndroid Build Coastguard Worker     if (executable->hasLinkedShaderStage(gl::ShaderType::Compute))
5477*8975f5c5SAndroid Build Coastguard Worker     {
5478*8975f5c5SAndroid Build Coastguard Worker         invalidateCurrentComputePipeline();
5479*8975f5c5SAndroid Build Coastguard Worker     }
5480*8975f5c5SAndroid Build Coastguard Worker 
5481*8975f5c5SAndroid Build Coastguard Worker     if (executable->hasLinkedShaderStage(gl::ShaderType::Vertex))
5482*8975f5c5SAndroid Build Coastguard Worker     {
5483*8975f5c5SAndroid Build Coastguard Worker         invalidateCurrentGraphicsPipeline();
5484*8975f5c5SAndroid Build Coastguard Worker         // No additional work is needed here. We will update the pipeline desc
5485*8975f5c5SAndroid Build Coastguard Worker         // later.
5486*8975f5c5SAndroid Build Coastguard Worker         invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask());
5487*8975f5c5SAndroid Build Coastguard Worker         invalidateVertexAndIndexBuffers();
5488*8975f5c5SAndroid Build Coastguard Worker         // If VK_EXT_vertex_input_dynamic_state is enabled then vkCmdSetVertexInputEXT must be
5489*8975f5c5SAndroid Build Coastguard Worker         // called in the current command buffer prior to the draw command, even if there are no
5490*8975f5c5SAndroid Build Coastguard Worker         // active vertex attributes.
5491*8975f5c5SAndroid Build Coastguard Worker         const bool useVertexBuffer = (executable->getMaxActiveAttribLocation() > 0) ||
5492*8975f5c5SAndroid Build Coastguard Worker                                      getFeatures().supportsVertexInputDynamicState.enabled;
5493*8975f5c5SAndroid Build Coastguard Worker         mNonIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer);
5494*8975f5c5SAndroid Build Coastguard Worker         mIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer);
5495*8975f5c5SAndroid Build Coastguard Worker         resetCurrentGraphicsPipeline();
5496*8975f5c5SAndroid Build Coastguard Worker 
5497*8975f5c5SAndroid Build Coastguard Worker         const vk::FramebufferFetchMode framebufferFetchMode =
5498*8975f5c5SAndroid Build Coastguard Worker             vk::GetProgramFramebufferFetchMode(executable);
5499*8975f5c5SAndroid Build Coastguard Worker         const bool hasColorFramebufferFetch =
5500*8975f5c5SAndroid Build Coastguard Worker             framebufferFetchMode != vk::FramebufferFetchMode::None;
5501*8975f5c5SAndroid Build Coastguard Worker         if (getFeatures().preferDynamicRendering.enabled)
5502*8975f5c5SAndroid Build Coastguard Worker         {
5503*8975f5c5SAndroid Build Coastguard Worker             // Update the framebuffer fetch mode on the pipeline desc directly.  This is an inherent
5504*8975f5c5SAndroid Build Coastguard Worker             // property of the executable. Even if the bit is placed in RenderPassDesc because of
5505*8975f5c5SAndroid Build Coastguard Worker             // the non-dynamic-rendering path, updating it without affecting the transition bits is
5506*8975f5c5SAndroid Build Coastguard Worker             // valid because there cannot be a transition link between pipelines of different
5507*8975f5c5SAndroid Build Coastguard Worker             // programs.  This is attested by the fact that |resetCurrentGraphicsPipeline| above
5508*8975f5c5SAndroid Build Coastguard Worker             // sets |mCurrentGraphicsPipeline| to nullptr.
5509*8975f5c5SAndroid Build Coastguard Worker             mGraphicsPipelineDesc->setRenderPassFramebufferFetchMode(framebufferFetchMode);
5510*8975f5c5SAndroid Build Coastguard Worker 
5511*8975f5c5SAndroid Build Coastguard Worker             if (framebufferFetchMode != vk::FramebufferFetchMode::None)
5512*8975f5c5SAndroid Build Coastguard Worker             {
5513*8975f5c5SAndroid Build Coastguard Worker                 onFramebufferFetchUse(framebufferFetchMode);
5514*8975f5c5SAndroid Build Coastguard Worker             }
5515*8975f5c5SAndroid Build Coastguard Worker         }
5516*8975f5c5SAndroid Build Coastguard Worker         else
5517*8975f5c5SAndroid Build Coastguard Worker         {
5518*8975f5c5SAndroid Build Coastguard Worker             ASSERT(!FramebufferFetchModeHasDepthStencil(framebufferFetchMode));
5519*8975f5c5SAndroid Build Coastguard Worker             if (mIsInColorFramebufferFetchMode != hasColorFramebufferFetch)
5520*8975f5c5SAndroid Build Coastguard Worker             {
5521*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(getDrawFramebuffer()->getRenderPassDesc().hasColorFramebufferFetch() ==
5522*8975f5c5SAndroid Build Coastguard Worker                        mIsInColorFramebufferFetchMode);
5523*8975f5c5SAndroid Build Coastguard Worker 
5524*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(switchToColorFramebufferFetchMode(hasColorFramebufferFetch));
5525*8975f5c5SAndroid Build Coastguard Worker 
5526*8975f5c5SAndroid Build Coastguard Worker                 // When framebuffer fetch is enabled, attachments can be read from even if output is
5527*8975f5c5SAndroid Build Coastguard Worker                 // masked, so update their access.
5528*8975f5c5SAndroid Build Coastguard Worker                 onColorAccessChange();
5529*8975f5c5SAndroid Build Coastguard Worker             }
5530*8975f5c5SAndroid Build Coastguard Worker 
5531*8975f5c5SAndroid Build Coastguard Worker             // If permanentlySwitchToFramebufferFetchMode is enabled,
5532*8975f5c5SAndroid Build Coastguard Worker             // mIsInColorFramebufferFetchMode will remain true throughout the entire time.
5533*8975f5c5SAndroid Build Coastguard Worker             // If we switch from a program that doesn't use framebuffer fetch and doesn't
5534*8975f5c5SAndroid Build Coastguard Worker             // read/write to the framebuffer color attachment, to a
5535*8975f5c5SAndroid Build Coastguard Worker             // program that uses framebuffer fetch and needs to read from the framebuffer
5536*8975f5c5SAndroid Build Coastguard Worker             // color attachment, we will miss the call
5537*8975f5c5SAndroid Build Coastguard Worker             // onColorAccessChange() above and miss setting the dirty bit
5538*8975f5c5SAndroid Build Coastguard Worker             // DIRTY_BIT_COLOR_ACCESS. This means we will not call
5539*8975f5c5SAndroid Build Coastguard Worker             // handleDirtyGraphicsColorAccess that updates the access value of
5540*8975f5c5SAndroid Build Coastguard Worker             // framebuffer color attachment from unused to readonly. This makes the
5541*8975f5c5SAndroid Build Coastguard Worker             // color attachment to continue using LoadOpNone, and the second program
5542*8975f5c5SAndroid Build Coastguard Worker             // will not be able to read the value in the color attachment.
5543*8975f5c5SAndroid Build Coastguard Worker             if (getFeatures().permanentlySwitchToFramebufferFetchMode.enabled &&
5544*8975f5c5SAndroid Build Coastguard Worker                 hasColorFramebufferFetch)
5545*8975f5c5SAndroid Build Coastguard Worker             {
5546*8975f5c5SAndroid Build Coastguard Worker                 onColorAccessChange();
5547*8975f5c5SAndroid Build Coastguard Worker             }
5548*8975f5c5SAndroid Build Coastguard Worker         }
5549*8975f5c5SAndroid Build Coastguard Worker 
5550*8975f5c5SAndroid Build Coastguard Worker         // If framebuffer fetch is exposed but is internally non-coherent, make sure a framebuffer
5551*8975f5c5SAndroid Build Coastguard Worker         // fetch barrier is issued before each draw call as long as a program with framebuffer fetch
5552*8975f5c5SAndroid Build Coastguard Worker         // is used.  If the application would have correctly used non-coherent framebuffer fetch, it
5553*8975f5c5SAndroid Build Coastguard Worker         // would have been optimal _not_ to expose the coherent extension.  However, lots of
5554*8975f5c5SAndroid Build Coastguard Worker         // Android applications expect coherent framebuffer fetch to be available.
5555*8975f5c5SAndroid Build Coastguard Worker         if (mRenderer->isCoherentColorFramebufferFetchEmulated())
5556*8975f5c5SAndroid Build Coastguard Worker         {
5557*8975f5c5SAndroid Build Coastguard Worker             mGraphicsDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_FETCH_BARRIER, hasColorFramebufferFetch);
5558*8975f5c5SAndroid Build Coastguard Worker         }
5559*8975f5c5SAndroid Build Coastguard Worker 
5560*8975f5c5SAndroid Build Coastguard Worker         updateStencilWriteWorkaround();
5561*8975f5c5SAndroid Build Coastguard Worker 
5562*8975f5c5SAndroid Build Coastguard Worker         mGraphicsPipelineDesc->updateVertexShaderComponentTypes(
5563*8975f5c5SAndroid Build Coastguard Worker             &mGraphicsPipelineTransition, executable->getNonBuiltinAttribLocationsMask(),
5564*8975f5c5SAndroid Build Coastguard Worker             executable->getAttributesTypeMask());
5565*8975f5c5SAndroid Build Coastguard Worker 
5566*8975f5c5SAndroid Build Coastguard Worker         updateMissingOutputsMask();
5567*8975f5c5SAndroid Build Coastguard Worker     }
5568*8975f5c5SAndroid Build Coastguard Worker 
5569*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
5570*8975f5c5SAndroid Build Coastguard Worker }
5571*8975f5c5SAndroid Build Coastguard Worker 
syncState(const gl::Context * context,const gl::state::DirtyBits dirtyBits,const gl::state::DirtyBits bitMask,const gl::state::ExtendedDirtyBits extendedDirtyBits,const gl::state::ExtendedDirtyBits extendedBitMask,gl::Command command)5572*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::syncState(const gl::Context *context,
5573*8975f5c5SAndroid Build Coastguard Worker                                    const gl::state::DirtyBits dirtyBits,
5574*8975f5c5SAndroid Build Coastguard Worker                                    const gl::state::DirtyBits bitMask,
5575*8975f5c5SAndroid Build Coastguard Worker                                    const gl::state::ExtendedDirtyBits extendedDirtyBits,
5576*8975f5c5SAndroid Build Coastguard Worker                                    const gl::state::ExtendedDirtyBits extendedBitMask,
5577*8975f5c5SAndroid Build Coastguard Worker                                    gl::Command command)
5578*8975f5c5SAndroid Build Coastguard Worker {
5579*8975f5c5SAndroid Build Coastguard Worker     const gl::State &glState                       = context->getState();
5580*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *programExecutable = glState.getProgramExecutable();
5581*8975f5c5SAndroid Build Coastguard Worker 
5582*8975f5c5SAndroid Build Coastguard Worker     if ((dirtyBits & mPipelineDirtyBitsMask).any() &&
5583*8975f5c5SAndroid Build Coastguard Worker         (programExecutable == nullptr || command != gl::Command::Dispatch))
5584*8975f5c5SAndroid Build Coastguard Worker     {
5585*8975f5c5SAndroid Build Coastguard Worker         invalidateCurrentGraphicsPipeline();
5586*8975f5c5SAndroid Build Coastguard Worker     }
5587*8975f5c5SAndroid Build Coastguard Worker 
5588*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
5589*8975f5c5SAndroid Build Coastguard Worker     VertexArrayVk *vertexArrayVk     = getVertexArray();
5590*8975f5c5SAndroid Build Coastguard Worker 
5591*8975f5c5SAndroid Build Coastguard Worker     for (auto iter = dirtyBits.begin(), endIter = dirtyBits.end(); iter != endIter; ++iter)
5592*8975f5c5SAndroid Build Coastguard Worker     {
5593*8975f5c5SAndroid Build Coastguard Worker         size_t dirtyBit = *iter;
5594*8975f5c5SAndroid Build Coastguard Worker         switch (dirtyBit)
5595*8975f5c5SAndroid Build Coastguard Worker         {
5596*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_SCISSOR_TEST_ENABLED:
5597*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_SCISSOR:
5598*8975f5c5SAndroid Build Coastguard Worker                 updateScissor(glState);
5599*8975f5c5SAndroid Build Coastguard Worker                 break;
5600*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_VIEWPORT:
5601*8975f5c5SAndroid Build Coastguard Worker             {
5602*8975f5c5SAndroid Build Coastguard Worker                 FramebufferVk *framebufferVk = vk::GetImpl(glState.getDrawFramebuffer());
5603*8975f5c5SAndroid Build Coastguard Worker                 updateViewport(framebufferVk, glState.getViewport(), glState.getNearPlane(),
5604*8975f5c5SAndroid Build Coastguard Worker                                glState.getFarPlane());
5605*8975f5c5SAndroid Build Coastguard Worker                 // Update the scissor, which will be constrained to the viewport
5606*8975f5c5SAndroid Build Coastguard Worker                 updateScissor(glState);
5607*8975f5c5SAndroid Build Coastguard Worker                 break;
5608*8975f5c5SAndroid Build Coastguard Worker             }
5609*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_DEPTH_RANGE:
5610*8975f5c5SAndroid Build Coastguard Worker                 updateDepthRange(glState.getNearPlane(), glState.getFarPlane());
5611*8975f5c5SAndroid Build Coastguard Worker                 break;
5612*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_BLEND_ENABLED:
5613*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsPipelineDesc->updateBlendEnabled(
5614*8975f5c5SAndroid Build Coastguard Worker                     &mGraphicsPipelineTransition, glState.getBlendStateExt().getEnabledMask());
5615*8975f5c5SAndroid Build Coastguard Worker                 updateDither();
5616*8975f5c5SAndroid Build Coastguard Worker                 updateAdvancedBlendEquations(programExecutable);
5617*8975f5c5SAndroid Build Coastguard Worker                 break;
5618*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_BLEND_COLOR:
5619*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_BLEND_CONSTANTS);
5620*8975f5c5SAndroid Build Coastguard Worker                 break;
5621*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_BLEND_FUNCS:
5622*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsPipelineDesc->updateBlendFuncs(
5623*8975f5c5SAndroid Build Coastguard Worker                     &mGraphicsPipelineTransition, glState.getBlendStateExt(),
5624*8975f5c5SAndroid Build Coastguard Worker                     drawFramebufferVk->getState().getColorAttachmentsMask());
5625*8975f5c5SAndroid Build Coastguard Worker                 break;
5626*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_BLEND_EQUATIONS:
5627*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsPipelineDesc->updateBlendEquations(
5628*8975f5c5SAndroid Build Coastguard Worker                     &mGraphicsPipelineTransition, glState.getBlendStateExt(),
5629*8975f5c5SAndroid Build Coastguard Worker                     drawFramebufferVk->getState().getColorAttachmentsMask());
5630*8975f5c5SAndroid Build Coastguard Worker                 updateAdvancedBlendEquations(programExecutable);
5631*8975f5c5SAndroid Build Coastguard Worker                 break;
5632*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_COLOR_MASK:
5633*8975f5c5SAndroid Build Coastguard Worker                 updateColorMasks();
5634*8975f5c5SAndroid Build Coastguard Worker                 break;
5635*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
5636*8975f5c5SAndroid Build Coastguard Worker                 updateAlphaToCoverageWithRasterizationSamples(drawFramebufferVk->getSamples());
5637*8975f5c5SAndroid Build Coastguard Worker                 updateStencilWriteWorkaround();
5638*8975f5c5SAndroid Build Coastguard Worker 
5639*8975f5c5SAndroid Build Coastguard Worker                 static_assert(gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE >
5640*8975f5c5SAndroid Build Coastguard Worker                                   gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED,
5641*8975f5c5SAndroid Build Coastguard Worker                               "Dirty bit order");
5642*8975f5c5SAndroid Build Coastguard Worker                 iter.setLaterBit(gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE);
5643*8975f5c5SAndroid Build Coastguard Worker                 break;
5644*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED:
5645*8975f5c5SAndroid Build Coastguard Worker                 updateSampleMaskWithRasterizationSamples(drawFramebufferVk->getSamples());
5646*8975f5c5SAndroid Build Coastguard Worker                 break;
5647*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_SAMPLE_COVERAGE:
5648*8975f5c5SAndroid Build Coastguard Worker                 updateSampleMaskWithRasterizationSamples(drawFramebufferVk->getSamples());
5649*8975f5c5SAndroid Build Coastguard Worker                 break;
5650*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_SAMPLE_MASK_ENABLED:
5651*8975f5c5SAndroid Build Coastguard Worker                 updateSampleMaskWithRasterizationSamples(drawFramebufferVk->getSamples());
5652*8975f5c5SAndroid Build Coastguard Worker                 break;
5653*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_SAMPLE_MASK:
5654*8975f5c5SAndroid Build Coastguard Worker                 updateSampleMaskWithRasterizationSamples(drawFramebufferVk->getSamples());
5655*8975f5c5SAndroid Build Coastguard Worker                 break;
5656*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_DEPTH_TEST_ENABLED:
5657*8975f5c5SAndroid Build Coastguard Worker                 updateDepthTestEnabled(glState);
5658*8975f5c5SAndroid Build Coastguard Worker                 iter.setLaterBit(gl::state::DIRTY_BIT_DEPTH_MASK);
5659*8975f5c5SAndroid Build Coastguard Worker                 break;
5660*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_DEPTH_FUNC:
5661*8975f5c5SAndroid Build Coastguard Worker                 updateDepthFunc(glState);
5662*8975f5c5SAndroid Build Coastguard Worker                 onDepthStencilAccessChange();
5663*8975f5c5SAndroid Build Coastguard Worker                 break;
5664*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_DEPTH_MASK:
5665*8975f5c5SAndroid Build Coastguard Worker                 updateDepthWriteEnabled(glState);
5666*8975f5c5SAndroid Build Coastguard Worker                 onDepthStencilAccessChange();
5667*8975f5c5SAndroid Build Coastguard Worker                 break;
5668*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_STENCIL_TEST_ENABLED:
5669*8975f5c5SAndroid Build Coastguard Worker                 updateStencilTestEnabled(glState);
5670*8975f5c5SAndroid Build Coastguard Worker                 onDepthStencilAccessChange();
5671*8975f5c5SAndroid Build Coastguard Worker                 break;
5672*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_STENCIL_FUNCS_FRONT:
5673*8975f5c5SAndroid Build Coastguard Worker                 if (mRenderer->getFeatures().useStencilOpDynamicState.enabled)
5674*8975f5c5SAndroid Build Coastguard Worker                 {
5675*8975f5c5SAndroid Build Coastguard Worker                     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_OP);
5676*8975f5c5SAndroid Build Coastguard Worker                 }
5677*8975f5c5SAndroid Build Coastguard Worker                 else
5678*8975f5c5SAndroid Build Coastguard Worker                 {
5679*8975f5c5SAndroid Build Coastguard Worker                     mGraphicsPipelineDesc->updateStencilFrontFuncs(&mGraphicsPipelineTransition,
5680*8975f5c5SAndroid Build Coastguard Worker                                                                    glState.getDepthStencilState());
5681*8975f5c5SAndroid Build Coastguard Worker                 }
5682*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_COMPARE_MASK);
5683*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_REFERENCE);
5684*8975f5c5SAndroid Build Coastguard Worker                 onDepthStencilAccessChange();
5685*8975f5c5SAndroid Build Coastguard Worker                 break;
5686*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_STENCIL_FUNCS_BACK:
5687*8975f5c5SAndroid Build Coastguard Worker                 if (mRenderer->getFeatures().useStencilOpDynamicState.enabled)
5688*8975f5c5SAndroid Build Coastguard Worker                 {
5689*8975f5c5SAndroid Build Coastguard Worker                     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_OP);
5690*8975f5c5SAndroid Build Coastguard Worker                 }
5691*8975f5c5SAndroid Build Coastguard Worker                 else
5692*8975f5c5SAndroid Build Coastguard Worker                 {
5693*8975f5c5SAndroid Build Coastguard Worker                     mGraphicsPipelineDesc->updateStencilBackFuncs(&mGraphicsPipelineTransition,
5694*8975f5c5SAndroid Build Coastguard Worker                                                                   glState.getDepthStencilState());
5695*8975f5c5SAndroid Build Coastguard Worker                 }
5696*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_COMPARE_MASK);
5697*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_REFERENCE);
5698*8975f5c5SAndroid Build Coastguard Worker                 onDepthStencilAccessChange();
5699*8975f5c5SAndroid Build Coastguard Worker                 break;
5700*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_STENCIL_OPS_FRONT:
5701*8975f5c5SAndroid Build Coastguard Worker                 if (mRenderer->getFeatures().useStencilOpDynamicState.enabled)
5702*8975f5c5SAndroid Build Coastguard Worker                 {
5703*8975f5c5SAndroid Build Coastguard Worker                     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_OP);
5704*8975f5c5SAndroid Build Coastguard Worker                 }
5705*8975f5c5SAndroid Build Coastguard Worker                 else
5706*8975f5c5SAndroid Build Coastguard Worker                 {
5707*8975f5c5SAndroid Build Coastguard Worker                     mGraphicsPipelineDesc->updateStencilFrontOps(&mGraphicsPipelineTransition,
5708*8975f5c5SAndroid Build Coastguard Worker                                                                  glState.getDepthStencilState());
5709*8975f5c5SAndroid Build Coastguard Worker                 }
5710*8975f5c5SAndroid Build Coastguard Worker                 onDepthStencilAccessChange();
5711*8975f5c5SAndroid Build Coastguard Worker                 break;
5712*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_STENCIL_OPS_BACK:
5713*8975f5c5SAndroid Build Coastguard Worker                 if (mRenderer->getFeatures().useStencilOpDynamicState.enabled)
5714*8975f5c5SAndroid Build Coastguard Worker                 {
5715*8975f5c5SAndroid Build Coastguard Worker                     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_OP);
5716*8975f5c5SAndroid Build Coastguard Worker                 }
5717*8975f5c5SAndroid Build Coastguard Worker                 else
5718*8975f5c5SAndroid Build Coastguard Worker                 {
5719*8975f5c5SAndroid Build Coastguard Worker                     mGraphicsPipelineDesc->updateStencilBackOps(&mGraphicsPipelineTransition,
5720*8975f5c5SAndroid Build Coastguard Worker                                                                 glState.getDepthStencilState());
5721*8975f5c5SAndroid Build Coastguard Worker                 }
5722*8975f5c5SAndroid Build Coastguard Worker                 onDepthStencilAccessChange();
5723*8975f5c5SAndroid Build Coastguard Worker                 break;
5724*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
5725*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
5726*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_STENCIL_WRITE_MASK);
5727*8975f5c5SAndroid Build Coastguard Worker                 onDepthStencilAccessChange();
5728*8975f5c5SAndroid Build Coastguard Worker                 break;
5729*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_CULL_FACE_ENABLED:
5730*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_CULL_FACE:
5731*8975f5c5SAndroid Build Coastguard Worker                 if (mRenderer->getFeatures().useCullModeDynamicState.enabled)
5732*8975f5c5SAndroid Build Coastguard Worker                 {
5733*8975f5c5SAndroid Build Coastguard Worker                     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_CULL_MODE);
5734*8975f5c5SAndroid Build Coastguard Worker                 }
5735*8975f5c5SAndroid Build Coastguard Worker                 else
5736*8975f5c5SAndroid Build Coastguard Worker                 {
5737*8975f5c5SAndroid Build Coastguard Worker                     mGraphicsPipelineDesc->updateCullMode(&mGraphicsPipelineTransition,
5738*8975f5c5SAndroid Build Coastguard Worker                                                           glState.getRasterizerState());
5739*8975f5c5SAndroid Build Coastguard Worker                 }
5740*8975f5c5SAndroid Build Coastguard Worker                 break;
5741*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_FRONT_FACE:
5742*8975f5c5SAndroid Build Coastguard Worker                 updateFrontFace();
5743*8975f5c5SAndroid Build Coastguard Worker                 break;
5744*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
5745*8975f5c5SAndroid Build Coastguard Worker                 if (mRenderer->getFeatures().useDepthBiasEnableDynamicState.enabled)
5746*8975f5c5SAndroid Build Coastguard Worker                 {
5747*8975f5c5SAndroid Build Coastguard Worker                     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_BIAS_ENABLE);
5748*8975f5c5SAndroid Build Coastguard Worker                 }
5749*8975f5c5SAndroid Build Coastguard Worker                 else
5750*8975f5c5SAndroid Build Coastguard Worker                 {
5751*8975f5c5SAndroid Build Coastguard Worker                     mGraphicsPipelineDesc->updatePolygonOffsetEnabled(
5752*8975f5c5SAndroid Build Coastguard Worker                         &mGraphicsPipelineTransition, glState.isPolygonOffsetEnabled());
5753*8975f5c5SAndroid Build Coastguard Worker                 }
5754*8975f5c5SAndroid Build Coastguard Worker                 break;
5755*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_POLYGON_OFFSET:
5756*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_BIAS);
5757*8975f5c5SAndroid Build Coastguard Worker                 break;
5758*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
5759*8975f5c5SAndroid Build Coastguard Worker                 updateRasterizerDiscardEnabled(
5760*8975f5c5SAndroid Build Coastguard Worker                     mState.isQueryActive(gl::QueryType::PrimitivesGenerated));
5761*8975f5c5SAndroid Build Coastguard Worker                 onColorAccessChange();
5762*8975f5c5SAndroid Build Coastguard Worker                 break;
5763*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_LINE_WIDTH:
5764*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_LINE_WIDTH);
5765*8975f5c5SAndroid Build Coastguard Worker                 break;
5766*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED:
5767*8975f5c5SAndroid Build Coastguard Worker                 if (mRenderer->getFeatures().usePrimitiveRestartEnableDynamicState.enabled)
5768*8975f5c5SAndroid Build Coastguard Worker                 {
5769*8975f5c5SAndroid Build Coastguard Worker                     mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_PRIMITIVE_RESTART_ENABLE);
5770*8975f5c5SAndroid Build Coastguard Worker                 }
5771*8975f5c5SAndroid Build Coastguard Worker                 else
5772*8975f5c5SAndroid Build Coastguard Worker                 {
5773*8975f5c5SAndroid Build Coastguard Worker                     mGraphicsPipelineDesc->updatePrimitiveRestartEnabled(
5774*8975f5c5SAndroid Build Coastguard Worker                         &mGraphicsPipelineTransition, glState.isPrimitiveRestartEnabled());
5775*8975f5c5SAndroid Build Coastguard Worker                 }
5776*8975f5c5SAndroid Build Coastguard Worker                 // Additionally set the index buffer dirty if conversion from uint8 might have been
5777*8975f5c5SAndroid Build Coastguard Worker                 // necessary.  Otherwise if primitive restart is enabled and the index buffer is
5778*8975f5c5SAndroid Build Coastguard Worker                 // translated to uint16_t with a value of 0xFFFF, it cannot be reused when primitive
5779*8975f5c5SAndroid Build Coastguard Worker                 // restart is disabled.
5780*8975f5c5SAndroid Build Coastguard Worker                 if (!mRenderer->getFeatures().supportsIndexTypeUint8.enabled)
5781*8975f5c5SAndroid Build Coastguard Worker                 {
5782*8975f5c5SAndroid Build Coastguard Worker                     mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
5783*8975f5c5SAndroid Build Coastguard Worker                 }
5784*8975f5c5SAndroid Build Coastguard Worker                 break;
5785*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_CLEAR_COLOR:
5786*8975f5c5SAndroid Build Coastguard Worker                 mClearColorValue.color.float32[0] = glState.getColorClearValue().red;
5787*8975f5c5SAndroid Build Coastguard Worker                 mClearColorValue.color.float32[1] = glState.getColorClearValue().green;
5788*8975f5c5SAndroid Build Coastguard Worker                 mClearColorValue.color.float32[2] = glState.getColorClearValue().blue;
5789*8975f5c5SAndroid Build Coastguard Worker                 mClearColorValue.color.float32[3] = glState.getColorClearValue().alpha;
5790*8975f5c5SAndroid Build Coastguard Worker                 break;
5791*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_CLEAR_DEPTH:
5792*8975f5c5SAndroid Build Coastguard Worker                 mClearDepthStencilValue.depthStencil.depth = glState.getDepthClearValue();
5793*8975f5c5SAndroid Build Coastguard Worker                 break;
5794*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_CLEAR_STENCIL:
5795*8975f5c5SAndroid Build Coastguard Worker                 mClearDepthStencilValue.depthStencil.stencil =
5796*8975f5c5SAndroid Build Coastguard Worker                     static_cast<uint32_t>(glState.getStencilClearValue());
5797*8975f5c5SAndroid Build Coastguard Worker                 break;
5798*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_UNPACK_STATE:
5799*8975f5c5SAndroid Build Coastguard Worker                 // This is a no-op, it's only important to use the right unpack state when we do
5800*8975f5c5SAndroid Build Coastguard Worker                 // setImage or setSubImage in TextureVk, which is plumbed through the frontend
5801*8975f5c5SAndroid Build Coastguard Worker                 // call
5802*8975f5c5SAndroid Build Coastguard Worker                 break;
5803*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_UNPACK_BUFFER_BINDING:
5804*8975f5c5SAndroid Build Coastguard Worker                 break;
5805*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_PACK_STATE:
5806*8975f5c5SAndroid Build Coastguard Worker                 // This is a no-op, its only important to use the right pack state when we do
5807*8975f5c5SAndroid Build Coastguard Worker                 // call readPixels later on.
5808*8975f5c5SAndroid Build Coastguard Worker                 break;
5809*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_PACK_BUFFER_BINDING:
5810*8975f5c5SAndroid Build Coastguard Worker                 break;
5811*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_DITHER_ENABLED:
5812*8975f5c5SAndroid Build Coastguard Worker                 updateDither();
5813*8975f5c5SAndroid Build Coastguard Worker                 break;
5814*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_READ_FRAMEBUFFER_BINDING:
5815*8975f5c5SAndroid Build Coastguard Worker                 updateFlipViewportReadFramebuffer(context->getState());
5816*8975f5c5SAndroid Build Coastguard Worker                 updateSurfaceRotationReadFramebuffer(glState, context->getCurrentReadSurface());
5817*8975f5c5SAndroid Build Coastguard Worker                 break;
5818*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
5819*8975f5c5SAndroid Build Coastguard Worker             {
5820*8975f5c5SAndroid Build Coastguard Worker                 // FramebufferVk::syncState signals that we should start a new command buffer.
5821*8975f5c5SAndroid Build Coastguard Worker                 // But changing the binding can skip FramebufferVk::syncState if the Framebuffer
5822*8975f5c5SAndroid Build Coastguard Worker                 // has no dirty bits. Thus we need to explicitly clear the current command
5823*8975f5c5SAndroid Build Coastguard Worker                 // buffer to ensure we start a new one. We don't actually close the render pass here
5824*8975f5c5SAndroid Build Coastguard Worker                 // as some optimizations in non-draw commands require the render pass to remain
5825*8975f5c5SAndroid Build Coastguard Worker                 // open, such as invalidate or blit. Note that we always start a new command buffer
5826*8975f5c5SAndroid Build Coastguard Worker                 // because we currently can only support one open RenderPass at a time.
5827*8975f5c5SAndroid Build Coastguard Worker                 //
5828*8975f5c5SAndroid Build Coastguard Worker                 // The render pass is not closed if binding is changed to the same framebuffer as
5829*8975f5c5SAndroid Build Coastguard Worker                 // before.
5830*8975f5c5SAndroid Build Coastguard Worker                 if (hasActiveRenderPass() && hasStartedRenderPassWithQueueSerial(
5831*8975f5c5SAndroid Build Coastguard Worker                                                  drawFramebufferVk->getLastRenderPassQueueSerial()))
5832*8975f5c5SAndroid Build Coastguard Worker                 {
5833*8975f5c5SAndroid Build Coastguard Worker                     break;
5834*8975f5c5SAndroid Build Coastguard Worker                 }
5835*8975f5c5SAndroid Build Coastguard Worker 
5836*8975f5c5SAndroid Build Coastguard Worker                 onRenderPassFinished(RenderPassClosureReason::FramebufferBindingChange);
5837*8975f5c5SAndroid Build Coastguard Worker                 // If we are switching from user FBO to system frame buffer, we always submit work
5838*8975f5c5SAndroid Build Coastguard Worker                 // first so that these FBO rendering will not have to wait for ANI semaphore (which
5839*8975f5c5SAndroid Build Coastguard Worker                 // draw to system frame buffer must wait for).
5840*8975f5c5SAndroid Build Coastguard Worker                 if ((getFeatures().preferSubmitAtFBOBoundary.enabled ||
5841*8975f5c5SAndroid Build Coastguard Worker                      mState.getDrawFramebuffer()->isDefault()) &&
5842*8975f5c5SAndroid Build Coastguard Worker                     mRenderPassCommands->started())
5843*8975f5c5SAndroid Build Coastguard Worker                 {
5844*8975f5c5SAndroid Build Coastguard Worker                     // This will behave as if user called glFlush, but the actual flush will be
5845*8975f5c5SAndroid Build Coastguard Worker                     // triggered at endRenderPass time.
5846*8975f5c5SAndroid Build Coastguard Worker                     mHasDeferredFlush = true;
5847*8975f5c5SAndroid Build Coastguard Worker                 }
5848*8975f5c5SAndroid Build Coastguard Worker 
5849*8975f5c5SAndroid Build Coastguard Worker                 mDepthStencilAttachmentFlags.reset();
5850*8975f5c5SAndroid Build Coastguard Worker                 updateFlipViewportDrawFramebuffer(glState);
5851*8975f5c5SAndroid Build Coastguard Worker                 updateSurfaceRotationDrawFramebuffer(glState, context->getCurrentDrawSurface());
5852*8975f5c5SAndroid Build Coastguard Worker                 updateViewport(drawFramebufferVk, glState.getViewport(), glState.getNearPlane(),
5853*8975f5c5SAndroid Build Coastguard Worker                                glState.getFarPlane());
5854*8975f5c5SAndroid Build Coastguard Worker                 updateColorMasks();
5855*8975f5c5SAndroid Build Coastguard Worker                 updateMissingOutputsMask();
5856*8975f5c5SAndroid Build Coastguard Worker                 updateRasterizationSamples(drawFramebufferVk->getSamples());
5857*8975f5c5SAndroid Build Coastguard Worker                 updateRasterizerDiscardEnabled(
5858*8975f5c5SAndroid Build Coastguard Worker                     mState.isQueryActive(gl::QueryType::PrimitivesGenerated));
5859*8975f5c5SAndroid Build Coastguard Worker 
5860*8975f5c5SAndroid Build Coastguard Worker                 updateFrontFace();
5861*8975f5c5SAndroid Build Coastguard Worker                 updateScissor(glState);
5862*8975f5c5SAndroid Build Coastguard Worker                 updateDepthStencil(glState);
5863*8975f5c5SAndroid Build Coastguard Worker                 updateDither();
5864*8975f5c5SAndroid Build Coastguard Worker 
5865*8975f5c5SAndroid Build Coastguard Worker                 // Clear the blend funcs/equations for color attachment indices that no longer
5866*8975f5c5SAndroid Build Coastguard Worker                 // exist.
5867*8975f5c5SAndroid Build Coastguard Worker                 gl::DrawBufferMask newColorAttachmentMask =
5868*8975f5c5SAndroid Build Coastguard Worker                     drawFramebufferVk->getState().getColorAttachmentsMask();
5869*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsPipelineDesc->resetBlendFuncsAndEquations(
5870*8975f5c5SAndroid Build Coastguard Worker                     &mGraphicsPipelineTransition, glState.getBlendStateExt(),
5871*8975f5c5SAndroid Build Coastguard Worker                     mCachedDrawFramebufferColorAttachmentMask, newColorAttachmentMask);
5872*8975f5c5SAndroid Build Coastguard Worker                 mCachedDrawFramebufferColorAttachmentMask = newColorAttachmentMask;
5873*8975f5c5SAndroid Build Coastguard Worker 
5874*8975f5c5SAndroid Build Coastguard Worker                 if (!getFeatures().preferDynamicRendering.enabled)
5875*8975f5c5SAndroid Build Coastguard Worker                 {
5876*8975f5c5SAndroid Build Coastguard Worker                     // The framebuffer may not be in sync with usage of framebuffer fetch programs.
5877*8975f5c5SAndroid Build Coastguard Worker                     drawFramebufferVk->switchToColorFramebufferFetchMode(
5878*8975f5c5SAndroid Build Coastguard Worker                         this, mIsInColorFramebufferFetchMode);
5879*8975f5c5SAndroid Build Coastguard Worker                 }
5880*8975f5c5SAndroid Build Coastguard Worker 
5881*8975f5c5SAndroid Build Coastguard Worker                 onDrawFramebufferRenderPassDescChange(drawFramebufferVk, nullptr);
5882*8975f5c5SAndroid Build Coastguard Worker 
5883*8975f5c5SAndroid Build Coastguard Worker                 break;
5884*8975f5c5SAndroid Build Coastguard Worker             }
5885*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_RENDERBUFFER_BINDING:
5886*8975f5c5SAndroid Build Coastguard Worker                 break;
5887*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_VERTEX_ARRAY_BINDING:
5888*8975f5c5SAndroid Build Coastguard Worker             {
5889*8975f5c5SAndroid Build Coastguard Worker                 invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask());
5890*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(vertexArrayVk->updateActiveAttribInfo(this));
5891*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(onIndexBufferChange(vertexArrayVk->getCurrentElementArrayBuffer()));
5892*8975f5c5SAndroid Build Coastguard Worker                 break;
5893*8975f5c5SAndroid Build Coastguard Worker             }
5894*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
5895*8975f5c5SAndroid Build Coastguard Worker                 break;
5896*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING:
5897*8975f5c5SAndroid Build Coastguard Worker                 break;
5898*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_PROGRAM_BINDING:
5899*8975f5c5SAndroid Build Coastguard Worker                 static_assert(
5900*8975f5c5SAndroid Build Coastguard Worker                     gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE > gl::state::DIRTY_BIT_PROGRAM_BINDING,
5901*8975f5c5SAndroid Build Coastguard Worker                     "Dirty bit order");
5902*8975f5c5SAndroid Build Coastguard Worker                 iter.setLaterBit(gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE);
5903*8975f5c5SAndroid Build Coastguard Worker                 break;
5904*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE:
5905*8975f5c5SAndroid Build Coastguard Worker             {
5906*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(programExecutable);
5907*8975f5c5SAndroid Build Coastguard Worker                 invalidateCurrentDefaultUniforms();
5908*8975f5c5SAndroid Build Coastguard Worker                 updateAdvancedBlendEquations(programExecutable);
5909*8975f5c5SAndroid Build Coastguard Worker                 vk::GetImpl(programExecutable)->onProgramBind();
5910*8975f5c5SAndroid Build Coastguard Worker                 static_assert(
5911*8975f5c5SAndroid Build Coastguard Worker                     gl::state::DIRTY_BIT_TEXTURE_BINDINGS > gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE,
5912*8975f5c5SAndroid Build Coastguard Worker                     "Dirty bit order");
5913*8975f5c5SAndroid Build Coastguard Worker                 iter.setLaterBit(gl::state::DIRTY_BIT_TEXTURE_BINDINGS);
5914*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(invalidateCurrentShaderResources(command));
5915*8975f5c5SAndroid Build Coastguard Worker                 invalidateDriverUniforms();
5916*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(invalidateProgramExecutableHelper(context));
5917*8975f5c5SAndroid Build Coastguard Worker 
5918*8975f5c5SAndroid Build Coastguard Worker                 static_assert(
5919*8975f5c5SAndroid Build Coastguard Worker                     gl::state::DIRTY_BIT_SAMPLE_SHADING > gl::state::DIRTY_BIT_PROGRAM_EXECUTABLE,
5920*8975f5c5SAndroid Build Coastguard Worker                     "Dirty bit order");
5921*8975f5c5SAndroid Build Coastguard Worker                 if (getFeatures().explicitlyEnablePerSampleShading.enabled)
5922*8975f5c5SAndroid Build Coastguard Worker                 {
5923*8975f5c5SAndroid Build Coastguard Worker                     iter.setLaterBit(gl::state::DIRTY_BIT_SAMPLE_SHADING);
5924*8975f5c5SAndroid Build Coastguard Worker                 }
5925*8975f5c5SAndroid Build Coastguard Worker 
5926*8975f5c5SAndroid Build Coastguard Worker                 break;
5927*8975f5c5SAndroid Build Coastguard Worker             }
5928*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_SAMPLER_BINDINGS:
5929*8975f5c5SAndroid Build Coastguard Worker             {
5930*8975f5c5SAndroid Build Coastguard Worker                 static_assert(
5931*8975f5c5SAndroid Build Coastguard Worker                     gl::state::DIRTY_BIT_TEXTURE_BINDINGS > gl::state::DIRTY_BIT_SAMPLER_BINDINGS,
5932*8975f5c5SAndroid Build Coastguard Worker                     "Dirty bit order");
5933*8975f5c5SAndroid Build Coastguard Worker                 iter.setLaterBit(gl::state::DIRTY_BIT_TEXTURE_BINDINGS);
5934*8975f5c5SAndroid Build Coastguard Worker                 break;
5935*8975f5c5SAndroid Build Coastguard Worker             }
5936*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_TEXTURE_BINDINGS:
5937*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(invalidateCurrentTextures(context, command));
5938*8975f5c5SAndroid Build Coastguard Worker                 break;
5939*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
5940*8975f5c5SAndroid Build Coastguard Worker                 // Nothing to do.
5941*8975f5c5SAndroid Build Coastguard Worker                 break;
5942*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_IMAGE_BINDINGS:
5943*8975f5c5SAndroid Build Coastguard Worker                 static_assert(gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING >
5944*8975f5c5SAndroid Build Coastguard Worker                                   gl::state::DIRTY_BIT_IMAGE_BINDINGS,
5945*8975f5c5SAndroid Build Coastguard Worker                               "Dirty bit order");
5946*8975f5c5SAndroid Build Coastguard Worker                 iter.setLaterBit(gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
5947*8975f5c5SAndroid Build Coastguard Worker                 break;
5948*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
5949*8975f5c5SAndroid Build Coastguard Worker                 static_assert(gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING >
5950*8975f5c5SAndroid Build Coastguard Worker                                   gl::state::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING,
5951*8975f5c5SAndroid Build Coastguard Worker                               "Dirty bit order");
5952*8975f5c5SAndroid Build Coastguard Worker                 iter.setLaterBit(gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
5953*8975f5c5SAndroid Build Coastguard Worker                 break;
5954*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
5955*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(invalidateCurrentShaderUniformBuffers(command));
5956*8975f5c5SAndroid Build Coastguard Worker                 break;
5957*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
5958*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(invalidateCurrentShaderResources(command));
5959*8975f5c5SAndroid Build Coastguard Worker                 invalidateDriverUniforms();
5960*8975f5c5SAndroid Build Coastguard Worker                 break;
5961*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_MULTISAMPLING:
5962*8975f5c5SAndroid Build Coastguard Worker                 // When disabled, this should configure the pipeline to render as if single-sampled,
5963*8975f5c5SAndroid Build Coastguard Worker                 // and write the results to all samples of a pixel regardless of coverage. See
5964*8975f5c5SAndroid Build Coastguard Worker                 // EXT_multisample_compatibility.  This is not possible in Vulkan without some
5965*8975f5c5SAndroid Build Coastguard Worker                 // gymnastics, so continue multisampled rendering anyway.
5966*8975f5c5SAndroid Build Coastguard Worker                 // http://anglebug.com/42266123
5967*8975f5c5SAndroid Build Coastguard Worker                 //
5968*8975f5c5SAndroid Build Coastguard Worker                 // Potentially, the GLES1 renderer can switch rendering between two images and blit
5969*8975f5c5SAndroid Build Coastguard Worker                 // from one to the other when the mode changes.  Then this extension wouldn't need
5970*8975f5c5SAndroid Build Coastguard Worker                 // to be exposed.
5971*8975f5c5SAndroid Build Coastguard Worker                 iter.setLaterBit(gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
5972*8975f5c5SAndroid Build Coastguard Worker                 break;
5973*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_SAMPLE_ALPHA_TO_ONE:
5974*8975f5c5SAndroid Build Coastguard Worker                 // This is part of EXT_multisample_compatibility, and requires the alphaToOne Vulkan
5975*8975f5c5SAndroid Build Coastguard Worker                 // feature.
5976*8975f5c5SAndroid Build Coastguard Worker                 // http://anglebug.com/42266123
5977*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsPipelineDesc->updateAlphaToOneEnable(
5978*8975f5c5SAndroid Build Coastguard Worker                     &mGraphicsPipelineTransition,
5979*8975f5c5SAndroid Build Coastguard Worker                     glState.isMultisamplingEnabled() && glState.isSampleAlphaToOneEnabled());
5980*8975f5c5SAndroid Build Coastguard Worker                 break;
5981*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_SAMPLE_SHADING:
5982*8975f5c5SAndroid Build Coastguard Worker                 updateSampleShadingWithRasterizationSamples(drawFramebufferVk->getSamples());
5983*8975f5c5SAndroid Build Coastguard Worker                 break;
5984*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_COVERAGE_MODULATION:
5985*8975f5c5SAndroid Build Coastguard Worker                 break;
5986*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE:
5987*8975f5c5SAndroid Build Coastguard Worker                 break;
5988*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_CURRENT_VALUES:
5989*8975f5c5SAndroid Build Coastguard Worker             {
5990*8975f5c5SAndroid Build Coastguard Worker                 invalidateDefaultAttributes(glState.getAndResetDirtyCurrentValues());
5991*8975f5c5SAndroid Build Coastguard Worker                 break;
5992*8975f5c5SAndroid Build Coastguard Worker             }
5993*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_PROVOKING_VERTEX:
5994*8975f5c5SAndroid Build Coastguard Worker                 break;
5995*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_EXTENDED:
5996*8975f5c5SAndroid Build Coastguard Worker             {
5997*8975f5c5SAndroid Build Coastguard Worker                 for (auto extendedIter    = extendedDirtyBits.begin(),
5998*8975f5c5SAndroid Build Coastguard Worker                           extendedEndIter = extendedDirtyBits.end();
5999*8975f5c5SAndroid Build Coastguard Worker                      extendedIter != extendedEndIter; ++extendedIter)
6000*8975f5c5SAndroid Build Coastguard Worker                 {
6001*8975f5c5SAndroid Build Coastguard Worker                     const size_t extendedDirtyBit = *extendedIter;
6002*8975f5c5SAndroid Build Coastguard Worker                     switch (extendedDirtyBit)
6003*8975f5c5SAndroid Build Coastguard Worker                     {
6004*8975f5c5SAndroid Build Coastguard Worker                         case gl::state::EXTENDED_DIRTY_BIT_CLIP_CONTROL:
6005*8975f5c5SAndroid Build Coastguard Worker                             updateViewport(vk::GetImpl(glState.getDrawFramebuffer()),
6006*8975f5c5SAndroid Build Coastguard Worker                                            glState.getViewport(), glState.getNearPlane(),
6007*8975f5c5SAndroid Build Coastguard Worker                                            glState.getFarPlane());
6008*8975f5c5SAndroid Build Coastguard Worker                             // Since we are flipping the y coordinate, update front face state
6009*8975f5c5SAndroid Build Coastguard Worker                             updateFrontFace();
6010*8975f5c5SAndroid Build Coastguard Worker                             updateScissor(glState);
6011*8975f5c5SAndroid Build Coastguard Worker 
6012*8975f5c5SAndroid Build Coastguard Worker                             // If VK_EXT_depth_clip_control is not enabled, there's nothing needed
6013*8975f5c5SAndroid Build Coastguard Worker                             // for depth correction for EXT_clip_control.
6014*8975f5c5SAndroid Build Coastguard Worker                             // glState will be used to toggle control path of depth correction code
6015*8975f5c5SAndroid Build Coastguard Worker                             // in SPIR-V tranform options.
6016*8975f5c5SAndroid Build Coastguard Worker                             if (getFeatures().supportsDepthClipControl.enabled)
6017*8975f5c5SAndroid Build Coastguard Worker                             {
6018*8975f5c5SAndroid Build Coastguard Worker                                 mGraphicsPipelineDesc->updateDepthClipControl(
6019*8975f5c5SAndroid Build Coastguard Worker                                     &mGraphicsPipelineTransition,
6020*8975f5c5SAndroid Build Coastguard Worker                                     !glState.isClipDepthModeZeroToOne());
6021*8975f5c5SAndroid Build Coastguard Worker                             }
6022*8975f5c5SAndroid Build Coastguard Worker                             else
6023*8975f5c5SAndroid Build Coastguard Worker                             {
6024*8975f5c5SAndroid Build Coastguard Worker                                 invalidateGraphicsDriverUniforms();
6025*8975f5c5SAndroid Build Coastguard Worker                             }
6026*8975f5c5SAndroid Build Coastguard Worker                             break;
6027*8975f5c5SAndroid Build Coastguard Worker                         case gl::state::EXTENDED_DIRTY_BIT_CLIP_DISTANCES:
6028*8975f5c5SAndroid Build Coastguard Worker                             invalidateGraphicsDriverUniforms();
6029*8975f5c5SAndroid Build Coastguard Worker                             break;
6030*8975f5c5SAndroid Build Coastguard Worker                         case gl::state::EXTENDED_DIRTY_BIT_DEPTH_CLAMP_ENABLED:
6031*8975f5c5SAndroid Build Coastguard Worker                             // TODO(https://anglebug.com/42266182): Use EDS3
6032*8975f5c5SAndroid Build Coastguard Worker                             mGraphicsPipelineDesc->updateDepthClampEnabled(
6033*8975f5c5SAndroid Build Coastguard Worker                                 &mGraphicsPipelineTransition, glState.isDepthClampEnabled());
6034*8975f5c5SAndroid Build Coastguard Worker                             break;
6035*8975f5c5SAndroid Build Coastguard Worker                         case gl::state::EXTENDED_DIRTY_BIT_MIPMAP_GENERATION_HINT:
6036*8975f5c5SAndroid Build Coastguard Worker                             break;
6037*8975f5c5SAndroid Build Coastguard Worker                         case gl::state::EXTENDED_DIRTY_BIT_POLYGON_MODE:
6038*8975f5c5SAndroid Build Coastguard Worker                             // TODO(https://anglebug.com/42266182): Use EDS3
6039*8975f5c5SAndroid Build Coastguard Worker                             mGraphicsPipelineDesc->updatePolygonMode(&mGraphicsPipelineTransition,
6040*8975f5c5SAndroid Build Coastguard Worker                                                                      glState.getPolygonMode());
6041*8975f5c5SAndroid Build Coastguard Worker                             // When polygon mode is changed, depth bias might need to be toggled.
6042*8975f5c5SAndroid Build Coastguard Worker                             static_assert(
6043*8975f5c5SAndroid Build Coastguard Worker                                 gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED >
6044*8975f5c5SAndroid Build Coastguard Worker                                     gl::state::EXTENDED_DIRTY_BIT_POLYGON_MODE,
6045*8975f5c5SAndroid Build Coastguard Worker                                 "Dirty bit order");
6046*8975f5c5SAndroid Build Coastguard Worker                             extendedIter.setLaterBit(
6047*8975f5c5SAndroid Build Coastguard Worker                                 gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED);
6048*8975f5c5SAndroid Build Coastguard Worker                             break;
6049*8975f5c5SAndroid Build Coastguard Worker                         case gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_POINT_ENABLED:
6050*8975f5c5SAndroid Build Coastguard Worker                         case gl::state::EXTENDED_DIRTY_BIT_POLYGON_OFFSET_LINE_ENABLED:
6051*8975f5c5SAndroid Build Coastguard Worker                             if (mRenderer->getFeatures().useDepthBiasEnableDynamicState.enabled)
6052*8975f5c5SAndroid Build Coastguard Worker                             {
6053*8975f5c5SAndroid Build Coastguard Worker                                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_DEPTH_BIAS_ENABLE);
6054*8975f5c5SAndroid Build Coastguard Worker                             }
6055*8975f5c5SAndroid Build Coastguard Worker                             else
6056*8975f5c5SAndroid Build Coastguard Worker                             {
6057*8975f5c5SAndroid Build Coastguard Worker                                 mGraphicsPipelineDesc->updatePolygonOffsetEnabled(
6058*8975f5c5SAndroid Build Coastguard Worker                                     &mGraphicsPipelineTransition, glState.isPolygonOffsetEnabled());
6059*8975f5c5SAndroid Build Coastguard Worker                             }
6060*8975f5c5SAndroid Build Coastguard Worker                             break;
6061*8975f5c5SAndroid Build Coastguard Worker                         case gl::state::EXTENDED_DIRTY_BIT_SHADER_DERIVATIVE_HINT:
6062*8975f5c5SAndroid Build Coastguard Worker                             break;
6063*8975f5c5SAndroid Build Coastguard Worker                         case gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED:
6064*8975f5c5SAndroid Build Coastguard Worker                             mGraphicsPipelineDesc->updateLogicOpEnabled(
6065*8975f5c5SAndroid Build Coastguard Worker                                 &mGraphicsPipelineTransition, glState.isLogicOpEnabled());
6066*8975f5c5SAndroid Build Coastguard Worker                             break;
6067*8975f5c5SAndroid Build Coastguard Worker                         case gl::state::EXTENDED_DIRTY_BIT_LOGIC_OP:
6068*8975f5c5SAndroid Build Coastguard Worker                             if (mRenderer->getFeatures().supportsLogicOpDynamicState.enabled)
6069*8975f5c5SAndroid Build Coastguard Worker                             {
6070*8975f5c5SAndroid Build Coastguard Worker                                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_LOGIC_OP);
6071*8975f5c5SAndroid Build Coastguard Worker                             }
6072*8975f5c5SAndroid Build Coastguard Worker                             else
6073*8975f5c5SAndroid Build Coastguard Worker                             {
6074*8975f5c5SAndroid Build Coastguard Worker                                 mGraphicsPipelineDesc->updateLogicOp(
6075*8975f5c5SAndroid Build Coastguard Worker                                     &mGraphicsPipelineTransition,
6076*8975f5c5SAndroid Build Coastguard Worker                                     gl_vk::GetLogicOp(gl::ToGLenum(glState.getLogicOp())));
6077*8975f5c5SAndroid Build Coastguard Worker                             }
6078*8975f5c5SAndroid Build Coastguard Worker                             break;
6079*8975f5c5SAndroid Build Coastguard Worker                         case gl::state::EXTENDED_DIRTY_BIT_SHADING_RATE:
6080*8975f5c5SAndroid Build Coastguard Worker                             if (getFeatures().supportsFragmentShadingRate.enabled)
6081*8975f5c5SAndroid Build Coastguard Worker                             {
6082*8975f5c5SAndroid Build Coastguard Worker                                 mGraphicsDirtyBits.set(DIRTY_BIT_DYNAMIC_FRAGMENT_SHADING_RATE);
6083*8975f5c5SAndroid Build Coastguard Worker                             }
6084*8975f5c5SAndroid Build Coastguard Worker                             break;
6085*8975f5c5SAndroid Build Coastguard Worker                         case gl::state::EXTENDED_DIRTY_BIT_BLEND_ADVANCED_COHERENT:
6086*8975f5c5SAndroid Build Coastguard Worker                             break;
6087*8975f5c5SAndroid Build Coastguard Worker                         default:
6088*8975f5c5SAndroid Build Coastguard Worker                             UNREACHABLE();
6089*8975f5c5SAndroid Build Coastguard Worker                     }
6090*8975f5c5SAndroid Build Coastguard Worker                 }
6091*8975f5c5SAndroid Build Coastguard Worker                 break;
6092*8975f5c5SAndroid Build Coastguard Worker             }
6093*8975f5c5SAndroid Build Coastguard Worker             case gl::state::DIRTY_BIT_PATCH_VERTICES:
6094*8975f5c5SAndroid Build Coastguard Worker                 mGraphicsPipelineDesc->updatePatchVertices(&mGraphicsPipelineTransition,
6095*8975f5c5SAndroid Build Coastguard Worker                                                            glState.getPatchVertices());
6096*8975f5c5SAndroid Build Coastguard Worker                 break;
6097*8975f5c5SAndroid Build Coastguard Worker             default:
6098*8975f5c5SAndroid Build Coastguard Worker                 UNREACHABLE();
6099*8975f5c5SAndroid Build Coastguard Worker                 break;
6100*8975f5c5SAndroid Build Coastguard Worker         }
6101*8975f5c5SAndroid Build Coastguard Worker     }
6102*8975f5c5SAndroid Build Coastguard Worker 
6103*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
6104*8975f5c5SAndroid Build Coastguard Worker }
6105*8975f5c5SAndroid Build Coastguard Worker 
getGPUDisjoint()6106*8975f5c5SAndroid Build Coastguard Worker GLint ContextVk::getGPUDisjoint()
6107*8975f5c5SAndroid Build Coastguard Worker {
6108*8975f5c5SAndroid Build Coastguard Worker     // No extension seems to be available to query this information.
6109*8975f5c5SAndroid Build Coastguard Worker     return 0;
6110*8975f5c5SAndroid Build Coastguard Worker }
6111*8975f5c5SAndroid Build Coastguard Worker 
getTimestamp()6112*8975f5c5SAndroid Build Coastguard Worker GLint64 ContextVk::getTimestamp()
6113*8975f5c5SAndroid Build Coastguard Worker {
6114*8975f5c5SAndroid Build Coastguard Worker     // This function should only be called if timestamp queries are available.
6115*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mRenderer->getQueueFamilyProperties().timestampValidBits > 0);
6116*8975f5c5SAndroid Build Coastguard Worker 
6117*8975f5c5SAndroid Build Coastguard Worker     uint64_t timestamp = 0;
6118*8975f5c5SAndroid Build Coastguard Worker 
6119*8975f5c5SAndroid Build Coastguard Worker     (void)getTimestamp(&timestamp);
6120*8975f5c5SAndroid Build Coastguard Worker 
6121*8975f5c5SAndroid Build Coastguard Worker     return static_cast<GLint64>(timestamp);
6122*8975f5c5SAndroid Build Coastguard Worker }
6123*8975f5c5SAndroid Build Coastguard Worker 
onMakeCurrent(const gl::Context * context)6124*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::onMakeCurrent(const gl::Context *context)
6125*8975f5c5SAndroid Build Coastguard Worker {
6126*8975f5c5SAndroid Build Coastguard Worker     mRenderer->reloadVolkIfNeeded();
6127*8975f5c5SAndroid Build Coastguard Worker 
6128*8975f5c5SAndroid Build Coastguard Worker     if (mCurrentQueueSerialIndex == kInvalidQueueSerialIndex)
6129*8975f5c5SAndroid Build Coastguard Worker     {
6130*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(allocateQueueSerialIndex());
6131*8975f5c5SAndroid Build Coastguard Worker     }
6132*8975f5c5SAndroid Build Coastguard Worker 
6133*8975f5c5SAndroid Build Coastguard Worker     // Flip viewports if the user did not request that the surface is flipped.
6134*8975f5c5SAndroid Build Coastguard Worker     const egl::Surface *drawSurface = context->getCurrentDrawSurface();
6135*8975f5c5SAndroid Build Coastguard Worker     const egl::Surface *readSurface = context->getCurrentReadSurface();
6136*8975f5c5SAndroid Build Coastguard Worker     mFlipYForCurrentSurface =
6137*8975f5c5SAndroid Build Coastguard Worker         drawSurface != nullptr &&
6138*8975f5c5SAndroid Build Coastguard Worker         !IsMaskFlagSet(drawSurface->getOrientation(), EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE);
6139*8975f5c5SAndroid Build Coastguard Worker 
6140*8975f5c5SAndroid Build Coastguard Worker     if (drawSurface && drawSurface->getType() == EGL_WINDOW_BIT)
6141*8975f5c5SAndroid Build Coastguard Worker     {
6142*8975f5c5SAndroid Build Coastguard Worker         mCurrentWindowSurface = GetImplAs<WindowSurfaceVk>(drawSurface);
6143*8975f5c5SAndroid Build Coastguard Worker     }
6144*8975f5c5SAndroid Build Coastguard Worker     else
6145*8975f5c5SAndroid Build Coastguard Worker     {
6146*8975f5c5SAndroid Build Coastguard Worker         mCurrentWindowSurface = nullptr;
6147*8975f5c5SAndroid Build Coastguard Worker     }
6148*8975f5c5SAndroid Build Coastguard Worker 
6149*8975f5c5SAndroid Build Coastguard Worker     const gl::State &glState = context->getState();
6150*8975f5c5SAndroid Build Coastguard Worker     updateFlipViewportDrawFramebuffer(glState);
6151*8975f5c5SAndroid Build Coastguard Worker     updateFlipViewportReadFramebuffer(glState);
6152*8975f5c5SAndroid Build Coastguard Worker     updateSurfaceRotationDrawFramebuffer(glState, drawSurface);
6153*8975f5c5SAndroid Build Coastguard Worker     updateSurfaceRotationReadFramebuffer(glState, readSurface);
6154*8975f5c5SAndroid Build Coastguard Worker 
6155*8975f5c5SAndroid Build Coastguard Worker     invalidateDriverUniforms();
6156*8975f5c5SAndroid Build Coastguard Worker 
6157*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6158*8975f5c5SAndroid Build Coastguard Worker     if (executable && executable->hasTransformFeedbackOutput() &&
6159*8975f5c5SAndroid Build Coastguard Worker         mState.isTransformFeedbackActive())
6160*8975f5c5SAndroid Build Coastguard Worker     {
6161*8975f5c5SAndroid Build Coastguard Worker         onTransformFeedbackStateChanged();
6162*8975f5c5SAndroid Build Coastguard Worker         if (getFeatures().supportsTransformFeedbackExtension.enabled)
6163*8975f5c5SAndroid Build Coastguard Worker         {
6164*8975f5c5SAndroid Build Coastguard Worker             mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
6165*8975f5c5SAndroid Build Coastguard Worker         }
6166*8975f5c5SAndroid Build Coastguard Worker     }
6167*8975f5c5SAndroid Build Coastguard Worker 
6168*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
6169*8975f5c5SAndroid Build Coastguard Worker }
6170*8975f5c5SAndroid Build Coastguard Worker 
onUnMakeCurrent(const gl::Context * context)6171*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::onUnMakeCurrent(const gl::Context *context)
6172*8975f5c5SAndroid Build Coastguard Worker {
6173*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr, RenderPassClosureReason::ContextChange));
6174*8975f5c5SAndroid Build Coastguard Worker     mCurrentWindowSurface = nullptr;
6175*8975f5c5SAndroid Build Coastguard Worker 
6176*8975f5c5SAndroid Build Coastguard Worker     if (mCurrentQueueSerialIndex != kInvalidQueueSerialIndex)
6177*8975f5c5SAndroid Build Coastguard Worker     {
6178*8975f5c5SAndroid Build Coastguard Worker         releaseQueueSerialIndex();
6179*8975f5c5SAndroid Build Coastguard Worker     }
6180*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
6181*8975f5c5SAndroid Build Coastguard Worker }
6182*8975f5c5SAndroid Build Coastguard Worker 
onSurfaceUnMakeCurrent(WindowSurfaceVk * surface)6183*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::onSurfaceUnMakeCurrent(WindowSurfaceVk *surface)
6184*8975f5c5SAndroid Build Coastguard Worker {
6185*8975f5c5SAndroid Build Coastguard Worker     // It is possible to destroy "WindowSurfaceVk" while not all rendering commands are submitted:
6186*8975f5c5SAndroid Build Coastguard Worker     // 1. Make "WindowSurfaceVk" current.
6187*8975f5c5SAndroid Build Coastguard Worker     // 2. Draw something.
6188*8975f5c5SAndroid Build Coastguard Worker     // 3. Make other Surface current (same Context).
6189*8975f5c5SAndroid Build Coastguard Worker     // 4. (optional) Draw something.
6190*8975f5c5SAndroid Build Coastguard Worker     // 5. Delete "WindowSurfaceVk".
6191*8975f5c5SAndroid Build Coastguard Worker     // 6. UnMake the Context from current.
6192*8975f5c5SAndroid Build Coastguard Worker     // Flush all command to the GPU while still having access to the Context.
6193*8975f5c5SAndroid Build Coastguard Worker 
6194*8975f5c5SAndroid Build Coastguard Worker     // The above "onUnMakeCurrent()" may have already been called.
6195*8975f5c5SAndroid Build Coastguard Worker     if (mCurrentQueueSerialIndex != kInvalidQueueSerialIndex)
6196*8975f5c5SAndroid Build Coastguard Worker     {
6197*8975f5c5SAndroid Build Coastguard Worker         // May be nullptr if only used as a readSurface.
6198*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mCurrentWindowSurface == surface || mCurrentWindowSurface == nullptr);
6199*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr,
6200*8975f5c5SAndroid Build Coastguard Worker                                          RenderPassClosureReason::SurfaceUnMakeCurrent));
6201*8975f5c5SAndroid Build Coastguard Worker         mCurrentWindowSurface = nullptr;
6202*8975f5c5SAndroid Build Coastguard Worker     }
6203*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mCurrentWindowSurface == nullptr);
6204*8975f5c5SAndroid Build Coastguard Worker 
6205*8975f5c5SAndroid Build Coastguard Worker     // Everything must be flushed and submitted.
6206*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mOutsideRenderPassCommands->empty());
6207*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mRenderPassCommands->started());
6208*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mWaitSemaphores.empty());
6209*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mHasWaitSemaphoresPendingSubmission);
6210*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mLastSubmittedQueueSerial == mLastFlushedQueueSerial);
6211*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
6212*8975f5c5SAndroid Build Coastguard Worker }
6213*8975f5c5SAndroid Build Coastguard Worker 
onSurfaceUnMakeCurrent(OffscreenSurfaceVk * surface)6214*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::onSurfaceUnMakeCurrent(OffscreenSurfaceVk *surface)
6215*8975f5c5SAndroid Build Coastguard Worker {
6216*8975f5c5SAndroid Build Coastguard Worker     // It is possible to destroy "OffscreenSurfaceVk" while RenderPass is still opened:
6217*8975f5c5SAndroid Build Coastguard Worker     // 1. Make "OffscreenSurfaceVk" current.
6218*8975f5c5SAndroid Build Coastguard Worker     // 2. Draw something with RenderPass.
6219*8975f5c5SAndroid Build Coastguard Worker     // 3. Make other Surface current (same Context)
6220*8975f5c5SAndroid Build Coastguard Worker     // 4. Delete "OffscreenSurfaceVk".
6221*8975f5c5SAndroid Build Coastguard Worker     // 5. UnMake the Context from current.
6222*8975f5c5SAndroid Build Coastguard Worker     // End RenderPass to avoid crash in the "RenderPassCommandBufferHelper::endRenderPass()".
6223*8975f5c5SAndroid Build Coastguard Worker     // Flush commands unconditionally even if surface is not used in the RenderPass to fix possible
6224*8975f5c5SAndroid Build Coastguard Worker     // problems related to other accesses. "flushAndSubmitCommands()" is not required because
6225*8975f5c5SAndroid Build Coastguard Worker     // "OffscreenSurfaceVk" uses GC.
6226*8975f5c5SAndroid Build Coastguard Worker 
6227*8975f5c5SAndroid Build Coastguard Worker     // The above "onUnMakeCurrent()" may have already been called.
6228*8975f5c5SAndroid Build Coastguard Worker     if (mCurrentQueueSerialIndex != kInvalidQueueSerialIndex)
6229*8975f5c5SAndroid Build Coastguard Worker     {
6230*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushCommandsAndEndRenderPass(RenderPassClosureReason::SurfaceUnMakeCurrent));
6231*8975f5c5SAndroid Build Coastguard Worker     }
6232*8975f5c5SAndroid Build Coastguard Worker 
6233*8975f5c5SAndroid Build Coastguard Worker     // Everything must be flushed but may be pending submission.
6234*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mOutsideRenderPassCommands->empty());
6235*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mRenderPassCommands->started());
6236*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mWaitSemaphores.empty());
6237*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
6238*8975f5c5SAndroid Build Coastguard Worker }
6239*8975f5c5SAndroid Build Coastguard Worker 
updateFlipViewportDrawFramebuffer(const gl::State & glState)6240*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateFlipViewportDrawFramebuffer(const gl::State &glState)
6241*8975f5c5SAndroid Build Coastguard Worker {
6242*8975f5c5SAndroid Build Coastguard Worker     // The default framebuffer (originating from the swapchain) is rendered upside-down due to the
6243*8975f5c5SAndroid Build Coastguard Worker     // difference in the coordinate systems of Vulkan and GLES.  Rendering upside-down has the
6244*8975f5c5SAndroid Build Coastguard Worker     // effect that rendering is done the same way as OpenGL.  The KHR_MAINTENANCE_1 extension is
6245*8975f5c5SAndroid Build Coastguard Worker     // subsequently enabled to allow negative viewports.  We inverse rendering to the backbuffer by
6246*8975f5c5SAndroid Build Coastguard Worker     // reversing the height of the viewport and increasing Y by the height.  So if the viewport was
6247*8975f5c5SAndroid Build Coastguard Worker     // (0, 0, width, height), it becomes (0, height, width, -height).  Unfortunately, when we start
6248*8975f5c5SAndroid Build Coastguard Worker     // doing this, we also need to adjust a number of places since the rendering now happens
6249*8975f5c5SAndroid Build Coastguard Worker     // upside-down.  Affected places so far:
6250*8975f5c5SAndroid Build Coastguard Worker     //
6251*8975f5c5SAndroid Build Coastguard Worker     // - readPixels
6252*8975f5c5SAndroid Build Coastguard Worker     // - copyTexImage
6253*8975f5c5SAndroid Build Coastguard Worker     // - framebuffer blit
6254*8975f5c5SAndroid Build Coastguard Worker     // - generating mipmaps
6255*8975f5c5SAndroid Build Coastguard Worker     // - Point sprites tests
6256*8975f5c5SAndroid Build Coastguard Worker     // - texStorage
6257*8975f5c5SAndroid Build Coastguard Worker     gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
6258*8975f5c5SAndroid Build Coastguard Worker     mFlipViewportForDrawFramebuffer  = drawFramebuffer->isDefault();
6259*8975f5c5SAndroid Build Coastguard Worker }
6260*8975f5c5SAndroid Build Coastguard Worker 
updateFlipViewportReadFramebuffer(const gl::State & glState)6261*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateFlipViewportReadFramebuffer(const gl::State &glState)
6262*8975f5c5SAndroid Build Coastguard Worker {
6263*8975f5c5SAndroid Build Coastguard Worker     gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
6264*8975f5c5SAndroid Build Coastguard Worker     mFlipViewportForReadFramebuffer  = readFramebuffer->isDefault();
6265*8975f5c5SAndroid Build Coastguard Worker }
6266*8975f5c5SAndroid Build Coastguard Worker 
updateSurfaceRotationDrawFramebuffer(const gl::State & glState,const egl::Surface * currentDrawSurface)6267*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateSurfaceRotationDrawFramebuffer(const gl::State &glState,
6268*8975f5c5SAndroid Build Coastguard Worker                                                      const egl::Surface *currentDrawSurface)
6269*8975f5c5SAndroid Build Coastguard Worker {
6270*8975f5c5SAndroid Build Coastguard Worker     const SurfaceRotation rotation =
6271*8975f5c5SAndroid Build Coastguard Worker         getSurfaceRotationImpl(glState.getDrawFramebuffer(), currentDrawSurface);
6272*8975f5c5SAndroid Build Coastguard Worker     mCurrentRotationDrawFramebuffer = rotation;
6273*8975f5c5SAndroid Build Coastguard Worker 
6274*8975f5c5SAndroid Build Coastguard Worker     if (!getFeatures().preferDriverUniformOverSpecConst.enabled)
6275*8975f5c5SAndroid Build Coastguard Worker     {
6276*8975f5c5SAndroid Build Coastguard Worker         const bool isRotatedAspectRatio = IsRotatedAspectRatio(rotation);
6277*8975f5c5SAndroid Build Coastguard Worker         // Update spec consts
6278*8975f5c5SAndroid Build Coastguard Worker         if (isRotatedAspectRatio != mGraphicsPipelineDesc->getSurfaceRotation())
6279*8975f5c5SAndroid Build Coastguard Worker         {
6280*8975f5c5SAndroid Build Coastguard Worker             // surface rotation are specialization constants, which affects program compilation.
6281*8975f5c5SAndroid Build Coastguard Worker             // When rotation changes, we need to update GraphicsPipelineDesc so that the correct
6282*8975f5c5SAndroid Build Coastguard Worker             // pipeline program object will be retrieved.
6283*8975f5c5SAndroid Build Coastguard Worker             mGraphicsPipelineDesc->updateSurfaceRotation(&mGraphicsPipelineTransition,
6284*8975f5c5SAndroid Build Coastguard Worker                                                          isRotatedAspectRatio);
6285*8975f5c5SAndroid Build Coastguard Worker             invalidateCurrentGraphicsPipeline();
6286*8975f5c5SAndroid Build Coastguard Worker         }
6287*8975f5c5SAndroid Build Coastguard Worker     }
6288*8975f5c5SAndroid Build Coastguard Worker }
6289*8975f5c5SAndroid Build Coastguard Worker 
updateSurfaceRotationReadFramebuffer(const gl::State & glState,const egl::Surface * currentReadSurface)6290*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateSurfaceRotationReadFramebuffer(const gl::State &glState,
6291*8975f5c5SAndroid Build Coastguard Worker                                                      const egl::Surface *currentReadSurface)
6292*8975f5c5SAndroid Build Coastguard Worker {
6293*8975f5c5SAndroid Build Coastguard Worker     mCurrentRotationReadFramebuffer =
6294*8975f5c5SAndroid Build Coastguard Worker         getSurfaceRotationImpl(glState.getReadFramebuffer(), currentReadSurface);
6295*8975f5c5SAndroid Build Coastguard Worker }
6296*8975f5c5SAndroid Build Coastguard Worker 
getNativeCaps() const6297*8975f5c5SAndroid Build Coastguard Worker gl::Caps ContextVk::getNativeCaps() const
6298*8975f5c5SAndroid Build Coastguard Worker {
6299*8975f5c5SAndroid Build Coastguard Worker     return mRenderer->getNativeCaps();
6300*8975f5c5SAndroid Build Coastguard Worker }
6301*8975f5c5SAndroid Build Coastguard Worker 
getNativeTextureCaps() const6302*8975f5c5SAndroid Build Coastguard Worker const gl::TextureCapsMap &ContextVk::getNativeTextureCaps() const
6303*8975f5c5SAndroid Build Coastguard Worker {
6304*8975f5c5SAndroid Build Coastguard Worker     return mRenderer->getNativeTextureCaps();
6305*8975f5c5SAndroid Build Coastguard Worker }
6306*8975f5c5SAndroid Build Coastguard Worker 
getNativeExtensions() const6307*8975f5c5SAndroid Build Coastguard Worker const gl::Extensions &ContextVk::getNativeExtensions() const
6308*8975f5c5SAndroid Build Coastguard Worker {
6309*8975f5c5SAndroid Build Coastguard Worker     return mRenderer->getNativeExtensions();
6310*8975f5c5SAndroid Build Coastguard Worker }
6311*8975f5c5SAndroid Build Coastguard Worker 
getNativeLimitations() const6312*8975f5c5SAndroid Build Coastguard Worker const gl::Limitations &ContextVk::getNativeLimitations() const
6313*8975f5c5SAndroid Build Coastguard Worker {
6314*8975f5c5SAndroid Build Coastguard Worker     return mRenderer->getNativeLimitations();
6315*8975f5c5SAndroid Build Coastguard Worker }
6316*8975f5c5SAndroid Build Coastguard Worker 
getNativePixelLocalStorageOptions() const6317*8975f5c5SAndroid Build Coastguard Worker const ShPixelLocalStorageOptions &ContextVk::getNativePixelLocalStorageOptions() const
6318*8975f5c5SAndroid Build Coastguard Worker {
6319*8975f5c5SAndroid Build Coastguard Worker     return mRenderer->getNativePixelLocalStorageOptions();
6320*8975f5c5SAndroid Build Coastguard Worker }
6321*8975f5c5SAndroid Build Coastguard Worker 
createCompiler()6322*8975f5c5SAndroid Build Coastguard Worker CompilerImpl *ContextVk::createCompiler()
6323*8975f5c5SAndroid Build Coastguard Worker {
6324*8975f5c5SAndroid Build Coastguard Worker     return new CompilerVk();
6325*8975f5c5SAndroid Build Coastguard Worker }
6326*8975f5c5SAndroid Build Coastguard Worker 
createShader(const gl::ShaderState & state)6327*8975f5c5SAndroid Build Coastguard Worker ShaderImpl *ContextVk::createShader(const gl::ShaderState &state)
6328*8975f5c5SAndroid Build Coastguard Worker {
6329*8975f5c5SAndroid Build Coastguard Worker     return new ShaderVk(state);
6330*8975f5c5SAndroid Build Coastguard Worker }
6331*8975f5c5SAndroid Build Coastguard Worker 
createProgram(const gl::ProgramState & state)6332*8975f5c5SAndroid Build Coastguard Worker ProgramImpl *ContextVk::createProgram(const gl::ProgramState &state)
6333*8975f5c5SAndroid Build Coastguard Worker {
6334*8975f5c5SAndroid Build Coastguard Worker     return new ProgramVk(state);
6335*8975f5c5SAndroid Build Coastguard Worker }
6336*8975f5c5SAndroid Build Coastguard Worker 
createProgramExecutable(const gl::ProgramExecutable * executable)6337*8975f5c5SAndroid Build Coastguard Worker ProgramExecutableImpl *ContextVk::createProgramExecutable(const gl::ProgramExecutable *executable)
6338*8975f5c5SAndroid Build Coastguard Worker {
6339*8975f5c5SAndroid Build Coastguard Worker     return new ProgramExecutableVk(executable);
6340*8975f5c5SAndroid Build Coastguard Worker }
6341*8975f5c5SAndroid Build Coastguard Worker 
createFramebuffer(const gl::FramebufferState & state)6342*8975f5c5SAndroid Build Coastguard Worker FramebufferImpl *ContextVk::createFramebuffer(const gl::FramebufferState &state)
6343*8975f5c5SAndroid Build Coastguard Worker {
6344*8975f5c5SAndroid Build Coastguard Worker     return new FramebufferVk(mRenderer, state);
6345*8975f5c5SAndroid Build Coastguard Worker }
6346*8975f5c5SAndroid Build Coastguard Worker 
createTexture(const gl::TextureState & state)6347*8975f5c5SAndroid Build Coastguard Worker TextureImpl *ContextVk::createTexture(const gl::TextureState &state)
6348*8975f5c5SAndroid Build Coastguard Worker {
6349*8975f5c5SAndroid Build Coastguard Worker     return new TextureVk(state, mRenderer);
6350*8975f5c5SAndroid Build Coastguard Worker }
6351*8975f5c5SAndroid Build Coastguard Worker 
createRenderbuffer(const gl::RenderbufferState & state)6352*8975f5c5SAndroid Build Coastguard Worker RenderbufferImpl *ContextVk::createRenderbuffer(const gl::RenderbufferState &state)
6353*8975f5c5SAndroid Build Coastguard Worker {
6354*8975f5c5SAndroid Build Coastguard Worker     return new RenderbufferVk(state);
6355*8975f5c5SAndroid Build Coastguard Worker }
6356*8975f5c5SAndroid Build Coastguard Worker 
createBuffer(const gl::BufferState & state)6357*8975f5c5SAndroid Build Coastguard Worker BufferImpl *ContextVk::createBuffer(const gl::BufferState &state)
6358*8975f5c5SAndroid Build Coastguard Worker {
6359*8975f5c5SAndroid Build Coastguard Worker     return new BufferVk(state);
6360*8975f5c5SAndroid Build Coastguard Worker }
6361*8975f5c5SAndroid Build Coastguard Worker 
createVertexArray(const gl::VertexArrayState & state)6362*8975f5c5SAndroid Build Coastguard Worker VertexArrayImpl *ContextVk::createVertexArray(const gl::VertexArrayState &state)
6363*8975f5c5SAndroid Build Coastguard Worker {
6364*8975f5c5SAndroid Build Coastguard Worker     return new VertexArrayVk(this, state);
6365*8975f5c5SAndroid Build Coastguard Worker }
6366*8975f5c5SAndroid Build Coastguard Worker 
createQuery(gl::QueryType type)6367*8975f5c5SAndroid Build Coastguard Worker QueryImpl *ContextVk::createQuery(gl::QueryType type)
6368*8975f5c5SAndroid Build Coastguard Worker {
6369*8975f5c5SAndroid Build Coastguard Worker     return new QueryVk(type);
6370*8975f5c5SAndroid Build Coastguard Worker }
6371*8975f5c5SAndroid Build Coastguard Worker 
createFenceNV()6372*8975f5c5SAndroid Build Coastguard Worker FenceNVImpl *ContextVk::createFenceNV()
6373*8975f5c5SAndroid Build Coastguard Worker {
6374*8975f5c5SAndroid Build Coastguard Worker     return new FenceNVVk();
6375*8975f5c5SAndroid Build Coastguard Worker }
6376*8975f5c5SAndroid Build Coastguard Worker 
createSync()6377*8975f5c5SAndroid Build Coastguard Worker SyncImpl *ContextVk::createSync()
6378*8975f5c5SAndroid Build Coastguard Worker {
6379*8975f5c5SAndroid Build Coastguard Worker     return new SyncVk();
6380*8975f5c5SAndroid Build Coastguard Worker }
6381*8975f5c5SAndroid Build Coastguard Worker 
createTransformFeedback(const gl::TransformFeedbackState & state)6382*8975f5c5SAndroid Build Coastguard Worker TransformFeedbackImpl *ContextVk::createTransformFeedback(const gl::TransformFeedbackState &state)
6383*8975f5c5SAndroid Build Coastguard Worker {
6384*8975f5c5SAndroid Build Coastguard Worker     return new TransformFeedbackVk(state);
6385*8975f5c5SAndroid Build Coastguard Worker }
6386*8975f5c5SAndroid Build Coastguard Worker 
createSampler(const gl::SamplerState & state)6387*8975f5c5SAndroid Build Coastguard Worker SamplerImpl *ContextVk::createSampler(const gl::SamplerState &state)
6388*8975f5c5SAndroid Build Coastguard Worker {
6389*8975f5c5SAndroid Build Coastguard Worker     return new SamplerVk(state);
6390*8975f5c5SAndroid Build Coastguard Worker }
6391*8975f5c5SAndroid Build Coastguard Worker 
createProgramPipeline(const gl::ProgramPipelineState & state)6392*8975f5c5SAndroid Build Coastguard Worker ProgramPipelineImpl *ContextVk::createProgramPipeline(const gl::ProgramPipelineState &state)
6393*8975f5c5SAndroid Build Coastguard Worker {
6394*8975f5c5SAndroid Build Coastguard Worker     return new ProgramPipelineVk(state);
6395*8975f5c5SAndroid Build Coastguard Worker }
6396*8975f5c5SAndroid Build Coastguard Worker 
createMemoryObject()6397*8975f5c5SAndroid Build Coastguard Worker MemoryObjectImpl *ContextVk::createMemoryObject()
6398*8975f5c5SAndroid Build Coastguard Worker {
6399*8975f5c5SAndroid Build Coastguard Worker     return new MemoryObjectVk();
6400*8975f5c5SAndroid Build Coastguard Worker }
6401*8975f5c5SAndroid Build Coastguard Worker 
createSemaphore()6402*8975f5c5SAndroid Build Coastguard Worker SemaphoreImpl *ContextVk::createSemaphore()
6403*8975f5c5SAndroid Build Coastguard Worker {
6404*8975f5c5SAndroid Build Coastguard Worker     return new SemaphoreVk();
6405*8975f5c5SAndroid Build Coastguard Worker }
6406*8975f5c5SAndroid Build Coastguard Worker 
createOverlay(const gl::OverlayState & state)6407*8975f5c5SAndroid Build Coastguard Worker OverlayImpl *ContextVk::createOverlay(const gl::OverlayState &state)
6408*8975f5c5SAndroid Build Coastguard Worker {
6409*8975f5c5SAndroid Build Coastguard Worker     return new OverlayVk(state);
6410*8975f5c5SAndroid Build Coastguard Worker }
6411*8975f5c5SAndroid Build Coastguard Worker 
invalidateCurrentDefaultUniforms()6412*8975f5c5SAndroid Build Coastguard Worker void ContextVk::invalidateCurrentDefaultUniforms()
6413*8975f5c5SAndroid Build Coastguard Worker {
6414*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6415*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executable);
6416*8975f5c5SAndroid Build Coastguard Worker 
6417*8975f5c5SAndroid Build Coastguard Worker     if (executable->hasDefaultUniforms())
6418*8975f5c5SAndroid Build Coastguard Worker     {
6419*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
6420*8975f5c5SAndroid Build Coastguard Worker         mComputeDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
6421*8975f5c5SAndroid Build Coastguard Worker     }
6422*8975f5c5SAndroid Build Coastguard Worker }
6423*8975f5c5SAndroid Build Coastguard Worker 
invalidateCurrentTextures(const gl::Context * context,gl::Command command)6424*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::invalidateCurrentTextures(const gl::Context *context, gl::Command command)
6425*8975f5c5SAndroid Build Coastguard Worker {
6426*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6427*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executable);
6428*8975f5c5SAndroid Build Coastguard Worker 
6429*8975f5c5SAndroid Build Coastguard Worker     if (executable->hasTextures())
6430*8975f5c5SAndroid Build Coastguard Worker     {
6431*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits |= kTexturesAndDescSetDirtyBits;
6432*8975f5c5SAndroid Build Coastguard Worker         mComputeDirtyBits |= kTexturesAndDescSetDirtyBits;
6433*8975f5c5SAndroid Build Coastguard Worker 
6434*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(updateActiveTextures(context, command));
6435*8975f5c5SAndroid Build Coastguard Worker 
6436*8975f5c5SAndroid Build Coastguard Worker         if (command == gl::Command::Dispatch)
6437*8975f5c5SAndroid Build Coastguard Worker         {
6438*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(endRenderPassIfComputeAccessAfterGraphicsImageAccess());
6439*8975f5c5SAndroid Build Coastguard Worker         }
6440*8975f5c5SAndroid Build Coastguard Worker     }
6441*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
6442*8975f5c5SAndroid Build Coastguard Worker }
6443*8975f5c5SAndroid Build Coastguard Worker 
invalidateCurrentShaderResources(gl::Command command)6444*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::invalidateCurrentShaderResources(gl::Command command)
6445*8975f5c5SAndroid Build Coastguard Worker {
6446*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6447*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executable);
6448*8975f5c5SAndroid Build Coastguard Worker 
6449*8975f5c5SAndroid Build Coastguard Worker     const bool hasImages = executable->hasImages();
6450*8975f5c5SAndroid Build Coastguard Worker     const bool hasStorageBuffers =
6451*8975f5c5SAndroid Build Coastguard Worker         executable->hasStorageBuffers() || executable->hasAtomicCounterBuffers();
6452*8975f5c5SAndroid Build Coastguard Worker     const bool hasUniformBuffers = executable->hasUniformBuffers();
6453*8975f5c5SAndroid Build Coastguard Worker 
6454*8975f5c5SAndroid Build Coastguard Worker     if (hasUniformBuffers || hasStorageBuffers || hasImages ||
6455*8975f5c5SAndroid Build Coastguard Worker         executable->usesColorFramebufferFetch() || executable->usesDepthFramebufferFetch() ||
6456*8975f5c5SAndroid Build Coastguard Worker         executable->usesStencilFramebufferFetch())
6457*8975f5c5SAndroid Build Coastguard Worker     {
6458*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits |= kResourcesAndDescSetDirtyBits;
6459*8975f5c5SAndroid Build Coastguard Worker         mComputeDirtyBits |= kResourcesAndDescSetDirtyBits;
6460*8975f5c5SAndroid Build Coastguard Worker     }
6461*8975f5c5SAndroid Build Coastguard Worker 
6462*8975f5c5SAndroid Build Coastguard Worker     // Take care of read-after-write hazards that require implicit synchronization.
6463*8975f5c5SAndroid Build Coastguard Worker     if (hasUniformBuffers && command == gl::Command::Dispatch)
6464*8975f5c5SAndroid Build Coastguard Worker     {
6465*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(endRenderPassIfComputeReadAfterTransformFeedbackWrite());
6466*8975f5c5SAndroid Build Coastguard Worker     }
6467*8975f5c5SAndroid Build Coastguard Worker 
6468*8975f5c5SAndroid Build Coastguard Worker     // Take care of implict layout transition by compute program access-after-read.
6469*8975f5c5SAndroid Build Coastguard Worker     if (hasImages && command == gl::Command::Dispatch)
6470*8975f5c5SAndroid Build Coastguard Worker     {
6471*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(endRenderPassIfComputeAccessAfterGraphicsImageAccess());
6472*8975f5c5SAndroid Build Coastguard Worker     }
6473*8975f5c5SAndroid Build Coastguard Worker 
6474*8975f5c5SAndroid Build Coastguard Worker     // If memory barrier has been issued but the command buffers haven't been flushed, make sure
6475*8975f5c5SAndroid Build Coastguard Worker     // they get a chance to do so if necessary on program and storage buffer/image binding change.
6476*8975f5c5SAndroid Build Coastguard Worker     const bool hasGLMemoryBarrierIssuedInCommandBuffers =
6477*8975f5c5SAndroid Build Coastguard Worker         mOutsideRenderPassCommands->hasGLMemoryBarrierIssued() ||
6478*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommands->hasGLMemoryBarrierIssued();
6479*8975f5c5SAndroid Build Coastguard Worker 
6480*8975f5c5SAndroid Build Coastguard Worker     if ((hasStorageBuffers || hasImages) && hasGLMemoryBarrierIssuedInCommandBuffers)
6481*8975f5c5SAndroid Build Coastguard Worker     {
6482*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_MEMORY_BARRIER);
6483*8975f5c5SAndroid Build Coastguard Worker         mComputeDirtyBits.set(DIRTY_BIT_MEMORY_BARRIER);
6484*8975f5c5SAndroid Build Coastguard Worker     }
6485*8975f5c5SAndroid Build Coastguard Worker 
6486*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
6487*8975f5c5SAndroid Build Coastguard Worker }
6488*8975f5c5SAndroid Build Coastguard Worker 
invalidateCurrentShaderUniformBuffers(gl::Command command)6489*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::invalidateCurrentShaderUniformBuffers(gl::Command command)
6490*8975f5c5SAndroid Build Coastguard Worker {
6491*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6492*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executable);
6493*8975f5c5SAndroid Build Coastguard Worker 
6494*8975f5c5SAndroid Build Coastguard Worker     if (executable->hasUniformBuffers())
6495*8975f5c5SAndroid Build Coastguard Worker     {
6496*8975f5c5SAndroid Build Coastguard Worker         if (executable->hasLinkedShaderStage(gl::ShaderType::Compute))
6497*8975f5c5SAndroid Build Coastguard Worker         {
6498*8975f5c5SAndroid Build Coastguard Worker             mComputeDirtyBits |= kUniformBuffersAndDescSetDirtyBits;
6499*8975f5c5SAndroid Build Coastguard Worker         }
6500*8975f5c5SAndroid Build Coastguard Worker         else
6501*8975f5c5SAndroid Build Coastguard Worker         {
6502*8975f5c5SAndroid Build Coastguard Worker             mGraphicsDirtyBits |= kUniformBuffersAndDescSetDirtyBits;
6503*8975f5c5SAndroid Build Coastguard Worker         }
6504*8975f5c5SAndroid Build Coastguard Worker 
6505*8975f5c5SAndroid Build Coastguard Worker         if (command == gl::Command::Dispatch)
6506*8975f5c5SAndroid Build Coastguard Worker         {
6507*8975f5c5SAndroid Build Coastguard Worker             // Take care of read-after-write hazards that require implicit synchronization.
6508*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(endRenderPassIfComputeReadAfterTransformFeedbackWrite());
6509*8975f5c5SAndroid Build Coastguard Worker         }
6510*8975f5c5SAndroid Build Coastguard Worker     }
6511*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
6512*8975f5c5SAndroid Build Coastguard Worker }
6513*8975f5c5SAndroid Build Coastguard Worker 
updateShaderResourcesWithSharedCacheKey(const vk::SharedDescriptorSetCacheKey & sharedCacheKey)6514*8975f5c5SAndroid Build Coastguard Worker void ContextVk::updateShaderResourcesWithSharedCacheKey(
6515*8975f5c5SAndroid Build Coastguard Worker     const vk::SharedDescriptorSetCacheKey &sharedCacheKey)
6516*8975f5c5SAndroid Build Coastguard Worker {
6517*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6518*8975f5c5SAndroid Build Coastguard Worker     ProgramExecutableVk *executableVk       = vk::GetImpl(executable);
6519*8975f5c5SAndroid Build Coastguard Worker 
6520*8975f5c5SAndroid Build Coastguard Worker     if (executable->hasUniformBuffers())
6521*8975f5c5SAndroid Build Coastguard Worker     {
6522*8975f5c5SAndroid Build Coastguard Worker         const std::vector<gl::InterfaceBlock> &blocks = executable->getUniformBlocks();
6523*8975f5c5SAndroid Build Coastguard Worker         for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
6524*8975f5c5SAndroid Build Coastguard Worker         {
6525*8975f5c5SAndroid Build Coastguard Worker             const GLuint binding = executable->getUniformBlockBinding(bufferIndex);
6526*8975f5c5SAndroid Build Coastguard Worker             UpdateBufferWithSharedCacheKey(mState.getOffsetBindingPointerUniformBuffers()[binding],
6527*8975f5c5SAndroid Build Coastguard Worker                                            executableVk->getUniformBufferDescriptorType(),
6528*8975f5c5SAndroid Build Coastguard Worker                                            sharedCacheKey);
6529*8975f5c5SAndroid Build Coastguard Worker         }
6530*8975f5c5SAndroid Build Coastguard Worker     }
6531*8975f5c5SAndroid Build Coastguard Worker     if (executable->hasStorageBuffers())
6532*8975f5c5SAndroid Build Coastguard Worker     {
6533*8975f5c5SAndroid Build Coastguard Worker         const std::vector<gl::InterfaceBlock> &blocks = executable->getShaderStorageBlocks();
6534*8975f5c5SAndroid Build Coastguard Worker         for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
6535*8975f5c5SAndroid Build Coastguard Worker         {
6536*8975f5c5SAndroid Build Coastguard Worker             const GLuint binding = executable->getShaderStorageBlockBinding(bufferIndex);
6537*8975f5c5SAndroid Build Coastguard Worker             UpdateBufferWithSharedCacheKey(
6538*8975f5c5SAndroid Build Coastguard Worker                 mState.getOffsetBindingPointerShaderStorageBuffers()[binding],
6539*8975f5c5SAndroid Build Coastguard Worker                 executableVk->getStorageBufferDescriptorType(), sharedCacheKey);
6540*8975f5c5SAndroid Build Coastguard Worker         }
6541*8975f5c5SAndroid Build Coastguard Worker     }
6542*8975f5c5SAndroid Build Coastguard Worker     if (executable->hasAtomicCounterBuffers())
6543*8975f5c5SAndroid Build Coastguard Worker     {
6544*8975f5c5SAndroid Build Coastguard Worker         const std::vector<gl::AtomicCounterBuffer> &blocks = executable->getAtomicCounterBuffers();
6545*8975f5c5SAndroid Build Coastguard Worker         for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
6546*8975f5c5SAndroid Build Coastguard Worker         {
6547*8975f5c5SAndroid Build Coastguard Worker             const GLuint binding = executable->getAtomicCounterBufferBinding(bufferIndex);
6548*8975f5c5SAndroid Build Coastguard Worker             UpdateBufferWithSharedCacheKey(
6549*8975f5c5SAndroid Build Coastguard Worker                 mState.getOffsetBindingPointerAtomicCounterBuffers()[binding],
6550*8975f5c5SAndroid Build Coastguard Worker                 executableVk->getAtomicCounterBufferDescriptorType(), sharedCacheKey);
6551*8975f5c5SAndroid Build Coastguard Worker         }
6552*8975f5c5SAndroid Build Coastguard Worker     }
6553*8975f5c5SAndroid Build Coastguard Worker     if (executable->hasImages())
6554*8975f5c5SAndroid Build Coastguard Worker     {
6555*8975f5c5SAndroid Build Coastguard Worker         UpdateImagesWithSharedCacheKey(mActiveImages, executable->getImageBindings(),
6556*8975f5c5SAndroid Build Coastguard Worker                                        sharedCacheKey);
6557*8975f5c5SAndroid Build Coastguard Worker     }
6558*8975f5c5SAndroid Build Coastguard Worker }
6559*8975f5c5SAndroid Build Coastguard Worker 
invalidateGraphicsDriverUniforms()6560*8975f5c5SAndroid Build Coastguard Worker void ContextVk::invalidateGraphicsDriverUniforms()
6561*8975f5c5SAndroid Build Coastguard Worker {
6562*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
6563*8975f5c5SAndroid Build Coastguard Worker }
6564*8975f5c5SAndroid Build Coastguard Worker 
invalidateDriverUniforms()6565*8975f5c5SAndroid Build Coastguard Worker void ContextVk::invalidateDriverUniforms()
6566*8975f5c5SAndroid Build Coastguard Worker {
6567*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
6568*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
6569*8975f5c5SAndroid Build Coastguard Worker }
6570*8975f5c5SAndroid Build Coastguard Worker 
onFramebufferChange(FramebufferVk * framebufferVk,gl::Command command)6571*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::onFramebufferChange(FramebufferVk *framebufferVk, gl::Command command)
6572*8975f5c5SAndroid Build Coastguard Worker {
6573*8975f5c5SAndroid Build Coastguard Worker     // This is called from FramebufferVk::syncState.  Skip these updates if the framebuffer being
6574*8975f5c5SAndroid Build Coastguard Worker     // synced is the read framebuffer (which is not equal the draw framebuffer).
6575*8975f5c5SAndroid Build Coastguard Worker     if (framebufferVk != vk::GetImpl(mState.getDrawFramebuffer()))
6576*8975f5c5SAndroid Build Coastguard Worker     {
6577*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
6578*8975f5c5SAndroid Build Coastguard Worker     }
6579*8975f5c5SAndroid Build Coastguard Worker 
6580*8975f5c5SAndroid Build Coastguard Worker     // Always consider the render pass finished.  FramebufferVk::syncState (caller of this function)
6581*8975f5c5SAndroid Build Coastguard Worker     // normally closes the render pass, except for blit to allow an optimization.  The following
6582*8975f5c5SAndroid Build Coastguard Worker     // code nevertheless must treat the render pass closed.
6583*8975f5c5SAndroid Build Coastguard Worker     onRenderPassFinished(RenderPassClosureReason::FramebufferChange);
6584*8975f5c5SAndroid Build Coastguard Worker 
6585*8975f5c5SAndroid Build Coastguard Worker     // Ensure that the pipeline description is updated.
6586*8975f5c5SAndroid Build Coastguard Worker     if (mGraphicsPipelineDesc->getRasterizationSamples() !=
6587*8975f5c5SAndroid Build Coastguard Worker         static_cast<uint32_t>(framebufferVk->getSamples()))
6588*8975f5c5SAndroid Build Coastguard Worker     {
6589*8975f5c5SAndroid Build Coastguard Worker         updateRasterizationSamples(framebufferVk->getSamples());
6590*8975f5c5SAndroid Build Coastguard Worker     }
6591*8975f5c5SAndroid Build Coastguard Worker 
6592*8975f5c5SAndroid Build Coastguard Worker     // Update scissor.
6593*8975f5c5SAndroid Build Coastguard Worker     updateScissor(mState);
6594*8975f5c5SAndroid Build Coastguard Worker 
6595*8975f5c5SAndroid Build Coastguard Worker     // Update depth and stencil.
6596*8975f5c5SAndroid Build Coastguard Worker     updateDepthStencil(mState);
6597*8975f5c5SAndroid Build Coastguard Worker 
6598*8975f5c5SAndroid Build Coastguard Worker     // Update dither based on attachment formats.
6599*8975f5c5SAndroid Build Coastguard Worker     updateDither();
6600*8975f5c5SAndroid Build Coastguard Worker 
6601*8975f5c5SAndroid Build Coastguard Worker     // Attachments might have changed.
6602*8975f5c5SAndroid Build Coastguard Worker     updateMissingOutputsMask();
6603*8975f5c5SAndroid Build Coastguard Worker 
6604*8975f5c5SAndroid Build Coastguard Worker     if (mState.getProgramExecutable())
6605*8975f5c5SAndroid Build Coastguard Worker     {
6606*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(invalidateCurrentShaderResources(command));
6607*8975f5c5SAndroid Build Coastguard Worker     }
6608*8975f5c5SAndroid Build Coastguard Worker 
6609*8975f5c5SAndroid Build Coastguard Worker     onDrawFramebufferRenderPassDescChange(framebufferVk, nullptr);
6610*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
6611*8975f5c5SAndroid Build Coastguard Worker }
6612*8975f5c5SAndroid Build Coastguard Worker 
onDrawFramebufferRenderPassDescChange(FramebufferVk * framebufferVk,bool * renderPassDescChangedOut)6613*8975f5c5SAndroid Build Coastguard Worker void ContextVk::onDrawFramebufferRenderPassDescChange(FramebufferVk *framebufferVk,
6614*8975f5c5SAndroid Build Coastguard Worker                                                       bool *renderPassDescChangedOut)
6615*8975f5c5SAndroid Build Coastguard Worker {
6616*8975f5c5SAndroid Build Coastguard Worker     ASSERT(getFeatures().supportsFragmentShadingRate.enabled ||
6617*8975f5c5SAndroid Build Coastguard Worker            !framebufferVk->isFoveationEnabled());
6618*8975f5c5SAndroid Build Coastguard Worker 
6619*8975f5c5SAndroid Build Coastguard Worker     const vk::FramebufferFetchMode framebufferFetchMode =
6620*8975f5c5SAndroid Build Coastguard Worker         vk::GetProgramFramebufferFetchMode(mState.getProgramExecutable());
6621*8975f5c5SAndroid Build Coastguard Worker     mGraphicsPipelineDesc->updateRenderPassDesc(&mGraphicsPipelineTransition, getFeatures(),
6622*8975f5c5SAndroid Build Coastguard Worker                                                 framebufferVk->getRenderPassDesc(),
6623*8975f5c5SAndroid Build Coastguard Worker                                                 framebufferFetchMode);
6624*8975f5c5SAndroid Build Coastguard Worker 
6625*8975f5c5SAndroid Build Coastguard Worker     if (renderPassDescChangedOut)
6626*8975f5c5SAndroid Build Coastguard Worker     {
6627*8975f5c5SAndroid Build Coastguard Worker         // If render pass desc has changed while processing the dirty bits, notify the caller.
6628*8975f5c5SAndroid Build Coastguard Worker         // In most paths, |renderPassDescChangedOut| is nullptr and the pipeline will be
6629*8975f5c5SAndroid Build Coastguard Worker         // invalidated.
6630*8975f5c5SAndroid Build Coastguard Worker         //
6631*8975f5c5SAndroid Build Coastguard Worker         // |renderPassDescChangedOut| only serves |ContextVk::handleDirtyGraphicsRenderPass|, which
6632*8975f5c5SAndroid Build Coastguard Worker         // may need to reprocess the pipeline while processing dirty bits.  At that point, marking
6633*8975f5c5SAndroid Build Coastguard Worker         // the pipeline dirty is ineffective, and the pipeline dirty bit handler is directly called
6634*8975f5c5SAndroid Build Coastguard Worker         // as a result of setting this variable to true.
6635*8975f5c5SAndroid Build Coastguard Worker         *renderPassDescChangedOut = true;
6636*8975f5c5SAndroid Build Coastguard Worker     }
6637*8975f5c5SAndroid Build Coastguard Worker     else
6638*8975f5c5SAndroid Build Coastguard Worker     {
6639*8975f5c5SAndroid Build Coastguard Worker         // Otherwise mark the pipeline as dirty.
6640*8975f5c5SAndroid Build Coastguard Worker         invalidateCurrentGraphicsPipeline();
6641*8975f5c5SAndroid Build Coastguard Worker     }
6642*8975f5c5SAndroid Build Coastguard Worker 
6643*8975f5c5SAndroid Build Coastguard Worker     // Update render area in the driver uniforms.
6644*8975f5c5SAndroid Build Coastguard Worker     invalidateGraphicsDriverUniforms();
6645*8975f5c5SAndroid Build Coastguard Worker }
6646*8975f5c5SAndroid Build Coastguard Worker 
invalidateCurrentTransformFeedbackBuffers()6647*8975f5c5SAndroid Build Coastguard Worker void ContextVk::invalidateCurrentTransformFeedbackBuffers()
6648*8975f5c5SAndroid Build Coastguard Worker {
6649*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().supportsTransformFeedbackExtension.enabled)
6650*8975f5c5SAndroid Build Coastguard Worker     {
6651*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS);
6652*8975f5c5SAndroid Build Coastguard Worker     }
6653*8975f5c5SAndroid Build Coastguard Worker     else if (getFeatures().emulateTransformFeedback.enabled)
6654*8975f5c5SAndroid Build Coastguard Worker     {
6655*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits |= kXfbBuffersAndDescSetDirtyBits;
6656*8975f5c5SAndroid Build Coastguard Worker     }
6657*8975f5c5SAndroid Build Coastguard Worker }
6658*8975f5c5SAndroid Build Coastguard Worker 
onTransformFeedbackStateChanged()6659*8975f5c5SAndroid Build Coastguard Worker void ContextVk::onTransformFeedbackStateChanged()
6660*8975f5c5SAndroid Build Coastguard Worker {
6661*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().supportsTransformFeedbackExtension.enabled)
6662*8975f5c5SAndroid Build Coastguard Worker     {
6663*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS);
6664*8975f5c5SAndroid Build Coastguard Worker     }
6665*8975f5c5SAndroid Build Coastguard Worker     else if (getFeatures().emulateTransformFeedback.enabled)
6666*8975f5c5SAndroid Build Coastguard Worker     {
6667*8975f5c5SAndroid Build Coastguard Worker         invalidateGraphicsDriverUniforms();
6668*8975f5c5SAndroid Build Coastguard Worker         invalidateCurrentTransformFeedbackBuffers();
6669*8975f5c5SAndroid Build Coastguard Worker 
6670*8975f5c5SAndroid Build Coastguard Worker         // Invalidate the graphics pipeline too.  On transform feedback state change, the current
6671*8975f5c5SAndroid Build Coastguard Worker         // program may be used again, and it should switch between outputting transform feedback and
6672*8975f5c5SAndroid Build Coastguard Worker         // not.
6673*8975f5c5SAndroid Build Coastguard Worker         invalidateCurrentGraphicsPipeline();
6674*8975f5c5SAndroid Build Coastguard Worker         resetCurrentGraphicsPipeline();
6675*8975f5c5SAndroid Build Coastguard Worker     }
6676*8975f5c5SAndroid Build Coastguard Worker }
6677*8975f5c5SAndroid Build Coastguard Worker 
onBeginTransformFeedback(size_t bufferCount,const gl::TransformFeedbackBuffersArray<vk::BufferHelper * > & buffers,const gl::TransformFeedbackBuffersArray<vk::BufferHelper> & counterBuffers)6678*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::onBeginTransformFeedback(
6679*8975f5c5SAndroid Build Coastguard Worker     size_t bufferCount,
6680*8975f5c5SAndroid Build Coastguard Worker     const gl::TransformFeedbackBuffersArray<vk::BufferHelper *> &buffers,
6681*8975f5c5SAndroid Build Coastguard Worker     const gl::TransformFeedbackBuffersArray<vk::BufferHelper> &counterBuffers)
6682*8975f5c5SAndroid Build Coastguard Worker {
6683*8975f5c5SAndroid Build Coastguard Worker     onTransformFeedbackStateChanged();
6684*8975f5c5SAndroid Build Coastguard Worker 
6685*8975f5c5SAndroid Build Coastguard Worker     bool shouldEndRenderPass = false;
6686*8975f5c5SAndroid Build Coastguard Worker 
6687*8975f5c5SAndroid Build Coastguard Worker     if (hasActiveRenderPass())
6688*8975f5c5SAndroid Build Coastguard Worker     {
6689*8975f5c5SAndroid Build Coastguard Worker         // If any of the buffers were previously used in the render pass, break the render pass as a
6690*8975f5c5SAndroid Build Coastguard Worker         // barrier is needed.
6691*8975f5c5SAndroid Build Coastguard Worker         for (size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
6692*8975f5c5SAndroid Build Coastguard Worker         {
6693*8975f5c5SAndroid Build Coastguard Worker             const vk::BufferHelper *buffer = buffers[bufferIndex];
6694*8975f5c5SAndroid Build Coastguard Worker             if (mRenderPassCommands->usesBuffer(*buffer))
6695*8975f5c5SAndroid Build Coastguard Worker             {
6696*8975f5c5SAndroid Build Coastguard Worker                 shouldEndRenderPass = true;
6697*8975f5c5SAndroid Build Coastguard Worker                 break;
6698*8975f5c5SAndroid Build Coastguard Worker             }
6699*8975f5c5SAndroid Build Coastguard Worker         }
6700*8975f5c5SAndroid Build Coastguard Worker     }
6701*8975f5c5SAndroid Build Coastguard Worker 
6702*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().supportsTransformFeedbackExtension.enabled)
6703*8975f5c5SAndroid Build Coastguard Worker     {
6704*8975f5c5SAndroid Build Coastguard Worker         // Break the render pass if the counter buffers are used too.  Note that Vulkan requires a
6705*8975f5c5SAndroid Build Coastguard Worker         // barrier on the counter buffer between pause and resume, so it cannot be resumed in the
6706*8975f5c5SAndroid Build Coastguard Worker         // same render pass.  Note additionally that we don't need to test all counters being used
6707*8975f5c5SAndroid Build Coastguard Worker         // in the render pass, as outside of the transform feedback object these buffers are
6708*8975f5c5SAndroid Build Coastguard Worker         // inaccessible and are therefore always used together.
6709*8975f5c5SAndroid Build Coastguard Worker         if (!shouldEndRenderPass && isRenderPassStartedAndUsesBuffer(counterBuffers[0]))
6710*8975f5c5SAndroid Build Coastguard Worker         {
6711*8975f5c5SAndroid Build Coastguard Worker             shouldEndRenderPass = true;
6712*8975f5c5SAndroid Build Coastguard Worker         }
6713*8975f5c5SAndroid Build Coastguard Worker 
6714*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
6715*8975f5c5SAndroid Build Coastguard Worker     }
6716*8975f5c5SAndroid Build Coastguard Worker 
6717*8975f5c5SAndroid Build Coastguard Worker     if (shouldEndRenderPass)
6718*8975f5c5SAndroid Build Coastguard Worker     {
6719*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushCommandsAndEndRenderPass(RenderPassClosureReason::BufferUseThenXfbWrite));
6720*8975f5c5SAndroid Build Coastguard Worker     }
6721*8975f5c5SAndroid Build Coastguard Worker 
6722*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
6723*8975f5c5SAndroid Build Coastguard Worker }
6724*8975f5c5SAndroid Build Coastguard Worker 
onEndTransformFeedback()6725*8975f5c5SAndroid Build Coastguard Worker void ContextVk::onEndTransformFeedback()
6726*8975f5c5SAndroid Build Coastguard Worker {
6727*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().supportsTransformFeedbackExtension.enabled)
6728*8975f5c5SAndroid Build Coastguard Worker     {
6729*8975f5c5SAndroid Build Coastguard Worker         if (mRenderPassCommands->isTransformFeedbackStarted())
6730*8975f5c5SAndroid Build Coastguard Worker         {
6731*8975f5c5SAndroid Build Coastguard Worker             mRenderPassCommands->endTransformFeedback();
6732*8975f5c5SAndroid Build Coastguard Worker         }
6733*8975f5c5SAndroid Build Coastguard Worker     }
6734*8975f5c5SAndroid Build Coastguard Worker     else if (getFeatures().emulateTransformFeedback.enabled)
6735*8975f5c5SAndroid Build Coastguard Worker     {
6736*8975f5c5SAndroid Build Coastguard Worker         onTransformFeedbackStateChanged();
6737*8975f5c5SAndroid Build Coastguard Worker     }
6738*8975f5c5SAndroid Build Coastguard Worker }
6739*8975f5c5SAndroid Build Coastguard Worker 
onPauseTransformFeedback()6740*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::onPauseTransformFeedback()
6741*8975f5c5SAndroid Build Coastguard Worker {
6742*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().supportsTransformFeedbackExtension.enabled)
6743*8975f5c5SAndroid Build Coastguard Worker     {
6744*8975f5c5SAndroid Build Coastguard Worker         // If transform feedback was already active on this render pass, break it.  This
6745*8975f5c5SAndroid Build Coastguard Worker         // is for simplicity to avoid tracking multiple simultaneously active transform feedback
6746*8975f5c5SAndroid Build Coastguard Worker         // settings in the render pass.
6747*8975f5c5SAndroid Build Coastguard Worker         if (mRenderPassCommands->isTransformFeedbackActiveUnpaused())
6748*8975f5c5SAndroid Build Coastguard Worker         {
6749*8975f5c5SAndroid Build Coastguard Worker             return flushCommandsAndEndRenderPass(RenderPassClosureReason::XfbPause);
6750*8975f5c5SAndroid Build Coastguard Worker         }
6751*8975f5c5SAndroid Build Coastguard Worker     }
6752*8975f5c5SAndroid Build Coastguard Worker     onTransformFeedbackStateChanged();
6753*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
6754*8975f5c5SAndroid Build Coastguard Worker }
6755*8975f5c5SAndroid Build Coastguard Worker 
invalidateGraphicsPipelineBinding()6756*8975f5c5SAndroid Build Coastguard Worker void ContextVk::invalidateGraphicsPipelineBinding()
6757*8975f5c5SAndroid Build Coastguard Worker {
6758*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits.set(DIRTY_BIT_PIPELINE_BINDING);
6759*8975f5c5SAndroid Build Coastguard Worker }
6760*8975f5c5SAndroid Build Coastguard Worker 
invalidateComputePipelineBinding()6761*8975f5c5SAndroid Build Coastguard Worker void ContextVk::invalidateComputePipelineBinding()
6762*8975f5c5SAndroid Build Coastguard Worker {
6763*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBits.set(DIRTY_BIT_PIPELINE_BINDING);
6764*8975f5c5SAndroid Build Coastguard Worker }
6765*8975f5c5SAndroid Build Coastguard Worker 
invalidateGraphicsDescriptorSet(DescriptorSetIndex usedDescriptorSet)6766*8975f5c5SAndroid Build Coastguard Worker void ContextVk::invalidateGraphicsDescriptorSet(DescriptorSetIndex usedDescriptorSet)
6767*8975f5c5SAndroid Build Coastguard Worker {
6768*8975f5c5SAndroid Build Coastguard Worker     // UtilsVk currently only uses set 0
6769*8975f5c5SAndroid Build Coastguard Worker     ASSERT(usedDescriptorSet == DescriptorSetIndex::Internal);
6770*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6771*8975f5c5SAndroid Build Coastguard Worker 
6772*8975f5c5SAndroid Build Coastguard Worker     if (executable && executable->hasUniformBuffers())
6773*8975f5c5SAndroid Build Coastguard Worker     {
6774*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
6775*8975f5c5SAndroid Build Coastguard Worker         return;
6776*8975f5c5SAndroid Build Coastguard Worker     }
6777*8975f5c5SAndroid Build Coastguard Worker }
6778*8975f5c5SAndroid Build Coastguard Worker 
invalidateComputeDescriptorSet(DescriptorSetIndex usedDescriptorSet)6779*8975f5c5SAndroid Build Coastguard Worker void ContextVk::invalidateComputeDescriptorSet(DescriptorSetIndex usedDescriptorSet)
6780*8975f5c5SAndroid Build Coastguard Worker {
6781*8975f5c5SAndroid Build Coastguard Worker     // UtilsVk currently only uses set 0
6782*8975f5c5SAndroid Build Coastguard Worker     ASSERT(usedDescriptorSet == DescriptorSetIndex::Internal);
6783*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
6784*8975f5c5SAndroid Build Coastguard Worker 
6785*8975f5c5SAndroid Build Coastguard Worker     if (executable && executable->hasUniformBuffers())
6786*8975f5c5SAndroid Build Coastguard Worker     {
6787*8975f5c5SAndroid Build Coastguard Worker         mComputeDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
6788*8975f5c5SAndroid Build Coastguard Worker         return;
6789*8975f5c5SAndroid Build Coastguard Worker     }
6790*8975f5c5SAndroid Build Coastguard Worker }
6791*8975f5c5SAndroid Build Coastguard Worker 
invalidateAllDynamicState()6792*8975f5c5SAndroid Build Coastguard Worker void ContextVk::invalidateAllDynamicState()
6793*8975f5c5SAndroid Build Coastguard Worker {
6794*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits |= mDynamicStateDirtyBits;
6795*8975f5c5SAndroid Build Coastguard Worker }
6796*8975f5c5SAndroid Build Coastguard Worker 
dispatchCompute(const gl::Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)6797*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::dispatchCompute(const gl::Context *context,
6798*8975f5c5SAndroid Build Coastguard Worker                                          GLuint numGroupsX,
6799*8975f5c5SAndroid Build Coastguard Worker                                          GLuint numGroupsY,
6800*8975f5c5SAndroid Build Coastguard Worker                                          GLuint numGroupsZ)
6801*8975f5c5SAndroid Build Coastguard Worker {
6802*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(setupDispatch(context));
6803*8975f5c5SAndroid Build Coastguard Worker 
6804*8975f5c5SAndroid Build Coastguard Worker     mOutsideRenderPassCommands->getCommandBuffer().dispatch(numGroupsX, numGroupsY, numGroupsZ);
6805*8975f5c5SAndroid Build Coastguard Worker     // Track completion of compute.
6806*8975f5c5SAndroid Build Coastguard Worker     mOutsideRenderPassCommands->flushSetEvents(this);
6807*8975f5c5SAndroid Build Coastguard Worker 
6808*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
6809*8975f5c5SAndroid Build Coastguard Worker }
6810*8975f5c5SAndroid Build Coastguard Worker 
dispatchComputeIndirect(const gl::Context * context,GLintptr indirect)6811*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
6812*8975f5c5SAndroid Build Coastguard Worker {
6813*8975f5c5SAndroid Build Coastguard Worker     gl::Buffer *glBuffer     = getState().getTargetBuffer(gl::BufferBinding::DispatchIndirect);
6814*8975f5c5SAndroid Build Coastguard Worker     vk::BufferHelper &buffer = vk::GetImpl(glBuffer)->getBuffer();
6815*8975f5c5SAndroid Build Coastguard Worker 
6816*8975f5c5SAndroid Build Coastguard Worker     // Break the render pass if the indirect buffer was previously used as the output from transform
6817*8975f5c5SAndroid Build Coastguard Worker     // feedback.
6818*8975f5c5SAndroid Build Coastguard Worker     if (mCurrentTransformFeedbackQueueSerial.valid() &&
6819*8975f5c5SAndroid Build Coastguard Worker         buffer.writtenByCommandBuffer(mCurrentTransformFeedbackQueueSerial))
6820*8975f5c5SAndroid Build Coastguard Worker     {
6821*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushCommandsAndEndRenderPass(
6822*8975f5c5SAndroid Build Coastguard Worker             RenderPassClosureReason::XfbWriteThenIndirectDispatchBuffer));
6823*8975f5c5SAndroid Build Coastguard Worker     }
6824*8975f5c5SAndroid Build Coastguard Worker 
6825*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(setupDispatch(context));
6826*8975f5c5SAndroid Build Coastguard Worker 
6827*8975f5c5SAndroid Build Coastguard Worker     // Process indirect buffer after command buffer has started.
6828*8975f5c5SAndroid Build Coastguard Worker     mOutsideRenderPassCommands->bufferRead(VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
6829*8975f5c5SAndroid Build Coastguard Worker                                            vk::PipelineStage::DrawIndirect, &buffer);
6830*8975f5c5SAndroid Build Coastguard Worker 
6831*8975f5c5SAndroid Build Coastguard Worker     mOutsideRenderPassCommands->getCommandBuffer().dispatchIndirect(buffer.getBuffer(),
6832*8975f5c5SAndroid Build Coastguard Worker                                                                     buffer.getOffset() + indirect);
6833*8975f5c5SAndroid Build Coastguard Worker 
6834*8975f5c5SAndroid Build Coastguard Worker     // Track completion of compute.
6835*8975f5c5SAndroid Build Coastguard Worker     mOutsideRenderPassCommands->flushSetEvents(this);
6836*8975f5c5SAndroid Build Coastguard Worker 
6837*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
6838*8975f5c5SAndroid Build Coastguard Worker }
6839*8975f5c5SAndroid Build Coastguard Worker 
memoryBarrier(const gl::Context * context,GLbitfield barriers)6840*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::memoryBarrier(const gl::Context *context, GLbitfield barriers)
6841*8975f5c5SAndroid Build Coastguard Worker {
6842*8975f5c5SAndroid Build Coastguard Worker     // First, turn GL_ALL_BARRIER_BITS into a mask that has only the valid barriers set.
6843*8975f5c5SAndroid Build Coastguard Worker     constexpr GLbitfield kAllMemoryBarrierBits = kBufferMemoryBarrierBits | kImageMemoryBarrierBits;
6844*8975f5c5SAndroid Build Coastguard Worker     barriers &= kAllMemoryBarrierBits;
6845*8975f5c5SAndroid Build Coastguard Worker 
6846*8975f5c5SAndroid Build Coastguard Worker     // GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT specifies that a fence sync or glFinish must be used
6847*8975f5c5SAndroid Build Coastguard Worker     // after the barrier for the CPU to to see the shader writes.  Since host-visible buffer writes
6848*8975f5c5SAndroid Build Coastguard Worker     // always issue a barrier automatically for the sake of glMapBuffer() (see
6849*8975f5c5SAndroid Build Coastguard Worker     // comment on |mIsAnyHostVisibleBufferWritten|), there's nothing to do for
6850*8975f5c5SAndroid Build Coastguard Worker     // GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT.
6851*8975f5c5SAndroid Build Coastguard Worker     barriers &= ~GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT;
6852*8975f5c5SAndroid Build Coastguard Worker 
6853*8975f5c5SAndroid Build Coastguard Worker     // If no other barrier, early out.
6854*8975f5c5SAndroid Build Coastguard Worker     if (barriers == 0)
6855*8975f5c5SAndroid Build Coastguard Worker     {
6856*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
6857*8975f5c5SAndroid Build Coastguard Worker     }
6858*8975f5c5SAndroid Build Coastguard Worker 
6859*8975f5c5SAndroid Build Coastguard Worker     // glMemoryBarrier for barrier bit X_BARRIER_BIT implies:
6860*8975f5c5SAndroid Build Coastguard Worker     //
6861*8975f5c5SAndroid Build Coastguard Worker     // - An execution+memory barrier: shader writes are made visible to subsequent X accesses
6862*8975f5c5SAndroid Build Coastguard Worker     //
6863*8975f5c5SAndroid Build Coastguard Worker     // Additionally, SHADER_IMAGE_ACCESS_BARRIER_BIT and SHADER_STORAGE_BARRIER_BIT imply:
6864*8975f5c5SAndroid Build Coastguard Worker     //
6865*8975f5c5SAndroid Build Coastguard Worker     // - An execution+memory barrier: all accesses are finished before image/buffer writes
6866*8975f5c5SAndroid Build Coastguard Worker     //
6867*8975f5c5SAndroid Build Coastguard Worker     // For the first barrier, we can simplify the implementation by assuming that prior writes are
6868*8975f5c5SAndroid Build Coastguard Worker     // expected to be used right after this barrier, so we can close the render pass or flush the
6869*8975f5c5SAndroid Build Coastguard Worker     // outside render pass commands right away if they have had any writes.
6870*8975f5c5SAndroid Build Coastguard Worker     //
6871*8975f5c5SAndroid Build Coastguard Worker     // It's noteworthy that some barrier bits affect draw/dispatch calls only, while others affect
6872*8975f5c5SAndroid Build Coastguard Worker     // other commands.  For the latter, since storage buffer and images are not tracked in command
6873*8975f5c5SAndroid Build Coastguard Worker     // buffers, we can't rely on the command buffers being flushed in the usual way when recording
6874*8975f5c5SAndroid Build Coastguard Worker     // these commands (i.e. through |getOutsideRenderPassCommandBuffer()| and
6875*8975f5c5SAndroid Build Coastguard Worker     // |vk::CommandBufferAccess|).  Conservatively flushing command buffers with any storage output
6876*8975f5c5SAndroid Build Coastguard Worker     // simplifies this use case.  If this needs to be avoided in the future,
6877*8975f5c5SAndroid Build Coastguard Worker     // |getOutsideRenderPassCommandBuffer()| can be modified to flush the command buffers if they
6878*8975f5c5SAndroid Build Coastguard Worker     // have had any storage output.
6879*8975f5c5SAndroid Build Coastguard Worker     //
6880*8975f5c5SAndroid Build Coastguard Worker     // For the second barrier, we need to defer closing the render pass until there's a draw or
6881*8975f5c5SAndroid Build Coastguard Worker     // dispatch call that uses storage buffers or images that were previously used in the render
6882*8975f5c5SAndroid Build Coastguard Worker     // pass.  This allows the render pass to remain open in scenarios such as this:
6883*8975f5c5SAndroid Build Coastguard Worker     //
6884*8975f5c5SAndroid Build Coastguard Worker     // - Draw using resource X
6885*8975f5c5SAndroid Build Coastguard Worker     // - glMemoryBarrier
6886*8975f5c5SAndroid Build Coastguard Worker     // - Draw/dispatch with storage buffer/image Y
6887*8975f5c5SAndroid Build Coastguard Worker     //
6888*8975f5c5SAndroid Build Coastguard Worker     // To achieve this, a dirty bit is added that breaks the render pass if any storage
6889*8975f5c5SAndroid Build Coastguard Worker     // buffer/images are used in it.  Until the render pass breaks, changing the program or storage
6890*8975f5c5SAndroid Build Coastguard Worker     // buffer/image bindings should set this dirty bit again.
6891*8975f5c5SAndroid Build Coastguard Worker 
6892*8975f5c5SAndroid Build Coastguard Worker     if (mRenderPassCommands->hasShaderStorageOutput())
6893*8975f5c5SAndroid Build Coastguard Worker     {
6894*8975f5c5SAndroid Build Coastguard Worker         // Break the render pass if necessary as future non-draw commands can't know if they should.
6895*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushCommandsAndEndRenderPass(
6896*8975f5c5SAndroid Build Coastguard Worker             RenderPassClosureReason::StorageResourceUseThenGLMemoryBarrier));
6897*8975f5c5SAndroid Build Coastguard Worker     }
6898*8975f5c5SAndroid Build Coastguard Worker     else if (mOutsideRenderPassCommands->hasShaderStorageOutput())
6899*8975f5c5SAndroid Build Coastguard Worker     {
6900*8975f5c5SAndroid Build Coastguard Worker         // Otherwise flush the outside render pass commands if necessary.
6901*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushOutsideRenderPassCommands());
6902*8975f5c5SAndroid Build Coastguard Worker     }
6903*8975f5c5SAndroid Build Coastguard Worker 
6904*8975f5c5SAndroid Build Coastguard Worker     if ((barriers & kWriteAfterAccessMemoryBarriers) == 0)
6905*8975f5c5SAndroid Build Coastguard Worker     {
6906*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
6907*8975f5c5SAndroid Build Coastguard Worker     }
6908*8975f5c5SAndroid Build Coastguard Worker 
6909*8975f5c5SAndroid Build Coastguard Worker     // Accumulate unprocessed memoryBarrier bits
6910*8975f5c5SAndroid Build Coastguard Worker     mDeferredMemoryBarriers |= barriers;
6911*8975f5c5SAndroid Build Coastguard Worker 
6912*8975f5c5SAndroid Build Coastguard Worker     // Defer flushing the command buffers until a draw/dispatch with storage buffer/image is
6913*8975f5c5SAndroid Build Coastguard Worker     // encountered.
6914*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits.set(DIRTY_BIT_MEMORY_BARRIER);
6915*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBits.set(DIRTY_BIT_MEMORY_BARRIER);
6916*8975f5c5SAndroid Build Coastguard Worker 
6917*8975f5c5SAndroid Build Coastguard Worker     // Make sure memory barrier is issued for future usages of storage buffers and images even if
6918*8975f5c5SAndroid Build Coastguard Worker     // there's no binding change.
6919*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
6920*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
6921*8975f5c5SAndroid Build Coastguard Worker 
6922*8975f5c5SAndroid Build Coastguard Worker     // Mark the command buffers as affected by glMemoryBarrier, so future program and storage
6923*8975f5c5SAndroid Build Coastguard Worker     // buffer/image binding changes can set DIRTY_BIT_MEMORY_BARRIER again.
6924*8975f5c5SAndroid Build Coastguard Worker     mOutsideRenderPassCommands->setGLMemoryBarrierIssued();
6925*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommands->setGLMemoryBarrierIssued();
6926*8975f5c5SAndroid Build Coastguard Worker 
6927*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
6928*8975f5c5SAndroid Build Coastguard Worker }
6929*8975f5c5SAndroid Build Coastguard Worker 
memoryBarrierByRegion(const gl::Context * context,GLbitfield barriers)6930*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers)
6931*8975f5c5SAndroid Build Coastguard Worker {
6932*8975f5c5SAndroid Build Coastguard Worker     // Note: memoryBarrierByRegion is expected to affect only the fragment pipeline, but is
6933*8975f5c5SAndroid Build Coastguard Worker     // otherwise similar to memoryBarrier in function.
6934*8975f5c5SAndroid Build Coastguard Worker     //
6935*8975f5c5SAndroid Build Coastguard Worker     // TODO: Optimize memoryBarrierByRegion by issuing an in-subpass pipeline barrier instead of
6936*8975f5c5SAndroid Build Coastguard Worker     // breaking the render pass.  http://anglebug.com/42263695
6937*8975f5c5SAndroid Build Coastguard Worker     return memoryBarrier(context, barriers);
6938*8975f5c5SAndroid Build Coastguard Worker }
6939*8975f5c5SAndroid Build Coastguard Worker 
framebufferFetchBarrier()6940*8975f5c5SAndroid Build Coastguard Worker void ContextVk::framebufferFetchBarrier()
6941*8975f5c5SAndroid Build Coastguard Worker {
6942*8975f5c5SAndroid Build Coastguard Worker     // No need for a barrier with VK_EXT_rasterization_order_attachment_access.
6943*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().supportsRasterizationOrderAttachmentAccess.enabled)
6944*8975f5c5SAndroid Build Coastguard Worker     {
6945*8975f5c5SAndroid Build Coastguard Worker         return;
6946*8975f5c5SAndroid Build Coastguard Worker     }
6947*8975f5c5SAndroid Build Coastguard Worker 
6948*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_FETCH_BARRIER);
6949*8975f5c5SAndroid Build Coastguard Worker }
6950*8975f5c5SAndroid Build Coastguard Worker 
blendBarrier()6951*8975f5c5SAndroid Build Coastguard Worker void ContextVk::blendBarrier()
6952*8975f5c5SAndroid Build Coastguard Worker {
6953*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().emulateAdvancedBlendEquations.enabled)
6954*8975f5c5SAndroid Build Coastguard Worker     {
6955*8975f5c5SAndroid Build Coastguard Worker         // When emulated, advanced blend is implemented through framebuffer fetch.
6956*8975f5c5SAndroid Build Coastguard Worker         framebufferFetchBarrier();
6957*8975f5c5SAndroid Build Coastguard Worker     }
6958*8975f5c5SAndroid Build Coastguard Worker     else
6959*8975f5c5SAndroid Build Coastguard Worker     {
6960*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_BLEND_BARRIER);
6961*8975f5c5SAndroid Build Coastguard Worker     }
6962*8975f5c5SAndroid Build Coastguard Worker }
6963*8975f5c5SAndroid Build Coastguard Worker 
acquireTextures(const gl::Context * context,const gl::TextureBarrierVector & textureBarriers)6964*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::acquireTextures(const gl::Context *context,
6965*8975f5c5SAndroid Build Coastguard Worker                                          const gl::TextureBarrierVector &textureBarriers)
6966*8975f5c5SAndroid Build Coastguard Worker {
6967*8975f5c5SAndroid Build Coastguard Worker     for (const gl::TextureAndLayout &textureBarrier : textureBarriers)
6968*8975f5c5SAndroid Build Coastguard Worker     {
6969*8975f5c5SAndroid Build Coastguard Worker         TextureVk *textureVk   = vk::GetImpl(textureBarrier.texture);
6970*8975f5c5SAndroid Build Coastguard Worker         vk::ImageHelper &image = textureVk->getImage();
6971*8975f5c5SAndroid Build Coastguard Worker         vk::ImageLayout layout = vk::GetImageLayoutFromGLImageLayout(this, textureBarrier.layout);
6972*8975f5c5SAndroid Build Coastguard Worker         // Image should not be accessed while unowned. Emulated formats may have staged updates
6973*8975f5c5SAndroid Build Coastguard Worker         // to clear the image after initialization.
6974*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!image.hasStagedUpdatesInAllocatedLevels() || image.hasEmulatedImageChannels());
6975*8975f5c5SAndroid Build Coastguard Worker         image.setCurrentImageLayout(getRenderer(), layout);
6976*8975f5c5SAndroid Build Coastguard Worker     }
6977*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
6978*8975f5c5SAndroid Build Coastguard Worker }
6979*8975f5c5SAndroid Build Coastguard Worker 
releaseTextures(const gl::Context * context,gl::TextureBarrierVector * textureBarriers)6980*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::releaseTextures(const gl::Context *context,
6981*8975f5c5SAndroid Build Coastguard Worker                                          gl::TextureBarrierVector *textureBarriers)
6982*8975f5c5SAndroid Build Coastguard Worker {
6983*8975f5c5SAndroid Build Coastguard Worker     for (gl::TextureAndLayout &textureBarrier : *textureBarriers)
6984*8975f5c5SAndroid Build Coastguard Worker     {
6985*8975f5c5SAndroid Build Coastguard Worker         TextureVk *textureVk = vk::GetImpl(textureBarrier.texture);
6986*8975f5c5SAndroid Build Coastguard Worker 
6987*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(textureVk->ensureImageInitialized(this, ImageMipLevels::EnabledLevels));
6988*8975f5c5SAndroid Build Coastguard Worker 
6989*8975f5c5SAndroid Build Coastguard Worker         vk::ImageHelper &image = textureVk->getImage();
6990*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(onImageReleaseToExternal(image));
6991*8975f5c5SAndroid Build Coastguard Worker 
6992*8975f5c5SAndroid Build Coastguard Worker         textureBarrier.layout =
6993*8975f5c5SAndroid Build Coastguard Worker             vk::ConvertImageLayoutToGLImageLayout(image.getCurrentImageLayout());
6994*8975f5c5SAndroid Build Coastguard Worker     }
6995*8975f5c5SAndroid Build Coastguard Worker 
6996*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr,
6997*8975f5c5SAndroid Build Coastguard Worker                                      RenderPassClosureReason::ImageUseThenReleaseToExternal));
6998*8975f5c5SAndroid Build Coastguard Worker     return mRenderer->waitForResourceUseToBeSubmittedToDevice(this, mSubmittedResourceUse);
6999*8975f5c5SAndroid Build Coastguard Worker }
7000*8975f5c5SAndroid Build Coastguard Worker 
getQueryPool(gl::QueryType queryType)7001*8975f5c5SAndroid Build Coastguard Worker vk::DynamicQueryPool *ContextVk::getQueryPool(gl::QueryType queryType)
7002*8975f5c5SAndroid Build Coastguard Worker {
7003*8975f5c5SAndroid Build Coastguard Worker     ASSERT(queryType == gl::QueryType::AnySamples ||
7004*8975f5c5SAndroid Build Coastguard Worker            queryType == gl::QueryType::AnySamplesConservative ||
7005*8975f5c5SAndroid Build Coastguard Worker            queryType == gl::QueryType::PrimitivesGenerated ||
7006*8975f5c5SAndroid Build Coastguard Worker            queryType == gl::QueryType::TransformFeedbackPrimitivesWritten ||
7007*8975f5c5SAndroid Build Coastguard Worker            queryType == gl::QueryType::Timestamp || queryType == gl::QueryType::TimeElapsed);
7008*8975f5c5SAndroid Build Coastguard Worker 
7009*8975f5c5SAndroid Build Coastguard Worker     // For PrimitivesGenerated queries:
7010*8975f5c5SAndroid Build Coastguard Worker     //
7011*8975f5c5SAndroid Build Coastguard Worker     // - If VK_EXT_primitives_generated_query is supported, use that.
7012*8975f5c5SAndroid Build Coastguard Worker     // - Otherwise, if pipelineStatisticsQuery is supported, use that,
7013*8975f5c5SAndroid Build Coastguard Worker     // - Otherwise, use the same pool as TransformFeedbackPrimitivesWritten and share the query as
7014*8975f5c5SAndroid Build Coastguard Worker     //   the Vulkan transform feedback query produces both results.  This option is non-conformant
7015*8975f5c5SAndroid Build Coastguard Worker     //   as the primitives generated query will not be functional without transform feedback.
7016*8975f5c5SAndroid Build Coastguard Worker     //
7017*8975f5c5SAndroid Build Coastguard Worker     if (queryType == gl::QueryType::PrimitivesGenerated &&
7018*8975f5c5SAndroid Build Coastguard Worker         !getFeatures().supportsPrimitivesGeneratedQuery.enabled &&
7019*8975f5c5SAndroid Build Coastguard Worker         !getFeatures().supportsPipelineStatisticsQuery.enabled)
7020*8975f5c5SAndroid Build Coastguard Worker     {
7021*8975f5c5SAndroid Build Coastguard Worker         queryType = gl::QueryType::TransformFeedbackPrimitivesWritten;
7022*8975f5c5SAndroid Build Coastguard Worker     }
7023*8975f5c5SAndroid Build Coastguard Worker 
7024*8975f5c5SAndroid Build Coastguard Worker     // Assert that timestamp extension is available if needed.
7025*8975f5c5SAndroid Build Coastguard Worker     ASSERT((queryType != gl::QueryType::Timestamp && queryType != gl::QueryType::TimeElapsed) ||
7026*8975f5c5SAndroid Build Coastguard Worker            mRenderer->getQueueFamilyProperties().timestampValidBits > 0);
7027*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mQueryPools[queryType].isValid());
7028*8975f5c5SAndroid Build Coastguard Worker     return &mQueryPools[queryType];
7029*8975f5c5SAndroid Build Coastguard Worker }
7030*8975f5c5SAndroid Build Coastguard Worker 
getClearColorValue() const7031*8975f5c5SAndroid Build Coastguard Worker const VkClearValue &ContextVk::getClearColorValue() const
7032*8975f5c5SAndroid Build Coastguard Worker {
7033*8975f5c5SAndroid Build Coastguard Worker     return mClearColorValue;
7034*8975f5c5SAndroid Build Coastguard Worker }
7035*8975f5c5SAndroid Build Coastguard Worker 
getClearDepthStencilValue() const7036*8975f5c5SAndroid Build Coastguard Worker const VkClearValue &ContextVk::getClearDepthStencilValue() const
7037*8975f5c5SAndroid Build Coastguard Worker {
7038*8975f5c5SAndroid Build Coastguard Worker     return mClearDepthStencilValue;
7039*8975f5c5SAndroid Build Coastguard Worker }
7040*8975f5c5SAndroid Build Coastguard Worker 
getClearColorMasks() const7041*8975f5c5SAndroid Build Coastguard Worker gl::BlendStateExt::ColorMaskStorage::Type ContextVk::getClearColorMasks() const
7042*8975f5c5SAndroid Build Coastguard Worker {
7043*8975f5c5SAndroid Build Coastguard Worker     return mClearColorMasks;
7044*8975f5c5SAndroid Build Coastguard Worker }
7045*8975f5c5SAndroid Build Coastguard Worker 
writeAtomicCounterBufferDriverUniformOffsets(uint32_t * offsetsOut,size_t offsetsSize)7046*8975f5c5SAndroid Build Coastguard Worker void ContextVk::writeAtomicCounterBufferDriverUniformOffsets(uint32_t *offsetsOut,
7047*8975f5c5SAndroid Build Coastguard Worker                                                              size_t offsetsSize)
7048*8975f5c5SAndroid Build Coastguard Worker {
7049*8975f5c5SAndroid Build Coastguard Worker     const VkDeviceSize offsetAlignment =
7050*8975f5c5SAndroid Build Coastguard Worker         mRenderer->getPhysicalDeviceProperties().limits.minStorageBufferOffsetAlignment;
7051*8975f5c5SAndroid Build Coastguard Worker     size_t atomicCounterBufferCount = mState.getAtomicCounterBufferCount();
7052*8975f5c5SAndroid Build Coastguard Worker 
7053*8975f5c5SAndroid Build Coastguard Worker     ASSERT(atomicCounterBufferCount <= offsetsSize * 4);
7054*8975f5c5SAndroid Build Coastguard Worker 
7055*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
7056*8975f5c5SAndroid Build Coastguard Worker     {
7057*8975f5c5SAndroid Build Coastguard Worker         uint32_t offsetDiff = 0;
7058*8975f5c5SAndroid Build Coastguard Worker 
7059*8975f5c5SAndroid Build Coastguard Worker         const gl::OffsetBindingPointer<gl::Buffer> *atomicCounterBuffer =
7060*8975f5c5SAndroid Build Coastguard Worker             &mState.getIndexedAtomicCounterBuffer(bufferIndex);
7061*8975f5c5SAndroid Build Coastguard Worker         if (atomicCounterBuffer->get())
7062*8975f5c5SAndroid Build Coastguard Worker         {
7063*8975f5c5SAndroid Build Coastguard Worker             VkDeviceSize offset        = atomicCounterBuffer->getOffset();
7064*8975f5c5SAndroid Build Coastguard Worker             VkDeviceSize alignedOffset = (offset / offsetAlignment) * offsetAlignment;
7065*8975f5c5SAndroid Build Coastguard Worker 
7066*8975f5c5SAndroid Build Coastguard Worker             // GL requires the atomic counter buffer offset to be aligned with uint.
7067*8975f5c5SAndroid Build Coastguard Worker             ASSERT((offset - alignedOffset) % sizeof(uint32_t) == 0);
7068*8975f5c5SAndroid Build Coastguard Worker             offsetDiff = static_cast<uint32_t>((offset - alignedOffset) / sizeof(uint32_t));
7069*8975f5c5SAndroid Build Coastguard Worker 
7070*8975f5c5SAndroid Build Coastguard Worker             // We expect offsetDiff to fit in an 8-bit value.  The maximum difference is
7071*8975f5c5SAndroid Build Coastguard Worker             // minStorageBufferOffsetAlignment / 4, where minStorageBufferOffsetAlignment
7072*8975f5c5SAndroid Build Coastguard Worker             // currently has a maximum value of 256 on any device.
7073*8975f5c5SAndroid Build Coastguard Worker             ASSERT(offsetDiff < (1 << 8));
7074*8975f5c5SAndroid Build Coastguard Worker         }
7075*8975f5c5SAndroid Build Coastguard Worker 
7076*8975f5c5SAndroid Build Coastguard Worker         // The output array is already cleared prior to this call.
7077*8975f5c5SAndroid Build Coastguard Worker         ASSERT(bufferIndex % 4 != 0 || offsetsOut[bufferIndex / 4] == 0);
7078*8975f5c5SAndroid Build Coastguard Worker 
7079*8975f5c5SAndroid Build Coastguard Worker         offsetsOut[bufferIndex / 4] |= static_cast<uint8_t>(offsetDiff) << ((bufferIndex % 4) * 8);
7080*8975f5c5SAndroid Build Coastguard Worker     }
7081*8975f5c5SAndroid Build Coastguard Worker }
7082*8975f5c5SAndroid Build Coastguard Worker 
pauseTransformFeedbackIfActiveUnpaused()7083*8975f5c5SAndroid Build Coastguard Worker void ContextVk::pauseTransformFeedbackIfActiveUnpaused()
7084*8975f5c5SAndroid Build Coastguard Worker {
7085*8975f5c5SAndroid Build Coastguard Worker     if (mRenderPassCommands->isTransformFeedbackActiveUnpaused())
7086*8975f5c5SAndroid Build Coastguard Worker     {
7087*8975f5c5SAndroid Build Coastguard Worker         ASSERT(getFeatures().supportsTransformFeedbackExtension.enabled);
7088*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommands->pauseTransformFeedback();
7089*8975f5c5SAndroid Build Coastguard Worker 
7090*8975f5c5SAndroid Build Coastguard Worker         // Note that this function is called when render pass break is imminent
7091*8975f5c5SAndroid Build Coastguard Worker         // (flushCommandsAndEndRenderPass(), or UtilsVk::clearFramebuffer which will close the
7092*8975f5c5SAndroid Build Coastguard Worker         // render pass after the clear).  This dirty bit allows transform feedback to resume
7093*8975f5c5SAndroid Build Coastguard Worker         // automatically on next render pass.
7094*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
7095*8975f5c5SAndroid Build Coastguard Worker     }
7096*8975f5c5SAndroid Build Coastguard Worker }
7097*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyGraphicsDriverUniforms(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask)7098*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyGraphicsDriverUniforms(DirtyBits::Iterator *dirtyBitsIterator,
7099*8975f5c5SAndroid Build Coastguard Worker                                                            DirtyBits dirtyBitMask)
7100*8975f5c5SAndroid Build Coastguard Worker {
7101*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
7102*8975f5c5SAndroid Build Coastguard Worker 
7103*8975f5c5SAndroid Build Coastguard Worker     static_assert(gl::IMPLEMENTATION_MAX_FRAMEBUFFER_SIZE <= 0xFFFF,
7104*8975f5c5SAndroid Build Coastguard Worker                   "Not enough bits for render area");
7105*8975f5c5SAndroid Build Coastguard Worker     static_assert(gl::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE <= 0xFFFF,
7106*8975f5c5SAndroid Build Coastguard Worker                   "Not enough bits for render area");
7107*8975f5c5SAndroid Build Coastguard Worker     uint16_t renderAreaWidth, renderAreaHeight;
7108*8975f5c5SAndroid Build Coastguard Worker     SetBitField(renderAreaWidth, drawFramebufferVk->getState().getDimensions().width);
7109*8975f5c5SAndroid Build Coastguard Worker     SetBitField(renderAreaHeight, drawFramebufferVk->getState().getDimensions().height);
7110*8975f5c5SAndroid Build Coastguard Worker     const uint32_t renderArea = renderAreaHeight << 16 | renderAreaWidth;
7111*8975f5c5SAndroid Build Coastguard Worker 
7112*8975f5c5SAndroid Build Coastguard Worker     bool flipX = false;
7113*8975f5c5SAndroid Build Coastguard Worker     bool flipY = false;
7114*8975f5c5SAndroid Build Coastguard Worker     // Y-axis flipping only comes into play with the default framebuffer (i.e. a swapchain
7115*8975f5c5SAndroid Build Coastguard Worker     // image). For 0-degree rotation, an FBO or pbuffer could be the draw framebuffer, and so we
7116*8975f5c5SAndroid Build Coastguard Worker     // must check whether flipY should be positive or negative.  All other rotations, will be to
7117*8975f5c5SAndroid Build Coastguard Worker     // the default framebuffer, and so the value of isViewportFlipEnabledForDrawFBO() is assumed
7118*8975f5c5SAndroid Build Coastguard Worker     // true; the appropriate flipY value is chosen such that gl_FragCoord is positioned at the
7119*8975f5c5SAndroid Build Coastguard Worker     // lower-left corner of the window.
7120*8975f5c5SAndroid Build Coastguard Worker     switch (mCurrentRotationDrawFramebuffer)
7121*8975f5c5SAndroid Build Coastguard Worker     {
7122*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Identity:
7123*8975f5c5SAndroid Build Coastguard Worker             flipY = isViewportFlipEnabledForDrawFBO();
7124*8975f5c5SAndroid Build Coastguard Worker             break;
7125*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Rotated90Degrees:
7126*8975f5c5SAndroid Build Coastguard Worker             ASSERT(isViewportFlipEnabledForDrawFBO());
7127*8975f5c5SAndroid Build Coastguard Worker             break;
7128*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Rotated180Degrees:
7129*8975f5c5SAndroid Build Coastguard Worker             ASSERT(isViewportFlipEnabledForDrawFBO());
7130*8975f5c5SAndroid Build Coastguard Worker             flipX = true;
7131*8975f5c5SAndroid Build Coastguard Worker             break;
7132*8975f5c5SAndroid Build Coastguard Worker         case SurfaceRotation::Rotated270Degrees:
7133*8975f5c5SAndroid Build Coastguard Worker             ASSERT(isViewportFlipEnabledForDrawFBO());
7134*8975f5c5SAndroid Build Coastguard Worker             flipX = true;
7135*8975f5c5SAndroid Build Coastguard Worker             flipY = true;
7136*8975f5c5SAndroid Build Coastguard Worker             break;
7137*8975f5c5SAndroid Build Coastguard Worker         default:
7138*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
7139*8975f5c5SAndroid Build Coastguard Worker             break;
7140*8975f5c5SAndroid Build Coastguard Worker     }
7141*8975f5c5SAndroid Build Coastguard Worker 
7142*8975f5c5SAndroid Build Coastguard Worker     const bool invertViewport = isViewportFlipEnabledForDrawFBO();
7143*8975f5c5SAndroid Build Coastguard Worker 
7144*8975f5c5SAndroid Build Coastguard Worker     // Create the extended driver uniform, and populate the extended data fields if necessary.
7145*8975f5c5SAndroid Build Coastguard Worker     GraphicsDriverUniformsExtended driverUniformsExt = {};
7146*8975f5c5SAndroid Build Coastguard Worker     if (ShouldUseGraphicsDriverUniformsExtended(this))
7147*8975f5c5SAndroid Build Coastguard Worker     {
7148*8975f5c5SAndroid Build Coastguard Worker         if (mState.isTransformFeedbackActiveUnpaused())
7149*8975f5c5SAndroid Build Coastguard Worker         {
7150*8975f5c5SAndroid Build Coastguard Worker             TransformFeedbackVk *transformFeedbackVk =
7151*8975f5c5SAndroid Build Coastguard Worker                 vk::GetImpl(mState.getCurrentTransformFeedback());
7152*8975f5c5SAndroid Build Coastguard Worker             transformFeedbackVk->getBufferOffsets(this, mXfbBaseVertex,
7153*8975f5c5SAndroid Build Coastguard Worker                                                   driverUniformsExt.xfbBufferOffsets.data(),
7154*8975f5c5SAndroid Build Coastguard Worker                                                   driverUniformsExt.xfbBufferOffsets.size());
7155*8975f5c5SAndroid Build Coastguard Worker         }
7156*8975f5c5SAndroid Build Coastguard Worker         driverUniformsExt.xfbVerticesPerInstance = static_cast<int32_t>(mXfbVertexCountPerInstance);
7157*8975f5c5SAndroid Build Coastguard Worker     }
7158*8975f5c5SAndroid Build Coastguard Worker 
7159*8975f5c5SAndroid Build Coastguard Worker     // Create the driver uniform object that will be used as push constant argument.
7160*8975f5c5SAndroid Build Coastguard Worker     GraphicsDriverUniforms *driverUniforms = &driverUniformsExt.common;
7161*8975f5c5SAndroid Build Coastguard Worker     uint32_t driverUniformSize             = GetDriverUniformSize(this, PipelineType::Graphics);
7162*8975f5c5SAndroid Build Coastguard Worker 
7163*8975f5c5SAndroid Build Coastguard Worker     const float depthRangeNear = mState.getNearPlane();
7164*8975f5c5SAndroid Build Coastguard Worker     const float depthRangeFar  = mState.getFarPlane();
7165*8975f5c5SAndroid Build Coastguard Worker     const uint32_t numSamples  = drawFramebufferVk->getSamples();
7166*8975f5c5SAndroid Build Coastguard Worker     const uint32_t isLayered   = drawFramebufferVk->getLayerCount() > 1;
7167*8975f5c5SAndroid Build Coastguard Worker 
7168*8975f5c5SAndroid Build Coastguard Worker     uint32_t advancedBlendEquation = 0;
7169*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().emulateAdvancedBlendEquations.enabled && mState.isBlendEnabled())
7170*8975f5c5SAndroid Build Coastguard Worker     {
7171*8975f5c5SAndroid Build Coastguard Worker         // Pass the advanced blend equation to shader as-is.  If the equation is not one of the
7172*8975f5c5SAndroid Build Coastguard Worker         // advanced ones, 0 is expected.
7173*8975f5c5SAndroid Build Coastguard Worker         const gl::BlendStateExt &blendStateExt = mState.getBlendStateExt();
7174*8975f5c5SAndroid Build Coastguard Worker         if (blendStateExt.getUsesAdvancedBlendEquationMask().test(0))
7175*8975f5c5SAndroid Build Coastguard Worker         {
7176*8975f5c5SAndroid Build Coastguard Worker             advancedBlendEquation =
7177*8975f5c5SAndroid Build Coastguard Worker                 static_cast<uint32_t>(getState().getBlendStateExt().getEquationColorIndexed(0));
7178*8975f5c5SAndroid Build Coastguard Worker         }
7179*8975f5c5SAndroid Build Coastguard Worker     }
7180*8975f5c5SAndroid Build Coastguard Worker 
7181*8975f5c5SAndroid Build Coastguard Worker     const uint32_t swapXY               = IsRotatedAspectRatio(mCurrentRotationDrawFramebuffer);
7182*8975f5c5SAndroid Build Coastguard Worker     const uint32_t enabledClipDistances = mState.getEnabledClipDistances().bits();
7183*8975f5c5SAndroid Build Coastguard Worker     const uint32_t transformDepth =
7184*8975f5c5SAndroid Build Coastguard Worker         getFeatures().supportsDepthClipControl.enabled ? 0 : !mState.isClipDepthModeZeroToOne();
7185*8975f5c5SAndroid Build Coastguard Worker 
7186*8975f5c5SAndroid Build Coastguard Worker     static_assert(angle::BitMask<uint32_t>(gl::IMPLEMENTATION_MAX_CLIP_DISTANCES) <=
7187*8975f5c5SAndroid Build Coastguard Worker                       sh::vk::kDriverUniformsMiscEnabledClipPlanesMask,
7188*8975f5c5SAndroid Build Coastguard Worker                   "Not enough bits for enabled clip planes");
7189*8975f5c5SAndroid Build Coastguard Worker 
7190*8975f5c5SAndroid Build Coastguard Worker     ASSERT((swapXY & ~sh::vk::kDriverUniformsMiscSwapXYMask) == 0);
7191*8975f5c5SAndroid Build Coastguard Worker     ASSERT((advancedBlendEquation & ~sh::vk::kDriverUniformsMiscAdvancedBlendEquationMask) == 0);
7192*8975f5c5SAndroid Build Coastguard Worker     ASSERT((numSamples & ~sh::vk::kDriverUniformsMiscSampleCountMask) == 0);
7193*8975f5c5SAndroid Build Coastguard Worker     ASSERT((enabledClipDistances & ~sh::vk::kDriverUniformsMiscEnabledClipPlanesMask) == 0);
7194*8975f5c5SAndroid Build Coastguard Worker     ASSERT((transformDepth & ~sh::vk::kDriverUniformsMiscTransformDepthMask) == 0);
7195*8975f5c5SAndroid Build Coastguard Worker 
7196*8975f5c5SAndroid Build Coastguard Worker     const uint32_t misc =
7197*8975f5c5SAndroid Build Coastguard Worker         swapXY | advancedBlendEquation << sh::vk::kDriverUniformsMiscAdvancedBlendEquationOffset |
7198*8975f5c5SAndroid Build Coastguard Worker         numSamples << sh::vk::kDriverUniformsMiscSampleCountOffset |
7199*8975f5c5SAndroid Build Coastguard Worker         enabledClipDistances << sh::vk::kDriverUniformsMiscEnabledClipPlanesOffset |
7200*8975f5c5SAndroid Build Coastguard Worker         transformDepth << sh::vk::kDriverUniformsMiscTransformDepthOffset |
7201*8975f5c5SAndroid Build Coastguard Worker         isLayered << sh::vk::kDriverUniformsMiscLayeredFramebufferOffset;
7202*8975f5c5SAndroid Build Coastguard Worker 
7203*8975f5c5SAndroid Build Coastguard Worker     // Copy and flush to the device.
7204*8975f5c5SAndroid Build Coastguard Worker     *driverUniforms = {
7205*8975f5c5SAndroid Build Coastguard Worker         {},
7206*8975f5c5SAndroid Build Coastguard Worker         {depthRangeNear, depthRangeFar},
7207*8975f5c5SAndroid Build Coastguard Worker         renderArea,
7208*8975f5c5SAndroid Build Coastguard Worker         MakeFlipUniform(flipX, flipY, invertViewport),
7209*8975f5c5SAndroid Build Coastguard Worker         mGraphicsPipelineDesc->getEmulatedDitherControl(),
7210*8975f5c5SAndroid Build Coastguard Worker         misc,
7211*8975f5c5SAndroid Build Coastguard Worker     };
7212*8975f5c5SAndroid Build Coastguard Worker 
7213*8975f5c5SAndroid Build Coastguard Worker     if (mState.hasValidAtomicCounterBuffer())
7214*8975f5c5SAndroid Build Coastguard Worker     {
7215*8975f5c5SAndroid Build Coastguard Worker         writeAtomicCounterBufferDriverUniformOffsets(driverUniforms->acbBufferOffsets.data(),
7216*8975f5c5SAndroid Build Coastguard Worker                                                      driverUniforms->acbBufferOffsets.size());
7217*8975f5c5SAndroid Build Coastguard Worker     }
7218*8975f5c5SAndroid Build Coastguard Worker 
7219*8975f5c5SAndroid Build Coastguard Worker     // Update push constant driver uniforms.
7220*8975f5c5SAndroid Build Coastguard Worker     ProgramExecutableVk *executableVk = vk::GetImpl(mState.getProgramExecutable());
7221*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommands->getCommandBuffer().pushConstants(
7222*8975f5c5SAndroid Build Coastguard Worker         executableVk->getPipelineLayout(), getRenderer()->getSupportedVulkanShaderStageMask(), 0,
7223*8975f5c5SAndroid Build Coastguard Worker         driverUniformSize, driverUniforms);
7224*8975f5c5SAndroid Build Coastguard Worker 
7225*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
7226*8975f5c5SAndroid Build Coastguard Worker }
7227*8975f5c5SAndroid Build Coastguard Worker 
handleDirtyComputeDriverUniforms(DirtyBits::Iterator * dirtyBitsIterator)7228*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::handleDirtyComputeDriverUniforms(DirtyBits::Iterator *dirtyBitsIterator)
7229*8975f5c5SAndroid Build Coastguard Worker {
7230*8975f5c5SAndroid Build Coastguard Worker     // Create the driver uniform object that will be used as push constant argument.
7231*8975f5c5SAndroid Build Coastguard Worker     ComputeDriverUniforms driverUniforms = {};
7232*8975f5c5SAndroid Build Coastguard Worker     uint32_t driverUniformSize           = GetDriverUniformSize(this, PipelineType::Compute);
7233*8975f5c5SAndroid Build Coastguard Worker 
7234*8975f5c5SAndroid Build Coastguard Worker     if (mState.hasValidAtomicCounterBuffer())
7235*8975f5c5SAndroid Build Coastguard Worker     {
7236*8975f5c5SAndroid Build Coastguard Worker         writeAtomicCounterBufferDriverUniformOffsets(driverUniforms.acbBufferOffsets.data(),
7237*8975f5c5SAndroid Build Coastguard Worker                                                      driverUniforms.acbBufferOffsets.size());
7238*8975f5c5SAndroid Build Coastguard Worker     }
7239*8975f5c5SAndroid Build Coastguard Worker 
7240*8975f5c5SAndroid Build Coastguard Worker     // Update push constant driver uniforms.
7241*8975f5c5SAndroid Build Coastguard Worker     ProgramExecutableVk *executableVk = vk::GetImpl(mState.getProgramExecutable());
7242*8975f5c5SAndroid Build Coastguard Worker     mOutsideRenderPassCommands->getCommandBuffer().pushConstants(
7243*8975f5c5SAndroid Build Coastguard Worker         executableVk->getPipelineLayout(), getRenderer()->getSupportedVulkanShaderStageMask(), 0,
7244*8975f5c5SAndroid Build Coastguard Worker         driverUniformSize, &driverUniforms);
7245*8975f5c5SAndroid Build Coastguard Worker 
7246*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
7247*8975f5c5SAndroid Build Coastguard Worker }
7248*8975f5c5SAndroid Build Coastguard Worker 
handleError(VkResult errorCode,const char * file,const char * function,unsigned int line)7249*8975f5c5SAndroid Build Coastguard Worker void ContextVk::handleError(VkResult errorCode,
7250*8975f5c5SAndroid Build Coastguard Worker                             const char *file,
7251*8975f5c5SAndroid Build Coastguard Worker                             const char *function,
7252*8975f5c5SAndroid Build Coastguard Worker                             unsigned int line)
7253*8975f5c5SAndroid Build Coastguard Worker {
7254*8975f5c5SAndroid Build Coastguard Worker     ASSERT(errorCode != VK_SUCCESS);
7255*8975f5c5SAndroid Build Coastguard Worker 
7256*8975f5c5SAndroid Build Coastguard Worker     GLenum glErrorCode = DefaultGLErrorCode(errorCode);
7257*8975f5c5SAndroid Build Coastguard Worker 
7258*8975f5c5SAndroid Build Coastguard Worker     std::stringstream errorStream;
7259*8975f5c5SAndroid Build Coastguard Worker     errorStream << "Internal Vulkan error (" << errorCode << "): " << VulkanResultString(errorCode)
7260*8975f5c5SAndroid Build Coastguard Worker                 << ".";
7261*8975f5c5SAndroid Build Coastguard Worker 
7262*8975f5c5SAndroid Build Coastguard Worker     getRenderer()->getMemoryAllocationTracker()->logMemoryStatsOnError();
7263*8975f5c5SAndroid Build Coastguard Worker 
7264*8975f5c5SAndroid Build Coastguard Worker     if (errorCode == VK_ERROR_DEVICE_LOST)
7265*8975f5c5SAndroid Build Coastguard Worker     {
7266*8975f5c5SAndroid Build Coastguard Worker         WARN() << errorStream.str();
7267*8975f5c5SAndroid Build Coastguard Worker         handleDeviceLost();
7268*8975f5c5SAndroid Build Coastguard Worker     }
7269*8975f5c5SAndroid Build Coastguard Worker 
7270*8975f5c5SAndroid Build Coastguard Worker     mErrors->handleError(glErrorCode, errorStream.str().c_str(), file, function, line);
7271*8975f5c5SAndroid Build Coastguard Worker }
7272*8975f5c5SAndroid Build Coastguard Worker 
initBufferAllocation(vk::BufferHelper * bufferHelper,uint32_t memoryTypeIndex,size_t allocationSize,size_t alignment,BufferUsageType bufferUsageType)7273*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::initBufferAllocation(vk::BufferHelper *bufferHelper,
7274*8975f5c5SAndroid Build Coastguard Worker                                               uint32_t memoryTypeIndex,
7275*8975f5c5SAndroid Build Coastguard Worker                                               size_t allocationSize,
7276*8975f5c5SAndroid Build Coastguard Worker                                               size_t alignment,
7277*8975f5c5SAndroid Build Coastguard Worker                                               BufferUsageType bufferUsageType)
7278*8975f5c5SAndroid Build Coastguard Worker {
7279*8975f5c5SAndroid Build Coastguard Worker     vk::BufferPool *pool = getDefaultBufferPool(allocationSize, memoryTypeIndex, bufferUsageType);
7280*8975f5c5SAndroid Build Coastguard Worker     VkResult result      = bufferHelper->initSuballocation(this, memoryTypeIndex, allocationSize,
7281*8975f5c5SAndroid Build Coastguard Worker                                                            alignment, bufferUsageType, pool);
7282*8975f5c5SAndroid Build Coastguard Worker     if (ANGLE_LIKELY(result == VK_SUCCESS))
7283*8975f5c5SAndroid Build Coastguard Worker     {
7284*8975f5c5SAndroid Build Coastguard Worker         if (mRenderer->getFeatures().allocateNonZeroMemory.enabled)
7285*8975f5c5SAndroid Build Coastguard Worker         {
7286*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(bufferHelper->initializeNonZeroMemory(
7287*8975f5c5SAndroid Build Coastguard Worker                 this, GetDefaultBufferUsageFlags(mRenderer), allocationSize));
7288*8975f5c5SAndroid Build Coastguard Worker         }
7289*8975f5c5SAndroid Build Coastguard Worker 
7290*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
7291*8975f5c5SAndroid Build Coastguard Worker     }
7292*8975f5c5SAndroid Build Coastguard Worker 
7293*8975f5c5SAndroid Build Coastguard Worker     // If the error is not OOM, we should stop and handle the error. In case of OOM, we can try
7294*8975f5c5SAndroid Build Coastguard Worker     // other options.
7295*8975f5c5SAndroid Build Coastguard Worker     bool shouldTryFallback = (result == VK_ERROR_OUT_OF_DEVICE_MEMORY);
7296*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_CHECK(this, shouldTryFallback, result);
7297*8975f5c5SAndroid Build Coastguard Worker 
7298*8975f5c5SAndroid Build Coastguard Worker     // If memory allocation fails, it is possible to retry the allocation after cleaning the garbage
7299*8975f5c5SAndroid Build Coastguard Worker     // and waiting for submitted commands to finish if necessary.
7300*8975f5c5SAndroid Build Coastguard Worker     bool anyGarbageCleaned  = false;
7301*8975f5c5SAndroid Build Coastguard Worker     bool someGarbageCleaned = false;
7302*8975f5c5SAndroid Build Coastguard Worker     do
7303*8975f5c5SAndroid Build Coastguard Worker     {
7304*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mRenderer->cleanupSomeGarbage(this, &anyGarbageCleaned));
7305*8975f5c5SAndroid Build Coastguard Worker         if (anyGarbageCleaned)
7306*8975f5c5SAndroid Build Coastguard Worker         {
7307*8975f5c5SAndroid Build Coastguard Worker             someGarbageCleaned = true;
7308*8975f5c5SAndroid Build Coastguard Worker             result = bufferHelper->initSuballocation(this, memoryTypeIndex, allocationSize,
7309*8975f5c5SAndroid Build Coastguard Worker                                                      alignment, bufferUsageType, pool);
7310*8975f5c5SAndroid Build Coastguard Worker         }
7311*8975f5c5SAndroid Build Coastguard Worker     } while (result != VK_SUCCESS && anyGarbageCleaned);
7312*8975f5c5SAndroid Build Coastguard Worker 
7313*8975f5c5SAndroid Build Coastguard Worker     if (someGarbageCleaned)
7314*8975f5c5SAndroid Build Coastguard Worker     {
7315*8975f5c5SAndroid Build Coastguard Worker         INFO() << "Initial allocation failed. Cleaned some garbage | Allocation result: "
7316*8975f5c5SAndroid Build Coastguard Worker                << ((result == VK_SUCCESS) ? "SUCCESS" : "FAIL");
7317*8975f5c5SAndroid Build Coastguard Worker     }
7318*8975f5c5SAndroid Build Coastguard Worker 
7319*8975f5c5SAndroid Build Coastguard Worker     // If memory allocation fails, it is possible retry after flushing the context and cleaning all
7320*8975f5c5SAndroid Build Coastguard Worker     // the garbage.
7321*8975f5c5SAndroid Build Coastguard Worker     if (result != VK_SUCCESS)
7322*8975f5c5SAndroid Build Coastguard Worker     {
7323*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(finishImpl(RenderPassClosureReason::OutOfMemory));
7324*8975f5c5SAndroid Build Coastguard Worker         INFO() << "Context flushed due to out-of-memory error.";
7325*8975f5c5SAndroid Build Coastguard Worker         result = bufferHelper->initSuballocation(this, memoryTypeIndex, allocationSize, alignment,
7326*8975f5c5SAndroid Build Coastguard Worker                                                  bufferUsageType, pool);
7327*8975f5c5SAndroid Build Coastguard Worker     }
7328*8975f5c5SAndroid Build Coastguard Worker 
7329*8975f5c5SAndroid Build Coastguard Worker     // If the allocation continues to fail despite all the fallback options, the error must be
7330*8975f5c5SAndroid Build Coastguard Worker     // returned.
7331*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_CHECK(this, result == VK_SUCCESS, result);
7332*8975f5c5SAndroid Build Coastguard Worker 
7333*8975f5c5SAndroid Build Coastguard Worker     // Initialize with non-zero value if needed.
7334*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().allocateNonZeroMemory.enabled)
7335*8975f5c5SAndroid Build Coastguard Worker     {
7336*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(bufferHelper->initializeNonZeroMemory(this, GetDefaultBufferUsageFlags(mRenderer),
7337*8975f5c5SAndroid Build Coastguard Worker                                                         allocationSize));
7338*8975f5c5SAndroid Build Coastguard Worker     }
7339*8975f5c5SAndroid Build Coastguard Worker 
7340*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
7341*8975f5c5SAndroid Build Coastguard Worker }
7342*8975f5c5SAndroid Build Coastguard Worker 
initImageAllocation(vk::ImageHelper * imageHelper,bool hasProtectedContent,const vk::MemoryProperties & memoryProperties,VkMemoryPropertyFlags flags,vk::MemoryAllocationType allocationType)7343*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::initImageAllocation(vk::ImageHelper *imageHelper,
7344*8975f5c5SAndroid Build Coastguard Worker                                              bool hasProtectedContent,
7345*8975f5c5SAndroid Build Coastguard Worker                                              const vk::MemoryProperties &memoryProperties,
7346*8975f5c5SAndroid Build Coastguard Worker                                              VkMemoryPropertyFlags flags,
7347*8975f5c5SAndroid Build Coastguard Worker                                              vk::MemoryAllocationType allocationType)
7348*8975f5c5SAndroid Build Coastguard Worker {
7349*8975f5c5SAndroid Build Coastguard Worker     VkMemoryPropertyFlags oomExcludedFlags = 0;
7350*8975f5c5SAndroid Build Coastguard Worker     VkMemoryPropertyFlags outputFlags;
7351*8975f5c5SAndroid Build Coastguard Worker     VkDeviceSize outputSize;
7352*8975f5c5SAndroid Build Coastguard Worker 
7353*8975f5c5SAndroid Build Coastguard Worker     if (hasProtectedContent)
7354*8975f5c5SAndroid Build Coastguard Worker     {
7355*8975f5c5SAndroid Build Coastguard Worker         flags |= VK_MEMORY_PROPERTY_PROTECTED_BIT;
7356*8975f5c5SAndroid Build Coastguard Worker     }
7357*8975f5c5SAndroid Build Coastguard Worker 
7358*8975f5c5SAndroid Build Coastguard Worker     // Get memory requirements for the allocation.
7359*8975f5c5SAndroid Build Coastguard Worker     VkMemoryRequirements memoryRequirements;
7360*8975f5c5SAndroid Build Coastguard Worker     imageHelper->getImage().getMemoryRequirements(getDevice(), &memoryRequirements);
7361*8975f5c5SAndroid Build Coastguard Worker     bool allocateDedicatedMemory =
7362*8975f5c5SAndroid Build Coastguard Worker         mRenderer->getImageMemorySuballocator().needsDedicatedMemory(memoryRequirements.size);
7363*8975f5c5SAndroid Build Coastguard Worker 
7364*8975f5c5SAndroid Build Coastguard Worker     VkResult result = imageHelper->initMemory(this, memoryProperties, flags, oomExcludedFlags,
7365*8975f5c5SAndroid Build Coastguard Worker                                               &memoryRequirements, allocateDedicatedMemory,
7366*8975f5c5SAndroid Build Coastguard Worker                                               allocationType, &outputFlags, &outputSize);
7367*8975f5c5SAndroid Build Coastguard Worker     if (ANGLE_LIKELY(result == VK_SUCCESS))
7368*8975f5c5SAndroid Build Coastguard Worker     {
7369*8975f5c5SAndroid Build Coastguard Worker         if (mRenderer->getFeatures().allocateNonZeroMemory.enabled)
7370*8975f5c5SAndroid Build Coastguard Worker         {
7371*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(imageHelper->initializeNonZeroMemory(this, hasProtectedContent, outputFlags,
7372*8975f5c5SAndroid Build Coastguard Worker                                                            outputSize));
7373*8975f5c5SAndroid Build Coastguard Worker         }
7374*8975f5c5SAndroid Build Coastguard Worker 
7375*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
7376*8975f5c5SAndroid Build Coastguard Worker     }
7377*8975f5c5SAndroid Build Coastguard Worker 
7378*8975f5c5SAndroid Build Coastguard Worker     // If the error is not OOM, we should stop and handle the error. In case of OOM, we can try
7379*8975f5c5SAndroid Build Coastguard Worker     // other options.
7380*8975f5c5SAndroid Build Coastguard Worker     bool shouldTryFallback = (result == VK_ERROR_OUT_OF_DEVICE_MEMORY);
7381*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_CHECK(this, shouldTryFallback, result);
7382*8975f5c5SAndroid Build Coastguard Worker 
7383*8975f5c5SAndroid Build Coastguard Worker     // If memory allocation fails, it is possible to retry the allocation after cleaning the garbage
7384*8975f5c5SAndroid Build Coastguard Worker     // and waiting for submitted commands to finish if necessary.
7385*8975f5c5SAndroid Build Coastguard Worker     bool anyGarbageCleaned  = false;
7386*8975f5c5SAndroid Build Coastguard Worker     bool someGarbageCleaned = false;
7387*8975f5c5SAndroid Build Coastguard Worker     do
7388*8975f5c5SAndroid Build Coastguard Worker     {
7389*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mRenderer->cleanupSomeGarbage(this, &anyGarbageCleaned));
7390*8975f5c5SAndroid Build Coastguard Worker         if (anyGarbageCleaned)
7391*8975f5c5SAndroid Build Coastguard Worker         {
7392*8975f5c5SAndroid Build Coastguard Worker             someGarbageCleaned = true;
7393*8975f5c5SAndroid Build Coastguard Worker             result = imageHelper->initMemory(this, memoryProperties, flags, oomExcludedFlags,
7394*8975f5c5SAndroid Build Coastguard Worker                                              &memoryRequirements, allocateDedicatedMemory,
7395*8975f5c5SAndroid Build Coastguard Worker                                              allocationType, &outputFlags, &outputSize);
7396*8975f5c5SAndroid Build Coastguard Worker         }
7397*8975f5c5SAndroid Build Coastguard Worker     } while (result != VK_SUCCESS && anyGarbageCleaned);
7398*8975f5c5SAndroid Build Coastguard Worker 
7399*8975f5c5SAndroid Build Coastguard Worker     if (someGarbageCleaned)
7400*8975f5c5SAndroid Build Coastguard Worker     {
7401*8975f5c5SAndroid Build Coastguard Worker         INFO() << "Initial allocation failed. Cleaned some garbage | Allocation result: "
7402*8975f5c5SAndroid Build Coastguard Worker                << ((result == VK_SUCCESS) ? "SUCCESS" : "FAIL");
7403*8975f5c5SAndroid Build Coastguard Worker     }
7404*8975f5c5SAndroid Build Coastguard Worker 
7405*8975f5c5SAndroid Build Coastguard Worker     // If memory allocation fails, it is possible retry after flushing the context and cleaning all
7406*8975f5c5SAndroid Build Coastguard Worker     // the garbage.
7407*8975f5c5SAndroid Build Coastguard Worker     if (result != VK_SUCCESS)
7408*8975f5c5SAndroid Build Coastguard Worker     {
7409*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(finishImpl(RenderPassClosureReason::OutOfMemory));
7410*8975f5c5SAndroid Build Coastguard Worker         INFO() << "Context flushed due to out-of-memory error.";
7411*8975f5c5SAndroid Build Coastguard Worker         result = imageHelper->initMemory(this, memoryProperties, flags, oomExcludedFlags,
7412*8975f5c5SAndroid Build Coastguard Worker                                          &memoryRequirements, allocateDedicatedMemory,
7413*8975f5c5SAndroid Build Coastguard Worker                                          allocationType, &outputFlags, &outputSize);
7414*8975f5c5SAndroid Build Coastguard Worker     }
7415*8975f5c5SAndroid Build Coastguard Worker 
7416*8975f5c5SAndroid Build Coastguard Worker     // If no fallback has worked so far, we should record the failed allocation information in case
7417*8975f5c5SAndroid Build Coastguard Worker     // it needs to be logged.
7418*8975f5c5SAndroid Build Coastguard Worker     if (result != VK_SUCCESS)
7419*8975f5c5SAndroid Build Coastguard Worker     {
7420*8975f5c5SAndroid Build Coastguard Worker         uint32_t pendingMemoryTypeIndex;
7421*8975f5c5SAndroid Build Coastguard Worker         if (vma::FindMemoryTypeIndexForImageInfo(
7422*8975f5c5SAndroid Build Coastguard Worker                 mRenderer->getAllocator().getHandle(), &imageHelper->getVkImageCreateInfo(), flags,
7423*8975f5c5SAndroid Build Coastguard Worker                 flags, allocateDedicatedMemory, &pendingMemoryTypeIndex) == VK_SUCCESS)
7424*8975f5c5SAndroid Build Coastguard Worker         {
7425*8975f5c5SAndroid Build Coastguard Worker             mRenderer->getMemoryAllocationTracker()->setPendingMemoryAlloc(
7426*8975f5c5SAndroid Build Coastguard Worker                 allocationType, memoryRequirements.size, pendingMemoryTypeIndex);
7427*8975f5c5SAndroid Build Coastguard Worker         }
7428*8975f5c5SAndroid Build Coastguard Worker     }
7429*8975f5c5SAndroid Build Coastguard Worker 
7430*8975f5c5SAndroid Build Coastguard Worker     // If there is no space for the new allocation and other fallbacks have proved ineffective, the
7431*8975f5c5SAndroid Build Coastguard Worker     // allocation may still be made outside the device from all other memory types, although it will
7432*8975f5c5SAndroid Build Coastguard Worker     // result in performance penalty. This is a last resort.
7433*8975f5c5SAndroid Build Coastguard Worker     if (result != VK_SUCCESS)
7434*8975f5c5SAndroid Build Coastguard Worker     {
7435*8975f5c5SAndroid Build Coastguard Worker         oomExcludedFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
7436*8975f5c5SAndroid Build Coastguard Worker         result           = imageHelper->initMemory(this, memoryProperties, flags, oomExcludedFlags,
7437*8975f5c5SAndroid Build Coastguard Worker                                                    &memoryRequirements, allocateDedicatedMemory,
7438*8975f5c5SAndroid Build Coastguard Worker                                                    allocationType, &outputFlags, &outputSize);
7439*8975f5c5SAndroid Build Coastguard Worker         INFO()
7440*8975f5c5SAndroid Build Coastguard Worker             << "Allocation failed. Removed the DEVICE_LOCAL bit requirement | Allocation result: "
7441*8975f5c5SAndroid Build Coastguard Worker             << ((result == VK_SUCCESS) ? "SUCCESS" : "FAIL");
7442*8975f5c5SAndroid Build Coastguard Worker 
7443*8975f5c5SAndroid Build Coastguard Worker         if (result == VK_SUCCESS)
7444*8975f5c5SAndroid Build Coastguard Worker         {
7445*8975f5c5SAndroid Build Coastguard Worker             // For images allocated here, although allocation is preferred on the device, it is not
7446*8975f5c5SAndroid Build Coastguard Worker             // required.
7447*8975f5c5SAndroid Build Coastguard Worker             mRenderer->getMemoryAllocationTracker()->compareExpectedFlagsWithAllocatedFlags(
7448*8975f5c5SAndroid Build Coastguard Worker                 flags & ~oomExcludedFlags, flags, outputFlags,
7449*8975f5c5SAndroid Build Coastguard Worker                 reinterpret_cast<void *>(imageHelper->getAllocation().getHandle()));
7450*8975f5c5SAndroid Build Coastguard Worker 
7451*8975f5c5SAndroid Build Coastguard Worker             getPerfCounters().deviceMemoryImageAllocationFallbacks++;
7452*8975f5c5SAndroid Build Coastguard Worker         }
7453*8975f5c5SAndroid Build Coastguard Worker     }
7454*8975f5c5SAndroid Build Coastguard Worker 
7455*8975f5c5SAndroid Build Coastguard Worker     // If the allocation continues to fail despite all the fallback options, the error must be
7456*8975f5c5SAndroid Build Coastguard Worker     // returned.
7457*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_CHECK(this, result == VK_SUCCESS, result);
7458*8975f5c5SAndroid Build Coastguard Worker 
7459*8975f5c5SAndroid Build Coastguard Worker     // Initialize with non-zero value if needed.
7460*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().allocateNonZeroMemory.enabled)
7461*8975f5c5SAndroid Build Coastguard Worker     {
7462*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(imageHelper->initializeNonZeroMemory(this, hasProtectedContent, outputFlags,
7463*8975f5c5SAndroid Build Coastguard Worker                                                        outputSize));
7464*8975f5c5SAndroid Build Coastguard Worker         imageHelper->getImage().getHandle();
7465*8975f5c5SAndroid Build Coastguard Worker     }
7466*8975f5c5SAndroid Build Coastguard Worker 
7467*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
7468*8975f5c5SAndroid Build Coastguard Worker }
7469*8975f5c5SAndroid Build Coastguard Worker 
releaseBufferAllocation(vk::BufferHelper * bufferHelper)7470*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::releaseBufferAllocation(vk::BufferHelper *bufferHelper)
7471*8975f5c5SAndroid Build Coastguard Worker {
7472*8975f5c5SAndroid Build Coastguard Worker     bufferHelper->releaseBufferAndDescriptorSetCache(mRenderer);
7473*8975f5c5SAndroid Build Coastguard Worker 
7474*8975f5c5SAndroid Build Coastguard Worker     if (ANGLE_UNLIKELY(hasExcessPendingGarbage()))
7475*8975f5c5SAndroid Build Coastguard Worker     {
7476*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr,
7477*8975f5c5SAndroid Build Coastguard Worker                                          RenderPassClosureReason::ExcessivePendingGarbage));
7478*8975f5c5SAndroid Build Coastguard Worker     }
7479*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
7480*8975f5c5SAndroid Build Coastguard Worker }
7481*8975f5c5SAndroid Build Coastguard Worker 
initBufferForBufferCopy(vk::BufferHelper * bufferHelper,size_t size,vk::MemoryCoherency coherency)7482*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::initBufferForBufferCopy(vk::BufferHelper *bufferHelper,
7483*8975f5c5SAndroid Build Coastguard Worker                                                  size_t size,
7484*8975f5c5SAndroid Build Coastguard Worker                                                  vk::MemoryCoherency coherency)
7485*8975f5c5SAndroid Build Coastguard Worker {
7486*8975f5c5SAndroid Build Coastguard Worker     uint32_t memoryTypeIndex = mRenderer->getStagingBufferMemoryTypeIndex(coherency);
7487*8975f5c5SAndroid Build Coastguard Worker     size_t alignment         = mRenderer->getStagingBufferAlignment();
7488*8975f5c5SAndroid Build Coastguard Worker     return initBufferAllocation(bufferHelper, memoryTypeIndex, size, alignment,
7489*8975f5c5SAndroid Build Coastguard Worker                                 BufferUsageType::Dynamic);
7490*8975f5c5SAndroid Build Coastguard Worker }
7491*8975f5c5SAndroid Build Coastguard Worker 
initBufferForImageCopy(vk::BufferHelper * bufferHelper,size_t size,vk::MemoryCoherency coherency,angle::FormatID formatId,VkDeviceSize * offset,uint8_t ** dataPtr)7492*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::initBufferForImageCopy(vk::BufferHelper *bufferHelper,
7493*8975f5c5SAndroid Build Coastguard Worker                                                 size_t size,
7494*8975f5c5SAndroid Build Coastguard Worker                                                 vk::MemoryCoherency coherency,
7495*8975f5c5SAndroid Build Coastguard Worker                                                 angle::FormatID formatId,
7496*8975f5c5SAndroid Build Coastguard Worker                                                 VkDeviceSize *offset,
7497*8975f5c5SAndroid Build Coastguard Worker                                                 uint8_t **dataPtr)
7498*8975f5c5SAndroid Build Coastguard Worker {
7499*8975f5c5SAndroid Build Coastguard Worker     // When a buffer is used in copyImage, the offset must be multiple of pixel bytes. This may
7500*8975f5c5SAndroid Build Coastguard Worker     // result in non-power of two alignment. VMA's virtual allocator can not handle non-power of two
7501*8975f5c5SAndroid Build Coastguard Worker     // alignment. We have to adjust offset manually.
7502*8975f5c5SAndroid Build Coastguard Worker     uint32_t memoryTypeIndex  = mRenderer->getStagingBufferMemoryTypeIndex(coherency);
7503*8975f5c5SAndroid Build Coastguard Worker     size_t imageCopyAlignment = vk::GetImageCopyBufferAlignment(formatId);
7504*8975f5c5SAndroid Build Coastguard Worker 
7505*8975f5c5SAndroid Build Coastguard Worker     // Add extra padding for potential offset alignment
7506*8975f5c5SAndroid Build Coastguard Worker     size_t allocationSize   = size + imageCopyAlignment;
7507*8975f5c5SAndroid Build Coastguard Worker     allocationSize          = roundUp(allocationSize, imageCopyAlignment);
7508*8975f5c5SAndroid Build Coastguard Worker     size_t stagingAlignment = static_cast<size_t>(mRenderer->getStagingBufferAlignment());
7509*8975f5c5SAndroid Build Coastguard Worker 
7510*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(initBufferAllocation(bufferHelper, memoryTypeIndex, allocationSize, stagingAlignment,
7511*8975f5c5SAndroid Build Coastguard Worker                                    BufferUsageType::Static));
7512*8975f5c5SAndroid Build Coastguard Worker 
7513*8975f5c5SAndroid Build Coastguard Worker     *offset  = roundUp(bufferHelper->getOffset(), static_cast<VkDeviceSize>(imageCopyAlignment));
7514*8975f5c5SAndroid Build Coastguard Worker     *dataPtr = bufferHelper->getMappedMemory() + (*offset) - bufferHelper->getOffset();
7515*8975f5c5SAndroid Build Coastguard Worker 
7516*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
7517*8975f5c5SAndroid Build Coastguard Worker }
7518*8975f5c5SAndroid Build Coastguard Worker 
initBufferForVertexConversion(ConversionBuffer * conversionBuffer,size_t size,vk::MemoryHostVisibility hostVisibility)7519*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::initBufferForVertexConversion(ConversionBuffer *conversionBuffer,
7520*8975f5c5SAndroid Build Coastguard Worker                                                        size_t size,
7521*8975f5c5SAndroid Build Coastguard Worker                                                        vk::MemoryHostVisibility hostVisibility)
7522*8975f5c5SAndroid Build Coastguard Worker {
7523*8975f5c5SAndroid Build Coastguard Worker     vk::BufferHelper *bufferHelper = conversionBuffer->getBuffer();
7524*8975f5c5SAndroid Build Coastguard Worker     if (bufferHelper->valid())
7525*8975f5c5SAndroid Build Coastguard Worker     {
7526*8975f5c5SAndroid Build Coastguard Worker         // If size is big enough and it is idle, then just reuse the existing buffer. Or if current
7527*8975f5c5SAndroid Build Coastguard Worker         // render pass uses the buffer, try to allocate a new one to avoid breaking the render pass.
7528*8975f5c5SAndroid Build Coastguard Worker         if (size <= bufferHelper->getSize() &&
7529*8975f5c5SAndroid Build Coastguard Worker             (hostVisibility == vk::MemoryHostVisibility::Visible) ==
7530*8975f5c5SAndroid Build Coastguard Worker                 bufferHelper->isHostVisible() &&
7531*8975f5c5SAndroid Build Coastguard Worker             !isRenderPassStartedAndUsesBuffer(*bufferHelper))
7532*8975f5c5SAndroid Build Coastguard Worker         {
7533*8975f5c5SAndroid Build Coastguard Worker             if (mRenderer->hasResourceUseFinished(bufferHelper->getResourceUse()))
7534*8975f5c5SAndroid Build Coastguard Worker             {
7535*8975f5c5SAndroid Build Coastguard Worker                 bufferHelper->initializeBarrierTracker(this);
7536*8975f5c5SAndroid Build Coastguard Worker                 return angle::Result::Continue;
7537*8975f5c5SAndroid Build Coastguard Worker             }
7538*8975f5c5SAndroid Build Coastguard Worker             else if (hostVisibility == vk::MemoryHostVisibility::NonVisible)
7539*8975f5c5SAndroid Build Coastguard Worker             {
7540*8975f5c5SAndroid Build Coastguard Worker                 // For device local buffer, we can reuse the buffer even if it is still GPU busy.
7541*8975f5c5SAndroid Build Coastguard Worker                 // The memory barrier should take care of this.
7542*8975f5c5SAndroid Build Coastguard Worker                 return angle::Result::Continue;
7543*8975f5c5SAndroid Build Coastguard Worker             }
7544*8975f5c5SAndroid Build Coastguard Worker         }
7545*8975f5c5SAndroid Build Coastguard Worker 
7546*8975f5c5SAndroid Build Coastguard Worker         bufferHelper->release(mRenderer);
7547*8975f5c5SAndroid Build Coastguard Worker     }
7548*8975f5c5SAndroid Build Coastguard Worker 
7549*8975f5c5SAndroid Build Coastguard Worker     //  Mark entire buffer dirty if we have to reallocate the buffer.
7550*8975f5c5SAndroid Build Coastguard Worker     conversionBuffer->setEntireBufferDirty();
7551*8975f5c5SAndroid Build Coastguard Worker 
7552*8975f5c5SAndroid Build Coastguard Worker     uint32_t memoryTypeIndex = mRenderer->getVertexConversionBufferMemoryTypeIndex(hostVisibility);
7553*8975f5c5SAndroid Build Coastguard Worker     size_t alignment         = static_cast<size_t>(mRenderer->getVertexConversionBufferAlignment());
7554*8975f5c5SAndroid Build Coastguard Worker 
7555*8975f5c5SAndroid Build Coastguard Worker     // The size is retrieved and used in descriptor set. The descriptor set wants aligned size,
7556*8975f5c5SAndroid Build Coastguard Worker     // otherwise there are test failures. Note that the underlying VMA allocation is always
7557*8975f5c5SAndroid Build Coastguard Worker     // allocated with an aligned size anyway.
7558*8975f5c5SAndroid Build Coastguard Worker     size_t sizeToAllocate = roundUp(size, alignment);
7559*8975f5c5SAndroid Build Coastguard Worker 
7560*8975f5c5SAndroid Build Coastguard Worker     return initBufferAllocation(bufferHelper, memoryTypeIndex, sizeToAllocate, alignment,
7561*8975f5c5SAndroid Build Coastguard Worker                                 BufferUsageType::Static);
7562*8975f5c5SAndroid Build Coastguard Worker }
7563*8975f5c5SAndroid Build Coastguard Worker 
updateActiveTextures(const gl::Context * context,gl::Command command)7564*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::updateActiveTextures(const gl::Context *context, gl::Command command)
7565*8975f5c5SAndroid Build Coastguard Worker {
7566*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
7567*8975f5c5SAndroid Build Coastguard Worker     ProgramExecutableVk *executableVk       = vk::GetImpl(executable);
7568*8975f5c5SAndroid Build Coastguard Worker 
7569*8975f5c5SAndroid Build Coastguard Worker     const gl::ActiveTexturesCache &textures        = mState.getActiveTexturesCache();
7570*8975f5c5SAndroid Build Coastguard Worker     const gl::ActiveTextureMask &activeTextures    = executable->getActiveSamplersMask();
7571*8975f5c5SAndroid Build Coastguard Worker     const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
7572*8975f5c5SAndroid Build Coastguard Worker 
7573*8975f5c5SAndroid Build Coastguard Worker     FillWithNullptr(&mActiveTextures);
7574*8975f5c5SAndroid Build Coastguard Worker 
7575*8975f5c5SAndroid Build Coastguard Worker     bool recreatePipelineLayout                                     = false;
7576*8975f5c5SAndroid Build Coastguard Worker     ImmutableSamplerIndexMap immutableSamplerIndexMap               = {};
7577*8975f5c5SAndroid Build Coastguard Worker     std::unordered_map<size_t, uint32_t> textureUnitSamplerIndexMap = {};
7578*8975f5c5SAndroid Build Coastguard Worker     for (size_t textureUnit : activeTextures)
7579*8975f5c5SAndroid Build Coastguard Worker     {
7580*8975f5c5SAndroid Build Coastguard Worker         gl::Texture *texture        = textures[textureUnit];
7581*8975f5c5SAndroid Build Coastguard Worker         gl::TextureType textureType = textureTypes[textureUnit];
7582*8975f5c5SAndroid Build Coastguard Worker         ASSERT(textureType != gl::TextureType::InvalidEnum);
7583*8975f5c5SAndroid Build Coastguard Worker 
7584*8975f5c5SAndroid Build Coastguard Worker         const bool isIncompleteTexture = texture == nullptr;
7585*8975f5c5SAndroid Build Coastguard Worker 
7586*8975f5c5SAndroid Build Coastguard Worker         // Null textures represent incomplete textures.
7587*8975f5c5SAndroid Build Coastguard Worker         if (isIncompleteTexture)
7588*8975f5c5SAndroid Build Coastguard Worker         {
7589*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(getIncompleteTexture(
7590*8975f5c5SAndroid Build Coastguard Worker                 context, textureType, executable->getSamplerFormatForTextureUnitIndex(textureUnit),
7591*8975f5c5SAndroid Build Coastguard Worker                 &texture));
7592*8975f5c5SAndroid Build Coastguard Worker         }
7593*8975f5c5SAndroid Build Coastguard Worker 
7594*8975f5c5SAndroid Build Coastguard Worker         TextureVk *textureVk = vk::GetImpl(texture);
7595*8975f5c5SAndroid Build Coastguard Worker         ASSERT(textureVk != nullptr);
7596*8975f5c5SAndroid Build Coastguard Worker 
7597*8975f5c5SAndroid Build Coastguard Worker         mActiveTextures[textureUnit] = textureVk;
7598*8975f5c5SAndroid Build Coastguard Worker 
7599*8975f5c5SAndroid Build Coastguard Worker         if (textureType == gl::TextureType::Buffer)
7600*8975f5c5SAndroid Build Coastguard Worker         {
7601*8975f5c5SAndroid Build Coastguard Worker             continue;
7602*8975f5c5SAndroid Build Coastguard Worker         }
7603*8975f5c5SAndroid Build Coastguard Worker 
7604*8975f5c5SAndroid Build Coastguard Worker         if (!isIncompleteTexture && texture->isDepthOrStencil())
7605*8975f5c5SAndroid Build Coastguard Worker         {
7606*8975f5c5SAndroid Build Coastguard Worker             const bool isStencilTexture = IsStencilSamplerBinding(*executable, textureUnit);
7607*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(switchToReadOnlyDepthStencilMode(texture, command, getDrawFramebuffer(),
7608*8975f5c5SAndroid Build Coastguard Worker                                                        isStencilTexture));
7609*8975f5c5SAndroid Build Coastguard Worker         }
7610*8975f5c5SAndroid Build Coastguard Worker 
7611*8975f5c5SAndroid Build Coastguard Worker         gl::Sampler *sampler = mState.getSampler(static_cast<uint32_t>(textureUnit));
7612*8975f5c5SAndroid Build Coastguard Worker         const gl::SamplerState &samplerState =
7613*8975f5c5SAndroid Build Coastguard Worker             sampler ? sampler->getSamplerState() : texture->getSamplerState();
7614*8975f5c5SAndroid Build Coastguard Worker 
7615*8975f5c5SAndroid Build Coastguard Worker         // GL_EXT_texture_sRGB_decode
7616*8975f5c5SAndroid Build Coastguard Worker         //   The new parameter, TEXTURE_SRGB_DECODE_EXT controls whether the
7617*8975f5c5SAndroid Build Coastguard Worker         //   decoding happens at sample time. It only applies to textures with an
7618*8975f5c5SAndroid Build Coastguard Worker         //   internal format that is sRGB and is ignored for all other textures.
7619*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(textureVk->updateSrgbDecodeState(this, samplerState));
7620*8975f5c5SAndroid Build Coastguard Worker 
7621*8975f5c5SAndroid Build Coastguard Worker         const vk::ImageHelper &image = textureVk->getImage();
7622*8975f5c5SAndroid Build Coastguard Worker         if (image.hasInefficientlyEmulatedImageFormat())
7623*8975f5c5SAndroid Build Coastguard Worker         {
7624*8975f5c5SAndroid Build Coastguard Worker             ANGLE_VK_PERF_WARNING(
7625*8975f5c5SAndroid Build Coastguard Worker                 this, GL_DEBUG_SEVERITY_LOW,
7626*8975f5c5SAndroid Build Coastguard Worker                 "The Vulkan driver does not support texture format 0x%04X, emulating with 0x%04X",
7627*8975f5c5SAndroid Build Coastguard Worker                 image.getIntendedFormat().glInternalFormat,
7628*8975f5c5SAndroid Build Coastguard Worker                 image.getActualFormat().glInternalFormat);
7629*8975f5c5SAndroid Build Coastguard Worker         }
7630*8975f5c5SAndroid Build Coastguard Worker 
7631*8975f5c5SAndroid Build Coastguard Worker         if (image.hasImmutableSampler())
7632*8975f5c5SAndroid Build Coastguard Worker         {
7633*8975f5c5SAndroid Build Coastguard Worker             if (textureUnitSamplerIndexMap.empty())
7634*8975f5c5SAndroid Build Coastguard Worker             {
7635*8975f5c5SAndroid Build Coastguard Worker                 GenerateTextureUnitSamplerIndexMap(executable->getSamplerBoundTextureUnits(),
7636*8975f5c5SAndroid Build Coastguard Worker                                                    &textureUnitSamplerIndexMap);
7637*8975f5c5SAndroid Build Coastguard Worker             }
7638*8975f5c5SAndroid Build Coastguard Worker             immutableSamplerIndexMap[image.getYcbcrConversionDesc()] =
7639*8975f5c5SAndroid Build Coastguard Worker                 textureUnitSamplerIndexMap[textureUnit];
7640*8975f5c5SAndroid Build Coastguard Worker         }
7641*8975f5c5SAndroid Build Coastguard Worker 
7642*8975f5c5SAndroid Build Coastguard Worker         if (textureVk->getAndResetImmutableSamplerDirtyState())
7643*8975f5c5SAndroid Build Coastguard Worker         {
7644*8975f5c5SAndroid Build Coastguard Worker             recreatePipelineLayout = true;
7645*8975f5c5SAndroid Build Coastguard Worker         }
7646*8975f5c5SAndroid Build Coastguard Worker     }
7647*8975f5c5SAndroid Build Coastguard Worker 
7648*8975f5c5SAndroid Build Coastguard Worker     if (!executableVk->areImmutableSamplersCompatible(immutableSamplerIndexMap))
7649*8975f5c5SAndroid Build Coastguard Worker     {
7650*8975f5c5SAndroid Build Coastguard Worker         recreatePipelineLayout = true;
7651*8975f5c5SAndroid Build Coastguard Worker     }
7652*8975f5c5SAndroid Build Coastguard Worker 
7653*8975f5c5SAndroid Build Coastguard Worker     // Recreate the pipeline layout, if necessary.
7654*8975f5c5SAndroid Build Coastguard Worker     if (recreatePipelineLayout)
7655*8975f5c5SAndroid Build Coastguard Worker     {
7656*8975f5c5SAndroid Build Coastguard Worker         executableVk->resetLayout(this);
7657*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(executableVk->createPipelineLayout(
7658*8975f5c5SAndroid Build Coastguard Worker             this, &getPipelineLayoutCache(), &getDescriptorSetLayoutCache(), &mActiveTextures));
7659*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(executableVk->initializeDescriptorPools(this, &getDescriptorSetLayoutCache(),
7660*8975f5c5SAndroid Build Coastguard Worker                                                           &getMetaDescriptorPools()));
7661*8975f5c5SAndroid Build Coastguard Worker 
7662*8975f5c5SAndroid Build Coastguard Worker         // The default uniforms descriptor set was reset during createPipelineLayout(), so mark them
7663*8975f5c5SAndroid Build Coastguard Worker         // dirty to get everything reallocated/rebound before the next draw.
7664*8975f5c5SAndroid Build Coastguard Worker         if (executable->hasDefaultUniforms())
7665*8975f5c5SAndroid Build Coastguard Worker         {
7666*8975f5c5SAndroid Build Coastguard Worker             executableVk->setAllDefaultUniformsDirty();
7667*8975f5c5SAndroid Build Coastguard Worker         }
7668*8975f5c5SAndroid Build Coastguard Worker     }
7669*8975f5c5SAndroid Build Coastguard Worker 
7670*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
7671*8975f5c5SAndroid Build Coastguard Worker }
7672*8975f5c5SAndroid Build Coastguard Worker 
7673*8975f5c5SAndroid Build Coastguard Worker template <typename CommandBufferHelperT>
updateActiveImages(CommandBufferHelperT * commandBufferHelper)7674*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::updateActiveImages(CommandBufferHelperT *commandBufferHelper)
7675*8975f5c5SAndroid Build Coastguard Worker {
7676*8975f5c5SAndroid Build Coastguard Worker     const gl::State &glState                = mState;
7677*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = glState.getProgramExecutable();
7678*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executable);
7679*8975f5c5SAndroid Build Coastguard Worker 
7680*8975f5c5SAndroid Build Coastguard Worker     // If there are memoryBarrier call being made that requires we insert barriers for images we
7681*8975f5c5SAndroid Build Coastguard Worker     // must do so.
7682*8975f5c5SAndroid Build Coastguard Worker     bool memoryBarrierRequired = false;
7683*8975f5c5SAndroid Build Coastguard Worker     if ((mDeferredMemoryBarriers & kWriteAfterAccessImageMemoryBarriers) != 0)
7684*8975f5c5SAndroid Build Coastguard Worker     {
7685*8975f5c5SAndroid Build Coastguard Worker         memoryBarrierRequired = true;
7686*8975f5c5SAndroid Build Coastguard Worker         mDeferredMemoryBarriers &= ~kWriteAfterAccessImageMemoryBarriers;
7687*8975f5c5SAndroid Build Coastguard Worker     }
7688*8975f5c5SAndroid Build Coastguard Worker 
7689*8975f5c5SAndroid Build Coastguard Worker     FillWithNullptr(&mActiveImages);
7690*8975f5c5SAndroid Build Coastguard Worker 
7691*8975f5c5SAndroid Build Coastguard Worker     const gl::ActiveTextureMask &activeImages = executable->getActiveImagesMask();
7692*8975f5c5SAndroid Build Coastguard Worker     const gl::ActiveTextureArray<gl::ShaderBitSet> &activeImageShaderBits =
7693*8975f5c5SAndroid Build Coastguard Worker         executable->getActiveImageShaderBits();
7694*8975f5c5SAndroid Build Coastguard Worker 
7695*8975f5c5SAndroid Build Coastguard Worker     // Note: currently, the image layout is transitioned entirely even if only one level or layer is
7696*8975f5c5SAndroid Build Coastguard Worker     // used.  This is an issue if one subresource of the image is used as framebuffer attachment and
7697*8975f5c5SAndroid Build Coastguard Worker     // the other as image.  This is a similar issue to http://anglebug.com/40096531.  Another issue
7698*8975f5c5SAndroid Build Coastguard Worker     // however is if multiple subresources of the same image are used at the same time.
7699*8975f5c5SAndroid Build Coastguard Worker     // Inefficiencies aside, setting write dependency on the same image multiple times is not
7700*8975f5c5SAndroid Build Coastguard Worker     // supported.  The following makes sure write dependencies are set only once per image.
7701*8975f5c5SAndroid Build Coastguard Worker     std::set<vk::ImageHelper *> alreadyProcessed;
7702*8975f5c5SAndroid Build Coastguard Worker 
7703*8975f5c5SAndroid Build Coastguard Worker     for (size_t imageUnitIndex : activeImages)
7704*8975f5c5SAndroid Build Coastguard Worker     {
7705*8975f5c5SAndroid Build Coastguard Worker         const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
7706*8975f5c5SAndroid Build Coastguard Worker         const gl::Texture *texture     = imageUnit.texture.get();
7707*8975f5c5SAndroid Build Coastguard Worker         if (texture == nullptr)
7708*8975f5c5SAndroid Build Coastguard Worker         {
7709*8975f5c5SAndroid Build Coastguard Worker             continue;
7710*8975f5c5SAndroid Build Coastguard Worker         }
7711*8975f5c5SAndroid Build Coastguard Worker 
7712*8975f5c5SAndroid Build Coastguard Worker         TextureVk *textureVk          = vk::GetImpl(texture);
7713*8975f5c5SAndroid Build Coastguard Worker         mActiveImages[imageUnitIndex] = textureVk;
7714*8975f5c5SAndroid Build Coastguard Worker 
7715*8975f5c5SAndroid Build Coastguard Worker         // The image should be flushed and ready to use at this point. There may still be
7716*8975f5c5SAndroid Build Coastguard Worker         // lingering staged updates in its staging buffer for unused texture mip levels or
7717*8975f5c5SAndroid Build Coastguard Worker         // layers. Therefore we can't verify it has no staged updates right here.
7718*8975f5c5SAndroid Build Coastguard Worker         gl::ShaderBitSet shaderStages = activeImageShaderBits[imageUnitIndex];
7719*8975f5c5SAndroid Build Coastguard Worker         ASSERT(shaderStages.any());
7720*8975f5c5SAndroid Build Coastguard Worker 
7721*8975f5c5SAndroid Build Coastguard Worker         // Special handling of texture buffers.  They have a buffer attached instead of an image.
7722*8975f5c5SAndroid Build Coastguard Worker         if (texture->getType() == gl::TextureType::Buffer)
7723*8975f5c5SAndroid Build Coastguard Worker         {
7724*8975f5c5SAndroid Build Coastguard Worker             BufferVk *bufferVk = vk::GetImpl(textureVk->getBuffer().get());
7725*8975f5c5SAndroid Build Coastguard Worker 
7726*8975f5c5SAndroid Build Coastguard Worker             OnImageBufferWrite(bufferVk, shaderStages, commandBufferHelper);
7727*8975f5c5SAndroid Build Coastguard Worker 
7728*8975f5c5SAndroid Build Coastguard Worker             textureVk->retainBufferViews(commandBufferHelper);
7729*8975f5c5SAndroid Build Coastguard Worker             continue;
7730*8975f5c5SAndroid Build Coastguard Worker         }
7731*8975f5c5SAndroid Build Coastguard Worker 
7732*8975f5c5SAndroid Build Coastguard Worker         vk::ImageHelper *image = &textureVk->getImage();
7733*8975f5c5SAndroid Build Coastguard Worker 
7734*8975f5c5SAndroid Build Coastguard Worker         if (alreadyProcessed.find(image) != alreadyProcessed.end())
7735*8975f5c5SAndroid Build Coastguard Worker         {
7736*8975f5c5SAndroid Build Coastguard Worker             continue;
7737*8975f5c5SAndroid Build Coastguard Worker         }
7738*8975f5c5SAndroid Build Coastguard Worker         alreadyProcessed.insert(image);
7739*8975f5c5SAndroid Build Coastguard Worker 
7740*8975f5c5SAndroid Build Coastguard Worker         gl::LevelIndex level;
7741*8975f5c5SAndroid Build Coastguard Worker         uint32_t layerStart               = 0;
7742*8975f5c5SAndroid Build Coastguard Worker         uint32_t layerCount               = 0;
7743*8975f5c5SAndroid Build Coastguard Worker         const vk::ImageLayout imageLayout = GetImageWriteLayoutAndSubresource(
7744*8975f5c5SAndroid Build Coastguard Worker             imageUnit, *image, shaderStages, &level, &layerStart, &layerCount);
7745*8975f5c5SAndroid Build Coastguard Worker 
7746*8975f5c5SAndroid Build Coastguard Worker         if (imageLayout == image->getCurrentImageLayout() && !memoryBarrierRequired)
7747*8975f5c5SAndroid Build Coastguard Worker         {
7748*8975f5c5SAndroid Build Coastguard Worker             // GL spec does not require implementation to do WAW barriers for shader image access.
7749*8975f5c5SAndroid Build Coastguard Worker             // If there is no layout change, we skip the barrier here unless there is prior
7750*8975f5c5SAndroid Build Coastguard Worker             // memoryBarrier call.
7751*8975f5c5SAndroid Build Coastguard Worker             commandBufferHelper->retainImageWithEvent(this, image);
7752*8975f5c5SAndroid Build Coastguard Worker         }
7753*8975f5c5SAndroid Build Coastguard Worker         else
7754*8975f5c5SAndroid Build Coastguard Worker         {
7755*8975f5c5SAndroid Build Coastguard Worker             commandBufferHelper->imageWrite(this, level, layerStart, layerCount,
7756*8975f5c5SAndroid Build Coastguard Worker                                             image->getAspectFlags(), imageLayout, image);
7757*8975f5c5SAndroid Build Coastguard Worker         }
7758*8975f5c5SAndroid Build Coastguard Worker     }
7759*8975f5c5SAndroid Build Coastguard Worker 
7760*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
7761*8975f5c5SAndroid Build Coastguard Worker }
7762*8975f5c5SAndroid Build Coastguard Worker 
flushAndSubmitCommands(const vk::Semaphore * signalSemaphore,const vk::SharedExternalFence * externalFence,RenderPassClosureReason renderPassClosureReason)7763*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::flushAndSubmitCommands(const vk::Semaphore *signalSemaphore,
7764*8975f5c5SAndroid Build Coastguard Worker                                                 const vk::SharedExternalFence *externalFence,
7765*8975f5c5SAndroid Build Coastguard Worker                                                 RenderPassClosureReason renderPassClosureReason)
7766*8975f5c5SAndroid Build Coastguard Worker {
7767*8975f5c5SAndroid Build Coastguard Worker     // Even if render pass does not have any command, we may still need to submit it in case it has
7768*8975f5c5SAndroid Build Coastguard Worker     // CLEAR loadOp.
7769*8975f5c5SAndroid Build Coastguard Worker     bool someCommandsNeedFlush =
7770*8975f5c5SAndroid Build Coastguard Worker         !mOutsideRenderPassCommands->empty() || mRenderPassCommands->started();
7771*8975f5c5SAndroid Build Coastguard Worker     bool someCommandAlreadyFlushedNeedsSubmit =
7772*8975f5c5SAndroid Build Coastguard Worker         mLastFlushedQueueSerial != mLastSubmittedQueueSerial;
7773*8975f5c5SAndroid Build Coastguard Worker     bool someOtherReasonNeedsSubmit = signalSemaphore != nullptr || externalFence != nullptr ||
7774*8975f5c5SAndroid Build Coastguard Worker                                       mHasWaitSemaphoresPendingSubmission;
7775*8975f5c5SAndroid Build Coastguard Worker 
7776*8975f5c5SAndroid Build Coastguard Worker     if (!someCommandsNeedFlush && !someCommandAlreadyFlushedNeedsSubmit &&
7777*8975f5c5SAndroid Build Coastguard Worker         !someOtherReasonNeedsSubmit)
7778*8975f5c5SAndroid Build Coastguard Worker     {
7779*8975f5c5SAndroid Build Coastguard Worker         // We have nothing to submit.
7780*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
7781*8975f5c5SAndroid Build Coastguard Worker     }
7782*8975f5c5SAndroid Build Coastguard Worker 
7783*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::flushAndSubmitCommands");
7784*8975f5c5SAndroid Build Coastguard Worker     if (someCommandsNeedFlush)
7785*8975f5c5SAndroid Build Coastguard Worker     {
7786*8975f5c5SAndroid Build Coastguard Worker         // If any of secondary command buffer not empty, we need to do flush
7787*8975f5c5SAndroid Build Coastguard Worker         // Avoid calling vkQueueSubmit() twice, since submitCommands() below will do that.
7788*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushCommandsAndEndRenderPassWithoutSubmit(renderPassClosureReason));
7789*8975f5c5SAndroid Build Coastguard Worker     }
7790*8975f5c5SAndroid Build Coastguard Worker     else if (someCommandAlreadyFlushedNeedsSubmit)
7791*8975f5c5SAndroid Build Coastguard Worker     {
7792*8975f5c5SAndroid Build Coastguard Worker         // This is when someone already called flushCommandsAndEndRenderPassWithoutQueueSubmit.
7793*8975f5c5SAndroid Build Coastguard Worker         // Nothing to flush but we have some command to submit.
7794*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mLastFlushedQueueSerial.valid());
7795*8975f5c5SAndroid Build Coastguard Worker         ASSERT(QueueSerialsHaveDifferentIndexOrSmaller(mLastSubmittedQueueSerial,
7796*8975f5c5SAndroid Build Coastguard Worker                                                        mLastFlushedQueueSerial));
7797*8975f5c5SAndroid Build Coastguard Worker     }
7798*8975f5c5SAndroid Build Coastguard Worker 
7799*8975f5c5SAndroid Build Coastguard Worker     const bool outsideRenderPassWritesToBuffer =
7800*8975f5c5SAndroid Build Coastguard Worker         mOutsideRenderPassCommands->getAndResetHasHostVisibleBufferWrite();
7801*8975f5c5SAndroid Build Coastguard Worker     const bool renderPassWritesToBuffer =
7802*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommands->getAndResetHasHostVisibleBufferWrite();
7803*8975f5c5SAndroid Build Coastguard Worker     if (mIsAnyHostVisibleBufferWritten || outsideRenderPassWritesToBuffer ||
7804*8975f5c5SAndroid Build Coastguard Worker         renderPassWritesToBuffer)
7805*8975f5c5SAndroid Build Coastguard Worker     {
7806*8975f5c5SAndroid Build Coastguard Worker         // Make sure all writes to host-visible buffers are flushed.  We have no way of knowing
7807*8975f5c5SAndroid Build Coastguard Worker         // whether any buffer will be mapped for readback in the future, and we can't afford to
7808*8975f5c5SAndroid Build Coastguard Worker         // flush and wait on a one-pipeline-barrier command buffer on every map().
7809*8975f5c5SAndroid Build Coastguard Worker         VkMemoryBarrier memoryBarrier = {};
7810*8975f5c5SAndroid Build Coastguard Worker         memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
7811*8975f5c5SAndroid Build Coastguard Worker         memoryBarrier.srcAccessMask   = VK_ACCESS_MEMORY_WRITE_BIT;
7812*8975f5c5SAndroid Build Coastguard Worker         memoryBarrier.dstAccessMask   = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_HOST_WRITE_BIT;
7813*8975f5c5SAndroid Build Coastguard Worker 
7814*8975f5c5SAndroid Build Coastguard Worker         mOutsideRenderPassCommands->getCommandBuffer().memoryBarrier(
7815*8975f5c5SAndroid Build Coastguard Worker             mRenderer->getSupportedBufferWritePipelineStageMask(), VK_PIPELINE_STAGE_HOST_BIT,
7816*8975f5c5SAndroid Build Coastguard Worker             memoryBarrier);
7817*8975f5c5SAndroid Build Coastguard Worker         mIsAnyHostVisibleBufferWritten = false;
7818*8975f5c5SAndroid Build Coastguard Worker     }
7819*8975f5c5SAndroid Build Coastguard Worker 
7820*8975f5c5SAndroid Build Coastguard Worker     if (mGpuEventsEnabled)
7821*8975f5c5SAndroid Build Coastguard Worker     {
7822*8975f5c5SAndroid Build Coastguard Worker         EventName eventName = GetTraceEventName("Primary", mPrimaryBufferEventCounter);
7823*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
7824*8975f5c5SAndroid Build Coastguard Worker                                 TRACE_EVENT_PHASE_END, eventName));
7825*8975f5c5SAndroid Build Coastguard Worker     }
7826*8975f5c5SAndroid Build Coastguard Worker 
7827*8975f5c5SAndroid Build Coastguard Worker     // This will handle any commands that might be recorded above as well as flush any wait
7828*8975f5c5SAndroid Build Coastguard Worker     // semaphores.
7829*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flushOutsideRenderPassCommands());
7830*8975f5c5SAndroid Build Coastguard Worker 
7831*8975f5c5SAndroid Build Coastguard Worker     if (mLastFlushedQueueSerial == mLastSubmittedQueueSerial)
7832*8975f5c5SAndroid Build Coastguard Worker     {
7833*8975f5c5SAndroid Build Coastguard Worker         // We have to do empty submission...
7834*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!someCommandsNeedFlush);
7835*8975f5c5SAndroid Build Coastguard Worker         mLastFlushedQueueSerial = mOutsideRenderPassCommands->getQueueSerial();
7836*8975f5c5SAndroid Build Coastguard Worker         generateOutsideRenderPassCommandsQueueSerial();
7837*8975f5c5SAndroid Build Coastguard Worker     }
7838*8975f5c5SAndroid Build Coastguard Worker 
7839*8975f5c5SAndroid Build Coastguard Worker     // We must add the per context dynamic buffers into resourceUseList before submission so that
7840*8975f5c5SAndroid Build Coastguard Worker     // they get retained properly until GPU completes. We do not add current buffer into
7841*8975f5c5SAndroid Build Coastguard Worker     // resourceUseList since they never get reused or freed until context gets destroyed, at which
7842*8975f5c5SAndroid Build Coastguard Worker     // time we always wait for GPU to finish before destroying the dynamic buffers.
7843*8975f5c5SAndroid Build Coastguard Worker     mDefaultUniformStorage.updateQueueSerialAndReleaseInFlightBuffers(this,
7844*8975f5c5SAndroid Build Coastguard Worker                                                                       mLastFlushedQueueSerial);
7845*8975f5c5SAndroid Build Coastguard Worker 
7846*8975f5c5SAndroid Build Coastguard Worker     if (mHasInFlightStreamedVertexBuffers.any())
7847*8975f5c5SAndroid Build Coastguard Worker     {
7848*8975f5c5SAndroid Build Coastguard Worker         for (size_t attribIndex : mHasInFlightStreamedVertexBuffers)
7849*8975f5c5SAndroid Build Coastguard Worker         {
7850*8975f5c5SAndroid Build Coastguard Worker             mStreamedVertexBuffers[attribIndex].updateQueueSerialAndReleaseInFlightBuffers(
7851*8975f5c5SAndroid Build Coastguard Worker                 this, mLastFlushedQueueSerial);
7852*8975f5c5SAndroid Build Coastguard Worker         }
7853*8975f5c5SAndroid Build Coastguard Worker         mHasInFlightStreamedVertexBuffers.reset();
7854*8975f5c5SAndroid Build Coastguard Worker     }
7855*8975f5c5SAndroid Build Coastguard Worker 
7856*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mWaitSemaphores.empty());
7857*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mWaitSemaphoreStageMasks.empty());
7858*8975f5c5SAndroid Build Coastguard Worker 
7859*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(submitCommands(signalSemaphore, externalFence, Submit::AllCommands));
7860*8975f5c5SAndroid Build Coastguard Worker 
7861*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mOutsideRenderPassCommands->getQueueSerial() > mLastSubmittedQueueSerial);
7862*8975f5c5SAndroid Build Coastguard Worker 
7863*8975f5c5SAndroid Build Coastguard Worker     mHasAnyCommandsPendingSubmission    = false;
7864*8975f5c5SAndroid Build Coastguard Worker     mHasWaitSemaphoresPendingSubmission = false;
7865*8975f5c5SAndroid Build Coastguard Worker     onRenderPassFinished(RenderPassClosureReason::AlreadySpecifiedElsewhere);
7866*8975f5c5SAndroid Build Coastguard Worker 
7867*8975f5c5SAndroid Build Coastguard Worker     if (mGpuEventsEnabled)
7868*8975f5c5SAndroid Build Coastguard Worker     {
7869*8975f5c5SAndroid Build Coastguard Worker         EventName eventName = GetTraceEventName("Primary", ++mPrimaryBufferEventCounter);
7870*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
7871*8975f5c5SAndroid Build Coastguard Worker                                 TRACE_EVENT_PHASE_BEGIN, eventName));
7872*8975f5c5SAndroid Build Coastguard Worker     }
7873*8975f5c5SAndroid Build Coastguard Worker 
7874*8975f5c5SAndroid Build Coastguard Worker     // Since we just flushed, deferred flush is no longer deferred.
7875*8975f5c5SAndroid Build Coastguard Worker     mHasDeferredFlush = false;
7876*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
7877*8975f5c5SAndroid Build Coastguard Worker }
7878*8975f5c5SAndroid Build Coastguard Worker 
finishImpl(RenderPassClosureReason renderPassClosureReason)7879*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::finishImpl(RenderPassClosureReason renderPassClosureReason)
7880*8975f5c5SAndroid Build Coastguard Worker {
7881*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::finishImpl");
7882*8975f5c5SAndroid Build Coastguard Worker 
7883*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr, renderPassClosureReason));
7884*8975f5c5SAndroid Build Coastguard Worker 
7885*8975f5c5SAndroid Build Coastguard Worker     // You must have to wait for all queue indices ever used to finish. Just wait for
7886*8975f5c5SAndroid Build Coastguard Worker     // mLastSubmittedQueueSerial (which only contains current index) to finish is not enough, if it
7887*8975f5c5SAndroid Build Coastguard Worker     // has ever became unCurrent and then Current again.
7888*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mRenderer->finishResourceUse(this, mSubmittedResourceUse));
7889*8975f5c5SAndroid Build Coastguard Worker 
7890*8975f5c5SAndroid Build Coastguard Worker     clearAllGarbage();
7891*8975f5c5SAndroid Build Coastguard Worker 
7892*8975f5c5SAndroid Build Coastguard Worker     if (mGpuEventsEnabled)
7893*8975f5c5SAndroid Build Coastguard Worker     {
7894*8975f5c5SAndroid Build Coastguard Worker         // This loop should in practice execute once since the queue is already idle.
7895*8975f5c5SAndroid Build Coastguard Worker         while (mInFlightGpuEventQueries.size() > 0)
7896*8975f5c5SAndroid Build Coastguard Worker         {
7897*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(checkCompletedGpuEvents());
7898*8975f5c5SAndroid Build Coastguard Worker         }
7899*8975f5c5SAndroid Build Coastguard Worker         // Recalculate the CPU/GPU time difference to account for clock drifting.  Avoid
7900*8975f5c5SAndroid Build Coastguard Worker         // unnecessary synchronization if there is no event to be adjusted (happens when
7901*8975f5c5SAndroid Build Coastguard Worker         // finish() gets called multiple times towards the end of the application).
7902*8975f5c5SAndroid Build Coastguard Worker         if (mGpuEvents.size() > 0)
7903*8975f5c5SAndroid Build Coastguard Worker         {
7904*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(synchronizeCpuGpuTime());
7905*8975f5c5SAndroid Build Coastguard Worker         }
7906*8975f5c5SAndroid Build Coastguard Worker     }
7907*8975f5c5SAndroid Build Coastguard Worker 
7908*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
7909*8975f5c5SAndroid Build Coastguard Worker }
7910*8975f5c5SAndroid Build Coastguard Worker 
addWaitSemaphore(VkSemaphore semaphore,VkPipelineStageFlags stageMask)7911*8975f5c5SAndroid Build Coastguard Worker void ContextVk::addWaitSemaphore(VkSemaphore semaphore, VkPipelineStageFlags stageMask)
7912*8975f5c5SAndroid Build Coastguard Worker {
7913*8975f5c5SAndroid Build Coastguard Worker     mWaitSemaphores.push_back(semaphore);
7914*8975f5c5SAndroid Build Coastguard Worker     mWaitSemaphoreStageMasks.push_back(stageMask);
7915*8975f5c5SAndroid Build Coastguard Worker     mHasWaitSemaphoresPendingSubmission = true;
7916*8975f5c5SAndroid Build Coastguard Worker }
7917*8975f5c5SAndroid Build Coastguard Worker 
getCompatibleRenderPass(const vk::RenderPassDesc & desc,const vk::RenderPass ** renderPassOut)7918*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::getCompatibleRenderPass(const vk::RenderPassDesc &desc,
7919*8975f5c5SAndroid Build Coastguard Worker                                                  const vk::RenderPass **renderPassOut)
7920*8975f5c5SAndroid Build Coastguard Worker {
7921*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().preferDynamicRendering.enabled)
7922*8975f5c5SAndroid Build Coastguard Worker     {
7923*8975f5c5SAndroid Build Coastguard Worker         *renderPassOut = &mNullRenderPass;
7924*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
7925*8975f5c5SAndroid Build Coastguard Worker     }
7926*8975f5c5SAndroid Build Coastguard Worker 
7927*8975f5c5SAndroid Build Coastguard Worker     // Note: Each context has it's own RenderPassCache so no locking needed.
7928*8975f5c5SAndroid Build Coastguard Worker     return mRenderPassCache.getCompatibleRenderPass(this, desc, renderPassOut);
7929*8975f5c5SAndroid Build Coastguard Worker }
7930*8975f5c5SAndroid Build Coastguard Worker 
getRenderPassWithOps(const vk::RenderPassDesc & desc,const vk::AttachmentOpsArray & ops,const vk::RenderPass ** renderPassOut)7931*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::getRenderPassWithOps(const vk::RenderPassDesc &desc,
7932*8975f5c5SAndroid Build Coastguard Worker                                               const vk::AttachmentOpsArray &ops,
7933*8975f5c5SAndroid Build Coastguard Worker                                               const vk::RenderPass **renderPassOut)
7934*8975f5c5SAndroid Build Coastguard Worker {
7935*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().preferDynamicRendering.enabled)
7936*8975f5c5SAndroid Build Coastguard Worker     {
7937*8975f5c5SAndroid Build Coastguard Worker         if (mState.isPerfMonitorActive())
7938*8975f5c5SAndroid Build Coastguard Worker         {
7939*8975f5c5SAndroid Build Coastguard Worker             mRenderPassCommands->updatePerfCountersForDynamicRenderingInstance(this,
7940*8975f5c5SAndroid Build Coastguard Worker                                                                                &mPerfCounters);
7941*8975f5c5SAndroid Build Coastguard Worker         }
7942*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
7943*8975f5c5SAndroid Build Coastguard Worker     }
7944*8975f5c5SAndroid Build Coastguard Worker 
7945*8975f5c5SAndroid Build Coastguard Worker     // Note: Each context has it's own RenderPassCache so no locking needed.
7946*8975f5c5SAndroid Build Coastguard Worker     return mRenderPassCache.getRenderPassWithOps(this, desc, ops, renderPassOut);
7947*8975f5c5SAndroid Build Coastguard Worker }
7948*8975f5c5SAndroid Build Coastguard Worker 
getTimestamp(uint64_t * timestampOut)7949*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::getTimestamp(uint64_t *timestampOut)
7950*8975f5c5SAndroid Build Coastguard Worker {
7951*8975f5c5SAndroid Build Coastguard Worker     // The intent of this function is to query the timestamp without stalling the GPU.
7952*8975f5c5SAndroid Build Coastguard Worker     // Currently, that seems impossible, so instead, we are going to make a small submission
7953*8975f5c5SAndroid Build Coastguard Worker     // with just a timestamp query.  First, the disjoint timer query extension says:
7954*8975f5c5SAndroid Build Coastguard Worker     //
7955*8975f5c5SAndroid Build Coastguard Worker     // > This will return the GL time after all previous commands have reached the GL server but
7956*8975f5c5SAndroid Build Coastguard Worker     // have not yet necessarily executed.
7957*8975f5c5SAndroid Build Coastguard Worker     //
7958*8975f5c5SAndroid Build Coastguard Worker     // The previous commands may be deferred at the moment and not yet flushed. The wording allows
7959*8975f5c5SAndroid Build Coastguard Worker     // us to make a submission to get the timestamp without flushing.
7960*8975f5c5SAndroid Build Coastguard Worker     //
7961*8975f5c5SAndroid Build Coastguard Worker     // Second:
7962*8975f5c5SAndroid Build Coastguard Worker     //
7963*8975f5c5SAndroid Build Coastguard Worker     // > By using a combination of this synchronous get command and the asynchronous timestamp
7964*8975f5c5SAndroid Build Coastguard Worker     // query object target, applications can measure the latency between when commands reach the
7965*8975f5c5SAndroid Build Coastguard Worker     // GL server and when they are realized in the framebuffer.
7966*8975f5c5SAndroid Build Coastguard Worker     //
7967*8975f5c5SAndroid Build Coastguard Worker     // This fits with the above strategy as well, although inevitably we are possibly
7968*8975f5c5SAndroid Build Coastguard Worker     // introducing a GPU bubble.  This function directly generates a command buffer and submits
7969*8975f5c5SAndroid Build Coastguard Worker     // it instead of using the other member functions.  This is to avoid changing any state,
7970*8975f5c5SAndroid Build Coastguard Worker     // such as the queue serial.
7971*8975f5c5SAndroid Build Coastguard Worker 
7972*8975f5c5SAndroid Build Coastguard Worker     // Create a query used to receive the GPU timestamp
7973*8975f5c5SAndroid Build Coastguard Worker     VkDevice device = getDevice();
7974*8975f5c5SAndroid Build Coastguard Worker     vk::DeviceScoped<vk::DynamicQueryPool> timestampQueryPool(device);
7975*8975f5c5SAndroid Build Coastguard Worker     vk::QueryHelper timestampQuery;
7976*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(timestampQueryPool.get().init(this, VK_QUERY_TYPE_TIMESTAMP, 1));
7977*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(timestampQueryPool.get().allocateQuery(this, &timestampQuery, 1));
7978*8975f5c5SAndroid Build Coastguard Worker 
7979*8975f5c5SAndroid Build Coastguard Worker     // Record the command buffer
7980*8975f5c5SAndroid Build Coastguard Worker     vk::DeviceScoped<vk::PrimaryCommandBuffer> commandBatch(device);
7981*8975f5c5SAndroid Build Coastguard Worker     vk::PrimaryCommandBuffer &commandBuffer = commandBatch.get();
7982*8975f5c5SAndroid Build Coastguard Worker 
7983*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mRenderer->getCommandBufferOneOff(this, getProtectionType(), &commandBuffer));
7984*8975f5c5SAndroid Build Coastguard Worker 
7985*8975f5c5SAndroid Build Coastguard Worker     timestampQuery.writeTimestampToPrimary(this, &commandBuffer);
7986*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_TRY(this, commandBuffer.end());
7987*8975f5c5SAndroid Build Coastguard Worker 
7988*8975f5c5SAndroid Build Coastguard Worker     QueueSerial submitQueueSerial;
7989*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mRenderer->queueSubmitOneOff(this, std::move(commandBuffer), getProtectionType(),
7990*8975f5c5SAndroid Build Coastguard Worker                                            mContextPriority, VK_NULL_HANDLE, 0,
7991*8975f5c5SAndroid Build Coastguard Worker                                            vk::SubmitPolicy::AllowDeferred, &submitQueueSerial));
7992*8975f5c5SAndroid Build Coastguard Worker     // Track it with the submitSerial.
7993*8975f5c5SAndroid Build Coastguard Worker     timestampQuery.setQueueSerial(submitQueueSerial);
7994*8975f5c5SAndroid Build Coastguard Worker 
7995*8975f5c5SAndroid Build Coastguard Worker     // Wait for the submission to finish.  Given no semaphores, there is hope that it would execute
7996*8975f5c5SAndroid Build Coastguard Worker     // in parallel with what's already running on the GPU.
7997*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mRenderer->finishQueueSerial(this, submitQueueSerial));
7998*8975f5c5SAndroid Build Coastguard Worker 
7999*8975f5c5SAndroid Build Coastguard Worker     // Get the query results
8000*8975f5c5SAndroid Build Coastguard Worker     vk::QueryResult result(1);
8001*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(timestampQuery.getUint64Result(this, &result));
8002*8975f5c5SAndroid Build Coastguard Worker     *timestampOut = result.getResult(vk::QueryResult::kDefaultResultIndex);
8003*8975f5c5SAndroid Build Coastguard Worker     timestampQueryPool.get().freeQuery(this, &timestampQuery);
8004*8975f5c5SAndroid Build Coastguard Worker 
8005*8975f5c5SAndroid Build Coastguard Worker     // Convert results to nanoseconds.
8006*8975f5c5SAndroid Build Coastguard Worker     *timestampOut = static_cast<uint64_t>(
8007*8975f5c5SAndroid Build Coastguard Worker         *timestampOut *
8008*8975f5c5SAndroid Build Coastguard Worker         static_cast<double>(getRenderer()->getPhysicalDeviceProperties().limits.timestampPeriod));
8009*8975f5c5SAndroid Build Coastguard Worker 
8010*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8011*8975f5c5SAndroid Build Coastguard Worker }
8012*8975f5c5SAndroid Build Coastguard Worker 
invalidateDefaultAttribute(size_t attribIndex)8013*8975f5c5SAndroid Build Coastguard Worker void ContextVk::invalidateDefaultAttribute(size_t attribIndex)
8014*8975f5c5SAndroid Build Coastguard Worker {
8015*8975f5c5SAndroid Build Coastguard Worker     mDirtyDefaultAttribsMask.set(attribIndex);
8016*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits.set(DIRTY_BIT_DEFAULT_ATTRIBS);
8017*8975f5c5SAndroid Build Coastguard Worker }
8018*8975f5c5SAndroid Build Coastguard Worker 
invalidateDefaultAttributes(const gl::AttributesMask & dirtyMask)8019*8975f5c5SAndroid Build Coastguard Worker void ContextVk::invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask)
8020*8975f5c5SAndroid Build Coastguard Worker {
8021*8975f5c5SAndroid Build Coastguard Worker     if (dirtyMask.any())
8022*8975f5c5SAndroid Build Coastguard Worker     {
8023*8975f5c5SAndroid Build Coastguard Worker         mDirtyDefaultAttribsMask |= dirtyMask;
8024*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_DEFAULT_ATTRIBS);
8025*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
8026*8975f5c5SAndroid Build Coastguard Worker     }
8027*8975f5c5SAndroid Build Coastguard Worker }
8028*8975f5c5SAndroid Build Coastguard Worker 
onBufferReleaseToExternal(const vk::BufferHelper & buffer)8029*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::onBufferReleaseToExternal(const vk::BufferHelper &buffer)
8030*8975f5c5SAndroid Build Coastguard Worker {
8031*8975f5c5SAndroid Build Coastguard Worker     if (mRenderPassCommands->usesBuffer(buffer))
8032*8975f5c5SAndroid Build Coastguard Worker     {
8033*8975f5c5SAndroid Build Coastguard Worker         return flushCommandsAndEndRenderPass(
8034*8975f5c5SAndroid Build Coastguard Worker             RenderPassClosureReason::BufferUseThenReleaseToExternal);
8035*8975f5c5SAndroid Build Coastguard Worker     }
8036*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8037*8975f5c5SAndroid Build Coastguard Worker }
8038*8975f5c5SAndroid Build Coastguard Worker 
onImageReleaseToExternal(const vk::ImageHelper & image)8039*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::onImageReleaseToExternal(const vk::ImageHelper &image)
8040*8975f5c5SAndroid Build Coastguard Worker {
8041*8975f5c5SAndroid Build Coastguard Worker     if (isRenderPassStartedAndUsesImage(image))
8042*8975f5c5SAndroid Build Coastguard Worker     {
8043*8975f5c5SAndroid Build Coastguard Worker         return flushCommandsAndEndRenderPass(
8044*8975f5c5SAndroid Build Coastguard Worker             RenderPassClosureReason::ImageUseThenReleaseToExternal);
8045*8975f5c5SAndroid Build Coastguard Worker     }
8046*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8047*8975f5c5SAndroid Build Coastguard Worker }
8048*8975f5c5SAndroid Build Coastguard Worker 
beginNewRenderPass(vk::RenderPassFramebuffer && framebuffer,const gl::Rectangle & renderArea,const vk::RenderPassDesc & renderPassDesc,const vk::AttachmentOpsArray & renderPassAttachmentOps,const vk::PackedAttachmentCount colorAttachmentCount,const vk::PackedAttachmentIndex depthStencilAttachmentIndex,const vk::PackedClearValuesArray & clearValues,vk::RenderPassCommandBuffer ** commandBufferOut)8049*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::beginNewRenderPass(
8050*8975f5c5SAndroid Build Coastguard Worker     vk::RenderPassFramebuffer &&framebuffer,
8051*8975f5c5SAndroid Build Coastguard Worker     const gl::Rectangle &renderArea,
8052*8975f5c5SAndroid Build Coastguard Worker     const vk::RenderPassDesc &renderPassDesc,
8053*8975f5c5SAndroid Build Coastguard Worker     const vk::AttachmentOpsArray &renderPassAttachmentOps,
8054*8975f5c5SAndroid Build Coastguard Worker     const vk::PackedAttachmentCount colorAttachmentCount,
8055*8975f5c5SAndroid Build Coastguard Worker     const vk::PackedAttachmentIndex depthStencilAttachmentIndex,
8056*8975f5c5SAndroid Build Coastguard Worker     const vk::PackedClearValuesArray &clearValues,
8057*8975f5c5SAndroid Build Coastguard Worker     vk::RenderPassCommandBuffer **commandBufferOut)
8058*8975f5c5SAndroid Build Coastguard Worker {
8059*8975f5c5SAndroid Build Coastguard Worker     // End any currently outstanding render pass. The render pass is normally closed before reaching
8060*8975f5c5SAndroid Build Coastguard Worker     // here for various reasons, except typically when UtilsVk needs to start one.
8061*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flushCommandsAndEndRenderPass(RenderPassClosureReason::NewRenderPass));
8062*8975f5c5SAndroid Build Coastguard Worker 
8063*8975f5c5SAndroid Build Coastguard Worker     // Now generate queueSerial for the renderPass.
8064*8975f5c5SAndroid Build Coastguard Worker     QueueSerial renderPassQueueSerial;
8065*8975f5c5SAndroid Build Coastguard Worker     generateRenderPassCommandsQueueSerial(&renderPassQueueSerial);
8066*8975f5c5SAndroid Build Coastguard Worker 
8067*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.renderPasses++;
8068*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mRenderPassCommands->beginRenderPass(
8069*8975f5c5SAndroid Build Coastguard Worker         this, std::move(framebuffer), renderArea, renderPassDesc, renderPassAttachmentOps,
8070*8975f5c5SAndroid Build Coastguard Worker         colorAttachmentCount, depthStencilAttachmentIndex, clearValues, renderPassQueueSerial,
8071*8975f5c5SAndroid Build Coastguard Worker         commandBufferOut));
8072*8975f5c5SAndroid Build Coastguard Worker 
8073*8975f5c5SAndroid Build Coastguard Worker     // By default all render pass should allow to be reactivated.
8074*8975f5c5SAndroid Build Coastguard Worker     mAllowRenderPassToReactivate = true;
8075*8975f5c5SAndroid Build Coastguard Worker 
8076*8975f5c5SAndroid Build Coastguard Worker     if (mCurrentGraphicsPipeline)
8077*8975f5c5SAndroid Build Coastguard Worker     {
8078*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mCurrentGraphicsPipeline->valid());
8079*8975f5c5SAndroid Build Coastguard Worker         mCurrentGraphicsPipeline->retainInRenderPass(mRenderPassCommands);
8080*8975f5c5SAndroid Build Coastguard Worker     }
8081*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8082*8975f5c5SAndroid Build Coastguard Worker }
8083*8975f5c5SAndroid Build Coastguard Worker 
startRenderPass(gl::Rectangle renderArea,vk::RenderPassCommandBuffer ** commandBufferOut,bool * renderPassDescChangedOut)8084*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea,
8085*8975f5c5SAndroid Build Coastguard Worker                                          vk::RenderPassCommandBuffer **commandBufferOut,
8086*8975f5c5SAndroid Build Coastguard Worker                                          bool *renderPassDescChangedOut)
8087*8975f5c5SAndroid Build Coastguard Worker {
8088*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
8089*8975f5c5SAndroid Build Coastguard Worker     ASSERT(drawFramebufferVk == vk::GetImpl(mState.getDrawFramebuffer()));
8090*8975f5c5SAndroid Build Coastguard Worker 
8091*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(drawFramebufferVk->startNewRenderPass(this, renderArea, &mRenderPassCommandBuffer,
8092*8975f5c5SAndroid Build Coastguard Worker                                                     renderPassDescChangedOut));
8093*8975f5c5SAndroid Build Coastguard Worker 
8094*8975f5c5SAndroid Build Coastguard Worker     // Make sure the render pass is not restarted if it is started by UtilsVk (as opposed to
8095*8975f5c5SAndroid Build Coastguard Worker     // setupDraw(), which clears this bit automatically).
8096*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits.reset(DIRTY_BIT_RENDER_PASS);
8097*8975f5c5SAndroid Build Coastguard Worker 
8098*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(resumeRenderPassQueriesIfActive());
8099*8975f5c5SAndroid Build Coastguard Worker 
8100*8975f5c5SAndroid Build Coastguard Worker     if (commandBufferOut)
8101*8975f5c5SAndroid Build Coastguard Worker     {
8102*8975f5c5SAndroid Build Coastguard Worker         *commandBufferOut = mRenderPassCommandBuffer;
8103*8975f5c5SAndroid Build Coastguard Worker     }
8104*8975f5c5SAndroid Build Coastguard Worker 
8105*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8106*8975f5c5SAndroid Build Coastguard Worker }
8107*8975f5c5SAndroid Build Coastguard Worker 
startNextSubpass()8108*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::startNextSubpass()
8109*8975f5c5SAndroid Build Coastguard Worker {
8110*8975f5c5SAndroid Build Coastguard Worker     ASSERT(hasActiveRenderPass());
8111*8975f5c5SAndroid Build Coastguard Worker 
8112*8975f5c5SAndroid Build Coastguard Worker     // The graphics pipelines are bound to a subpass, so update the subpass as well.
8113*8975f5c5SAndroid Build Coastguard Worker     mGraphicsPipelineDesc->nextSubpass(&mGraphicsPipelineTransition);
8114*8975f5c5SAndroid Build Coastguard Worker 
8115*8975f5c5SAndroid Build Coastguard Worker     return mRenderPassCommands->nextSubpass(this, &mRenderPassCommandBuffer);
8116*8975f5c5SAndroid Build Coastguard Worker }
8117*8975f5c5SAndroid Build Coastguard Worker 
getCurrentSubpassIndex() const8118*8975f5c5SAndroid Build Coastguard Worker uint32_t ContextVk::getCurrentSubpassIndex() const
8119*8975f5c5SAndroid Build Coastguard Worker {
8120*8975f5c5SAndroid Build Coastguard Worker     return mGraphicsPipelineDesc->getSubpass();
8121*8975f5c5SAndroid Build Coastguard Worker }
8122*8975f5c5SAndroid Build Coastguard Worker 
getCurrentViewCount() const8123*8975f5c5SAndroid Build Coastguard Worker uint32_t ContextVk::getCurrentViewCount() const
8124*8975f5c5SAndroid Build Coastguard Worker {
8125*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *drawFBO = vk::GetImpl(mState.getDrawFramebuffer());
8126*8975f5c5SAndroid Build Coastguard Worker     return drawFBO->getRenderPassDesc().viewCount();
8127*8975f5c5SAndroid Build Coastguard Worker }
8128*8975f5c5SAndroid Build Coastguard Worker 
flushCommandsAndEndRenderPassWithoutSubmit(RenderPassClosureReason reason)8129*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::flushCommandsAndEndRenderPassWithoutSubmit(RenderPassClosureReason reason)
8130*8975f5c5SAndroid Build Coastguard Worker {
8131*8975f5c5SAndroid Build Coastguard Worker     // Ensure we flush the RenderPass *after* the prior commands.
8132*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flushOutsideRenderPassCommands());
8133*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mOutsideRenderPassCommands->empty());
8134*8975f5c5SAndroid Build Coastguard Worker 
8135*8975f5c5SAndroid Build Coastguard Worker     if (!mRenderPassCommands->started())
8136*8975f5c5SAndroid Build Coastguard Worker     {
8137*8975f5c5SAndroid Build Coastguard Worker         onRenderPassFinished(RenderPassClosureReason::AlreadySpecifiedElsewhere);
8138*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
8139*8975f5c5SAndroid Build Coastguard Worker     }
8140*8975f5c5SAndroid Build Coastguard Worker 
8141*8975f5c5SAndroid Build Coastguard Worker     // Set dirty bits if render pass was open (and thus will be closed).
8142*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
8143*8975f5c5SAndroid Build Coastguard Worker 
8144*8975f5c5SAndroid Build Coastguard Worker     mCurrentTransformFeedbackQueueSerial = QueueSerial();
8145*8975f5c5SAndroid Build Coastguard Worker 
8146*8975f5c5SAndroid Build Coastguard Worker     onRenderPassFinished(reason);
8147*8975f5c5SAndroid Build Coastguard Worker 
8148*8975f5c5SAndroid Build Coastguard Worker     if (mGpuEventsEnabled)
8149*8975f5c5SAndroid Build Coastguard Worker     {
8150*8975f5c5SAndroid Build Coastguard Worker         EventName eventName = GetTraceEventName("RP", mPerfCounters.renderPasses);
8151*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
8152*8975f5c5SAndroid Build Coastguard Worker                                 TRACE_EVENT_PHASE_BEGIN, eventName));
8153*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushOutsideRenderPassCommands());
8154*8975f5c5SAndroid Build Coastguard Worker     }
8155*8975f5c5SAndroid Build Coastguard Worker 
8156*8975f5c5SAndroid Build Coastguard Worker     addOverlayUsedBuffersCount(mRenderPassCommands);
8157*8975f5c5SAndroid Build Coastguard Worker 
8158*8975f5c5SAndroid Build Coastguard Worker     pauseTransformFeedbackIfActiveUnpaused();
8159*8975f5c5SAndroid Build Coastguard Worker 
8160*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mRenderPassCommands->endRenderPass(this));
8161*8975f5c5SAndroid Build Coastguard Worker 
8162*8975f5c5SAndroid Build Coastguard Worker     if (kEnableCommandStreamDiagnostics)
8163*8975f5c5SAndroid Build Coastguard Worker     {
8164*8975f5c5SAndroid Build Coastguard Worker         addCommandBufferDiagnostics(mRenderPassCommands->getCommandDiagnostics());
8165*8975f5c5SAndroid Build Coastguard Worker     }
8166*8975f5c5SAndroid Build Coastguard Worker 
8167*8975f5c5SAndroid Build Coastguard Worker     flushDescriptorSetUpdates();
8168*8975f5c5SAndroid Build Coastguard Worker     // Collect RefCountedEvent garbage before submitting to renderer
8169*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommands->collectRefCountedEventsGarbage(
8170*8975f5c5SAndroid Build Coastguard Worker         mShareGroupVk->getRefCountedEventsGarbageRecycler());
8171*8975f5c5SAndroid Build Coastguard Worker 
8172*8975f5c5SAndroid Build Coastguard Worker     // Save the queueSerial before calling flushRenderPassCommands, which may return a new
8173*8975f5c5SAndroid Build Coastguard Worker     // mRenderPassCommands
8174*8975f5c5SAndroid Build Coastguard Worker     ASSERT(QueueSerialsHaveDifferentIndexOrSmaller(mLastFlushedQueueSerial,
8175*8975f5c5SAndroid Build Coastguard Worker                                                    mRenderPassCommands->getQueueSerial()));
8176*8975f5c5SAndroid Build Coastguard Worker     mLastFlushedQueueSerial = mRenderPassCommands->getQueueSerial();
8177*8975f5c5SAndroid Build Coastguard Worker 
8178*8975f5c5SAndroid Build Coastguard Worker     const vk::RenderPass unusedRenderPass;
8179*8975f5c5SAndroid Build Coastguard Worker     const vk::RenderPass *renderPass  = &unusedRenderPass;
8180*8975f5c5SAndroid Build Coastguard Worker     VkFramebuffer framebufferOverride = VK_NULL_HANDLE;
8181*8975f5c5SAndroid Build Coastguard Worker 
8182*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(getRenderPassWithOps(mRenderPassCommands->getRenderPassDesc(),
8183*8975f5c5SAndroid Build Coastguard Worker                                    mRenderPassCommands->getAttachmentOps(), &renderPass));
8184*8975f5c5SAndroid Build Coastguard Worker 
8185*8975f5c5SAndroid Build Coastguard Worker     // If a new framebuffer is used to accommodate resolve attachments that have been added
8186*8975f5c5SAndroid Build Coastguard Worker     // after the fact, create a temp one now and add it to garbage list.
8187*8975f5c5SAndroid Build Coastguard Worker     if (!getFeatures().preferDynamicRendering.enabled &&
8188*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommands->getFramebuffer().needsNewFramebufferWithResolveAttachments())
8189*8975f5c5SAndroid Build Coastguard Worker     {
8190*8975f5c5SAndroid Build Coastguard Worker         vk::Framebuffer tempFramebuffer;
8191*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mRenderPassCommands->getFramebuffer().packResolveViewsAndCreateFramebuffer(
8192*8975f5c5SAndroid Build Coastguard Worker             this, *renderPass, &tempFramebuffer));
8193*8975f5c5SAndroid Build Coastguard Worker 
8194*8975f5c5SAndroid Build Coastguard Worker         framebufferOverride = tempFramebuffer.getHandle();
8195*8975f5c5SAndroid Build Coastguard Worker         addGarbage(&tempFramebuffer);
8196*8975f5c5SAndroid Build Coastguard Worker     }
8197*8975f5c5SAndroid Build Coastguard Worker 
8198*8975f5c5SAndroid Build Coastguard Worker     if (mRenderPassCommands->getAndResetHasHostVisibleBufferWrite())
8199*8975f5c5SAndroid Build Coastguard Worker     {
8200*8975f5c5SAndroid Build Coastguard Worker         mIsAnyHostVisibleBufferWritten = true;
8201*8975f5c5SAndroid Build Coastguard Worker     }
8202*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mRenderer->flushRenderPassCommands(this, getProtectionType(), mContextPriority,
8203*8975f5c5SAndroid Build Coastguard Worker                                                  *renderPass, framebufferOverride,
8204*8975f5c5SAndroid Build Coastguard Worker                                                  &mRenderPassCommands));
8205*8975f5c5SAndroid Build Coastguard Worker 
8206*8975f5c5SAndroid Build Coastguard Worker     // We just flushed outSideRenderPassCommands above, and any future use of
8207*8975f5c5SAndroid Build Coastguard Worker     // outsideRenderPassCommands must have a queueSerial bigger than renderPassCommands. To ensure
8208*8975f5c5SAndroid Build Coastguard Worker     // this ordering, we generate a new queueSerial for outsideRenderPassCommands here.
8209*8975f5c5SAndroid Build Coastguard Worker     mOutsideRenderPassSerialFactory.reset();
8210*8975f5c5SAndroid Build Coastguard Worker 
8211*8975f5c5SAndroid Build Coastguard Worker     // Generate a new serial for outside commands.
8212*8975f5c5SAndroid Build Coastguard Worker     generateOutsideRenderPassCommandsQueueSerial();
8213*8975f5c5SAndroid Build Coastguard Worker 
8214*8975f5c5SAndroid Build Coastguard Worker     if (mGpuEventsEnabled)
8215*8975f5c5SAndroid Build Coastguard Worker     {
8216*8975f5c5SAndroid Build Coastguard Worker         EventName eventName = GetTraceEventName("RP", mPerfCounters.renderPasses);
8217*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands->getCommandBuffer(),
8218*8975f5c5SAndroid Build Coastguard Worker                                 TRACE_EVENT_PHASE_END, eventName));
8219*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushOutsideRenderPassCommands());
8220*8975f5c5SAndroid Build Coastguard Worker     }
8221*8975f5c5SAndroid Build Coastguard Worker 
8222*8975f5c5SAndroid Build Coastguard Worker     mHasAnyCommandsPendingSubmission = true;
8223*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8224*8975f5c5SAndroid Build Coastguard Worker }
8225*8975f5c5SAndroid Build Coastguard Worker 
flushCommandsAndEndRenderPass(RenderPassClosureReason reason)8226*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::flushCommandsAndEndRenderPass(RenderPassClosureReason reason)
8227*8975f5c5SAndroid Build Coastguard Worker {
8228*8975f5c5SAndroid Build Coastguard Worker     // The main reason we have mHasDeferredFlush is not to break render pass just because we want
8229*8975f5c5SAndroid Build Coastguard Worker     // to issue a flush. So there must be a started RP if it is true. Otherwise we should just
8230*8975f5c5SAndroid Build Coastguard Worker     // issue a flushAndSubmitCommands immediately instead of set mHasDeferredFlush to true.
8231*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mHasDeferredFlush || mRenderPassCommands->started());
8232*8975f5c5SAndroid Build Coastguard Worker 
8233*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flushCommandsAndEndRenderPassWithoutSubmit(reason));
8234*8975f5c5SAndroid Build Coastguard Worker 
8235*8975f5c5SAndroid Build Coastguard Worker     if (mHasDeferredFlush || hasExcessPendingGarbage())
8236*8975f5c5SAndroid Build Coastguard Worker     {
8237*8975f5c5SAndroid Build Coastguard Worker         // If we have deferred glFlush call in the middle of render pass, or if there is too much
8238*8975f5c5SAndroid Build Coastguard Worker         // pending garbage, perform a flush now.
8239*8975f5c5SAndroid Build Coastguard Worker         RenderPassClosureReason flushImplReason =
8240*8975f5c5SAndroid Build Coastguard Worker             (hasExcessPendingGarbage()) ? RenderPassClosureReason::ExcessivePendingGarbage
8241*8975f5c5SAndroid Build Coastguard Worker                                         : RenderPassClosureReason::AlreadySpecifiedElsewhere;
8242*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flushAndSubmitCommands(nullptr, nullptr, flushImplReason));
8243*8975f5c5SAndroid Build Coastguard Worker     }
8244*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8245*8975f5c5SAndroid Build Coastguard Worker }
8246*8975f5c5SAndroid Build Coastguard Worker 
flushDirtyGraphicsRenderPass(DirtyBits::Iterator * dirtyBitsIterator,DirtyBits dirtyBitMask,RenderPassClosureReason reason)8247*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::flushDirtyGraphicsRenderPass(DirtyBits::Iterator *dirtyBitsIterator,
8248*8975f5c5SAndroid Build Coastguard Worker                                                       DirtyBits dirtyBitMask,
8249*8975f5c5SAndroid Build Coastguard Worker                                                       RenderPassClosureReason reason)
8250*8975f5c5SAndroid Build Coastguard Worker {
8251*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mRenderPassCommands->started());
8252*8975f5c5SAndroid Build Coastguard Worker 
8253*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flushCommandsAndEndRenderPass(reason));
8254*8975f5c5SAndroid Build Coastguard Worker 
8255*8975f5c5SAndroid Build Coastguard Worker     // Set dirty bits that need processing on new render pass on the dirty bits iterator that's
8256*8975f5c5SAndroid Build Coastguard Worker     // being processed right now.
8257*8975f5c5SAndroid Build Coastguard Worker     dirtyBitsIterator->setLaterBits(mNewGraphicsCommandBufferDirtyBits & dirtyBitMask);
8258*8975f5c5SAndroid Build Coastguard Worker 
8259*8975f5c5SAndroid Build Coastguard Worker     // Additionally, make sure any dirty bits not included in the mask are left for future
8260*8975f5c5SAndroid Build Coastguard Worker     // processing.  Note that |dirtyBitMask| is removed from |mNewGraphicsCommandBufferDirtyBits|
8261*8975f5c5SAndroid Build Coastguard Worker     // after dirty bits are iterated, so there's no need to mask them out.
8262*8975f5c5SAndroid Build Coastguard Worker     mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
8263*8975f5c5SAndroid Build Coastguard Worker 
8264*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mGraphicsPipelineDesc->getSubpass() == 0);
8265*8975f5c5SAndroid Build Coastguard Worker 
8266*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8267*8975f5c5SAndroid Build Coastguard Worker }
8268*8975f5c5SAndroid Build Coastguard Worker 
syncExternalMemory()8269*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::syncExternalMemory()
8270*8975f5c5SAndroid Build Coastguard Worker {
8271*8975f5c5SAndroid Build Coastguard Worker     VkMemoryBarrier memoryBarrier = {};
8272*8975f5c5SAndroid Build Coastguard Worker     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
8273*8975f5c5SAndroid Build Coastguard Worker     memoryBarrier.srcAccessMask   = VK_ACCESS_MEMORY_WRITE_BIT;
8274*8975f5c5SAndroid Build Coastguard Worker     memoryBarrier.dstAccessMask   = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
8275*8975f5c5SAndroid Build Coastguard Worker 
8276*8975f5c5SAndroid Build Coastguard Worker     mOutsideRenderPassCommands->getCommandBuffer().memoryBarrier(
8277*8975f5c5SAndroid Build Coastguard Worker         VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, memoryBarrier);
8278*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8279*8975f5c5SAndroid Build Coastguard Worker }
8280*8975f5c5SAndroid Build Coastguard Worker 
onSyncObjectInit(vk::SyncHelper * syncHelper,SyncFenceScope scope)8281*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::onSyncObjectInit(vk::SyncHelper *syncHelper, SyncFenceScope scope)
8282*8975f5c5SAndroid Build Coastguard Worker {
8283*8975f5c5SAndroid Build Coastguard Worker     // Submit the commands:
8284*8975f5c5SAndroid Build Coastguard Worker     //
8285*8975f5c5SAndroid Build Coastguard Worker     // - This breaks the current render pass to ensure the proper ordering of the sync object in the
8286*8975f5c5SAndroid Build Coastguard Worker     //   commands,
8287*8975f5c5SAndroid Build Coastguard Worker     // - The sync object has a valid serial when it's waited on later,
8288*8975f5c5SAndroid Build Coastguard Worker     // - After waiting on the sync object, every resource that's used so far (and is being synced)
8289*8975f5c5SAndroid Build Coastguard Worker     //   will also be aware that it's finished (based on the serial) and won't incur a further wait
8290*8975f5c5SAndroid Build Coastguard Worker     //   (for example when a buffer is mapped).
8291*8975f5c5SAndroid Build Coastguard Worker     //
8292*8975f5c5SAndroid Build Coastguard Worker     // The submission is done immediately for EGL sync objects, and when no render pass is open.  If
8293*8975f5c5SAndroid Build Coastguard Worker     // a render pass is open, the submission is deferred.  This is done to be able to optimize
8294*8975f5c5SAndroid Build Coastguard Worker     // scenarios such as sync object init followed by eglSwapBuffers() (that would otherwise incur
8295*8975f5c5SAndroid Build Coastguard Worker     // another submission, as well as not being able to optimize the render-to-swapchain render
8296*8975f5c5SAndroid Build Coastguard Worker     // pass).
8297*8975f5c5SAndroid Build Coastguard Worker     if (scope != SyncFenceScope::CurrentContextToShareGroup || !mRenderPassCommands->started())
8298*8975f5c5SAndroid Build Coastguard Worker     {
8299*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(
8300*8975f5c5SAndroid Build Coastguard Worker             flushAndSubmitCommands(nullptr, nullptr, RenderPassClosureReason::SyncObjectInit));
8301*8975f5c5SAndroid Build Coastguard Worker         // Even if no commands is generated, and flushAndSubmitCommands bails out, queueSerial is
8302*8975f5c5SAndroid Build Coastguard Worker         // valid since Context initialization. It will always test finished/signaled.
8303*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mLastSubmittedQueueSerial.valid());
8304*8975f5c5SAndroid Build Coastguard Worker 
8305*8975f5c5SAndroid Build Coastguard Worker         // If src synchronization scope is all contexts (an ANGLE extension), set the syncHelper
8306*8975f5c5SAndroid Build Coastguard Worker         // serial to the last serial of all contexts, instead of just the current context.
8307*8975f5c5SAndroid Build Coastguard Worker         if (scope == SyncFenceScope::AllContextsToAllContexts)
8308*8975f5c5SAndroid Build Coastguard Worker         {
8309*8975f5c5SAndroid Build Coastguard Worker             const size_t maxIndex = mRenderer->getLargestQueueSerialIndexEverAllocated();
8310*8975f5c5SAndroid Build Coastguard Worker             for (SerialIndex index = 0; index <= maxIndex; ++index)
8311*8975f5c5SAndroid Build Coastguard Worker             {
8312*8975f5c5SAndroid Build Coastguard Worker                 syncHelper->setSerial(index, mRenderer->getLastSubmittedSerial(index));
8313*8975f5c5SAndroid Build Coastguard Worker             }
8314*8975f5c5SAndroid Build Coastguard Worker         }
8315*8975f5c5SAndroid Build Coastguard Worker         else
8316*8975f5c5SAndroid Build Coastguard Worker         {
8317*8975f5c5SAndroid Build Coastguard Worker             syncHelper->setQueueSerial(mLastSubmittedQueueSerial);
8318*8975f5c5SAndroid Build Coastguard Worker         }
8319*8975f5c5SAndroid Build Coastguard Worker 
8320*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
8321*8975f5c5SAndroid Build Coastguard Worker     }
8322*8975f5c5SAndroid Build Coastguard Worker 
8323*8975f5c5SAndroid Build Coastguard Worker     // Otherwise we must have a started render pass. The sync object will track the completion of
8324*8975f5c5SAndroid Build Coastguard Worker     // this render pass.
8325*8975f5c5SAndroid Build Coastguard Worker     mRenderPassCommands->retainResource(syncHelper);
8326*8975f5c5SAndroid Build Coastguard Worker 
8327*8975f5c5SAndroid Build Coastguard Worker     onRenderPassFinished(RenderPassClosureReason::SyncObjectInit);
8328*8975f5c5SAndroid Build Coastguard Worker 
8329*8975f5c5SAndroid Build Coastguard Worker     // Mark the context as having a deffered flush.  This is later used to close the render pass and
8330*8975f5c5SAndroid Build Coastguard Worker     // cause a submission in this context if another context wants to wait on the fence while the
8331*8975f5c5SAndroid Build Coastguard Worker     // original context never issued a submission naturally.  Note that this also takes care of
8332*8975f5c5SAndroid Build Coastguard Worker     // contexts that think they issued a submission (through glFlush) but that the submission got
8333*8975f5c5SAndroid Build Coastguard Worker     // deferred.
8334*8975f5c5SAndroid Build Coastguard Worker     mHasDeferredFlush = true;
8335*8975f5c5SAndroid Build Coastguard Worker 
8336*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8337*8975f5c5SAndroid Build Coastguard Worker }
8338*8975f5c5SAndroid Build Coastguard Worker 
flushCommandsAndEndRenderPassIfDeferredSyncInit(RenderPassClosureReason reason)8339*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::flushCommandsAndEndRenderPassIfDeferredSyncInit(
8340*8975f5c5SAndroid Build Coastguard Worker     RenderPassClosureReason reason)
8341*8975f5c5SAndroid Build Coastguard Worker {
8342*8975f5c5SAndroid Build Coastguard Worker     if (!mHasDeferredFlush)
8343*8975f5c5SAndroid Build Coastguard Worker     {
8344*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
8345*8975f5c5SAndroid Build Coastguard Worker     }
8346*8975f5c5SAndroid Build Coastguard Worker 
8347*8975f5c5SAndroid Build Coastguard Worker     // If we have deferred glFlush call in the middle of render pass, flush them now.
8348*8975f5c5SAndroid Build Coastguard Worker     return flushCommandsAndEndRenderPass(reason);
8349*8975f5c5SAndroid Build Coastguard Worker }
8350*8975f5c5SAndroid Build Coastguard Worker 
addCommandBufferDiagnostics(const std::string & commandBufferDiagnostics)8351*8975f5c5SAndroid Build Coastguard Worker void ContextVk::addCommandBufferDiagnostics(const std::string &commandBufferDiagnostics)
8352*8975f5c5SAndroid Build Coastguard Worker {
8353*8975f5c5SAndroid Build Coastguard Worker     mCommandBufferDiagnostics.push_back(commandBufferDiagnostics);
8354*8975f5c5SAndroid Build Coastguard Worker }
8355*8975f5c5SAndroid Build Coastguard Worker 
dumpCommandStreamDiagnostics()8356*8975f5c5SAndroid Build Coastguard Worker void ContextVk::dumpCommandStreamDiagnostics()
8357*8975f5c5SAndroid Build Coastguard Worker {
8358*8975f5c5SAndroid Build Coastguard Worker     std::ostream &out = std::cout;
8359*8975f5c5SAndroid Build Coastguard Worker 
8360*8975f5c5SAndroid Build Coastguard Worker     if (mCommandBufferDiagnostics.empty())
8361*8975f5c5SAndroid Build Coastguard Worker         return;
8362*8975f5c5SAndroid Build Coastguard Worker 
8363*8975f5c5SAndroid Build Coastguard Worker     out << "digraph {\n" << "  node [shape=plaintext fontname=\"Consolas\"]\n";
8364*8975f5c5SAndroid Build Coastguard Worker 
8365*8975f5c5SAndroid Build Coastguard Worker     for (size_t index = 0; index < mCommandBufferDiagnostics.size(); ++index)
8366*8975f5c5SAndroid Build Coastguard Worker     {
8367*8975f5c5SAndroid Build Coastguard Worker         const std::string &payload = mCommandBufferDiagnostics[index];
8368*8975f5c5SAndroid Build Coastguard Worker         out << "  cb" << index << " [label =\"" << payload << "\"];\n";
8369*8975f5c5SAndroid Build Coastguard Worker     }
8370*8975f5c5SAndroid Build Coastguard Worker 
8371*8975f5c5SAndroid Build Coastguard Worker     for (size_t index = 0; index < mCommandBufferDiagnostics.size() - 1; ++index)
8372*8975f5c5SAndroid Build Coastguard Worker     {
8373*8975f5c5SAndroid Build Coastguard Worker         out << "  cb" << index << " -> cb" << index + 1 << "\n";
8374*8975f5c5SAndroid Build Coastguard Worker     }
8375*8975f5c5SAndroid Build Coastguard Worker 
8376*8975f5c5SAndroid Build Coastguard Worker     mCommandBufferDiagnostics.clear();
8377*8975f5c5SAndroid Build Coastguard Worker 
8378*8975f5c5SAndroid Build Coastguard Worker     out << "}\n";
8379*8975f5c5SAndroid Build Coastguard Worker }
8380*8975f5c5SAndroid Build Coastguard Worker 
initIndexTypeMap()8381*8975f5c5SAndroid Build Coastguard Worker void ContextVk::initIndexTypeMap()
8382*8975f5c5SAndroid Build Coastguard Worker {
8383*8975f5c5SAndroid Build Coastguard Worker     // Init gles-vulkan index type map
8384*8975f5c5SAndroid Build Coastguard Worker     mIndexTypeMap[gl::DrawElementsType::UnsignedByte] =
8385*8975f5c5SAndroid Build Coastguard Worker         mRenderer->getFeatures().supportsIndexTypeUint8.enabled ? VK_INDEX_TYPE_UINT8_EXT
8386*8975f5c5SAndroid Build Coastguard Worker                                                                 : VK_INDEX_TYPE_UINT16;
8387*8975f5c5SAndroid Build Coastguard Worker     mIndexTypeMap[gl::DrawElementsType::UnsignedShort] = VK_INDEX_TYPE_UINT16;
8388*8975f5c5SAndroid Build Coastguard Worker     mIndexTypeMap[gl::DrawElementsType::UnsignedInt]   = VK_INDEX_TYPE_UINT32;
8389*8975f5c5SAndroid Build Coastguard Worker }
8390*8975f5c5SAndroid Build Coastguard Worker 
getVkIndexType(gl::DrawElementsType glIndexType) const8391*8975f5c5SAndroid Build Coastguard Worker VkIndexType ContextVk::getVkIndexType(gl::DrawElementsType glIndexType) const
8392*8975f5c5SAndroid Build Coastguard Worker {
8393*8975f5c5SAndroid Build Coastguard Worker     return mIndexTypeMap[glIndexType];
8394*8975f5c5SAndroid Build Coastguard Worker }
8395*8975f5c5SAndroid Build Coastguard Worker 
getVkIndexTypeSize(gl::DrawElementsType glIndexType) const8396*8975f5c5SAndroid Build Coastguard Worker size_t ContextVk::getVkIndexTypeSize(gl::DrawElementsType glIndexType) const
8397*8975f5c5SAndroid Build Coastguard Worker {
8398*8975f5c5SAndroid Build Coastguard Worker     gl::DrawElementsType elementsType = shouldConvertUint8VkIndexType(glIndexType)
8399*8975f5c5SAndroid Build Coastguard Worker                                             ? gl::DrawElementsType::UnsignedShort
8400*8975f5c5SAndroid Build Coastguard Worker                                             : glIndexType;
8401*8975f5c5SAndroid Build Coastguard Worker     ASSERT(elementsType < gl::DrawElementsType::EnumCount);
8402*8975f5c5SAndroid Build Coastguard Worker 
8403*8975f5c5SAndroid Build Coastguard Worker     // Use GetDrawElementsTypeSize() to get the size
8404*8975f5c5SAndroid Build Coastguard Worker     return static_cast<size_t>(gl::GetDrawElementsTypeSize(elementsType));
8405*8975f5c5SAndroid Build Coastguard Worker }
8406*8975f5c5SAndroid Build Coastguard Worker 
shouldConvertUint8VkIndexType(gl::DrawElementsType glIndexType) const8407*8975f5c5SAndroid Build Coastguard Worker bool ContextVk::shouldConvertUint8VkIndexType(gl::DrawElementsType glIndexType) const
8408*8975f5c5SAndroid Build Coastguard Worker {
8409*8975f5c5SAndroid Build Coastguard Worker     return (glIndexType == gl::DrawElementsType::UnsignedByte &&
8410*8975f5c5SAndroid Build Coastguard Worker             !mRenderer->getFeatures().supportsIndexTypeUint8.enabled);
8411*8975f5c5SAndroid Build Coastguard Worker }
8412*8975f5c5SAndroid Build Coastguard Worker 
GetDriverUniformSize(vk::Context * context,PipelineType pipelineType)8413*8975f5c5SAndroid Build Coastguard Worker uint32_t GetDriverUniformSize(vk::Context *context, PipelineType pipelineType)
8414*8975f5c5SAndroid Build Coastguard Worker {
8415*8975f5c5SAndroid Build Coastguard Worker     if (pipelineType == PipelineType::Compute)
8416*8975f5c5SAndroid Build Coastguard Worker     {
8417*8975f5c5SAndroid Build Coastguard Worker         return sizeof(ComputeDriverUniforms);
8418*8975f5c5SAndroid Build Coastguard Worker     }
8419*8975f5c5SAndroid Build Coastguard Worker 
8420*8975f5c5SAndroid Build Coastguard Worker     ASSERT(pipelineType == PipelineType::Graphics);
8421*8975f5c5SAndroid Build Coastguard Worker     if (ShouldUseGraphicsDriverUniformsExtended(context))
8422*8975f5c5SAndroid Build Coastguard Worker     {
8423*8975f5c5SAndroid Build Coastguard Worker         return sizeof(GraphicsDriverUniformsExtended);
8424*8975f5c5SAndroid Build Coastguard Worker     }
8425*8975f5c5SAndroid Build Coastguard Worker     else
8426*8975f5c5SAndroid Build Coastguard Worker     {
8427*8975f5c5SAndroid Build Coastguard Worker         return sizeof(GraphicsDriverUniforms);
8428*8975f5c5SAndroid Build Coastguard Worker     }
8429*8975f5c5SAndroid Build Coastguard Worker }
8430*8975f5c5SAndroid Build Coastguard Worker 
flushAndSubmitOutsideRenderPassCommands()8431*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::flushAndSubmitOutsideRenderPassCommands()
8432*8975f5c5SAndroid Build Coastguard Worker {
8433*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::flushAndSubmitOutsideRenderPassCommands");
8434*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flushOutsideRenderPassCommands());
8435*8975f5c5SAndroid Build Coastguard Worker     return submitCommands(nullptr, nullptr, Submit::OutsideRenderPassCommandsOnly);
8436*8975f5c5SAndroid Build Coastguard Worker }
8437*8975f5c5SAndroid Build Coastguard Worker 
flushOutsideRenderPassCommands()8438*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::flushOutsideRenderPassCommands()
8439*8975f5c5SAndroid Build Coastguard Worker {
8440*8975f5c5SAndroid Build Coastguard Worker     if (!mWaitSemaphores.empty())
8441*8975f5c5SAndroid Build Coastguard Worker     {
8442*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mHasWaitSemaphoresPendingSubmission);
8443*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mRenderer->flushWaitSemaphores(getProtectionType(), mContextPriority,
8444*8975f5c5SAndroid Build Coastguard Worker                                                  std::move(mWaitSemaphores),
8445*8975f5c5SAndroid Build Coastguard Worker                                                  std::move(mWaitSemaphoreStageMasks)));
8446*8975f5c5SAndroid Build Coastguard Worker     }
8447*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mWaitSemaphores.empty());
8448*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mWaitSemaphoreStageMasks.empty());
8449*8975f5c5SAndroid Build Coastguard Worker 
8450*8975f5c5SAndroid Build Coastguard Worker     if (mOutsideRenderPassCommands->empty())
8451*8975f5c5SAndroid Build Coastguard Worker     {
8452*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
8453*8975f5c5SAndroid Build Coastguard Worker     }
8454*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mOutsideRenderPassCommands->getQueueSerial().valid());
8455*8975f5c5SAndroid Build Coastguard Worker 
8456*8975f5c5SAndroid Build Coastguard Worker     addOverlayUsedBuffersCount(mOutsideRenderPassCommands);
8457*8975f5c5SAndroid Build Coastguard Worker 
8458*8975f5c5SAndroid Build Coastguard Worker     if (kEnableCommandStreamDiagnostics)
8459*8975f5c5SAndroid Build Coastguard Worker     {
8460*8975f5c5SAndroid Build Coastguard Worker         addCommandBufferDiagnostics(mOutsideRenderPassCommands->getCommandDiagnostics());
8461*8975f5c5SAndroid Build Coastguard Worker     }
8462*8975f5c5SAndroid Build Coastguard Worker 
8463*8975f5c5SAndroid Build Coastguard Worker     flushDescriptorSetUpdates();
8464*8975f5c5SAndroid Build Coastguard Worker 
8465*8975f5c5SAndroid Build Coastguard Worker     // Track completion of this command buffer.
8466*8975f5c5SAndroid Build Coastguard Worker     mOutsideRenderPassCommands->flushSetEvents(this);
8467*8975f5c5SAndroid Build Coastguard Worker     mOutsideRenderPassCommands->collectRefCountedEventsGarbage(
8468*8975f5c5SAndroid Build Coastguard Worker         mShareGroupVk->getRefCountedEventsGarbageRecycler());
8469*8975f5c5SAndroid Build Coastguard Worker 
8470*8975f5c5SAndroid Build Coastguard Worker     // Save the queueSerial before calling flushOutsideRPCommands, which may return a new
8471*8975f5c5SAndroid Build Coastguard Worker     // mOutsideRenderPassCommands
8472*8975f5c5SAndroid Build Coastguard Worker     ASSERT(QueueSerialsHaveDifferentIndexOrSmaller(mLastFlushedQueueSerial,
8473*8975f5c5SAndroid Build Coastguard Worker                                                    mOutsideRenderPassCommands->getQueueSerial()));
8474*8975f5c5SAndroid Build Coastguard Worker     mLastFlushedQueueSerial = mOutsideRenderPassCommands->getQueueSerial();
8475*8975f5c5SAndroid Build Coastguard Worker 
8476*8975f5c5SAndroid Build Coastguard Worker     if (mOutsideRenderPassCommands->getAndResetHasHostVisibleBufferWrite())
8477*8975f5c5SAndroid Build Coastguard Worker     {
8478*8975f5c5SAndroid Build Coastguard Worker         mIsAnyHostVisibleBufferWritten = true;
8479*8975f5c5SAndroid Build Coastguard Worker     }
8480*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mRenderer->flushOutsideRPCommands(this, getProtectionType(), mContextPriority,
8481*8975f5c5SAndroid Build Coastguard Worker                                                 &mOutsideRenderPassCommands));
8482*8975f5c5SAndroid Build Coastguard Worker 
8483*8975f5c5SAndroid Build Coastguard Worker     // Make sure appropriate dirty bits are set, in case another thread makes a submission before
8484*8975f5c5SAndroid Build Coastguard Worker     // the next dispatch call.
8485*8975f5c5SAndroid Build Coastguard Worker     mComputeDirtyBits |= mNewComputeCommandBufferDirtyBits;
8486*8975f5c5SAndroid Build Coastguard Worker     mHasAnyCommandsPendingSubmission = true;
8487*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.flushedOutsideRenderPassCommandBuffers++;
8488*8975f5c5SAndroid Build Coastguard Worker 
8489*8975f5c5SAndroid Build Coastguard Worker     if (mRenderPassCommands->started() && mOutsideRenderPassSerialFactory.empty())
8490*8975f5c5SAndroid Build Coastguard Worker     {
8491*8975f5c5SAndroid Build Coastguard Worker         ANGLE_PERF_WARNING(
8492*8975f5c5SAndroid Build Coastguard Worker             getDebug(), GL_DEBUG_SEVERITY_HIGH,
8493*8975f5c5SAndroid Build Coastguard Worker             "Running out of reserved outsideRenderPass queueSerial. ending renderPass now.");
8494*8975f5c5SAndroid Build Coastguard Worker         // flushCommandsAndEndRenderPass will end up call back into this function again. We must
8495*8975f5c5SAndroid Build Coastguard Worker         // ensure mOutsideRenderPassCommands is empty so that it can early out.
8496*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mOutsideRenderPassCommands->empty());
8497*8975f5c5SAndroid Build Coastguard Worker         // We used up all reserved serials. In order to maintain serial order (outsideRenderPass
8498*8975f5c5SAndroid Build Coastguard Worker         // must be smaller than render pass), we also endRenderPass here as well. This is not
8499*8975f5c5SAndroid Build Coastguard Worker         // expected to happen often in real world usage.
8500*8975f5c5SAndroid Build Coastguard Worker         return flushCommandsAndEndRenderPass(
8501*8975f5c5SAndroid Build Coastguard Worker             RenderPassClosureReason::OutOfReservedQueueSerialForOutsideCommands);
8502*8975f5c5SAndroid Build Coastguard Worker     }
8503*8975f5c5SAndroid Build Coastguard Worker     else
8504*8975f5c5SAndroid Build Coastguard Worker     {
8505*8975f5c5SAndroid Build Coastguard Worker         // Since queueSerial is used to decide if a resource is being used or not, we have to
8506*8975f5c5SAndroid Build Coastguard Worker         // generate a new queueSerial for outsideCommandBuffer since we just flushed
8507*8975f5c5SAndroid Build Coastguard Worker         // outsideRenderPassCommands.
8508*8975f5c5SAndroid Build Coastguard Worker         generateOutsideRenderPassCommandsQueueSerial();
8509*8975f5c5SAndroid Build Coastguard Worker     }
8510*8975f5c5SAndroid Build Coastguard Worker 
8511*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8512*8975f5c5SAndroid Build Coastguard Worker }
8513*8975f5c5SAndroid Build Coastguard Worker 
beginRenderPassQuery(QueryVk * queryVk)8514*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::beginRenderPassQuery(QueryVk *queryVk)
8515*8975f5c5SAndroid Build Coastguard Worker {
8516*8975f5c5SAndroid Build Coastguard Worker     gl::QueryType type = queryVk->getType();
8517*8975f5c5SAndroid Build Coastguard Worker 
8518*8975f5c5SAndroid Build Coastguard Worker     // Emit debug-util markers before calling the query command.
8519*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd));
8520*8975f5c5SAndroid Build Coastguard Worker 
8521*8975f5c5SAndroid Build Coastguard Worker     // To avoid complexity, we always start and end these queries inside the render pass.  If the
8522*8975f5c5SAndroid Build Coastguard Worker     // render pass has not yet started, the query is deferred until it does.
8523*8975f5c5SAndroid Build Coastguard Worker     if (mRenderPassCommandBuffer)
8524*8975f5c5SAndroid Build Coastguard Worker     {
8525*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(queryVk->getQueryHelper()->beginRenderPassQuery(this));
8526*8975f5c5SAndroid Build Coastguard Worker         // Remove the dirty bit since next draw call will have active query enabled
8527*8975f5c5SAndroid Build Coastguard Worker         if (getFeatures().preferSubmitOnAnySamplesPassedQueryEnd.enabled && IsAnySamplesQuery(type))
8528*8975f5c5SAndroid Build Coastguard Worker         {
8529*8975f5c5SAndroid Build Coastguard Worker             mGraphicsDirtyBits.reset(DIRTY_BIT_ANY_SAMPLE_PASSED_QUERY_END);
8530*8975f5c5SAndroid Build Coastguard Worker         }
8531*8975f5c5SAndroid Build Coastguard Worker     }
8532*8975f5c5SAndroid Build Coastguard Worker 
8533*8975f5c5SAndroid Build Coastguard Worker     // Update rasterizer discard emulation with primitives generated query if necessary.
8534*8975f5c5SAndroid Build Coastguard Worker     if (type == gl::QueryType::PrimitivesGenerated)
8535*8975f5c5SAndroid Build Coastguard Worker     {
8536*8975f5c5SAndroid Build Coastguard Worker         updateRasterizerDiscardEnabled(true);
8537*8975f5c5SAndroid Build Coastguard Worker     }
8538*8975f5c5SAndroid Build Coastguard Worker 
8539*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mActiveRenderPassQueries[type] == nullptr);
8540*8975f5c5SAndroid Build Coastguard Worker     mActiveRenderPassQueries[type] = queryVk;
8541*8975f5c5SAndroid Build Coastguard Worker 
8542*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8543*8975f5c5SAndroid Build Coastguard Worker }
8544*8975f5c5SAndroid Build Coastguard Worker 
endRenderPassQuery(QueryVk * queryVk)8545*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::endRenderPassQuery(QueryVk *queryVk)
8546*8975f5c5SAndroid Build Coastguard Worker {
8547*8975f5c5SAndroid Build Coastguard Worker     gl::QueryType type = queryVk->getType();
8548*8975f5c5SAndroid Build Coastguard Worker 
8549*8975f5c5SAndroid Build Coastguard Worker     // Emit debug-util markers before calling the query command.
8550*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(handleGraphicsEventLog(rx::GraphicsEventCmdBuf::InRenderPassCmdBufQueryCmd));
8551*8975f5c5SAndroid Build Coastguard Worker 
8552*8975f5c5SAndroid Build Coastguard Worker     // End the query inside the render pass.  In some situations, the query may not have actually
8553*8975f5c5SAndroid Build Coastguard Worker     // been issued, so there is nothing to do there.  That is the case for transform feedback
8554*8975f5c5SAndroid Build Coastguard Worker     // queries which are deferred until a draw call with transform feedback active is issued, which
8555*8975f5c5SAndroid Build Coastguard Worker     // may have never happened.
8556*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mRenderPassCommandBuffer == nullptr ||
8557*8975f5c5SAndroid Build Coastguard Worker            type == gl::QueryType::TransformFeedbackPrimitivesWritten || queryVk->hasQueryBegun());
8558*8975f5c5SAndroid Build Coastguard Worker     if (mRenderPassCommandBuffer && queryVk->hasQueryBegun())
8559*8975f5c5SAndroid Build Coastguard Worker     {
8560*8975f5c5SAndroid Build Coastguard Worker         queryVk->getQueryHelper()->endRenderPassQuery(this);
8561*8975f5c5SAndroid Build Coastguard Worker         // Set dirty bit so that we can detect and do something when a draw without active query is
8562*8975f5c5SAndroid Build Coastguard Worker         // issued.
8563*8975f5c5SAndroid Build Coastguard Worker         if (getFeatures().preferSubmitOnAnySamplesPassedQueryEnd.enabled && IsAnySamplesQuery(type))
8564*8975f5c5SAndroid Build Coastguard Worker         {
8565*8975f5c5SAndroid Build Coastguard Worker             mGraphicsDirtyBits.set(DIRTY_BIT_ANY_SAMPLE_PASSED_QUERY_END);
8566*8975f5c5SAndroid Build Coastguard Worker         }
8567*8975f5c5SAndroid Build Coastguard Worker     }
8568*8975f5c5SAndroid Build Coastguard Worker 
8569*8975f5c5SAndroid Build Coastguard Worker     // Update rasterizer discard emulation with primitives generated query if necessary.
8570*8975f5c5SAndroid Build Coastguard Worker     if (type == gl::QueryType::PrimitivesGenerated)
8571*8975f5c5SAndroid Build Coastguard Worker     {
8572*8975f5c5SAndroid Build Coastguard Worker         updateRasterizerDiscardEnabled(false);
8573*8975f5c5SAndroid Build Coastguard Worker     }
8574*8975f5c5SAndroid Build Coastguard Worker 
8575*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mActiveRenderPassQueries[type] == queryVk);
8576*8975f5c5SAndroid Build Coastguard Worker     mActiveRenderPassQueries[type] = nullptr;
8577*8975f5c5SAndroid Build Coastguard Worker 
8578*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8579*8975f5c5SAndroid Build Coastguard Worker }
8580*8975f5c5SAndroid Build Coastguard Worker 
pauseRenderPassQueriesIfActive()8581*8975f5c5SAndroid Build Coastguard Worker void ContextVk::pauseRenderPassQueriesIfActive()
8582*8975f5c5SAndroid Build Coastguard Worker {
8583*8975f5c5SAndroid Build Coastguard Worker     for (QueryVk *activeQuery : mActiveRenderPassQueries)
8584*8975f5c5SAndroid Build Coastguard Worker     {
8585*8975f5c5SAndroid Build Coastguard Worker         if (activeQuery)
8586*8975f5c5SAndroid Build Coastguard Worker         {
8587*8975f5c5SAndroid Build Coastguard Worker             activeQuery->onRenderPassEnd(this);
8588*8975f5c5SAndroid Build Coastguard Worker             // No need to update rasterizer discard emulation with primitives generated query.  The
8589*8975f5c5SAndroid Build Coastguard Worker             // state will be updated when the next render pass starts.
8590*8975f5c5SAndroid Build Coastguard Worker         }
8591*8975f5c5SAndroid Build Coastguard Worker     }
8592*8975f5c5SAndroid Build Coastguard Worker }
8593*8975f5c5SAndroid Build Coastguard Worker 
resumeRenderPassQueriesIfActive()8594*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::resumeRenderPassQueriesIfActive()
8595*8975f5c5SAndroid Build Coastguard Worker {
8596*8975f5c5SAndroid Build Coastguard Worker     // Note: these queries should be processed in order.  See comment in QueryVk::onRenderPassStart.
8597*8975f5c5SAndroid Build Coastguard Worker     for (QueryVk *activeQuery : mActiveRenderPassQueries)
8598*8975f5c5SAndroid Build Coastguard Worker     {
8599*8975f5c5SAndroid Build Coastguard Worker         if (activeQuery)
8600*8975f5c5SAndroid Build Coastguard Worker         {
8601*8975f5c5SAndroid Build Coastguard Worker             // Transform feedback queries are handled separately.
8602*8975f5c5SAndroid Build Coastguard Worker             if (activeQuery->getType() == gl::QueryType::TransformFeedbackPrimitivesWritten)
8603*8975f5c5SAndroid Build Coastguard Worker             {
8604*8975f5c5SAndroid Build Coastguard Worker                 continue;
8605*8975f5c5SAndroid Build Coastguard Worker             }
8606*8975f5c5SAndroid Build Coastguard Worker 
8607*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(activeQuery->onRenderPassStart(this));
8608*8975f5c5SAndroid Build Coastguard Worker 
8609*8975f5c5SAndroid Build Coastguard Worker             // Update rasterizer discard emulation with primitives generated query if necessary.
8610*8975f5c5SAndroid Build Coastguard Worker             if (activeQuery->getType() == gl::QueryType::PrimitivesGenerated)
8611*8975f5c5SAndroid Build Coastguard Worker             {
8612*8975f5c5SAndroid Build Coastguard Worker                 updateRasterizerDiscardEnabled(true);
8613*8975f5c5SAndroid Build Coastguard Worker             }
8614*8975f5c5SAndroid Build Coastguard Worker         }
8615*8975f5c5SAndroid Build Coastguard Worker     }
8616*8975f5c5SAndroid Build Coastguard Worker 
8617*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8618*8975f5c5SAndroid Build Coastguard Worker }
8619*8975f5c5SAndroid Build Coastguard Worker 
resumeXfbRenderPassQueriesIfActive()8620*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::resumeXfbRenderPassQueriesIfActive()
8621*8975f5c5SAndroid Build Coastguard Worker {
8622*8975f5c5SAndroid Build Coastguard Worker     // All other queries are handled separately.
8623*8975f5c5SAndroid Build Coastguard Worker     QueryVk *xfbQuery = mActiveRenderPassQueries[gl::QueryType::TransformFeedbackPrimitivesWritten];
8624*8975f5c5SAndroid Build Coastguard Worker     if (xfbQuery && mState.isTransformFeedbackActiveUnpaused())
8625*8975f5c5SAndroid Build Coastguard Worker     {
8626*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(xfbQuery->onRenderPassStart(this));
8627*8975f5c5SAndroid Build Coastguard Worker     }
8628*8975f5c5SAndroid Build Coastguard Worker 
8629*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8630*8975f5c5SAndroid Build Coastguard Worker }
8631*8975f5c5SAndroid Build Coastguard Worker 
doesPrimitivesGeneratedQuerySupportRasterizerDiscard() const8632*8975f5c5SAndroid Build Coastguard Worker bool ContextVk::doesPrimitivesGeneratedQuerySupportRasterizerDiscard() const
8633*8975f5c5SAndroid Build Coastguard Worker {
8634*8975f5c5SAndroid Build Coastguard Worker     // If primitives generated is implemented with VK_EXT_primitives_generated_query, check the
8635*8975f5c5SAndroid Build Coastguard Worker     // corresponding feature bit.
8636*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().supportsPrimitivesGeneratedQuery.enabled)
8637*8975f5c5SAndroid Build Coastguard Worker     {
8638*8975f5c5SAndroid Build Coastguard Worker         return mRenderer->getPhysicalDevicePrimitivesGeneratedQueryFeatures()
8639*8975f5c5SAndroid Build Coastguard Worker                    .primitivesGeneratedQueryWithRasterizerDiscard == VK_TRUE;
8640*8975f5c5SAndroid Build Coastguard Worker     }
8641*8975f5c5SAndroid Build Coastguard Worker 
8642*8975f5c5SAndroid Build Coastguard Worker     // If primitives generated is emulated with pipeline statistics query, it's unknown on which
8643*8975f5c5SAndroid Build Coastguard Worker     // hardware rasterizer discard is supported.  Assume it's supported on none.
8644*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().supportsPipelineStatisticsQuery.enabled)
8645*8975f5c5SAndroid Build Coastguard Worker     {
8646*8975f5c5SAndroid Build Coastguard Worker         return false;
8647*8975f5c5SAndroid Build Coastguard Worker     }
8648*8975f5c5SAndroid Build Coastguard Worker 
8649*8975f5c5SAndroid Build Coastguard Worker     return true;
8650*8975f5c5SAndroid Build Coastguard Worker }
8651*8975f5c5SAndroid Build Coastguard Worker 
isEmulatingRasterizerDiscardDuringPrimitivesGeneratedQuery(bool isPrimitivesGeneratedQueryActive) const8652*8975f5c5SAndroid Build Coastguard Worker bool ContextVk::isEmulatingRasterizerDiscardDuringPrimitivesGeneratedQuery(
8653*8975f5c5SAndroid Build Coastguard Worker     bool isPrimitivesGeneratedQueryActive) const
8654*8975f5c5SAndroid Build Coastguard Worker {
8655*8975f5c5SAndroid Build Coastguard Worker     return isPrimitivesGeneratedQueryActive && mState.isRasterizerDiscardEnabled() &&
8656*8975f5c5SAndroid Build Coastguard Worker            !doesPrimitivesGeneratedQuerySupportRasterizerDiscard();
8657*8975f5c5SAndroid Build Coastguard Worker }
8658*8975f5c5SAndroid Build Coastguard Worker 
getActiveRenderPassQuery(gl::QueryType queryType) const8659*8975f5c5SAndroid Build Coastguard Worker QueryVk *ContextVk::getActiveRenderPassQuery(gl::QueryType queryType) const
8660*8975f5c5SAndroid Build Coastguard Worker {
8661*8975f5c5SAndroid Build Coastguard Worker     return mActiveRenderPassQueries[queryType];
8662*8975f5c5SAndroid Build Coastguard Worker }
8663*8975f5c5SAndroid Build Coastguard Worker 
isRobustResourceInitEnabled() const8664*8975f5c5SAndroid Build Coastguard Worker bool ContextVk::isRobustResourceInitEnabled() const
8665*8975f5c5SAndroid Build Coastguard Worker {
8666*8975f5c5SAndroid Build Coastguard Worker     return mState.isRobustResourceInitEnabled();
8667*8975f5c5SAndroid Build Coastguard Worker }
8668*8975f5c5SAndroid Build Coastguard Worker 
setDefaultUniformBlocksMinSizeForTesting(size_t minSize)8669*8975f5c5SAndroid Build Coastguard Worker void ContextVk::setDefaultUniformBlocksMinSizeForTesting(size_t minSize)
8670*8975f5c5SAndroid Build Coastguard Worker {
8671*8975f5c5SAndroid Build Coastguard Worker     mDefaultUniformStorage.setMinimumSizeForTesting(minSize);
8672*8975f5c5SAndroid Build Coastguard Worker }
8673*8975f5c5SAndroid Build Coastguard Worker 
initializeMultisampleTextureToBlack(const gl::Context * context,gl::Texture * glTexture)8674*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::initializeMultisampleTextureToBlack(const gl::Context *context,
8675*8975f5c5SAndroid Build Coastguard Worker                                                              gl::Texture *glTexture)
8676*8975f5c5SAndroid Build Coastguard Worker {
8677*8975f5c5SAndroid Build Coastguard Worker     ASSERT(glTexture->getType() == gl::TextureType::_2DMultisample);
8678*8975f5c5SAndroid Build Coastguard Worker     TextureVk *textureVk = vk::GetImpl(glTexture);
8679*8975f5c5SAndroid Build Coastguard Worker 
8680*8975f5c5SAndroid Build Coastguard Worker     return textureVk->initializeContentsWithBlack(context, GL_NONE,
8681*8975f5c5SAndroid Build Coastguard Worker                                                   gl::ImageIndex::Make2DMultisample());
8682*8975f5c5SAndroid Build Coastguard Worker }
8683*8975f5c5SAndroid Build Coastguard Worker 
onProgramExecutableReset(ProgramExecutableVk * executableVk)8684*8975f5c5SAndroid Build Coastguard Worker void ContextVk::onProgramExecutableReset(ProgramExecutableVk *executableVk)
8685*8975f5c5SAndroid Build Coastguard Worker {
8686*8975f5c5SAndroid Build Coastguard Worker     // We can not check if executableVk deleted is what we was bound to, since by the time we get
8687*8975f5c5SAndroid Build Coastguard Worker     // here, the program executable in the context's state has already been updated.
8688*8975f5c5SAndroid Build Coastguard Worker     // Reset ContextVk::mCurrentGraphicsPipeline, since programInfo.release() freed the
8689*8975f5c5SAndroid Build Coastguard Worker     // PipelineHelper that it's currently pointing to.
8690*8975f5c5SAndroid Build Coastguard Worker     // TODO(http://anglebug.com/42264159): rework updateActiveTextures(), createPipelineLayout(),
8691*8975f5c5SAndroid Build Coastguard Worker     // handleDirtyGraphicsPipeline(), and ProgramPipelineVk::link().
8692*8975f5c5SAndroid Build Coastguard Worker     resetCurrentGraphicsPipeline();
8693*8975f5c5SAndroid Build Coastguard Worker     invalidateCurrentComputePipeline();
8694*8975f5c5SAndroid Build Coastguard Worker     invalidateCurrentGraphicsPipeline();
8695*8975f5c5SAndroid Build Coastguard Worker }
8696*8975f5c5SAndroid Build Coastguard Worker 
switchToReadOnlyDepthStencilMode(gl::Texture * texture,gl::Command command,FramebufferVk * drawFramebuffer,bool isStencilTexture)8697*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::switchToReadOnlyDepthStencilMode(gl::Texture *texture,
8698*8975f5c5SAndroid Build Coastguard Worker                                                           gl::Command command,
8699*8975f5c5SAndroid Build Coastguard Worker                                                           FramebufferVk *drawFramebuffer,
8700*8975f5c5SAndroid Build Coastguard Worker                                                           bool isStencilTexture)
8701*8975f5c5SAndroid Build Coastguard Worker {
8702*8975f5c5SAndroid Build Coastguard Worker     ASSERT(texture->isDepthOrStencil());
8703*8975f5c5SAndroid Build Coastguard Worker 
8704*8975f5c5SAndroid Build Coastguard Worker     // When running compute we don't have a draw FBO.
8705*8975f5c5SAndroid Build Coastguard Worker     if (command == gl::Command::Dispatch)
8706*8975f5c5SAndroid Build Coastguard Worker     {
8707*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
8708*8975f5c5SAndroid Build Coastguard Worker     }
8709*8975f5c5SAndroid Build Coastguard Worker 
8710*8975f5c5SAndroid Build Coastguard Worker     // The readOnlyDepth/StencilMode flag enables read-only depth-stencil feedback loops.  We only
8711*8975f5c5SAndroid Build Coastguard Worker     // switch to read-only mode when there's a loop.  The render pass tracks the depth and stencil
8712*8975f5c5SAndroid Build Coastguard Worker     // access modes, which indicates whether it's possible to retroactively go back and change the
8713*8975f5c5SAndroid Build Coastguard Worker     // attachment layouts to read-only.
8714*8975f5c5SAndroid Build Coastguard Worker     //
8715*8975f5c5SAndroid Build Coastguard Worker     // If there are any writes, the render pass needs to break, so that one using the read-only
8716*8975f5c5SAndroid Build Coastguard Worker     // layouts can start.
8717*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *drawFramebufferVk = getDrawFramebuffer();
8718*8975f5c5SAndroid Build Coastguard Worker     if (!texture->isBoundToFramebuffer(drawFramebufferVk->getState().getFramebufferSerial()))
8719*8975f5c5SAndroid Build Coastguard Worker     {
8720*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
8721*8975f5c5SAndroid Build Coastguard Worker     }
8722*8975f5c5SAndroid Build Coastguard Worker 
8723*8975f5c5SAndroid Build Coastguard Worker     if (isStencilTexture)
8724*8975f5c5SAndroid Build Coastguard Worker     {
8725*8975f5c5SAndroid Build Coastguard Worker         if (mState.isStencilWriteEnabled(mState.getDrawFramebuffer()->getStencilBitCount()))
8726*8975f5c5SAndroid Build Coastguard Worker         {
8727*8975f5c5SAndroid Build Coastguard Worker             // This looks like a feedback loop, but we don't issue a warning because the application
8728*8975f5c5SAndroid Build Coastguard Worker             // may have correctly used BASE and MAX levels to avoid it.  ANGLE doesn't track that.
8729*8975f5c5SAndroid Build Coastguard Worker             mDepthStencilAttachmentFlags.set(vk::RenderPassUsage::StencilFeedbackLoop);
8730*8975f5c5SAndroid Build Coastguard Worker         }
8731*8975f5c5SAndroid Build Coastguard Worker         else if (!mDepthStencilAttachmentFlags[vk::RenderPassUsage::StencilFeedbackLoop])
8732*8975f5c5SAndroid Build Coastguard Worker         {
8733*8975f5c5SAndroid Build Coastguard Worker             // If we are not in the actual feedback loop mode, switch to read-only stencil mode
8734*8975f5c5SAndroid Build Coastguard Worker             mDepthStencilAttachmentFlags.set(vk::RenderPassUsage::StencilReadOnlyAttachment);
8735*8975f5c5SAndroid Build Coastguard Worker         }
8736*8975f5c5SAndroid Build Coastguard Worker     }
8737*8975f5c5SAndroid Build Coastguard Worker 
8738*8975f5c5SAndroid Build Coastguard Worker     // Switch to read-only depth feedback loop if not already
8739*8975f5c5SAndroid Build Coastguard Worker     if (mState.isDepthWriteEnabled())
8740*8975f5c5SAndroid Build Coastguard Worker     {
8741*8975f5c5SAndroid Build Coastguard Worker         // This looks like a feedback loop, but we don't issue a warning because the application
8742*8975f5c5SAndroid Build Coastguard Worker         // may have correctly used BASE and MAX levels to avoid it.  ANGLE doesn't track that.
8743*8975f5c5SAndroid Build Coastguard Worker         mDepthStencilAttachmentFlags.set(vk::RenderPassUsage::DepthFeedbackLoop);
8744*8975f5c5SAndroid Build Coastguard Worker     }
8745*8975f5c5SAndroid Build Coastguard Worker     else if (!mDepthStencilAttachmentFlags[vk::RenderPassUsage::DepthFeedbackLoop])
8746*8975f5c5SAndroid Build Coastguard Worker     {
8747*8975f5c5SAndroid Build Coastguard Worker         // If we are not in the actual feedback loop mode, switch to read-only depth mode
8748*8975f5c5SAndroid Build Coastguard Worker         mDepthStencilAttachmentFlags.set(vk::RenderPassUsage::DepthReadOnlyAttachment);
8749*8975f5c5SAndroid Build Coastguard Worker     }
8750*8975f5c5SAndroid Build Coastguard Worker 
8751*8975f5c5SAndroid Build Coastguard Worker     if ((mDepthStencilAttachmentFlags & vk::kDepthStencilReadOnlyBits).none())
8752*8975f5c5SAndroid Build Coastguard Worker     {
8753*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
8754*8975f5c5SAndroid Build Coastguard Worker     }
8755*8975f5c5SAndroid Build Coastguard Worker 
8756*8975f5c5SAndroid Build Coastguard Worker     // If the aspect that's switching to read-only has a pending clear, it can't be done in the same
8757*8975f5c5SAndroid Build Coastguard Worker     // render pass (as the clear is a write operation).  In that case, flush the deferred clears for
8758*8975f5c5SAndroid Build Coastguard Worker     // the aspect that is turning read-only first.  The other deferred clears (such as color) can
8759*8975f5c5SAndroid Build Coastguard Worker     // stay deferred.
8760*8975f5c5SAndroid Build Coastguard Worker     if ((!isStencilTexture && drawFramebuffer->hasDeferredDepthClear()) ||
8761*8975f5c5SAndroid Build Coastguard Worker         (isStencilTexture && drawFramebuffer->hasDeferredStencilClear()))
8762*8975f5c5SAndroid Build Coastguard Worker     {
8763*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(drawFramebuffer->flushDepthStencilDeferredClear(
8764*8975f5c5SAndroid Build Coastguard Worker             this, isStencilTexture ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT));
8765*8975f5c5SAndroid Build Coastguard Worker     }
8766*8975f5c5SAndroid Build Coastguard Worker 
8767*8975f5c5SAndroid Build Coastguard Worker     // If the render pass needs closing, mark it as such.  Note that a write to depth/stencil may be
8768*8975f5c5SAndroid Build Coastguard Worker     // pending through a deferred clear.
8769*8975f5c5SAndroid Build Coastguard Worker     if (hasActiveRenderPass())
8770*8975f5c5SAndroid Build Coastguard Worker     {
8771*8975f5c5SAndroid Build Coastguard Worker         const vk::RenderPassUsage readOnlyAttachmentUsage =
8772*8975f5c5SAndroid Build Coastguard Worker             isStencilTexture ? vk::RenderPassUsage::StencilReadOnlyAttachment
8773*8975f5c5SAndroid Build Coastguard Worker                              : vk::RenderPassUsage::DepthReadOnlyAttachment;
8774*8975f5c5SAndroid Build Coastguard Worker         TextureVk *textureVk = vk::GetImpl(texture);
8775*8975f5c5SAndroid Build Coastguard Worker 
8776*8975f5c5SAndroid Build Coastguard Worker         if (!textureVk->getImage().hasRenderPassUsageFlag(readOnlyAttachmentUsage))
8777*8975f5c5SAndroid Build Coastguard Worker         {
8778*8975f5c5SAndroid Build Coastguard Worker             // If the render pass has written to this aspect, it needs to be closed.
8779*8975f5c5SAndroid Build Coastguard Worker             if ((!isStencilTexture && getStartedRenderPassCommands().hasDepthWriteOrClear()) ||
8780*8975f5c5SAndroid Build Coastguard Worker                 (isStencilTexture && getStartedRenderPassCommands().hasStencilWriteOrClear()))
8781*8975f5c5SAndroid Build Coastguard Worker             {
8782*8975f5c5SAndroid Build Coastguard Worker                 onRenderPassFinished(RenderPassClosureReason::DepthStencilUseInFeedbackLoop);
8783*8975f5c5SAndroid Build Coastguard Worker 
8784*8975f5c5SAndroid Build Coastguard Worker                 // Don't let the render pass reactivate.
8785*8975f5c5SAndroid Build Coastguard Worker                 mAllowRenderPassToReactivate = false;
8786*8975f5c5SAndroid Build Coastguard Worker             }
8787*8975f5c5SAndroid Build Coastguard Worker         }
8788*8975f5c5SAndroid Build Coastguard Worker 
8789*8975f5c5SAndroid Build Coastguard Worker         // Make sure to update the current render pass's tracking of read-only depth/stencil mode.
8790*8975f5c5SAndroid Build Coastguard Worker         mGraphicsDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_ACCESS);
8791*8975f5c5SAndroid Build Coastguard Worker     }
8792*8975f5c5SAndroid Build Coastguard Worker 
8793*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8794*8975f5c5SAndroid Build Coastguard Worker }
8795*8975f5c5SAndroid Build Coastguard Worker 
onResourceAccess(const vk::CommandBufferAccess & access)8796*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::onResourceAccess(const vk::CommandBufferAccess &access)
8797*8975f5c5SAndroid Build Coastguard Worker {
8798*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flushCommandBuffersIfNecessary(access));
8799*8975f5c5SAndroid Build Coastguard Worker 
8800*8975f5c5SAndroid Build Coastguard Worker     for (const vk::CommandBufferImageAccess &imageAccess : access.getReadImages())
8801*8975f5c5SAndroid Build Coastguard Worker     {
8802*8975f5c5SAndroid Build Coastguard Worker         vk::ImageHelper *image = imageAccess.image;
8803*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!isRenderPassStartedAndUsesImage(*image));
8804*8975f5c5SAndroid Build Coastguard Worker 
8805*8975f5c5SAndroid Build Coastguard Worker         imageAccess.image->recordReadBarrier(this, imageAccess.aspectFlags, imageAccess.imageLayout,
8806*8975f5c5SAndroid Build Coastguard Worker                                              mOutsideRenderPassCommands);
8807*8975f5c5SAndroid Build Coastguard Worker         mOutsideRenderPassCommands->retainImage(image);
8808*8975f5c5SAndroid Build Coastguard Worker     }
8809*8975f5c5SAndroid Build Coastguard Worker 
8810*8975f5c5SAndroid Build Coastguard Worker     for (const vk::CommandBufferImageSubresourceAccess &imageReadAccess :
8811*8975f5c5SAndroid Build Coastguard Worker          access.getReadImageSubresources())
8812*8975f5c5SAndroid Build Coastguard Worker     {
8813*8975f5c5SAndroid Build Coastguard Worker         vk::ImageHelper *image = imageReadAccess.access.image;
8814*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!isRenderPassStartedAndUsesImage(*image));
8815*8975f5c5SAndroid Build Coastguard Worker 
8816*8975f5c5SAndroid Build Coastguard Worker         image->recordReadSubresourceBarrier(
8817*8975f5c5SAndroid Build Coastguard Worker             this, imageReadAccess.access.aspectFlags, imageReadAccess.access.imageLayout,
8818*8975f5c5SAndroid Build Coastguard Worker             imageReadAccess.levelStart, imageReadAccess.levelCount, imageReadAccess.layerStart,
8819*8975f5c5SAndroid Build Coastguard Worker             imageReadAccess.layerCount, mOutsideRenderPassCommands);
8820*8975f5c5SAndroid Build Coastguard Worker         mOutsideRenderPassCommands->retainImage(image);
8821*8975f5c5SAndroid Build Coastguard Worker     }
8822*8975f5c5SAndroid Build Coastguard Worker 
8823*8975f5c5SAndroid Build Coastguard Worker     for (const vk::CommandBufferImageSubresourceAccess &imageWrite : access.getWriteImages())
8824*8975f5c5SAndroid Build Coastguard Worker     {
8825*8975f5c5SAndroid Build Coastguard Worker         vk::ImageHelper *image = imageWrite.access.image;
8826*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!isRenderPassStartedAndUsesImage(*image));
8827*8975f5c5SAndroid Build Coastguard Worker 
8828*8975f5c5SAndroid Build Coastguard Worker         image->recordWriteBarrier(this, imageWrite.access.aspectFlags,
8829*8975f5c5SAndroid Build Coastguard Worker                                   imageWrite.access.imageLayout, imageWrite.levelStart,
8830*8975f5c5SAndroid Build Coastguard Worker                                   imageWrite.levelCount, imageWrite.layerStart,
8831*8975f5c5SAndroid Build Coastguard Worker                                   imageWrite.layerCount, mOutsideRenderPassCommands);
8832*8975f5c5SAndroid Build Coastguard Worker         mOutsideRenderPassCommands->retainImage(image);
8833*8975f5c5SAndroid Build Coastguard Worker         image->onWrite(imageWrite.levelStart, imageWrite.levelCount, imageWrite.layerStart,
8834*8975f5c5SAndroid Build Coastguard Worker                        imageWrite.layerCount, imageWrite.access.aspectFlags);
8835*8975f5c5SAndroid Build Coastguard Worker     }
8836*8975f5c5SAndroid Build Coastguard Worker 
8837*8975f5c5SAndroid Build Coastguard Worker     for (const vk::CommandBufferBufferAccess &bufferAccess : access.getReadBuffers())
8838*8975f5c5SAndroid Build Coastguard Worker     {
8839*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!isRenderPassStartedAndUsesBufferForWrite(*bufferAccess.buffer));
8840*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!mOutsideRenderPassCommands->usesBufferForWrite(*bufferAccess.buffer));
8841*8975f5c5SAndroid Build Coastguard Worker 
8842*8975f5c5SAndroid Build Coastguard Worker         mOutsideRenderPassCommands->bufferRead(bufferAccess.accessType, bufferAccess.stage,
8843*8975f5c5SAndroid Build Coastguard Worker                                                bufferAccess.buffer);
8844*8975f5c5SAndroid Build Coastguard Worker     }
8845*8975f5c5SAndroid Build Coastguard Worker 
8846*8975f5c5SAndroid Build Coastguard Worker     for (const vk::CommandBufferBufferAccess &bufferAccess : access.getWriteBuffers())
8847*8975f5c5SAndroid Build Coastguard Worker     {
8848*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!isRenderPassStartedAndUsesBuffer(*bufferAccess.buffer));
8849*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!mOutsideRenderPassCommands->usesBuffer(*bufferAccess.buffer));
8850*8975f5c5SAndroid Build Coastguard Worker 
8851*8975f5c5SAndroid Build Coastguard Worker         mOutsideRenderPassCommands->bufferWrite(bufferAccess.accessType, bufferAccess.stage,
8852*8975f5c5SAndroid Build Coastguard Worker                                                 bufferAccess.buffer);
8853*8975f5c5SAndroid Build Coastguard Worker     }
8854*8975f5c5SAndroid Build Coastguard Worker 
8855*8975f5c5SAndroid Build Coastguard Worker     for (const vk::CommandBufferBufferExternalAcquireRelease &bufferAcquireRelease :
8856*8975f5c5SAndroid Build Coastguard Worker          access.getExternalAcquireReleaseBuffers())
8857*8975f5c5SAndroid Build Coastguard Worker     {
8858*8975f5c5SAndroid Build Coastguard Worker         mOutsideRenderPassCommands->retainResourceForWrite(bufferAcquireRelease.buffer);
8859*8975f5c5SAndroid Build Coastguard Worker     }
8860*8975f5c5SAndroid Build Coastguard Worker 
8861*8975f5c5SAndroid Build Coastguard Worker     for (const vk::CommandBufferResourceAccess &resourceAccess : access.getAccessResources())
8862*8975f5c5SAndroid Build Coastguard Worker     {
8863*8975f5c5SAndroid Build Coastguard Worker         mOutsideRenderPassCommands->retainResource(resourceAccess.resource);
8864*8975f5c5SAndroid Build Coastguard Worker     }
8865*8975f5c5SAndroid Build Coastguard Worker 
8866*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8867*8975f5c5SAndroid Build Coastguard Worker }
8868*8975f5c5SAndroid Build Coastguard Worker 
flushCommandBuffersIfNecessary(const vk::CommandBufferAccess & access)8869*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::flushCommandBuffersIfNecessary(const vk::CommandBufferAccess &access)
8870*8975f5c5SAndroid Build Coastguard Worker {
8871*8975f5c5SAndroid Build Coastguard Worker     // Go over resources and decide whether the render pass needs to close, whether the outside
8872*8975f5c5SAndroid Build Coastguard Worker     // render pass commands need to be flushed, or neither.  Note that closing the render pass
8873*8975f5c5SAndroid Build Coastguard Worker     // implies flushing the outside render pass as well, so if that needs to be done, we can close
8874*8975f5c5SAndroid Build Coastguard Worker     // the render pass and immediately return from this function.  Otherwise, this function keeps
8875*8975f5c5SAndroid Build Coastguard Worker     // track of whether the outside render pass commands need to be closed, and if so, it will do
8876*8975f5c5SAndroid Build Coastguard Worker     // that once at the end.
8877*8975f5c5SAndroid Build Coastguard Worker 
8878*8975f5c5SAndroid Build Coastguard Worker     // Read images only need to close the render pass if they need a layout transition.
8879*8975f5c5SAndroid Build Coastguard Worker     for (const vk::CommandBufferImageAccess &imageAccess : access.getReadImages())
8880*8975f5c5SAndroid Build Coastguard Worker     {
8881*8975f5c5SAndroid Build Coastguard Worker         // Note that different read methods are not compatible. A shader read uses a different
8882*8975f5c5SAndroid Build Coastguard Worker         // layout than a transfer read. So we cannot support simultaneous read usage as easily as
8883*8975f5c5SAndroid Build Coastguard Worker         // for Buffers.  TODO: Don't close the render pass if the image was only used read-only in
8884*8975f5c5SAndroid Build Coastguard Worker         // the render pass.  http://anglebug.com/42263557
8885*8975f5c5SAndroid Build Coastguard Worker         if (isRenderPassStartedAndUsesImage(*imageAccess.image))
8886*8975f5c5SAndroid Build Coastguard Worker         {
8887*8975f5c5SAndroid Build Coastguard Worker             return flushCommandsAndEndRenderPass(RenderPassClosureReason::ImageUseThenOutOfRPRead);
8888*8975f5c5SAndroid Build Coastguard Worker         }
8889*8975f5c5SAndroid Build Coastguard Worker     }
8890*8975f5c5SAndroid Build Coastguard Worker 
8891*8975f5c5SAndroid Build Coastguard Worker     // In cases where the image has both read and write permissions, the render pass should be
8892*8975f5c5SAndroid Build Coastguard Worker     // closed if there is a read from a previously written subresource (in a specific level/layer),
8893*8975f5c5SAndroid Build Coastguard Worker     // or a write to a previously read one.
8894*8975f5c5SAndroid Build Coastguard Worker     for (const vk::CommandBufferImageSubresourceAccess &imageSubresourceAccess :
8895*8975f5c5SAndroid Build Coastguard Worker          access.getReadImageSubresources())
8896*8975f5c5SAndroid Build Coastguard Worker     {
8897*8975f5c5SAndroid Build Coastguard Worker         if (isRenderPassStartedAndUsesImage(*imageSubresourceAccess.access.image))
8898*8975f5c5SAndroid Build Coastguard Worker         {
8899*8975f5c5SAndroid Build Coastguard Worker             return flushCommandsAndEndRenderPass(RenderPassClosureReason::ImageUseThenOutOfRPRead);
8900*8975f5c5SAndroid Build Coastguard Worker         }
8901*8975f5c5SAndroid Build Coastguard Worker     }
8902*8975f5c5SAndroid Build Coastguard Worker 
8903*8975f5c5SAndroid Build Coastguard Worker     // Write images only need to close the render pass if they need a layout transition.
8904*8975f5c5SAndroid Build Coastguard Worker     for (const vk::CommandBufferImageSubresourceAccess &imageWrite : access.getWriteImages())
8905*8975f5c5SAndroid Build Coastguard Worker     {
8906*8975f5c5SAndroid Build Coastguard Worker         if (isRenderPassStartedAndUsesImage(*imageWrite.access.image))
8907*8975f5c5SAndroid Build Coastguard Worker         {
8908*8975f5c5SAndroid Build Coastguard Worker             return flushCommandsAndEndRenderPass(RenderPassClosureReason::ImageUseThenOutOfRPWrite);
8909*8975f5c5SAndroid Build Coastguard Worker         }
8910*8975f5c5SAndroid Build Coastguard Worker     }
8911*8975f5c5SAndroid Build Coastguard Worker 
8912*8975f5c5SAndroid Build Coastguard Worker     bool shouldCloseOutsideRenderPassCommands = false;
8913*8975f5c5SAndroid Build Coastguard Worker 
8914*8975f5c5SAndroid Build Coastguard Worker     // Read buffers only need a new command buffer if previously used for write.
8915*8975f5c5SAndroid Build Coastguard Worker     for (const vk::CommandBufferBufferAccess &bufferAccess : access.getReadBuffers())
8916*8975f5c5SAndroid Build Coastguard Worker     {
8917*8975f5c5SAndroid Build Coastguard Worker         if (isRenderPassStartedAndUsesBufferForWrite(*bufferAccess.buffer))
8918*8975f5c5SAndroid Build Coastguard Worker         {
8919*8975f5c5SAndroid Build Coastguard Worker             return flushCommandsAndEndRenderPass(
8920*8975f5c5SAndroid Build Coastguard Worker                 RenderPassClosureReason::BufferWriteThenOutOfRPRead);
8921*8975f5c5SAndroid Build Coastguard Worker         }
8922*8975f5c5SAndroid Build Coastguard Worker         else if (mOutsideRenderPassCommands->usesBufferForWrite(*bufferAccess.buffer))
8923*8975f5c5SAndroid Build Coastguard Worker         {
8924*8975f5c5SAndroid Build Coastguard Worker             shouldCloseOutsideRenderPassCommands = true;
8925*8975f5c5SAndroid Build Coastguard Worker         }
8926*8975f5c5SAndroid Build Coastguard Worker     }
8927*8975f5c5SAndroid Build Coastguard Worker 
8928*8975f5c5SAndroid Build Coastguard Worker     // Write buffers always need a new command buffer if previously used.
8929*8975f5c5SAndroid Build Coastguard Worker     for (const vk::CommandBufferBufferAccess &bufferAccess : access.getWriteBuffers())
8930*8975f5c5SAndroid Build Coastguard Worker     {
8931*8975f5c5SAndroid Build Coastguard Worker         if (isRenderPassStartedAndUsesBuffer(*bufferAccess.buffer))
8932*8975f5c5SAndroid Build Coastguard Worker         {
8933*8975f5c5SAndroid Build Coastguard Worker             return flushCommandsAndEndRenderPass(
8934*8975f5c5SAndroid Build Coastguard Worker                 RenderPassClosureReason::BufferUseThenOutOfRPWrite);
8935*8975f5c5SAndroid Build Coastguard Worker         }
8936*8975f5c5SAndroid Build Coastguard Worker         else if (mOutsideRenderPassCommands->usesBuffer(*bufferAccess.buffer))
8937*8975f5c5SAndroid Build Coastguard Worker         {
8938*8975f5c5SAndroid Build Coastguard Worker             shouldCloseOutsideRenderPassCommands = true;
8939*8975f5c5SAndroid Build Coastguard Worker         }
8940*8975f5c5SAndroid Build Coastguard Worker     }
8941*8975f5c5SAndroid Build Coastguard Worker 
8942*8975f5c5SAndroid Build Coastguard Worker     if (shouldCloseOutsideRenderPassCommands)
8943*8975f5c5SAndroid Build Coastguard Worker     {
8944*8975f5c5SAndroid Build Coastguard Worker         return flushOutsideRenderPassCommands();
8945*8975f5c5SAndroid Build Coastguard Worker     }
8946*8975f5c5SAndroid Build Coastguard Worker 
8947*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8948*8975f5c5SAndroid Build Coastguard Worker }
8949*8975f5c5SAndroid Build Coastguard Worker 
endRenderPassIfComputeReadAfterTransformFeedbackWrite()8950*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::endRenderPassIfComputeReadAfterTransformFeedbackWrite()
8951*8975f5c5SAndroid Build Coastguard Worker {
8952*8975f5c5SAndroid Build Coastguard Worker     // Similar to flushCommandBuffersIfNecessary(), but using uniform buffers currently bound and
8953*8975f5c5SAndroid Build Coastguard Worker     // used by the current (compute) program.  This is to handle read-after-write hazards where the
8954*8975f5c5SAndroid Build Coastguard Worker     // write originates from transform feedback.
8955*8975f5c5SAndroid Build Coastguard Worker     if (!mCurrentTransformFeedbackQueueSerial.valid())
8956*8975f5c5SAndroid Build Coastguard Worker     {
8957*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
8958*8975f5c5SAndroid Build Coastguard Worker     }
8959*8975f5c5SAndroid Build Coastguard Worker 
8960*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
8961*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executable && executable->hasLinkedShaderStage(gl::ShaderType::Compute));
8962*8975f5c5SAndroid Build Coastguard Worker 
8963*8975f5c5SAndroid Build Coastguard Worker     // Uniform buffers:
8964*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::InterfaceBlock> &blocks = executable->getUniformBlocks();
8965*8975f5c5SAndroid Build Coastguard Worker 
8966*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
8967*8975f5c5SAndroid Build Coastguard Worker     {
8968*8975f5c5SAndroid Build Coastguard Worker         const GLuint binding = executable->getUniformBlockBinding(bufferIndex);
8969*8975f5c5SAndroid Build Coastguard Worker         const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
8970*8975f5c5SAndroid Build Coastguard Worker             mState.getIndexedUniformBuffer(binding);
8971*8975f5c5SAndroid Build Coastguard Worker 
8972*8975f5c5SAndroid Build Coastguard Worker         if (bufferBinding.get() == nullptr)
8973*8975f5c5SAndroid Build Coastguard Worker         {
8974*8975f5c5SAndroid Build Coastguard Worker             continue;
8975*8975f5c5SAndroid Build Coastguard Worker         }
8976*8975f5c5SAndroid Build Coastguard Worker 
8977*8975f5c5SAndroid Build Coastguard Worker         vk::BufferHelper &buffer = vk::GetImpl(bufferBinding.get())->getBuffer();
8978*8975f5c5SAndroid Build Coastguard Worker         if (buffer.writtenByCommandBuffer(mCurrentTransformFeedbackQueueSerial))
8979*8975f5c5SAndroid Build Coastguard Worker         {
8980*8975f5c5SAndroid Build Coastguard Worker             return flushCommandsAndEndRenderPass(RenderPassClosureReason::XfbWriteThenComputeRead);
8981*8975f5c5SAndroid Build Coastguard Worker         }
8982*8975f5c5SAndroid Build Coastguard Worker     }
8983*8975f5c5SAndroid Build Coastguard Worker 
8984*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
8985*8975f5c5SAndroid Build Coastguard Worker }
8986*8975f5c5SAndroid Build Coastguard Worker 
8987*8975f5c5SAndroid Build Coastguard Worker // When textures/images bound/used by current compute program and have been accessed
8988*8975f5c5SAndroid Build Coastguard Worker // as sampled texture in current render pass, need to take care the implicit layout
8989*8975f5c5SAndroid Build Coastguard Worker // transition of these textures/images in the render pass.
endRenderPassIfComputeAccessAfterGraphicsImageAccess()8990*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::endRenderPassIfComputeAccessAfterGraphicsImageAccess()
8991*8975f5c5SAndroid Build Coastguard Worker {
8992*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramExecutable *executable = mState.getProgramExecutable();
8993*8975f5c5SAndroid Build Coastguard Worker     ASSERT(executable && executable->hasLinkedShaderStage(gl::ShaderType::Compute));
8994*8975f5c5SAndroid Build Coastguard Worker 
8995*8975f5c5SAndroid Build Coastguard Worker     for (size_t imageUnitIndex : executable->getActiveImagesMask())
8996*8975f5c5SAndroid Build Coastguard Worker     {
8997*8975f5c5SAndroid Build Coastguard Worker         const gl::Texture *texture = mState.getImageUnit(imageUnitIndex).texture.get();
8998*8975f5c5SAndroid Build Coastguard Worker         if (texture == nullptr)
8999*8975f5c5SAndroid Build Coastguard Worker         {
9000*8975f5c5SAndroid Build Coastguard Worker             continue;
9001*8975f5c5SAndroid Build Coastguard Worker         }
9002*8975f5c5SAndroid Build Coastguard Worker 
9003*8975f5c5SAndroid Build Coastguard Worker         TextureVk *textureVk = vk::GetImpl(texture);
9004*8975f5c5SAndroid Build Coastguard Worker 
9005*8975f5c5SAndroid Build Coastguard Worker         if (texture->getType() == gl::TextureType::Buffer)
9006*8975f5c5SAndroid Build Coastguard Worker         {
9007*8975f5c5SAndroid Build Coastguard Worker             continue;
9008*8975f5c5SAndroid Build Coastguard Worker         }
9009*8975f5c5SAndroid Build Coastguard Worker         else
9010*8975f5c5SAndroid Build Coastguard Worker         {
9011*8975f5c5SAndroid Build Coastguard Worker             vk::ImageHelper &image = textureVk->getImage();
9012*8975f5c5SAndroid Build Coastguard Worker 
9013*8975f5c5SAndroid Build Coastguard Worker             // This is to handle the implicit layout transition in render pass of this image,
9014*8975f5c5SAndroid Build Coastguard Worker             // while it currently be bound and used by current compute program.
9015*8975f5c5SAndroid Build Coastguard Worker             if (mRenderPassCommands->startedAndUsesImageWithBarrier(image))
9016*8975f5c5SAndroid Build Coastguard Worker             {
9017*8975f5c5SAndroid Build Coastguard Worker                 return flushCommandsAndEndRenderPass(
9018*8975f5c5SAndroid Build Coastguard Worker                     RenderPassClosureReason::GraphicsTextureImageAccessThenComputeAccess);
9019*8975f5c5SAndroid Build Coastguard Worker             }
9020*8975f5c5SAndroid Build Coastguard Worker         }
9021*8975f5c5SAndroid Build Coastguard Worker     }
9022*8975f5c5SAndroid Build Coastguard Worker 
9023*8975f5c5SAndroid Build Coastguard Worker     const gl::ActiveTexturesCache &textures        = mState.getActiveTexturesCache();
9024*8975f5c5SAndroid Build Coastguard Worker     const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
9025*8975f5c5SAndroid Build Coastguard Worker 
9026*8975f5c5SAndroid Build Coastguard Worker     for (size_t textureUnit : executable->getActiveSamplersMask())
9027*8975f5c5SAndroid Build Coastguard Worker     {
9028*8975f5c5SAndroid Build Coastguard Worker         gl::Texture *texture        = textures[textureUnit];
9029*8975f5c5SAndroid Build Coastguard Worker         gl::TextureType textureType = textureTypes[textureUnit];
9030*8975f5c5SAndroid Build Coastguard Worker 
9031*8975f5c5SAndroid Build Coastguard Worker         if (texture == nullptr || textureType == gl::TextureType::Buffer)
9032*8975f5c5SAndroid Build Coastguard Worker         {
9033*8975f5c5SAndroid Build Coastguard Worker             continue;
9034*8975f5c5SAndroid Build Coastguard Worker         }
9035*8975f5c5SAndroid Build Coastguard Worker 
9036*8975f5c5SAndroid Build Coastguard Worker         TextureVk *textureVk = vk::GetImpl(texture);
9037*8975f5c5SAndroid Build Coastguard Worker         ASSERT(textureVk != nullptr);
9038*8975f5c5SAndroid Build Coastguard Worker         vk::ImageHelper &image = textureVk->getImage();
9039*8975f5c5SAndroid Build Coastguard Worker 
9040*8975f5c5SAndroid Build Coastguard Worker         // Similar to flushCommandBuffersIfNecessary(), but using textures currently bound and used
9041*8975f5c5SAndroid Build Coastguard Worker         // by the current (compute) program.  This is to handle read-after-write hazards where the
9042*8975f5c5SAndroid Build Coastguard Worker         // write originates from a framebuffer attachment.
9043*8975f5c5SAndroid Build Coastguard Worker         if (image.hasRenderPassUsageFlag(vk::RenderPassUsage::RenderTargetAttachment) &&
9044*8975f5c5SAndroid Build Coastguard Worker             isRenderPassStartedAndUsesImage(image))
9045*8975f5c5SAndroid Build Coastguard Worker         {
9046*8975f5c5SAndroid Build Coastguard Worker             return flushCommandsAndEndRenderPass(
9047*8975f5c5SAndroid Build Coastguard Worker                 RenderPassClosureReason::ImageAttachmentThenComputeRead);
9048*8975f5c5SAndroid Build Coastguard Worker         }
9049*8975f5c5SAndroid Build Coastguard Worker 
9050*8975f5c5SAndroid Build Coastguard Worker         // Take care of the read image layout transition require implicit synchronization.
9051*8975f5c5SAndroid Build Coastguard Worker         if (mRenderPassCommands->startedAndUsesImageWithBarrier(image))
9052*8975f5c5SAndroid Build Coastguard Worker         {
9053*8975f5c5SAndroid Build Coastguard Worker             return flushCommandsAndEndRenderPass(
9054*8975f5c5SAndroid Build Coastguard Worker                 RenderPassClosureReason::GraphicsTextureImageAccessThenComputeAccess);
9055*8975f5c5SAndroid Build Coastguard Worker         }
9056*8975f5c5SAndroid Build Coastguard Worker     }
9057*8975f5c5SAndroid Build Coastguard Worker 
9058*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
9059*8975f5c5SAndroid Build Coastguard Worker }
9060*8975f5c5SAndroid Build Coastguard Worker 
getPerfMonitorCounters()9061*8975f5c5SAndroid Build Coastguard Worker const angle::PerfMonitorCounterGroups &ContextVk::getPerfMonitorCounters()
9062*8975f5c5SAndroid Build Coastguard Worker {
9063*8975f5c5SAndroid Build Coastguard Worker     syncObjectPerfCounters(mRenderer->getCommandQueuePerfCounters());
9064*8975f5c5SAndroid Build Coastguard Worker 
9065*8975f5c5SAndroid Build Coastguard Worker     angle::PerfMonitorCounters &counters =
9066*8975f5c5SAndroid Build Coastguard Worker         angle::GetPerfMonitorCounterGroup(mPerfMonitorCounters, "vulkan").counters;
9067*8975f5c5SAndroid Build Coastguard Worker 
9068*8975f5c5SAndroid Build Coastguard Worker #define ANGLE_UPDATE_PERF_MAP(COUNTER) \
9069*8975f5c5SAndroid Build Coastguard Worker     angle::GetPerfMonitorCounter(counters, #COUNTER).value = mPerfCounters.COUNTER;
9070*8975f5c5SAndroid Build Coastguard Worker 
9071*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_PERF_COUNTERS_X(ANGLE_UPDATE_PERF_MAP)
9072*8975f5c5SAndroid Build Coastguard Worker 
9073*8975f5c5SAndroid Build Coastguard Worker #undef ANGLE_UPDATE_PERF_MAP
9074*8975f5c5SAndroid Build Coastguard Worker 
9075*8975f5c5SAndroid Build Coastguard Worker     return mPerfMonitorCounters;
9076*8975f5c5SAndroid Build Coastguard Worker }
9077*8975f5c5SAndroid Build Coastguard Worker 
switchToColorFramebufferFetchMode(bool hasColorFramebufferFetch)9078*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::switchToColorFramebufferFetchMode(bool hasColorFramebufferFetch)
9079*8975f5c5SAndroid Build Coastguard Worker {
9080*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!getFeatures().preferDynamicRendering.enabled);
9081*8975f5c5SAndroid Build Coastguard Worker 
9082*8975f5c5SAndroid Build Coastguard Worker     // If framebuffer fetch is permanent, make sure we never switch out of it.
9083*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().permanentlySwitchToFramebufferFetchMode.enabled &&
9084*8975f5c5SAndroid Build Coastguard Worker         mIsInColorFramebufferFetchMode)
9085*8975f5c5SAndroid Build Coastguard Worker     {
9086*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
9087*8975f5c5SAndroid Build Coastguard Worker     }
9088*8975f5c5SAndroid Build Coastguard Worker 
9089*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mIsInColorFramebufferFetchMode != hasColorFramebufferFetch);
9090*8975f5c5SAndroid Build Coastguard Worker     mIsInColorFramebufferFetchMode = hasColorFramebufferFetch;
9091*8975f5c5SAndroid Build Coastguard Worker 
9092*8975f5c5SAndroid Build Coastguard Worker     // If a render pass is already open, close it.
9093*8975f5c5SAndroid Build Coastguard Worker     if (mRenderPassCommands->started())
9094*8975f5c5SAndroid Build Coastguard Worker     {
9095*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(
9096*8975f5c5SAndroid Build Coastguard Worker             flushCommandsAndEndRenderPass(RenderPassClosureReason::FramebufferFetchEmulation));
9097*8975f5c5SAndroid Build Coastguard Worker     }
9098*8975f5c5SAndroid Build Coastguard Worker 
9099*8975f5c5SAndroid Build Coastguard Worker     // If there's a draw buffer bound, switch it to framebuffer fetch mode.  Every other framebuffer
9100*8975f5c5SAndroid Build Coastguard Worker     // will switch when bound.
9101*8975f5c5SAndroid Build Coastguard Worker     if (mState.getDrawFramebuffer() != nullptr)
9102*8975f5c5SAndroid Build Coastguard Worker     {
9103*8975f5c5SAndroid Build Coastguard Worker         getDrawFramebuffer()->switchToColorFramebufferFetchMode(this,
9104*8975f5c5SAndroid Build Coastguard Worker                                                                 mIsInColorFramebufferFetchMode);
9105*8975f5c5SAndroid Build Coastguard Worker     }
9106*8975f5c5SAndroid Build Coastguard Worker 
9107*8975f5c5SAndroid Build Coastguard Worker     // Clear the render pass cache; all render passes will be incompatible from now on with the
9108*8975f5c5SAndroid Build Coastguard Worker     // old ones.
9109*8975f5c5SAndroid Build Coastguard Worker     if (getFeatures().permanentlySwitchToFramebufferFetchMode.enabled)
9110*8975f5c5SAndroid Build Coastguard Worker     {
9111*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCache.clear(this);
9112*8975f5c5SAndroid Build Coastguard Worker     }
9113*8975f5c5SAndroid Build Coastguard Worker 
9114*8975f5c5SAndroid Build Coastguard Worker     mRenderer->onColorFramebufferFetchUse();
9115*8975f5c5SAndroid Build Coastguard Worker 
9116*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
9117*8975f5c5SAndroid Build Coastguard Worker }
9118*8975f5c5SAndroid Build Coastguard Worker 
onFramebufferFetchUse(vk::FramebufferFetchMode framebufferFetchMode)9119*8975f5c5SAndroid Build Coastguard Worker void ContextVk::onFramebufferFetchUse(vk::FramebufferFetchMode framebufferFetchMode)
9120*8975f5c5SAndroid Build Coastguard Worker {
9121*8975f5c5SAndroid Build Coastguard Worker     ASSERT(getFeatures().preferDynamicRendering.enabled);
9122*8975f5c5SAndroid Build Coastguard Worker 
9123*8975f5c5SAndroid Build Coastguard Worker     if (mRenderPassCommands->started())
9124*8975f5c5SAndroid Build Coastguard Worker     {
9125*8975f5c5SAndroid Build Coastguard Worker         // Accumulate framebuffer fetch mode to allow multiple draw calls in the same render pass
9126*8975f5c5SAndroid Build Coastguard Worker         // where some use color framebuffer fetch and some depth/stencil
9127*8975f5c5SAndroid Build Coastguard Worker         const vk::FramebufferFetchMode mergedMode = vk::FramebufferFetchModeMerge(
9128*8975f5c5SAndroid Build Coastguard Worker             mRenderPassCommands->getRenderPassDesc().framebufferFetchMode(), framebufferFetchMode);
9129*8975f5c5SAndroid Build Coastguard Worker 
9130*8975f5c5SAndroid Build Coastguard Worker         mRenderPassCommands->setFramebufferFetchMode(mergedMode);
9131*8975f5c5SAndroid Build Coastguard Worker 
9132*8975f5c5SAndroid Build Coastguard Worker         // When framebuffer fetch is enabled, attachments can be read from even if output is
9133*8975f5c5SAndroid Build Coastguard Worker         // masked, so update their access.
9134*8975f5c5SAndroid Build Coastguard Worker         if (FramebufferFetchModeHasColor(framebufferFetchMode))
9135*8975f5c5SAndroid Build Coastguard Worker         {
9136*8975f5c5SAndroid Build Coastguard Worker             onColorAccessChange();
9137*8975f5c5SAndroid Build Coastguard Worker         }
9138*8975f5c5SAndroid Build Coastguard Worker         if (FramebufferFetchModeHasDepthStencil(framebufferFetchMode))
9139*8975f5c5SAndroid Build Coastguard Worker         {
9140*8975f5c5SAndroid Build Coastguard Worker             onDepthStencilAccessChange();
9141*8975f5c5SAndroid Build Coastguard Worker         }
9142*8975f5c5SAndroid Build Coastguard Worker     }
9143*8975f5c5SAndroid Build Coastguard Worker 
9144*8975f5c5SAndroid Build Coastguard Worker     if (FramebufferFetchModeHasColor(framebufferFetchMode))
9145*8975f5c5SAndroid Build Coastguard Worker     {
9146*8975f5c5SAndroid Build Coastguard Worker         mRenderer->onColorFramebufferFetchUse();
9147*8975f5c5SAndroid Build Coastguard Worker     }
9148*8975f5c5SAndroid Build Coastguard Worker }
9149*8975f5c5SAndroid Build Coastguard Worker 
allocateQueueSerialIndex()9150*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE angle::Result ContextVk::allocateQueueSerialIndex()
9151*8975f5c5SAndroid Build Coastguard Worker {
9152*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mCurrentQueueSerialIndex == kInvalidQueueSerialIndex);
9153*8975f5c5SAndroid Build Coastguard Worker     // Make everything appears to be flushed and submitted
9154*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mRenderer->allocateQueueSerialIndex(&mCurrentQueueSerialIndex));
9155*8975f5c5SAndroid Build Coastguard Worker     // Note queueSerial for render pass is deferred until begin time.
9156*8975f5c5SAndroid Build Coastguard Worker     generateOutsideRenderPassCommandsQueueSerial();
9157*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
9158*8975f5c5SAndroid Build Coastguard Worker }
9159*8975f5c5SAndroid Build Coastguard Worker 
releaseQueueSerialIndex()9160*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE void ContextVk::releaseQueueSerialIndex()
9161*8975f5c5SAndroid Build Coastguard Worker {
9162*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mCurrentQueueSerialIndex != kInvalidQueueSerialIndex);
9163*8975f5c5SAndroid Build Coastguard Worker     mRenderer->releaseQueueSerialIndex(mCurrentQueueSerialIndex);
9164*8975f5c5SAndroid Build Coastguard Worker     mCurrentQueueSerialIndex = kInvalidQueueSerialIndex;
9165*8975f5c5SAndroid Build Coastguard Worker }
9166*8975f5c5SAndroid Build Coastguard Worker 
generateOutsideRenderPassCommandsQueueSerial()9167*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE void ContextVk::generateOutsideRenderPassCommandsQueueSerial()
9168*8975f5c5SAndroid Build Coastguard Worker {
9169*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mCurrentQueueSerialIndex != kInvalidQueueSerialIndex);
9170*8975f5c5SAndroid Build Coastguard Worker 
9171*8975f5c5SAndroid Build Coastguard Worker     // If there is reserved serial number, use that. Otherwise generate a new one.
9172*8975f5c5SAndroid Build Coastguard Worker     Serial serial;
9173*8975f5c5SAndroid Build Coastguard Worker     if (mOutsideRenderPassSerialFactory.generate(&serial))
9174*8975f5c5SAndroid Build Coastguard Worker     {
9175*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mRenderPassCommands->getQueueSerial().valid());
9176*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mRenderPassCommands->getQueueSerial().getSerial() > serial);
9177*8975f5c5SAndroid Build Coastguard Worker         mOutsideRenderPassCommands->setQueueSerial(mCurrentQueueSerialIndex, serial);
9178*8975f5c5SAndroid Build Coastguard Worker         return;
9179*8975f5c5SAndroid Build Coastguard Worker     }
9180*8975f5c5SAndroid Build Coastguard Worker 
9181*8975f5c5SAndroid Build Coastguard Worker     serial = mRenderer->generateQueueSerial(mCurrentQueueSerialIndex);
9182*8975f5c5SAndroid Build Coastguard Worker     mOutsideRenderPassCommands->setQueueSerial(mCurrentQueueSerialIndex, serial);
9183*8975f5c5SAndroid Build Coastguard Worker }
9184*8975f5c5SAndroid Build Coastguard Worker 
generateRenderPassCommandsQueueSerial(QueueSerial * queueSerialOut)9185*8975f5c5SAndroid Build Coastguard Worker ANGLE_INLINE void ContextVk::generateRenderPassCommandsQueueSerial(QueueSerial *queueSerialOut)
9186*8975f5c5SAndroid Build Coastguard Worker {
9187*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mCurrentQueueSerialIndex != kInvalidQueueSerialIndex);
9188*8975f5c5SAndroid Build Coastguard Worker 
9189*8975f5c5SAndroid Build Coastguard Worker     // We reserve some serial number for outsideRenderPassCommands in case we have to flush.
9190*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mOutsideRenderPassCommands->getQueueSerial().valid());
9191*8975f5c5SAndroid Build Coastguard Worker     mRenderer->reserveQueueSerials(mCurrentQueueSerialIndex,
9192*8975f5c5SAndroid Build Coastguard Worker                                    kMaxReservedOutsideRenderPassQueueSerials,
9193*8975f5c5SAndroid Build Coastguard Worker                                    &mOutsideRenderPassSerialFactory);
9194*8975f5c5SAndroid Build Coastguard Worker 
9195*8975f5c5SAndroid Build Coastguard Worker     Serial serial   = mRenderer->generateQueueSerial(mCurrentQueueSerialIndex);
9196*8975f5c5SAndroid Build Coastguard Worker     *queueSerialOut = QueueSerial(mCurrentQueueSerialIndex, serial);
9197*8975f5c5SAndroid Build Coastguard Worker }
9198*8975f5c5SAndroid Build Coastguard Worker 
resetPerFramePerfCounters()9199*8975f5c5SAndroid Build Coastguard Worker void ContextVk::resetPerFramePerfCounters()
9200*8975f5c5SAndroid Build Coastguard Worker {
9201*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.renderPasses                           = 0;
9202*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.writeDescriptorSets                    = 0;
9203*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.flushedOutsideRenderPassCommandBuffers = 0;
9204*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.resolveImageCommands                   = 0;
9205*8975f5c5SAndroid Build Coastguard Worker     mPerfCounters.descriptorSetAllocations               = 0;
9206*8975f5c5SAndroid Build Coastguard Worker 
9207*8975f5c5SAndroid Build Coastguard Worker     mRenderer->resetCommandQueuePerFrameCounters();
9208*8975f5c5SAndroid Build Coastguard Worker 
9209*8975f5c5SAndroid Build Coastguard Worker     mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::UniformsAndXfb]
9210*8975f5c5SAndroid Build Coastguard Worker         .resetDescriptorCacheStats();
9211*8975f5c5SAndroid Build Coastguard Worker     mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::Texture]
9212*8975f5c5SAndroid Build Coastguard Worker         .resetDescriptorCacheStats();
9213*8975f5c5SAndroid Build Coastguard Worker     mShareGroupVk->getMetaDescriptorPools()[DescriptorSetIndex::ShaderResource]
9214*8975f5c5SAndroid Build Coastguard Worker         .resetDescriptorCacheStats();
9215*8975f5c5SAndroid Build Coastguard Worker }
9216*8975f5c5SAndroid Build Coastguard Worker 
ensureInterfacePipelineCache()9217*8975f5c5SAndroid Build Coastguard Worker angle::Result ContextVk::ensureInterfacePipelineCache()
9218*8975f5c5SAndroid Build Coastguard Worker {
9219*8975f5c5SAndroid Build Coastguard Worker     if (!mInterfacePipelinesCache.valid())
9220*8975f5c5SAndroid Build Coastguard Worker     {
9221*8975f5c5SAndroid Build Coastguard Worker         VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {};
9222*8975f5c5SAndroid Build Coastguard Worker         pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
9223*8975f5c5SAndroid Build Coastguard Worker 
9224*8975f5c5SAndroid Build Coastguard Worker         ANGLE_VK_TRY(this, mInterfacePipelinesCache.init(getDevice(), pipelineCacheCreateInfo));
9225*8975f5c5SAndroid Build Coastguard Worker     }
9226*8975f5c5SAndroid Build Coastguard Worker 
9227*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
9228*8975f5c5SAndroid Build Coastguard Worker }
9229*8975f5c5SAndroid Build Coastguard Worker }  // namespace rx
9230