• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ContextVk.h:
7 //    Defines the class interface for ContextVk, implementing ContextImpl.
8 //
9 
10 #ifndef LIBANGLE_RENDERER_VULKAN_CONTEXTVK_H_
11 #define LIBANGLE_RENDERER_VULKAN_CONTEXTVK_H_
12 
13 #include <condition_variable>
14 
15 #include "common/PackedEnums.h"
16 #include "libANGLE/renderer/ContextImpl.h"
17 #include "libANGLE/renderer/renderer_utils.h"
18 #include "libANGLE/renderer/vulkan/OverlayVk.h"
19 #include "libANGLE/renderer/vulkan/PersistentCommandPool.h"
20 #include "libANGLE/renderer/vulkan/RendererVk.h"
21 #include "libANGLE/renderer/vulkan/vk_headers.h"
22 #include "libANGLE/renderer/vulkan/vk_helpers.h"
23 
24 namespace angle
25 {
26 struct FeaturesVk;
27 }  // namespace angle
28 
29 namespace rx
30 {
31 class ProgramExecutableVk;
32 class RendererVk;
33 class WindowSurfaceVk;
34 
35 struct CommandBatch final : angle::NonCopyable
36 {
37     CommandBatch();
38     ~CommandBatch();
39     CommandBatch(CommandBatch &&other);
40     CommandBatch &operator=(CommandBatch &&other);
41 
42     void destroy(VkDevice device);
43 
44     vk::PrimaryCommandBuffer primaryCommands;
45     // commandPool is for secondary CommandBuffer allocation
46     vk::CommandPool commandPool;
47     vk::Shared<vk::Fence> fence;
48     Serial serial;
49 };
50 
51 class CommandQueue final : angle::NonCopyable
52 {
53   public:
54     CommandQueue();
55     ~CommandQueue();
56 
57     angle::Result init(vk::Context *context);
58     void destroy(VkDevice device);
59     void handleDeviceLost(RendererVk *renderer);
60 
61     bool hasInFlightCommands() const;
62 
63     angle::Result allocatePrimaryCommandBuffer(vk::Context *context,
64                                                const vk::CommandPool &commandPool,
65                                                vk::PrimaryCommandBuffer *commandBufferOut);
66     angle::Result releasePrimaryCommandBuffer(vk::Context *context,
67                                               vk::PrimaryCommandBuffer &&commandBuffer);
68 
69     void clearAllGarbage(RendererVk *renderer);
70 
71     angle::Result finishToSerial(vk::Context *context, Serial serial, uint64_t timeout);
72 
73     angle::Result submitFrame(vk::Context *context,
74                               egl::ContextPriority priority,
75                               const VkSubmitInfo &submitInfo,
76                               const vk::Shared<vk::Fence> &sharedFence,
77                               vk::GarbageList *currentGarbage,
78                               vk::CommandPool *commandPool,
79                               vk::PrimaryCommandBuffer &&commandBuffer);
80 
81     vk::Shared<vk::Fence> getLastSubmittedFence(const vk::Context *context) const;
82 
83     // Check to see which batches have finished completion (forward progress for
84     // mLastCompletedQueueSerial, for example for when the application busy waits on a query
85     // result). It would be nice if we didn't have to expose this for QueryVk::getResult.
86     angle::Result checkCompletedCommands(vk::Context *context);
87 
88   private:
89     angle::Result releaseToCommandBatch(vk::Context *context,
90                                         vk::PrimaryCommandBuffer &&commandBuffer,
91                                         vk::CommandPool *commandPool,
92                                         CommandBatch *batch);
93 
94     vk::GarbageQueue mGarbageQueue;
95     std::vector<CommandBatch> mInFlightCommands;
96 
97     // Keeps a free list of reusable primary command buffers.
98     vk::PersistentCommandPool mPrimaryCommandPool;
99 };
100 
101 static constexpr uint32_t kMaxGpuEventNameLen = 32;
102 using EventName                               = std::array<char, kMaxGpuEventNameLen>;
103 
104 class ContextVk : public ContextImpl, public vk::Context
105 {
106   public:
107     ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk *renderer);
108     ~ContextVk() override;
109 
110     angle::Result initialize() override;
111 
112     void onDestroy(const gl::Context *context) override;
113 
114     // Flush and finish.
115     angle::Result flush(const gl::Context *context) override;
116     angle::Result finish(const gl::Context *context) override;
117 
118     // Drawing methods.
119     angle::Result drawArrays(const gl::Context *context,
120                              gl::PrimitiveMode mode,
121                              GLint first,
122                              GLsizei count) override;
123     angle::Result drawArraysInstanced(const gl::Context *context,
124                                       gl::PrimitiveMode mode,
125                                       GLint first,
126                                       GLsizei count,
127                                       GLsizei instanceCount) override;
128     angle::Result drawArraysInstancedBaseInstance(const gl::Context *context,
129                                                   gl::PrimitiveMode mode,
130                                                   GLint first,
131                                                   GLsizei count,
132                                                   GLsizei instanceCount,
133                                                   GLuint baseInstance) override;
134 
135     angle::Result drawElements(const gl::Context *context,
136                                gl::PrimitiveMode mode,
137                                GLsizei count,
138                                gl::DrawElementsType type,
139                                const void *indices) override;
140     angle::Result drawElementsBaseVertex(const gl::Context *context,
141                                          gl::PrimitiveMode mode,
142                                          GLsizei count,
143                                          gl::DrawElementsType type,
144                                          const void *indices,
145                                          GLint baseVertex) override;
146     angle::Result drawElementsInstanced(const gl::Context *context,
147                                         gl::PrimitiveMode mode,
148                                         GLsizei count,
149                                         gl::DrawElementsType type,
150                                         const void *indices,
151                                         GLsizei instanceCount) override;
152     angle::Result drawElementsInstancedBaseVertex(const gl::Context *context,
153                                                   gl::PrimitiveMode mode,
154                                                   GLsizei count,
155                                                   gl::DrawElementsType type,
156                                                   const void *indices,
157                                                   GLsizei instanceCount,
158                                                   GLint baseVertex) override;
159     angle::Result drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
160                                                               gl::PrimitiveMode mode,
161                                                               GLsizei count,
162                                                               gl::DrawElementsType type,
163                                                               const void *indices,
164                                                               GLsizei instances,
165                                                               GLint baseVertex,
166                                                               GLuint baseInstance) override;
167     angle::Result drawRangeElements(const gl::Context *context,
168                                     gl::PrimitiveMode mode,
169                                     GLuint start,
170                                     GLuint end,
171                                     GLsizei count,
172                                     gl::DrawElementsType type,
173                                     const void *indices) override;
174     angle::Result drawRangeElementsBaseVertex(const gl::Context *context,
175                                               gl::PrimitiveMode mode,
176                                               GLuint start,
177                                               GLuint end,
178                                               GLsizei count,
179                                               gl::DrawElementsType type,
180                                               const void *indices,
181                                               GLint baseVertex) override;
182     angle::Result drawArraysIndirect(const gl::Context *context,
183                                      gl::PrimitiveMode mode,
184                                      const void *indirect) override;
185     angle::Result drawElementsIndirect(const gl::Context *context,
186                                        gl::PrimitiveMode mode,
187                                        gl::DrawElementsType type,
188                                        const void *indirect) override;
189 
190     // Device loss
191     gl::GraphicsResetStatus getResetStatus() override;
192 
193     // Vendor and description strings.
194     std::string getVendorString() const override;
195     std::string getRendererDescription() const override;
196 
197     // EXT_debug_marker
198     angle::Result insertEventMarker(GLsizei length, const char *marker) override;
199     angle::Result pushGroupMarker(GLsizei length, const char *marker) override;
200     angle::Result popGroupMarker() override;
201 
202     // KHR_debug
203     angle::Result pushDebugGroup(const gl::Context *context,
204                                  GLenum source,
205                                  GLuint id,
206                                  const std::string &message) override;
207     angle::Result popDebugGroup(const gl::Context *context) override;
208 
209     bool isViewportFlipEnabledForDrawFBO() const;
210     bool isViewportFlipEnabledForReadFBO() const;
211     // When the device/surface is rotated such that the surface's aspect ratio is different than
212     // the native device (e.g. 90 degrees), the width and height of the viewport, scissor, and
213     // render area must be swapped.
214     bool isRotatedAspectRatioForDrawFBO() const;
215     bool isRotatedAspectRatioForReadFBO() const;
216     SurfaceRotation getRotationDrawFramebuffer() const;
217     SurfaceRotation getRotationReadFramebuffer() const;
218 
219     void invalidateProgramBindingHelper(const gl::State &glState);
220     angle::Result invalidateProgramExecutableHelper(const gl::Context *context);
221 
222     // State sync with dirty bits.
223     angle::Result syncState(const gl::Context *context,
224                             const gl::State::DirtyBits &dirtyBits,
225                             const gl::State::DirtyBits &bitMask) override;
226 
227     // Disjoint timer queries
228     GLint getGPUDisjoint() override;
229     GLint64 getTimestamp() override;
230 
231     // Context switching
232     angle::Result onMakeCurrent(const gl::Context *context) override;
233     angle::Result onUnMakeCurrent(const gl::Context *context) override;
234 
235     // Native capabilities, unmodified by gl::Context.
236     gl::Caps getNativeCaps() const override;
237     const gl::TextureCapsMap &getNativeTextureCaps() const override;
238     const gl::Extensions &getNativeExtensions() const override;
239     const gl::Limitations &getNativeLimitations() const override;
240 
241     // Shader creation
242     CompilerImpl *createCompiler() override;
243     ShaderImpl *createShader(const gl::ShaderState &state) override;
244     ProgramImpl *createProgram(const gl::ProgramState &state) override;
245 
246     // Framebuffer creation
247     FramebufferImpl *createFramebuffer(const gl::FramebufferState &state) override;
248 
249     // Texture creation
250     TextureImpl *createTexture(const gl::TextureState &state) override;
251 
252     // Renderbuffer creation
253     RenderbufferImpl *createRenderbuffer(const gl::RenderbufferState &state) override;
254 
255     // Buffer creation
256     BufferImpl *createBuffer(const gl::BufferState &state) override;
257 
258     // Vertex Array creation
259     VertexArrayImpl *createVertexArray(const gl::VertexArrayState &state) override;
260 
261     // Query and Fence creation
262     QueryImpl *createQuery(gl::QueryType type) override;
263     FenceNVImpl *createFenceNV() override;
264     SyncImpl *createSync() override;
265 
266     // Transform Feedback creation
267     TransformFeedbackImpl *createTransformFeedback(
268         const gl::TransformFeedbackState &state) override;
269 
270     // Sampler object creation
271     SamplerImpl *createSampler(const gl::SamplerState &state) override;
272 
273     // Program Pipeline object creation
274     ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override;
275 
276     // Memory object creation.
277     MemoryObjectImpl *createMemoryObject() override;
278 
279     // Semaphore creation.
280     SemaphoreImpl *createSemaphore() override;
281 
282     // Overlay creation.
283     OverlayImpl *createOverlay(const gl::OverlayState &state) override;
284 
285     angle::Result dispatchCompute(const gl::Context *context,
286                                   GLuint numGroupsX,
287                                   GLuint numGroupsY,
288                                   GLuint numGroupsZ) override;
289     angle::Result dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) override;
290 
291     angle::Result memoryBarrier(const gl::Context *context, GLbitfield barriers) override;
292     angle::Result memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers) override;
293 
294     VkDevice getDevice() const;
getPriority()295     egl::ContextPriority getPriority() const { return mContextPriority; }
296 
getFeatures()297     ANGLE_INLINE const angle::FeaturesVk &getFeatures() const { return mRenderer->getFeatures(); }
298 
invalidateVertexAndIndexBuffers()299     ANGLE_INLINE void invalidateVertexAndIndexBuffers()
300     {
301         // TODO: Make the pipeline invalidate more fine-grained. Only need to dirty here if PSO
302         //  VtxInput state (stride, fmt, inputRate...) has changed. http://anglebug.com/3256
303         invalidateCurrentGraphicsPipeline();
304         mGraphicsDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
305         mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
306     }
307 
invalidateVertexBuffers()308     ANGLE_INLINE void invalidateVertexBuffers()
309     {
310         mGraphicsDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
311     }
312 
onVertexAttributeChange(size_t attribIndex,GLuint stride,GLuint divisor,angle::FormatID format,GLuint relativeOffset)313     ANGLE_INLINE void onVertexAttributeChange(size_t attribIndex,
314                                               GLuint stride,
315                                               GLuint divisor,
316                                               angle::FormatID format,
317                                               GLuint relativeOffset)
318     {
319         invalidateCurrentGraphicsPipeline();
320         mGraphicsDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
321         // Set divisor to 1 for attribs with emulated divisor
322         mGraphicsPipelineDesc->updateVertexInput(
323             &mGraphicsPipelineTransition, static_cast<uint32_t>(attribIndex), stride,
324             divisor > mRenderer->getMaxVertexAttribDivisor() ? 1 : divisor, format, relativeOffset);
325     }
326 
327     void invalidateDefaultAttribute(size_t attribIndex);
328     void invalidateDefaultAttributes(const gl::AttributesMask &dirtyMask);
329     void onDrawFramebufferChange(FramebufferVk *framebufferVk);
onHostVisibleBufferWrite()330     void onHostVisibleBufferWrite() { mIsAnyHostVisibleBufferWritten = true; }
331 
332     void invalidateCurrentTransformFeedbackBuffers();
333     void onTransformFeedbackStateChanged();
334 
335     // When UtilsVk issues draw or dispatch calls, it binds descriptor sets that the context is not
336     // aware of.  This function is called to make sure affected descriptor set bindings are dirtied
337     // for the next application draw/dispatch call.
338     void invalidateGraphicsDescriptorSet(uint32_t usedDescriptorSet);
339     void invalidateComputeDescriptorSet(uint32_t usedDescriptorSet);
340 
341     void optimizeRenderPassForPresent(VkFramebuffer framebufferHandle);
342 
343     vk::DynamicQueryPool *getQueryPool(gl::QueryType queryType);
344 
345     const VkClearValue &getClearColorValue() const;
346     const VkClearValue &getClearDepthStencilValue() const;
347     VkColorComponentFlags getClearColorMask() const;
348     angle::Result getIncompleteTexture(const gl::Context *context,
349                                        gl::TextureType type,
350                                        gl::Texture **textureOut);
351     void updateColorMask(const gl::BlendState &blendState);
352     void updateSampleMask(const gl::State &glState);
353 
354     void handleError(VkResult errorCode,
355                      const char *file,
356                      const char *function,
357                      unsigned int line) override;
getActiveTextures()358     const gl::ActiveTextureArray<vk::TextureUnit> &getActiveTextures() const
359     {
360         return mActiveTextures;
361     }
getActiveImages()362     const gl::ActiveTextureArray<TextureVk *> &getActiveImages() const { return mActiveImages; }
363 
setIndexBufferDirty()364     void setIndexBufferDirty()
365     {
366         mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
367         mLastIndexBufferOffset = reinterpret_cast<const void *>(angle::DirtyPointer);
368     }
369 
370     angle::Result flushImpl(const vk::Semaphore *semaphore);
371     angle::Result finishImpl();
372 
373     void addWaitSemaphore(VkSemaphore semaphore, VkPipelineStageFlags stageMask);
374 
375     const vk::CommandPool &getCommandPool() const;
376 
getCurrentQueueSerial()377     Serial getCurrentQueueSerial() const { return mRenderer->getCurrentQueueSerial(); }
getLastSubmittedQueueSerial()378     Serial getLastSubmittedQueueSerial() const { return mRenderer->getLastSubmittedQueueSerial(); }
getLastCompletedQueueSerial()379     Serial getLastCompletedQueueSerial() const { return mRenderer->getLastCompletedQueueSerial(); }
380 
381     bool isSerialInUse(Serial serial) const;
382 
383     template <typename T>
addGarbage(T * object)384     void addGarbage(T *object)
385     {
386         if (object->valid())
387         {
388             mCurrentGarbage.emplace_back(vk::GetGarbage(object));
389         }
390     }
391 
392     // It would be nice if we didn't have to expose this for QueryVk::getResult.
393     angle::Result checkCompletedCommands();
394 
395     // Wait for completion of batches until (at least) batch with given serial is finished.
396     angle::Result finishToSerial(Serial serial);
397 
398     angle::Result getCompatibleRenderPass(const vk::RenderPassDesc &desc,
399                                           vk::RenderPass **renderPassOut);
400     angle::Result getRenderPassWithOps(const vk::RenderPassDesc &desc,
401                                        const vk::AttachmentOpsArray &ops,
402                                        vk::RenderPass **renderPassOut);
403 
404     // Get (or allocate) the fence that will be signaled on next submission.
405     angle::Result getNextSubmitFence(vk::Shared<vk::Fence> *sharedFenceOut);
406     vk::Shared<vk::Fence> getLastSubmittedFence() const;
407 
getShaderLibrary()408     vk::ShaderLibrary &getShaderLibrary() { return mShaderLibrary; }
getUtils()409     UtilsVk &getUtils() { return mUtils; }
410 
411     angle::Result getTimestamp(uint64_t *timestampOut);
412 
413     // Create Begin/End/Instant GPU trace events, which take their timestamps from GPU queries.
414     // The events are queued until the query results are available.  Possible values for `phase`
415     // are TRACE_EVENT_PHASE_*
traceGpuEvent(vk::CommandBuffer * commandBuffer,char phase,const EventName & name)416     ANGLE_INLINE angle::Result traceGpuEvent(vk::CommandBuffer *commandBuffer,
417                                              char phase,
418                                              const EventName &name)
419     {
420         if (mGpuEventsEnabled)
421             return traceGpuEventImpl(commandBuffer, phase, name);
422         return angle::Result::Continue;
423     }
424 
getRenderPassCache()425     RenderPassCache &getRenderPassCache() { return mRenderPassCache; }
426 
427     vk::DescriptorSetLayoutDesc getDriverUniformsDescriptorSetDesc(
428         VkShaderStageFlags shaderStages) const;
429 
430     // We use texture serials to optimize texture binding updates. Each permutation of a
431     // {VkImage/VkSampler} generates a unique serial. These serials are combined to form a unique
432     // signature for each descriptor set. This allows us to keep a cache of descriptor sets and
433     // avoid calling vkAllocateDesctiporSets each texture update.
generateTextureSerial()434     Serial generateTextureSerial() { return mTextureSerialFactory.generate(); }
getActiveTexturesDesc()435     const vk::TextureDescriptorDesc &getActiveTexturesDesc() const { return mActiveTexturesDesc; }
generateAttachmentImageSerial()436     Serial generateAttachmentImageSerial() { return mAttachmentImageSerialFactory.generate(); }
437 
438     angle::Result updateScissor(const gl::State &glState);
439 
emulateSeamfulCubeMapSampling()440     bool emulateSeamfulCubeMapSampling() const { return mEmulateSeamfulCubeMapSampling; }
441 
useOldRewriteStructSamplers()442     bool useOldRewriteStructSamplers() const { return mUseOldRewriteStructSamplers; }
443 
getOverlay()444     const gl::OverlayType *getOverlay() const { return mState.getOverlay(); }
445 
getResourceUseList()446     vk::ResourceUseList &getResourceUseList() { return mResourceUseList; }
447 
onBufferTransferRead(vk::BufferHelper * buffer)448     angle::Result onBufferTransferRead(vk::BufferHelper *buffer)
449     {
450         return onBufferRead(VK_ACCESS_TRANSFER_READ_BIT, vk::PipelineStage::Transfer, buffer);
451     }
onBufferTransferWrite(vk::BufferHelper * buffer)452     angle::Result onBufferTransferWrite(vk::BufferHelper *buffer)
453     {
454         return onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, vk::PipelineStage::Transfer, buffer);
455     }
onBufferComputeShaderRead(vk::BufferHelper * buffer)456     angle::Result onBufferComputeShaderRead(vk::BufferHelper *buffer)
457     {
458         return onBufferRead(VK_ACCESS_SHADER_READ_BIT, vk::PipelineStage::ComputeShader, buffer);
459     }
onBufferComputeShaderWrite(vk::BufferHelper * buffer)460     angle::Result onBufferComputeShaderWrite(vk::BufferHelper *buffer)
461     {
462         return onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, vk::PipelineStage::ComputeShader, buffer);
463     }
464 
465     angle::Result onImageRead(VkImageAspectFlags aspectFlags,
466                               vk::ImageLayout imageLayout,
467                               vk::ImageHelper *image);
468 
469     angle::Result onImageWrite(VkImageAspectFlags aspectFlags,
470                                vk::ImageLayout imageLayout,
471                                vk::ImageHelper *image);
472 
473     void onRenderPassImageWrite(VkImageAspectFlags aspectFlags,
474                                 vk::ImageLayout imageLayout,
475                                 vk::ImageHelper *image);
476 
endRenderPassAndGetCommandBuffer(vk::CommandBuffer ** commandBufferOut)477     angle::Result endRenderPassAndGetCommandBuffer(vk::CommandBuffer **commandBufferOut)
478     {
479         // Only one command buffer should be active at a time
480         ASSERT(mOutsideRenderPassCommands->empty() || mRenderPassCommands->empty());
481         ANGLE_TRY(endRenderPass());
482         *commandBufferOut = &mOutsideRenderPassCommands->getCommandBuffer();
483         return angle::Result::Continue;
484     }
485 
486     angle::Result flushAndBeginRenderPass(const vk::Framebuffer &framebuffer,
487                                           const gl::Rectangle &renderArea,
488                                           const vk::RenderPassDesc &renderPassDesc,
489                                           const vk::AttachmentOpsArray &renderPassAttachmentOps,
490                                           const vk::ClearValuesArray &clearValues,
491                                           vk::CommandBuffer **commandBufferOut);
492 
hasStartedRenderPass()493     bool hasStartedRenderPass() const { return !mRenderPassCommands->empty(); }
494 
getStartedRenderPassCommands()495     vk::CommandBufferHelper &getStartedRenderPassCommands()
496     {
497         ASSERT(hasStartedRenderPass());
498         return *mRenderPassCommands;
499     }
500 
getContextPriority()501     egl::ContextPriority getContextPriority() const override { return mContextPriority; }
502     angle::Result startRenderPass(gl::Rectangle renderArea, vk::CommandBuffer **commandBufferOut);
503     angle::Result endRenderPass();
504 
505     angle::Result syncExternalMemory();
506 
507     void addCommandBufferDiagnostics(const std::string &commandBufferDiagnostics);
508 
509     VkIndexType getVkIndexType(gl::DrawElementsType glIndexType) const;
510     size_t getVkIndexTypeSize(gl::DrawElementsType glIndexType) const;
511     bool shouldConvertUint8VkIndexType(gl::DrawElementsType glIndexType) const;
512 
isBresenhamEmulationEnabled(const gl::PrimitiveMode mode)513     ANGLE_INLINE bool isBresenhamEmulationEnabled(const gl::PrimitiveMode mode)
514     {
515         return getFeatures().basicGLLineRasterization.enabled && gl::IsLineMode(mode);
516     }
517 
getExecutable()518     const ProgramExecutableVk *getExecutable() const { return mExecutable; }
getExecutable()519     ProgramExecutableVk *getExecutable() { return mExecutable; }
520 
521     bool isRobustResourceInitEnabled() const override;
522 
523     // occlusion query
524     void beginOcclusionQuery(QueryVk *queryVk);
525     void endOcclusionQuery(QueryVk *queryVk);
526 
527     void updateOverlayOnPresent();
528 
529     // Submit commands to worker thread for processing
queueCommandsToWorker(const vk::CommandProcessorTask & commands)530     ANGLE_INLINE void queueCommandsToWorker(const vk::CommandProcessorTask &commands)
531     {
532         mRenderer->queueCommands(commands);
533     }
534     // When worker thread completes, it releases command buffers back to context queue
535     void recycleCommandBuffer(vk::CommandBufferHelper *commandBuffer);
536 
537   private:
538     // Dirty bits.
539     enum DirtyBitType : size_t
540     {
541         DIRTY_BIT_DEFAULT_ATTRIBS,
542         DIRTY_BIT_PIPELINE,
543         DIRTY_BIT_TEXTURES,
544         DIRTY_BIT_VERTEX_BUFFERS,
545         DIRTY_BIT_INDEX_BUFFER,
546         DIRTY_BIT_DRIVER_UNIFORMS,
547         DIRTY_BIT_DRIVER_UNIFORMS_BINDING,
548         DIRTY_BIT_SHADER_RESOURCES,  // excluding textures, which are handled separately.
549         DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS,
550         DIRTY_BIT_TRANSFORM_FEEDBACK_STATE,
551         DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME,
552         DIRTY_BIT_DESCRIPTOR_SETS,
553         DIRTY_BIT_MAX,
554     };
555 
556     using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
557 
558     using DirtyBitHandler = angle::Result (ContextVk::*)(const gl::Context *,
559                                                          vk::CommandBuffer *commandBuffer);
560 
561     struct DriverUniformsDescriptorSet
562     {
563         vk::DynamicBuffer dynamicBuffer;
564         VkDescriptorSet descriptorSet;
565         uint32_t dynamicOffset;
566         vk::BindingPointer<vk::DescriptorSetLayout> descriptorSetLayout;
567         vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
568 
569         DriverUniformsDescriptorSet();
570         ~DriverUniformsDescriptorSet();
571 
572         void init(RendererVk *rendererVk);
573         void destroy(RendererVk *rendererVk);
574     };
575 
576     enum class PipelineType
577     {
578         Graphics = 0,
579         Compute  = 1,
580 
581         InvalidEnum = 2,
582         EnumCount   = 2,
583     };
584 
585     // The GpuEventQuery struct holds together a timestamp query and enough data to create a
586     // trace event based on that. Use traceGpuEvent to insert such queries.  They will be readback
587     // when the results are available, without inserting a GPU bubble.
588     //
589     // - eventName will be the reported name of the event
590     // - phase is either 'B' (duration begin), 'E' (duration end) or 'i' (instant // event).
591     //   See Google's "Trace Event Format":
592     //   https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU
593     // - serial is the serial of the batch the query was submitted on.  Until the batch is
594     //   submitted, the query is not checked to avoid incuring a flush.
595     struct GpuEventQuery final
596     {
597         EventName name;
598         char phase;
599         vk::QueryHelper queryHelper;
600     };
601 
602     // Once a query result is available, the timestamp is read and a GpuEvent object is kept until
603     // the next clock sync, at which point the clock drift is compensated in the results before
604     // handing them off to the application.
605     struct GpuEvent final
606     {
607         uint64_t gpuTimestampCycles;
608         std::array<char, kMaxGpuEventNameLen> name;
609         char phase;
610     };
611 
612     struct GpuClockSyncInfo
613     {
614         double gpuTimestampS;
615         double cpuTimestampS;
616     };
617 
618     angle::Result setupDraw(const gl::Context *context,
619                             gl::PrimitiveMode mode,
620                             GLint firstVertexOrInvalid,
621                             GLsizei vertexOrIndexCount,
622                             GLsizei instanceCount,
623                             gl::DrawElementsType indexTypeOrInvalid,
624                             const void *indices,
625                             DirtyBits dirtyBitMask,
626                             vk::CommandBuffer **commandBufferOut);
627     angle::Result setupIndexedDraw(const gl::Context *context,
628                                    gl::PrimitiveMode mode,
629                                    GLsizei indexCount,
630                                    GLsizei instanceCount,
631                                    gl::DrawElementsType indexType,
632                                    const void *indices,
633                                    vk::CommandBuffer **commandBufferOut);
634     angle::Result setupIndirectDraw(const gl::Context *context,
635                                     gl::PrimitiveMode mode,
636                                     DirtyBits dirtyBitMask,
637                                     vk::BufferHelper *indirectBuffer,
638                                     VkDeviceSize indirectBufferOffset,
639                                     vk::CommandBuffer **commandBufferOut);
640     angle::Result setupIndexedIndirectDraw(const gl::Context *context,
641                                            gl::PrimitiveMode mode,
642                                            gl::DrawElementsType indexType,
643                                            vk::BufferHelper *indirectBuffer,
644                                            VkDeviceSize indirectBufferOffset,
645                                            vk::CommandBuffer **commandBufferOut);
646 
647     angle::Result setupLineLoopIndexedIndirectDraw(const gl::Context *context,
648                                                    gl::PrimitiveMode mode,
649                                                    gl::DrawElementsType indexType,
650                                                    vk::BufferHelper *srcIndirectBuf,
651                                                    VkDeviceSize indirectBufferOffset,
652                                                    vk::CommandBuffer **commandBufferOut,
653                                                    vk::BufferHelper **indirectBufferOut,
654                                                    VkDeviceSize *indirectBufferOffsetOut);
655     angle::Result setupLineLoopIndirectDraw(const gl::Context *context,
656                                             gl::PrimitiveMode mode,
657                                             vk::BufferHelper *indirectBuffer,
658                                             VkDeviceSize indirectBufferOffset,
659                                             vk::CommandBuffer **commandBufferOut,
660                                             vk::BufferHelper **indirectBufferOut,
661                                             VkDeviceSize *indirectBufferOffsetOut);
662 
663     angle::Result setupLineLoopDraw(const gl::Context *context,
664                                     gl::PrimitiveMode mode,
665                                     GLint firstVertex,
666                                     GLsizei vertexOrIndexCount,
667                                     gl::DrawElementsType indexTypeOrInvalid,
668                                     const void *indices,
669                                     vk::CommandBuffer **commandBufferOut,
670                                     uint32_t *numIndicesOut);
671     angle::Result setupDispatch(const gl::Context *context, vk::CommandBuffer **commandBufferOut);
672 
673     gl::Rectangle getCorrectedViewport(const gl::Rectangle &viewport) const;
674     void updateViewport(FramebufferVk *framebufferVk,
675                         const gl::Rectangle &viewport,
676                         float nearPlane,
677                         float farPlane,
678                         bool invertViewport);
679     void updateDepthRange(float nearPlane, float farPlane);
680     void updateFlipViewportDrawFramebuffer(const gl::State &glState);
681     void updateFlipViewportReadFramebuffer(const gl::State &glState);
682     void updateSurfaceRotationDrawFramebuffer(const gl::State &glState);
683     void updateSurfaceRotationReadFramebuffer(const gl::State &glState);
684 
685     angle::Result updateActiveTextures(const gl::Context *context);
686     angle::Result updateActiveImages(const gl::Context *context,
687                                      vk::CommandBufferHelper *commandBufferHelper);
688     angle::Result updateDefaultAttribute(size_t attribIndex);
689 
invalidateCurrentGraphicsPipeline()690     ANGLE_INLINE void invalidateCurrentGraphicsPipeline()
691     {
692         mGraphicsDirtyBits |= mNewGraphicsPipelineDirtyBits;
693         // The draw mode may have changed, toggling whether line rasterization is
694         // enabled or not, which means we need to recreate the graphics pipeline.
695         mCurrentGraphicsPipeline = nullptr;
696     }
invalidateCurrentComputePipeline()697     ANGLE_INLINE void invalidateCurrentComputePipeline()
698     {
699         mComputeDirtyBits.set(DIRTY_BIT_PIPELINE);
700         mCurrentComputePipeline = nullptr;
701     }
702 
703     void invalidateCurrentDefaultUniforms();
704     angle::Result invalidateCurrentTextures(const gl::Context *context);
705     void invalidateCurrentShaderResources();
706     void invalidateGraphicsDriverUniforms();
707     void invalidateDriverUniforms();
708 
709     // Handlers for graphics pipeline dirty bits.
710     angle::Result handleDirtyGraphicsDefaultAttribs(const gl::Context *context,
711                                                     vk::CommandBuffer *commandBuffer);
712     angle::Result handleDirtyGraphicsPipeline(const gl::Context *context,
713                                               vk::CommandBuffer *commandBuffer);
714     angle::Result handleDirtyGraphicsTextures(const gl::Context *context,
715                                               vk::CommandBuffer *commandBuffer);
716     angle::Result handleDirtyGraphicsVertexBuffers(const gl::Context *context,
717                                                    vk::CommandBuffer *commandBuffer);
718     angle::Result handleDirtyGraphicsIndexBuffer(const gl::Context *context,
719                                                  vk::CommandBuffer *commandBuffer);
720     angle::Result handleDirtyGraphicsDriverUniforms(const gl::Context *context,
721                                                     vk::CommandBuffer *commandBuffer);
722     angle::Result handleDirtyGraphicsDriverUniformsBinding(const gl::Context *context,
723                                                            vk::CommandBuffer *commandBuffer);
724     angle::Result handleDirtyGraphicsShaderResources(const gl::Context *context,
725                                                      vk::CommandBuffer *commandBuffer);
726     angle::Result handleDirtyGraphicsTransformFeedbackBuffersEmulation(
727         const gl::Context *context,
728         vk::CommandBuffer *commandBuffer);
729     angle::Result handleDirtyGraphicsTransformFeedbackBuffersExtension(
730         const gl::Context *context,
731         vk::CommandBuffer *commandBuffer);
732     angle::Result handleDirtyGraphicsTransformFeedbackState(const gl::Context *context,
733                                                             vk::CommandBuffer *commandBuffer);
734     angle::Result handleDirtyGraphicsTransformFeedbackResume(const gl::Context *context,
735                                                              vk::CommandBuffer *commandBuffer);
736 
737     // Handlers for compute pipeline dirty bits.
738     angle::Result handleDirtyComputePipeline(const gl::Context *context,
739                                              vk::CommandBuffer *commandBuffer);
740     angle::Result handleDirtyComputeTextures(const gl::Context *context,
741                                              vk::CommandBuffer *commandBuffer);
742     angle::Result handleDirtyComputeDriverUniforms(const gl::Context *context,
743                                                    vk::CommandBuffer *commandBuffer);
744     angle::Result handleDirtyComputeDriverUniformsBinding(const gl::Context *context,
745                                                           vk::CommandBuffer *commandBuffer);
746     angle::Result handleDirtyComputeShaderResources(const gl::Context *context,
747                                                     vk::CommandBuffer *commandBuffer);
748 
749     // Common parts of the common dirty bit handlers.
750     angle::Result handleDirtyTexturesImpl(vk::CommandBufferHelper *commandBufferHelper);
751     angle::Result handleDirtyShaderResourcesImpl(const gl::Context *context,
752                                                  vk::CommandBufferHelper *commandBufferHelper);
753     void handleDirtyDriverUniformsBindingImpl(vk::CommandBuffer *commandBuffer,
754                                               VkPipelineBindPoint bindPoint,
755                                               const DriverUniformsDescriptorSet &driverUniforms);
756     angle::Result handleDirtyDescriptorSets(const gl::Context *context,
757                                             vk::CommandBuffer *commandBuffer);
758     angle::Result allocateDriverUniforms(size_t driverUniformsSize,
759                                          DriverUniformsDescriptorSet *driverUniforms,
760                                          VkBuffer *bufferOut,
761                                          uint8_t **ptrOut,
762                                          bool *newBufferOut);
763     angle::Result updateDriverUniformsDescriptorSet(VkBuffer buffer,
764                                                     bool newBuffer,
765                                                     size_t driverUniformsSize,
766                                                     DriverUniformsDescriptorSet *driverUniforms);
767 
768     void writeAtomicCounterBufferDriverUniformOffsets(uint32_t *offsetsOut, size_t offsetsSize);
769 
770     angle::Result submitFrame(const VkSubmitInfo &submitInfo,
771                               vk::PrimaryCommandBuffer &&commandBuffer);
772     angle::Result memoryBarrierImpl(GLbitfield barriers, VkPipelineStageFlags stageMask);
773 
774     angle::Result synchronizeCpuGpuTime();
775     angle::Result traceGpuEventImpl(vk::CommandBuffer *commandBuffer,
776                                     char phase,
777                                     const EventName &name);
778     angle::Result checkCompletedGpuEvents();
779     void flushGpuEvents(double nextSyncGpuTimestampS, double nextSyncCpuTimestampS);
780     void handleDeviceLost();
781     void waitForSwapchainImageIfNecessary();
782     bool shouldEmulateSeamfulCubeMapSampling() const;
783     bool shouldUseOldRewriteStructSamplers() const;
784     void clearAllGarbage();
785     angle::Result ensureSubmitFenceInitialized();
786     angle::Result startPrimaryCommandBuffer();
787     bool hasRecordedCommands();
788     void dumpCommandStreamDiagnostics();
789     angle::Result flushOutsideRenderPassCommands();
790 
onRenderPassFinished()791     ANGLE_INLINE void onRenderPassFinished() { mRenderPassCommandBuffer = nullptr; }
792 
793     angle::Result onBufferRead(VkAccessFlags readAccessType,
794                                vk::PipelineStage readStage,
795                                vk::BufferHelper *buffer);
796     angle::Result onBufferWrite(VkAccessFlags writeAccessType,
797                                 vk::PipelineStage writeStage,
798                                 vk::BufferHelper *buffer);
799 
800     void initIndexTypeMap();
801 
802     // Pull an available CBH ptr from the CBH queue and set to specified hasRenderPass state
803     void getNextAvailableCommandBuffer(vk::CommandBufferHelper **commandBuffer, bool hasRenderPass);
804 
805     std::array<DirtyBitHandler, DIRTY_BIT_MAX> mGraphicsDirtyBitHandlers;
806     std::array<DirtyBitHandler, DIRTY_BIT_MAX> mComputeDirtyBitHandlers;
807 
808     vk::CommandBuffer *mRenderPassCommandBuffer;
809 
810     vk::PipelineHelper *mCurrentGraphicsPipeline;
811     vk::PipelineAndSerial *mCurrentComputePipeline;
812     gl::PrimitiveMode mCurrentDrawMode;
813 
814     WindowSurfaceVk *mCurrentWindowSurface;
815     // Records the current rotation of the surface (draw/read) framebuffer, derived from
816     // mCurrentWindowSurface->getPreTransform().
817     SurfaceRotation mCurrentRotationDrawFramebuffer;
818     SurfaceRotation mCurrentRotationReadFramebuffer;
819 
820     // Keep a cached pipeline description structure that can be used to query the pipeline cache.
821     // Kept in a pointer so allocations can be aligned, and structs can be portably packed.
822     std::unique_ptr<vk::GraphicsPipelineDesc> mGraphicsPipelineDesc;
823     vk::GraphicsPipelineTransitionBits mGraphicsPipelineTransition;
824 
825     // These pools are externally sychronized, so cannot be accessed from different
826     // threads simultaneously. Hence, we keep them in the ContextVk instead of the RendererVk.
827     // Note that this implementation would need to change in shared resource scenarios. Likely
828     // we'd instead share a single set of pools between the share groups.
829     vk::DynamicDescriptorPool mDriverUniformsDescriptorPool;
830     angle::PackedEnumMap<gl::QueryType, vk::DynamicQueryPool> mQueryPools;
831 
832     // Dirty bits.
833     DirtyBits mGraphicsDirtyBits;
834     DirtyBits mComputeDirtyBits;
835     DirtyBits mNonIndexedDirtyBitsMask;
836     DirtyBits mIndexedDirtyBitsMask;
837     DirtyBits mNewGraphicsCommandBufferDirtyBits;
838     DirtyBits mNewComputeCommandBufferDirtyBits;
839     DirtyBits mNewGraphicsPipelineDirtyBits;
840 
841     // Cached back-end objects.
842     VertexArrayVk *mVertexArray;
843     FramebufferVk *mDrawFramebuffer;
844     ProgramVk *mProgram;
845     ProgramPipelineVk *mProgramPipeline;
846     ProgramExecutableVk *mExecutable;
847 
848     // occlusion query
849     QueryVk *mActiveQueryAnySamples;
850     QueryVk *mActiveQueryAnySamplesConservative;
851 
852     // Graph resource used to record dispatch commands and hold resource dependencies.
853     vk::DispatchHelper mDispatcher;
854 
855     // The offset we had the last time we bound the index buffer.
856     const GLvoid *mLastIndexBufferOffset;
857     gl::DrawElementsType mCurrentDrawElementsType;
858     angle::PackedEnumMap<gl::DrawElementsType, VkIndexType> mIndexTypeMap;
859 
860     // Cache the current draw call's firstVertex to be passed to
861     // TransformFeedbackVk::getBufferOffsets.  Unfortunately, gl_BaseVertex support in Vulkan is
862     // not yet ubiquitous, which would have otherwise removed the need for this value to be passed
863     // as a uniform.
864     GLint mXfbBaseVertex;
865     // Cache the current draw call's vertex count as well to support instanced draw calls
866     GLuint mXfbVertexCountPerInstance;
867 
868     // Cached clear value/mask for color and depth/stencil.
869     VkClearValue mClearColorValue;
870     VkClearValue mClearDepthStencilValue;
871     VkColorComponentFlags mClearColorMask;
872 
873     IncompleteTextureSet mIncompleteTextures;
874 
875     // If the current surface bound to this context wants to have all rendering flipped vertically.
876     // Updated on calls to onMakeCurrent.
877     bool mFlipYForCurrentSurface;
878     bool mFlipViewportForDrawFramebuffer;
879     bool mFlipViewportForReadFramebuffer;
880 
881     // If any host-visible buffer is written by the GPU since last submission, a barrier is inserted
882     // at the end of the command buffer to make that write available to the host.
883     bool mIsAnyHostVisibleBufferWritten;
884 
885     // Whether this context should do seamful cube map sampling emulation.
886     bool mEmulateSeamfulCubeMapSampling;
887 
888     // Whether this context should use the old version of the
889     // RewriteStructSamplers pass.
890     bool mUseOldRewriteStructSamplers;
891 
892     angle::PackedEnumMap<PipelineType, DriverUniformsDescriptorSet> mDriverUniforms;
893 
894     // This cache should also probably include the texture index (shader location) and array
895     // index (also in the shader). This info is used in the descriptor update step.
896     gl::ActiveTextureArray<vk::TextureUnit> mActiveTextures;
897     vk::TextureDescriptorDesc mActiveTexturesDesc;
898 
899     gl::ActiveTextureArray<TextureVk *> mActiveImages;
900 
901     // "Current Value" aka default vertex attribute state.
902     gl::AttributesMask mDirtyDefaultAttribsMask;
903     gl::AttribArray<vk::DynamicBuffer> mDefaultAttribBuffers;
904 
905     // We use a single pool for recording commands. We also keep a free list for pool recycling.
906     vk::CommandPool mCommandPool;
907 
908     CommandQueue mCommandQueue;
909     vk::GarbageList mCurrentGarbage;
910 
911     RenderPassCache mRenderPassCache;
912 
913     // mSubmitFence is the fence that's going to be signaled at the next submission.  This is used
914     // to support SyncVk objects, which may outlive the context (as EGLSync objects).
915     //
916     // TODO(geofflang): this is in preparation for moving RendererVk functionality to ContextVk, and
917     // is otherwise unnecessary as the SyncVk objects don't actually outlive the renderer currently.
918     // http://anglebug.com/2701
919     vk::Shared<vk::Fence> mSubmitFence;
920 
921     // When the command graph is disabled we record commands completely linearly. We have plans to
922     //  reorder independent draws so that we can create fewer RenderPasses in some scenarios.
923     // We have a queue of CommandBufferHelpers (CBHs) that is drawn from for the two active command
924     //  buffers in the main thread. The two active command buffers are the inside and outside
925     //  RenderPass command buffers.
926     constexpr static size_t kNumCommandBuffers = 2;
927     std::array<vk::CommandBufferHelper, kNumCommandBuffers> mCommandBuffers;
928 
929     // Lock access to the command buffer queue
930     std::mutex mCommandBufferQueueMutex;
931     std::queue<vk::CommandBufferHelper *> mAvailableCommandBuffers;
932     std::condition_variable mAvailableCommandBufferCondition;
933 
934     vk::CommandBufferHelper *mOutsideRenderPassCommands;
935     vk::CommandBufferHelper *mRenderPassCommands;
936     vk::PrimaryCommandBuffer mPrimaryCommands;
937     // Function recycleCommandBuffer() is public above
938     bool mHasPrimaryCommands;
939 
940     // Internal shader library.
941     vk::ShaderLibrary mShaderLibrary;
942     UtilsVk mUtils;
943 
944     bool mGpuEventsEnabled;
945     vk::DynamicQueryPool mGpuEventQueryPool;
946     // A list of queries that have yet to be turned into an event (their result is not yet
947     // available).
948     std::vector<GpuEventQuery> mInFlightGpuEventQueries;
949     // A list of gpu events since the last clock sync.
950     std::vector<GpuEvent> mGpuEvents;
951 
952     // Semaphores that must be waited on in the next submission.
953     std::vector<VkSemaphore> mWaitSemaphores;
954     std::vector<VkPipelineStageFlags> mWaitSemaphoreStageMasks;
955 
956     // Hold information from the last gpu clock sync for future gpu-to-cpu timestamp conversions.
957     GpuClockSyncInfo mGpuClockSync;
958 
959     // The very first timestamp queried for a GPU event is used as origin, so event timestamps would
960     // have a value close to zero, to avoid losing 12 bits when converting these 64 bit values to
961     // double.
962     uint64_t mGpuEventTimestampOrigin;
963 
964     // Used to count events for tracing.
965     uint32_t mPrimaryBufferCounter;
966     uint32_t mRenderPassCounter;
967 
968     // Generators for texture & framebuffer serials.
969     SerialFactory mTextureSerialFactory;
970     SerialFactory mAttachmentImageSerialFactory;
971 
972     gl::State::DirtyBits mPipelineDirtyBitsMask;
973 
974     // List of all resources currently being used by this ContextVk's recorded commands.
975     vk::ResourceUseList mResourceUseList;
976 
977     egl::ContextPriority mContextPriority;
978 
979     std::vector<std::string> mCommandBufferDiagnostics;
980 };
981 }  // namespace rx
982 
983 #endif  // LIBANGLE_RENDERER_VULKAN_CONTEXTVK_H_
984