xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/vk_helpers.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2018 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 // vk_helpers:
7 //   Helper utility classes that manage Vulkan resources.
8 
9 #ifndef LIBANGLE_RENDERER_VULKAN_VK_HELPERS_H_
10 #define LIBANGLE_RENDERER_VULKAN_VK_HELPERS_H_
11 
12 #include "common/MemoryBuffer.h"
13 #include "common/SimpleMutex.h"
14 #include "libANGLE/renderer/vulkan/MemoryTracking.h"
15 #include "libANGLE/renderer/vulkan/Suballocation.h"
16 #include "libANGLE/renderer/vulkan/vk_cache_utils.h"
17 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
18 #include "libANGLE/renderer/vulkan/vk_ref_counted_event.h"
19 
20 #include <functional>
21 
22 namespace gl
23 {
24 class ImageIndex;
25 }  // namespace gl
26 
27 namespace rx
28 {
29 namespace vk
30 {
31 constexpr VkBufferUsageFlags kVertexBufferUsageFlags =
32     VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
33 constexpr VkBufferUsageFlags kIndexBufferUsageFlags =
34     VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
35 constexpr VkBufferUsageFlags kIndirectBufferUsageFlags =
36     VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
37 constexpr size_t kVertexBufferAlignment   = 4;
38 constexpr size_t kIndexBufferAlignment    = 4;
39 constexpr size_t kIndirectBufferAlignment = 4;
40 
41 constexpr VkBufferUsageFlags kStagingBufferFlags =
42     VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
43 constexpr size_t kStagingBufferSize = 1024 * 16;
44 
45 constexpr VkImageCreateFlags kVkImageCreateFlagsNone = 0;
46 
47 // Most likely initial chroma filter mode given GL_TEXTURE_EXTERNAL_OES default
48 // min & mag filters are linear.
49 constexpr VkFilter kDefaultYCbCrChromaFilter = VK_FILTER_LINEAR;
50 
51 constexpr VkPipelineStageFlags kSwapchainAcquireImageWaitStageFlags =
52     VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |          // First use is a blit command.
53     VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |  // First use is a draw command.
54     VK_PIPELINE_STAGE_TRANSFER_BIT;                  // First use is a clear without scissor.
55 
56 // For each level, write  layers that don't conflict in parallel.  The layer is hashed to
57 // `layer % kMaxParallelLayerWrites` and used to track whether that subresource is currently
58 // being written.  If so, a barrier is inserted; otherwise, the barrier is avoided.  If the updated
59 // layer count is greater than kMaxParallelLayerWrites, there will be a few unnecessary
60 // barriers.
61 constexpr uint32_t kMaxParallelLayerWrites = 64;
62 using ImageLayerWriteMask                  = std::bitset<kMaxParallelLayerWrites>;
63 
64 using StagingBufferOffsetArray = std::array<VkDeviceSize, 2>;
65 
66 // Imagine an image going through a few layout transitions:
67 //
68 //           srcStage 1    dstStage 2          srcStage 2     dstStage 3
69 //  Layout 1 ------Transition 1-----> Layout 2 ------Transition 2------> Layout 3
70 //           srcAccess 1  dstAccess 2          srcAccess 2   dstAccess 3
71 //   \_________________  ___________________/
72 //                     \/
73 //               A transition
74 //
75 // Every transition requires 6 pieces of information: from/to layouts, src/dst stage masks and
76 // src/dst access masks.  At the moment we decide to transition the image to Layout 2 (i.e.
77 // Transition 1), we need to have Layout 1, srcStage 1 and srcAccess 1 stored as history of the
78 // image.  To perform the transition, we need to know Layout 2, dstStage 2 and dstAccess 2.
79 // Additionally, we need to know srcStage 2 and srcAccess 2 to retain them for the next transition.
80 //
81 // That is, with the history kept, on every new transition we need 5 pieces of new information:
82 // layout/dstStage/dstAccess to transition into the layout, and srcStage/srcAccess for the future
83 // transition out from it.  Given the small number of possible combinations of these values, an
84 // enum is used were each value encapsulates these 5 pieces of information:
85 //
86 //                       +--------------------------------+
87 //           srcStage 1  | dstStage 2          srcStage 2 |   dstStage 3
88 //  Layout 1 ------Transition 1-----> Layout 2 ------Transition 2------> Layout 3
89 //           srcAccess 1 |dstAccess 2          srcAccess 2|  dstAccess 3
90 //                       +---------------  ---------------+
91 //                                       \/
92 //                                 One enum value
93 //
94 // Note that, while generally dstStage for the to-transition and srcStage for the from-transition
95 // are the same, they may occasionally be BOTTOM_OF_PIPE and TOP_OF_PIPE respectively.
96 enum class ImageLayout
97 {
98     Undefined = 0,
99     // Framebuffer attachment layouts are placed first, so they can fit in fewer bits in
100     // PackedAttachmentOpsDesc.
101 
102     // Color (Write):
103     ColorWrite,
104     // Used only with dynamic rendering, because it needs a different VkImageLayout
105     ColorWriteAndInput,
106     MSRTTEmulationColorUnresolveAndResolve,
107 
108     // Depth (Write), Stencil (Write)
109     DepthWriteStencilWrite,
110     // Used only with dynamic rendering, because it needs a different VkImageLayout.  For
111     // simplicity, depth/stencil attachments when used as input attachments don't attempt to
112     // distinguish read-only aspects.  That's only useful for supporting feedback loops, but if an
113     // application is reading depth or stencil through an input attachment, it's safe to assume they
114     // wouldn't be accessing the other aspect through a sampler!
115     DepthStencilWriteAndInput,
116 
117     // Depth (Write), Stencil (Read)
118     DepthWriteStencilRead,
119     DepthWriteStencilReadFragmentShaderStencilRead,
120     DepthWriteStencilReadAllShadersStencilRead,
121 
122     // Depth (Read), Stencil (Write)
123     DepthReadStencilWrite,
124     DepthReadStencilWriteFragmentShaderDepthRead,
125     DepthReadStencilWriteAllShadersDepthRead,
126 
127     // Depth (Read), Stencil (Read)
128     DepthReadStencilRead,
129     DepthReadStencilReadFragmentShaderRead,
130     DepthReadStencilReadAllShadersRead,
131 
132     // The GENERAL layout is used when there's a feedback loop.  For depth/stencil it does't matter
133     // which aspect is participating in feedback and whether the other aspect is read-only.
134     ColorWriteFragmentShaderFeedback,
135     ColorWriteAllShadersFeedback,
136     DepthStencilFragmentShaderFeedback,
137     DepthStencilAllShadersFeedback,
138 
139     // Depth/stencil resolve is special because it uses the _color_ output stage and mask
140     DepthStencilResolve,
141     MSRTTEmulationDepthStencilUnresolveAndResolve,
142 
143     Present,
144     SharedPresent,
145     // The rest of the layouts.
146     ExternalPreInitialized,
147     ExternalShadersReadOnly,
148     ExternalShadersWrite,
149     TransferSrc,
150     TransferDst,
151     TransferSrcDst,
152     // Used when the image is transitioned on the host for use by host image copy
153     HostCopy,
154     VertexShaderReadOnly,
155     VertexShaderWrite,
156     // PreFragment == Vertex, Tessellation and Geometry stages
157     PreFragmentShadersReadOnly,
158     PreFragmentShadersWrite,
159     FragmentShadingRateAttachmentReadOnly,
160     FragmentShaderReadOnly,
161     FragmentShaderWrite,
162     ComputeShaderReadOnly,
163     ComputeShaderWrite,
164     AllGraphicsShadersReadOnly,
165     AllGraphicsShadersWrite,
166     TransferDstAndComputeWrite,
167 
168     InvalidEnum,
169     EnumCount = InvalidEnum,
170 };
171 
172 VkImageCreateFlags GetImageCreateFlags(gl::TextureType textureType);
173 
174 ImageLayout GetImageLayoutFromGLImageLayout(Context *context, GLenum layout);
175 
176 GLenum ConvertImageLayoutToGLImageLayout(ImageLayout imageLayout);
177 
178 VkImageLayout ConvertImageLayoutToVkImageLayout(Renderer *renderer, ImageLayout imageLayout);
179 
180 // A dynamic buffer is conceptually an infinitely long buffer. Each time you write to the buffer,
181 // you will always write to a previously unused portion. After a series of writes, you must flush
182 // the buffer data to the device. Buffer lifetime currently assumes that each new allocation will
183 // last as long or longer than each prior allocation.
184 //
185 // Dynamic buffers are used to implement a variety of data streaming operations in Vulkan, such
186 // as for immediate vertex array and element array data, uniform updates, and other dynamic data.
187 //
188 // Internally dynamic buffers keep a collection of VkBuffers. When we write past the end of a
189 // currently active VkBuffer we keep it until it is no longer in use. We then mark it available
190 // for future allocations in a free list.
191 class BufferHelper;
192 using BufferHelperQueue = std::deque<std::unique_ptr<BufferHelper>>;
193 
194 class DynamicBuffer : angle::NonCopyable
195 {
196   public:
197     DynamicBuffer();
198     DynamicBuffer(DynamicBuffer &&other);
199     ~DynamicBuffer();
200 
201     void init(Renderer *renderer,
202               VkBufferUsageFlags usage,
203               size_t alignment,
204               size_t initialSize,
205               bool hostVisible);
206 
207     // This call will allocate a new region at the end of the current buffer. If it can't find
208     // enough space in the current buffer, it returns false. This gives caller a chance to deal with
209     // buffer switch that may occur with allocate call.
210     bool allocateFromCurrentBuffer(size_t sizeInBytes, BufferHelper **bufferHelperOut);
211 
212     // This call will allocate a new region at the end of the buffer with default alignment. It
213     // internally may trigger a new buffer to be created (which is returned in the optional
214     // parameter `newBufferAllocatedOut`). The new region will be in the returned buffer at given
215     // offset.
216     angle::Result allocate(Context *context,
217                            size_t sizeInBytes,
218                            BufferHelper **bufferHelperOut,
219                            bool *newBufferAllocatedOut);
220 
221     // This releases resources when they might currently be in use.
222     void release(Renderer *renderer);
223 
224     // This adds in-flight buffers to the mResourceUseList in the share group and then releases
225     // them.
226     void updateQueueSerialAndReleaseInFlightBuffers(ContextVk *contextVk,
227                                                     const QueueSerial &queueSerial);
228 
229     // This frees resources immediately.
230     void destroy(Renderer *renderer);
231 
getCurrentBuffer()232     BufferHelper *getCurrentBuffer() const { return mBuffer.get(); }
233 
234     // **Accumulate** an alignment requirement.  A dynamic buffer is used as the staging buffer for
235     // image uploads, which can contain updates to unrelated mips, possibly with different formats.
236     // The staging buffer should have an alignment that can satisfy all those formats, i.e. it's the
237     // lcm of all alignments set in its lifetime.
238     void requireAlignment(Renderer *renderer, size_t alignment);
getAlignment()239     size_t getAlignment() const { return mAlignment; }
240 
241     // For testing only!
242     void setMinimumSizeForTesting(size_t minSize);
243 
isCoherent()244     bool isCoherent() const
245     {
246         return (mMemoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0;
247     }
248 
valid()249     bool valid() const { return mSize != 0; }
250 
251   private:
252     void reset();
253     angle::Result allocateNewBuffer(Context *context);
254 
255     VkBufferUsageFlags mUsage;
256     bool mHostVisible;
257     size_t mInitialSize;
258     std::unique_ptr<BufferHelper> mBuffer;
259     uint32_t mNextAllocationOffset;
260     size_t mSize;
261     size_t mSizeInRecentHistory;
262     size_t mAlignment;
263     VkMemoryPropertyFlags mMemoryPropertyFlags;
264 
265     BufferHelperQueue mInFlightBuffers;
266     BufferHelperQueue mBufferFreeList;
267 };
268 
269 // Class DescriptorSetHelper. This is a wrapper of VkDescriptorSet with GPU resource use tracking.
270 using DescriptorPoolPointer     = SharedPtr<DescriptorPoolHelper>;
271 using DescriptorPoolWeakPointer = WeakPtr<DescriptorPoolHelper>;
272 class DescriptorSetHelper final : public Resource
273 {
274   public:
DescriptorSetHelper()275     DescriptorSetHelper() : mDescriptorSet(VK_NULL_HANDLE), mLastUsedFrame(0) {}
DescriptorSetHelper(const VkDescriptorSet & descriptorSet,const DescriptorPoolPointer & pool)276     DescriptorSetHelper(const VkDescriptorSet &descriptorSet, const DescriptorPoolPointer &pool)
277         : mDescriptorSet(descriptorSet), mPool(pool), mLastUsedFrame(0)
278     {}
DescriptorSetHelper(const ResourceUse & use,const VkDescriptorSet & descriptorSet,const DescriptorPoolPointer & pool)279     DescriptorSetHelper(const ResourceUse &use,
280                         const VkDescriptorSet &descriptorSet,
281                         const DescriptorPoolPointer &pool)
282         : mDescriptorSet(descriptorSet), mPool(pool), mLastUsedFrame(0)
283     {
284         mUse = use;
285     }
DescriptorSetHelper(DescriptorSetHelper && other)286     DescriptorSetHelper(DescriptorSetHelper &&other)
287         : Resource(std::move(other)),
288           mDescriptorSet(other.mDescriptorSet),
289           mPool(other.mPool),
290           mLastUsedFrame(other.mLastUsedFrame)
291     {
292         other.mDescriptorSet = VK_NULL_HANDLE;
293         other.mPool.reset();
294         other.mLastUsedFrame = 0;
295     }
296 
~DescriptorSetHelper()297     ~DescriptorSetHelper() override
298     {
299         ASSERT(mDescriptorSet == VK_NULL_HANDLE);
300         ASSERT(!mPool);
301     }
302 
303     void destroy(VkDevice device);
304 
getDescriptorSet()305     VkDescriptorSet getDescriptorSet() const { return mDescriptorSet; }
getPool()306     DescriptorPoolWeakPointer &getPool() { return mPool; }
307 
valid()308     bool valid() const { return mDescriptorSet != VK_NULL_HANDLE; }
309 
updateLastUsedFrame(uint32_t frame)310     void updateLastUsedFrame(uint32_t frame) { mLastUsedFrame = frame; }
getLastUsedFrame()311     uint32_t getLastUsedFrame() const { return mLastUsedFrame; }
312 
313   private:
314     VkDescriptorSet mDescriptorSet;
315     // So that DescriptorPoolHelper::resetGarbage can clear mPool weak pointer here
316     friend class DescriptorPoolHelper;
317     // We hold weak pointer here due to DynamicDescriptorPool::allocateNewPool() and
318     // DynamicDescriptorPool::checkAndReleaseUnusedPool() rely on pool's refcount to tell if it is
319     // eligible for eviction or not.
320     DescriptorPoolWeakPointer mPool;
321     // The frame that it was last used.
322     uint32_t mLastUsedFrame;
323 };
324 using DescriptorSetPointer = SharedPtr<DescriptorSetHelper>;
325 using DescriptorSetList    = std::deque<DescriptorSetPointer>;
326 
327 // Uses DescriptorPool to allocate descriptor sets as needed. If a descriptor pool becomes full, we
328 // allocate new pools internally as needed. Renderer takes care of the lifetime of the discarded
329 // pools. Note that we used a fixed layout for descriptor pools in ANGLE.
330 
331 // Shared handle to a descriptor pool. Each helper is allocated from the dynamic descriptor pool.
332 // Can be used to share descriptor pools between multiple ProgramVks and the ContextVk.
333 class DescriptorPoolHelper final : angle::NonCopyable
334 {
335   public:
336     DescriptorPoolHelper();
337     ~DescriptorPoolHelper();
338 
valid()339     bool valid() { return mDescriptorPool.valid(); }
340 
341     angle::Result init(Context *context,
342                        const std::vector<VkDescriptorPoolSize> &poolSizesIn,
343                        uint32_t maxSets);
344     void destroy(VkDevice device);
345 
346     bool allocateDescriptorSet(Context *context,
347                                const DescriptorSetLayout &descriptorSetLayout,
348                                const DescriptorPoolPointer &pool,
349                                DescriptorSetPointer *descriptorSetOut);
350 
addPendingGarbage(DescriptorSetPointer && garbage)351     void addPendingGarbage(DescriptorSetPointer &&garbage)
352     {
353         ASSERT(garbage.unique());
354         mValidDescriptorSets--;
355         mPendingGarbageList.emplace_back(std::move(garbage));
356     }
addFinishedGarbage(DescriptorSetPointer && garbage)357     void addFinishedGarbage(DescriptorSetPointer &&garbage)
358     {
359         ASSERT(garbage.unique());
360         mValidDescriptorSets--;
361         mFinishedGarbageList.emplace_back(std::move(garbage));
362     }
363     bool recycleFromGarbage(Renderer *renderer, DescriptorSetPointer *descriptorSetOut);
364     void destroyGarbage();
365     void cleanupPendingGarbage();
366 
hasValidDescriptorSet()367     bool hasValidDescriptorSet() const { return mValidDescriptorSets != 0; }
canDestroy()368     bool canDestroy() const { return mValidDescriptorSets == 0 && mPendingGarbageList.empty(); }
369 
370   private:
371     bool allocateVkDescriptorSet(Context *context,
372                                  const DescriptorSetLayout &descriptorSetLayout,
373                                  VkDescriptorSet *descriptorSetOut);
374 
375     Renderer *mRenderer;
376 
377     // The initial number of descriptorSets when the pool is created. This should equal to
378     // mValidDescriptorSets+mGarbageList.size()+mFreeDescriptorSets.
379     uint32_t mMaxDescriptorSets;
380     // Track the number of descriptorSets allocated out of this pool that are valid. DescriptorSets
381     // that have been allocated but in the mGarbageList is considered as invalid.
382     uint32_t mValidDescriptorSets;
383     // The number of remaining descriptorSets in the pool that remain to be allocated.
384     uint32_t mFreeDescriptorSets;
385 
386     DescriptorPool mDescriptorPool;
387 
388     // Keeps track descriptorSets that has been released. Because freeing descriptorSet require
389     // DescriptorPool, we store individually released descriptor sets here instead of usual garbage
390     // list in the renderer to avoid complicated threading issues and other weirdness associated
391     // with pooled object destruction. This list is mutually exclusive with mDescriptorSetCache.
392     DescriptorSetList mFinishedGarbageList;
393     DescriptorSetList mPendingGarbageList;
394 };
395 
396 class DynamicDescriptorPool final : angle::NonCopyable
397 {
398   public:
399     DynamicDescriptorPool();
400     ~DynamicDescriptorPool();
401 
402     DynamicDescriptorPool(DynamicDescriptorPool &&other);
403     DynamicDescriptorPool &operator=(DynamicDescriptorPool &&other);
404 
405     // The DynamicDescriptorPool only handles one pool size at this time.
406     // Note that setSizes[i].descriptorCount is expected to be the number of descriptors in
407     // an individual set.  The pool size will be calculated accordingly.
408     angle::Result init(Context *context,
409                        const VkDescriptorPoolSize *setSizes,
410                        size_t setSizeCount,
411                        const DescriptorSetLayout &descriptorSetLayout);
412 
413     void destroy(VkDevice device);
414 
valid()415     bool valid() const { return !mDescriptorPools.empty(); }
416 
417     // We use the descriptor type to help count the number of free sets.
418     // By convention, sets are indexed according to the constants in vk_cache_utils.h.
419     angle::Result allocateDescriptorSet(Context *context,
420                                         const DescriptorSetLayout &descriptorSetLayout,
421                                         DescriptorSetPointer *descriptorSetOut);
422 
423     angle::Result getOrAllocateDescriptorSet(Context *context,
424                                              uint32_t currentFrame,
425                                              const DescriptorSetDesc &desc,
426                                              const DescriptorSetLayout &descriptorSetLayout,
427                                              DescriptorSetPointer *descriptorSetOut,
428                                              SharedDescriptorSetCacheKey *sharedCacheKeyOut);
429 
430     void releaseCachedDescriptorSet(Renderer *renderer, const DescriptorSetDesc &desc);
431     void destroyCachedDescriptorSet(Renderer *renderer, const DescriptorSetDesc &desc);
432 
433     template <typename Accumulator>
accumulateDescriptorCacheStats(VulkanCacheType cacheType,Accumulator * accum)434     void accumulateDescriptorCacheStats(VulkanCacheType cacheType, Accumulator *accum) const
435     {
436         accum->accumulateCacheStats(cacheType, mCacheStats);
437     }
resetDescriptorCacheStats()438     void resetDescriptorCacheStats() { mCacheStats.resetHitAndMissCount(); }
getTotalCacheKeySizeBytes()439     size_t getTotalCacheKeySizeBytes() const
440     {
441         return mDescriptorSetCache.getTotalCacheKeySizeBytes();
442     }
443 
444     // Release the pool if it is no longer been used and contains no valid descriptorSet.
445     void destroyUnusedPool(Renderer *renderer, const DescriptorPoolWeakPointer &pool);
446     void checkAndDestroyUnusedPool(Renderer *renderer);
447 
448     // For testing only!
449     static uint32_t GetMaxSetsPerPoolForTesting();
450     static void SetMaxSetsPerPoolForTesting(uint32_t maxSetsPerPool);
451     static uint32_t GetMaxSetsPerPoolMultiplierForTesting();
452     static void SetMaxSetsPerPoolMultiplierForTesting(uint32_t maxSetsPerPool);
453 
454   private:
455     angle::Result allocateNewPool(Context *context);
456     bool allocateFromExistingPool(Context *context,
457                                   const DescriptorSetLayout &descriptorSetLayout,
458                                   DescriptorSetPointer *descriptorSetOut);
459     bool recycleFromGarbage(Renderer *renderer, DescriptorSetPointer *descriptorSetOut);
460     bool evictStaleDescriptorSets(Renderer *renderer,
461                                   uint32_t oldestFrameToKeep,
462                                   uint32_t currentFrame);
463 
464     static constexpr uint32_t kMaxSetsPerPoolMax = 512;
465     static uint32_t mMaxSetsPerPool;
466     static uint32_t mMaxSetsPerPoolMultiplier;
467     std::vector<DescriptorPoolPointer> mDescriptorPools;
468     std::vector<VkDescriptorPoolSize> mPoolSizes;
469     // This cached handle is used for verifying the layout being used to allocate descriptor sets
470     // from the pool matches the layout that the pool was created for, to ensure that the free
471     // descriptor count is accurate and new pools are created appropriately.
472     VkDescriptorSetLayout mCachedDescriptorSetLayout;
473 
474     // LRU list for cache eviction: most recent used at front, least used at back.
475     struct DescriptorSetLRUEntry
476     {
477         SharedDescriptorSetCacheKey sharedCacheKey;
478         DescriptorSetPointer descriptorSet;
479     };
480     using DescriptorSetLRUList         = std::list<DescriptorSetLRUEntry>;
481     using DescriptorSetLRUListIterator = DescriptorSetLRUList::iterator;
482     DescriptorSetLRUList mLRUList;
483     // Tracks cache for descriptorSet. Note that cached DescriptorSet can be reuse even if it is GPU
484     // busy.
485     DescriptorSetCache<DescriptorSetLRUListIterator> mDescriptorSetCache;
486     // Statistics for the cache.
487     CacheStats mCacheStats;
488 };
489 using DynamicDescriptorPoolPointer = SharedPtr<DynamicDescriptorPool>;
490 
491 // Maps from a descriptor set layout (represented by DescriptorSetLayoutDesc) to a set of
492 // DynamicDescriptorPools. The purpose of the class is so multiple GL Programs can share descriptor
493 // set caches. We need to stratify the sets by the descriptor set layout to ensure compatibility.
494 class MetaDescriptorPool final : angle::NonCopyable
495 {
496   public:
497     MetaDescriptorPool();
498     ~MetaDescriptorPool();
499 
500     void destroy(Renderer *renderer);
501 
502     angle::Result bindCachedDescriptorPool(Context *context,
503                                            const DescriptorSetLayoutDesc &descriptorSetLayoutDesc,
504                                            uint32_t descriptorCountMultiplier,
505                                            DescriptorSetLayoutCache *descriptorSetLayoutCache,
506                                            DynamicDescriptorPoolPointer *dynamicDescriptorPoolOut);
507 
508     template <typename Accumulator>
accumulateDescriptorCacheStats(VulkanCacheType cacheType,Accumulator * accum)509     void accumulateDescriptorCacheStats(VulkanCacheType cacheType, Accumulator *accum) const
510     {
511         for (const auto &iter : mPayload)
512         {
513             const vk::DynamicDescriptorPoolPointer &pool = iter.second;
514             pool->accumulateDescriptorCacheStats(cacheType, accum);
515         }
516     }
517 
resetDescriptorCacheStats()518     void resetDescriptorCacheStats()
519     {
520         for (auto &iter : mPayload)
521         {
522             vk::DynamicDescriptorPoolPointer &pool = iter.second;
523             pool->resetDescriptorCacheStats();
524         }
525     }
526 
getTotalCacheKeySizeBytes()527     size_t getTotalCacheKeySizeBytes() const
528     {
529         size_t totalSize = 0;
530 
531         for (const auto &iter : mPayload)
532         {
533             const DynamicDescriptorPoolPointer &pool = iter.second;
534             totalSize += pool->getTotalCacheKeySizeBytes();
535         }
536 
537         return totalSize;
538     }
539 
540   private:
541     std::unordered_map<DescriptorSetLayoutDesc, DynamicDescriptorPoolPointer> mPayload;
542 };
543 
544 template <typename Pool>
545 class DynamicallyGrowingPool : angle::NonCopyable
546 {
547   public:
548     DynamicallyGrowingPool();
549     virtual ~DynamicallyGrowingPool();
550 
isValid()551     bool isValid() { return mPoolSize > 0; }
552 
553   protected:
554     angle::Result initEntryPool(Context *contextVk, uint32_t poolSize);
555 
556     virtual void destroyPoolImpl(VkDevice device, Pool &poolToDestroy) = 0;
557     void destroyEntryPool(VkDevice device);
558 
559     // Checks to see if any pool is already free, in which case it sets it as current pool and
560     // returns true.
561     bool findFreeEntryPool(ContextVk *contextVk);
562 
563     // Allocates a new entry and initializes it with the given pool.
564     angle::Result allocateNewEntryPool(ContextVk *contextVk, Pool &&pool);
565 
566     // Called by the implementation whenever an entry is freed.
567     void onEntryFreed(ContextVk *contextVk, size_t poolIndex, const ResourceUse &use);
568 
getPool(size_t index)569     const Pool &getPool(size_t index) const
570     {
571         return const_cast<DynamicallyGrowingPool *>(this)->getPool(index);
572     }
573 
getPool(size_t index)574     Pool &getPool(size_t index)
575     {
576         ASSERT(index < mPools.size());
577         return mPools[index].pool;
578     }
579 
getPoolSize()580     uint32_t getPoolSize() const { return mPoolSize; }
581 
582     virtual angle::Result allocatePoolImpl(ContextVk *contextVk,
583                                            Pool &poolToAllocate,
584                                            uint32_t entriesToAllocate) = 0;
585     angle::Result allocatePoolEntries(ContextVk *contextVk,
586                                       uint32_t entryCount,
587                                       uint32_t *poolIndexOut,
588                                       uint32_t *currentEntryOut);
589 
590   private:
591     // The pool size, to know when a pool is completely freed.
592     uint32_t mPoolSize;
593 
594     struct PoolResource : public Resource
595     {
596         PoolResource(Pool &&poolIn, uint32_t freedCountIn);
597         PoolResource(PoolResource &&other);
598 
599         Pool pool;
600 
601         // A count corresponding to each pool indicating how many of its allocated entries
602         // have been freed. Once that value reaches mPoolSize for each pool, that pool is considered
603         // free and reusable.  While keeping a bitset would allow allocation of each index, the
604         // slight runtime overhead of finding free indices is not worth the slight memory overhead
605         // of creating new pools when unnecessary.
606         uint32_t freedCount;
607     };
608     std::vector<PoolResource> mPools;
609 
610     // Index into mPools indicating pool we are currently allocating from.
611     size_t mCurrentPool;
612     // Index inside mPools[mCurrentPool] indicating which index can be allocated next.
613     uint32_t mCurrentFreeEntry;
614 };
615 
616 // DynamicQueryPool allocates indices out of QueryPool as needed.  Once a QueryPool is exhausted,
617 // another is created.  The query pools live permanently, but are recycled as indices get freed.
618 
619 // These are arbitrary default sizes for query pools.
620 constexpr uint32_t kDefaultOcclusionQueryPoolSize           = 64;
621 constexpr uint32_t kDefaultTimestampQueryPoolSize           = 64;
622 constexpr uint32_t kDefaultTransformFeedbackQueryPoolSize   = 128;
623 constexpr uint32_t kDefaultPrimitivesGeneratedQueryPoolSize = 128;
624 
625 class QueryHelper;
626 
627 class DynamicQueryPool final : public DynamicallyGrowingPool<QueryPool>
628 {
629   public:
630     DynamicQueryPool();
631     ~DynamicQueryPool() override;
632 
633     angle::Result init(ContextVk *contextVk, VkQueryType type, uint32_t poolSize);
634     void destroy(VkDevice device);
635 
636     angle::Result allocateQuery(ContextVk *contextVk, QueryHelper *queryOut, uint32_t queryCount);
637     void freeQuery(ContextVk *contextVk, QueryHelper *query);
638 
getQueryPool(size_t index)639     const QueryPool &getQueryPool(size_t index) const { return getPool(index); }
640 
641   private:
642     angle::Result allocatePoolImpl(ContextVk *contextVk,
643                                    QueryPool &poolToAllocate,
644                                    uint32_t entriesToAllocate) override;
645     void destroyPoolImpl(VkDevice device, QueryPool &poolToDestroy) override;
646 
647     // Information required to create new query pools
648     VkQueryType mQueryType;
649 };
650 
651 // Stores the result of a Vulkan query call. XFB queries in particular store two result values.
652 class QueryResult final
653 {
654   public:
QueryResult(uint32_t intsPerResult)655     QueryResult(uint32_t intsPerResult) : mIntsPerResult(intsPerResult), mResults{} {}
656 
657     void operator+=(const QueryResult &rhs)
658     {
659         mResults[0] += rhs.mResults[0];
660         mResults[1] += rhs.mResults[1];
661     }
662 
getDataSize()663     size_t getDataSize() const { return mIntsPerResult * sizeof(uint64_t); }
664     void setResults(uint64_t *results, uint32_t queryCount);
getResult(size_t index)665     uint64_t getResult(size_t index) const
666     {
667         ASSERT(index < mIntsPerResult);
668         return mResults[index];
669     }
670 
671     static constexpr size_t kDefaultResultIndex                      = 0;
672     static constexpr size_t kTransformFeedbackPrimitivesWrittenIndex = 0;
673     static constexpr size_t kPrimitivesGeneratedIndex                = 1;
674 
675   private:
676     uint32_t mIntsPerResult;
677     std::array<uint64_t, 2> mResults;
678 };
679 
680 // Queries in Vulkan are identified by the query pool and an index for a query within that pool.
681 // Unlike other pools, such as descriptor pools where an allocation returns an independent object
682 // from the pool, the query allocations are not done through a Vulkan function and are only an
683 // integer index.
684 //
685 // Furthermore, to support arbitrarily large number of queries, DynamicQueryPool creates query pools
686 // of a fixed size as needed and allocates indices within those pools.
687 //
688 // The QueryHelper class below keeps the pool and index pair together.  For multiview, multiple
689 // consecutive query indices are implicitly written to by the driver, so the query count is
690 // additionally kept.
691 class QueryHelper final : public Resource
692 {
693   public:
694     QueryHelper();
695     ~QueryHelper() override;
696     QueryHelper(QueryHelper &&rhs);
697     QueryHelper &operator=(QueryHelper &&rhs);
698     void init(const DynamicQueryPool *dynamicQueryPool,
699               const size_t queryPoolIndex,
700               uint32_t query,
701               uint32_t queryCount);
702     void deinit();
703 
valid()704     bool valid() const { return mDynamicQueryPool != nullptr; }
705 
706     // Begin/end queries.  These functions break the render pass.
707     angle::Result beginQuery(ContextVk *contextVk);
708     angle::Result endQuery(ContextVk *contextVk);
709     // Begin/end queries within a started render pass.
710     angle::Result beginRenderPassQuery(ContextVk *contextVk);
711     void endRenderPassQuery(ContextVk *contextVk);
712 
713     angle::Result flushAndWriteTimestamp(ContextVk *contextVk);
714     // When syncing gpu/cpu time, main thread accesses primary directly
715     void writeTimestampToPrimary(ContextVk *contextVk, PrimaryCommandBuffer *primary);
716     // All other timestamp accesses should be made on outsideRenderPassCommandBuffer
717     void writeTimestamp(ContextVk *contextVk,
718                         OutsideRenderPassCommandBuffer *outsideRenderPassCommandBuffer);
719 
720     // Whether this query helper has generated and submitted any commands.
721     bool hasSubmittedCommands() const;
722 
723     angle::Result getUint64ResultNonBlocking(ContextVk *contextVk,
724                                              QueryResult *resultOut,
725                                              bool *availableOut);
726     angle::Result getUint64Result(ContextVk *contextVk, QueryResult *resultOut);
727 
728   private:
729     friend class DynamicQueryPool;
getQueryPool()730     const QueryPool &getQueryPool() const
731     {
732         ASSERT(valid());
733         return mDynamicQueryPool->getQueryPool(mQueryPoolIndex);
734     }
735 
736     // Reset needs to always be done outside a render pass, which may be different from the
737     // passed-in command buffer (which could be the render pass').
738     template <typename CommandBufferT>
739     void beginQueryImpl(ContextVk *contextVk,
740                         OutsideRenderPassCommandBuffer *resetCommandBuffer,
741                         CommandBufferT *commandBuffer);
742     template <typename CommandBufferT>
743     void endQueryImpl(ContextVk *contextVk, CommandBufferT *commandBuffer);
744     template <typename CommandBufferT>
745     void resetQueryPoolImpl(ContextVk *contextVk,
746                             const QueryPool &queryPool,
747                             CommandBufferT *commandBuffer);
748     VkResult getResultImpl(ContextVk *contextVk,
749                            const VkQueryResultFlags flags,
750                            QueryResult *resultOut);
751 
752     const DynamicQueryPool *mDynamicQueryPool;
753     size_t mQueryPoolIndex;
754     uint32_t mQuery;
755     uint32_t mQueryCount;
756 
757     enum class QueryStatus
758     {
759         Inactive,
760         Active,
761         Ended
762     };
763     QueryStatus mStatus;
764 };
765 
766 // Semaphores that are allocated from the semaphore pool are encapsulated in a helper object,
767 // keeping track of where in the pool they are allocated from.
768 class SemaphoreHelper final : angle::NonCopyable
769 {
770   public:
771     SemaphoreHelper();
772     ~SemaphoreHelper();
773 
774     SemaphoreHelper(SemaphoreHelper &&other);
775     SemaphoreHelper &operator=(SemaphoreHelper &&other);
776 
777     void init(const size_t semaphorePoolIndex, const Semaphore *semaphore);
778     void deinit();
779 
getSemaphore()780     const Semaphore *getSemaphore() const { return mSemaphore; }
781 
782     // Used only by DynamicSemaphorePool.
getSemaphorePoolIndex()783     size_t getSemaphorePoolIndex() const { return mSemaphorePoolIndex; }
784 
785   private:
786     size_t mSemaphorePoolIndex;
787     const Semaphore *mSemaphore;
788 };
789 
790 // This defines enum for VkPipelineStageFlagBits so that we can use it to compare and index into
791 // array.
792 enum class PipelineStage : uint32_t
793 {
794     // Bellow are ordered based on Graphics Pipeline Stages
795     TopOfPipe              = 0,
796     DrawIndirect           = 1,
797     VertexInput            = 2,
798     VertexShader           = 3,
799     TessellationControl    = 4,
800     TessellationEvaluation = 5,
801     GeometryShader         = 6,
802     TransformFeedback      = 7,
803     FragmentShadingRate    = 8,
804     EarlyFragmentTest      = 9,
805     FragmentShader         = 10,
806     LateFragmentTest       = 11,
807     ColorAttachmentOutput  = 12,
808 
809     // Compute specific pipeline Stage
810     ComputeShader = 13,
811 
812     // Transfer specific pipeline Stage
813     Transfer     = 14,
814     BottomOfPipe = 15,
815 
816     // Host specific pipeline stage
817     Host = 16,
818 
819     InvalidEnum = 17,
820     EnumCount   = InvalidEnum,
821 };
822 using PipelineStagesMask = angle::PackedEnumBitSet<PipelineStage, uint32_t>;
823 
824 PipelineStage GetPipelineStage(gl::ShaderType stage);
825 
826 struct ImageMemoryBarrierData
827 {
828     const char *name;
829 
830     // The Vk layout corresponding to the ImageLayout key.
831     VkImageLayout layout;
832 
833     // The stage in which the image is used (or Bottom/Top if not using any specific stage).  Unless
834     // Bottom/Top (Bottom used for transition to and Top used for transition from), the two values
835     // should match.
836     VkPipelineStageFlags dstStageMask;
837     VkPipelineStageFlags srcStageMask;
838     // Access mask when transitioning into this layout.
839     VkAccessFlags dstAccessMask;
840     // Access mask when transitioning out from this layout.  Note that source access mask never
841     // needs a READ bit, as WAR hazards don't need memory barriers (just execution barriers).
842     VkAccessFlags srcAccessMask;
843     // Read or write.
844     ResourceAccess type;
845     // *CommandBufferHelper track an array of PipelineBarriers. This indicates which array element
846     // this should be merged into. Right now we track individual barrier for every PipelineStage. If
847     // layout has a single stage mask bit, we use that stage as index. If layout has multiple stage
848     // mask bits, we pick the lowest stage as the index since it is the first stage that needs
849     // barrier.
850     PipelineStage barrierIndex;
851     EventStage eventStage;
852     // The pipeline stage flags group that used for heuristic.
853     PipelineStageGroup pipelineStageGroup;
854 };
855 // Initialize ImageLayout to ImageMemoryBarrierData mapping table.
856 void InitializeImageLayoutAndMemoryBarrierDataMap(
857     angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> *mapping,
858     VkPipelineStageFlags supportedVulkanPipelineStageMask);
859 bool EventAndPipelineBarrierHaveMatchingStageFlags(
860     const angle::PackedEnumMap<EventStage, VkPipelineStageFlags> &eventStageMap,
861     const angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> &barrierDataMap);
862 
863 // This wraps data and API for vkCmdPipelineBarrier call
864 class PipelineBarrier : angle::NonCopyable
865 {
866   public:
PipelineBarrier()867     PipelineBarrier()
868         : mSrcStageMask(0),
869           mDstStageMask(0),
870           mMemoryBarrierSrcAccess(0),
871           mMemoryBarrierDstAccess(0),
872           mImageMemoryBarriers()
873     {}
~PipelineBarrier()874     ~PipelineBarrier() { ASSERT(mImageMemoryBarriers.empty()); }
875 
isEmpty()876     bool isEmpty() const { return mImageMemoryBarriers.empty() && mMemoryBarrierDstAccess == 0; }
877 
execute(PrimaryCommandBuffer * primary)878     void execute(PrimaryCommandBuffer *primary)
879     {
880         if (isEmpty())
881         {
882             return;
883         }
884 
885         // Issue vkCmdPipelineBarrier call
886         VkMemoryBarrier memoryBarrier = {};
887         uint32_t memoryBarrierCount   = 0;
888         if (mMemoryBarrierDstAccess != 0)
889         {
890             memoryBarrier.sType         = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
891             memoryBarrier.srcAccessMask = mMemoryBarrierSrcAccess;
892             memoryBarrier.dstAccessMask = mMemoryBarrierDstAccess;
893             memoryBarrierCount++;
894         }
895         primary->pipelineBarrier(
896             mSrcStageMask, mDstStageMask, 0, memoryBarrierCount, &memoryBarrier, 0, nullptr,
897             static_cast<uint32_t>(mImageMemoryBarriers.size()), mImageMemoryBarriers.data());
898 
899         reset();
900     }
901 
902     // merge two barriers into one
merge(PipelineBarrier * other)903     void merge(PipelineBarrier *other)
904     {
905         mSrcStageMask |= other->mSrcStageMask;
906         mDstStageMask |= other->mDstStageMask;
907         mMemoryBarrierSrcAccess |= other->mMemoryBarrierSrcAccess;
908         mMemoryBarrierDstAccess |= other->mMemoryBarrierDstAccess;
909         mImageMemoryBarriers.insert(mImageMemoryBarriers.end(), other->mImageMemoryBarriers.begin(),
910                                     other->mImageMemoryBarriers.end());
911         other->reset();
912     }
913 
mergeMemoryBarrier(VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,VkAccessFlags srcAccess,VkAccessFlags dstAccess)914     void mergeMemoryBarrier(VkPipelineStageFlags srcStageMask,
915                             VkPipelineStageFlags dstStageMask,
916                             VkAccessFlags srcAccess,
917                             VkAccessFlags dstAccess)
918     {
919         mSrcStageMask |= srcStageMask;
920         mDstStageMask |= dstStageMask;
921         mMemoryBarrierSrcAccess |= srcAccess;
922         mMemoryBarrierDstAccess |= dstAccess;
923     }
924 
mergeImageBarrier(VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,const VkImageMemoryBarrier & imageMemoryBarrier)925     void mergeImageBarrier(VkPipelineStageFlags srcStageMask,
926                            VkPipelineStageFlags dstStageMask,
927                            const VkImageMemoryBarrier &imageMemoryBarrier)
928     {
929         ASSERT(imageMemoryBarrier.pNext == nullptr);
930         mSrcStageMask |= srcStageMask;
931         mDstStageMask |= dstStageMask;
932         mImageMemoryBarriers.push_back(imageMemoryBarrier);
933     }
934 
reset()935     void reset()
936     {
937         mSrcStageMask           = 0;
938         mDstStageMask           = 0;
939         mMemoryBarrierSrcAccess = 0;
940         mMemoryBarrierDstAccess = 0;
941         mImageMemoryBarriers.clear();
942     }
943 
944     void addDiagnosticsString(std::ostringstream &out) const;
945 
946   private:
947     VkPipelineStageFlags mSrcStageMask;
948     VkPipelineStageFlags mDstStageMask;
949     VkAccessFlags mMemoryBarrierSrcAccess;
950     VkAccessFlags mMemoryBarrierDstAccess;
951     std::vector<VkImageMemoryBarrier> mImageMemoryBarriers;
952 };
953 
954 class PipelineBarrierArray final
955 {
956   public:
mergeMemoryBarrier(PipelineStage stageIndex,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,VkAccessFlags srcAccess,VkAccessFlags dstAccess)957     void mergeMemoryBarrier(PipelineStage stageIndex,
958                             VkPipelineStageFlags srcStageMask,
959                             VkPipelineStageFlags dstStageMask,
960                             VkAccessFlags srcAccess,
961                             VkAccessFlags dstAccess)
962     {
963         mBarriers[stageIndex].mergeMemoryBarrier(srcStageMask, dstStageMask, srcAccess, dstAccess);
964         mBarrierMask.set(stageIndex);
965     }
966 
mergeImageBarrier(PipelineStage stageIndex,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,const VkImageMemoryBarrier & imageMemoryBarrier)967     void mergeImageBarrier(PipelineStage stageIndex,
968                            VkPipelineStageFlags srcStageMask,
969                            VkPipelineStageFlags dstStageMask,
970                            const VkImageMemoryBarrier &imageMemoryBarrier)
971     {
972         mBarriers[stageIndex].mergeImageBarrier(srcStageMask, dstStageMask, imageMemoryBarrier);
973         mBarrierMask.set(stageIndex);
974     }
975 
976     void execute(Renderer *renderer, PrimaryCommandBuffer *primary);
977 
978     void addDiagnosticsString(std::ostringstream &out) const;
979 
980   private:
981     angle::PackedEnumMap<PipelineStage, PipelineBarrier> mBarriers;
982     PipelineStagesMask mBarrierMask;
983 };
984 
985 enum class MemoryCoherency : uint8_t
986 {
987     CachedNonCoherent,
988     CachedPreferCoherent,
989     UnCachedCoherent,
990 
991     InvalidEnum = 3,
992     EnumCount   = 3,
993 };
IsCached(MemoryCoherency coherency)994 ANGLE_INLINE bool IsCached(MemoryCoherency coherency)
995 {
996     return coherency == MemoryCoherency::CachedNonCoherent ||
997            coherency == MemoryCoherency::CachedPreferCoherent;
998 }
999 
1000 class BufferPool;
1001 
1002 class BufferHelper : public ReadWriteResource
1003 {
1004   public:
1005     BufferHelper();
1006     ~BufferHelper() override;
1007 
1008     BufferHelper(BufferHelper &&other);
1009     BufferHelper &operator=(BufferHelper &&other);
1010 
1011     angle::Result init(Context *context,
1012                        const VkBufferCreateInfo &createInfo,
1013                        VkMemoryPropertyFlags memoryPropertyFlags);
1014     angle::Result initExternal(Context *context,
1015                                VkMemoryPropertyFlags memoryProperties,
1016                                const VkBufferCreateInfo &requestedCreateInfo,
1017                                GLeglClientBufferEXT clientBuffer);
1018     VkResult initSuballocation(Context *context,
1019                                uint32_t memoryTypeIndex,
1020                                size_t size,
1021                                size_t alignment,
1022                                BufferUsageType usageType,
1023                                BufferPool *pool);
1024 
1025     void destroy(Renderer *renderer);
1026     void release(Renderer *renderer);
1027     void releaseBufferAndDescriptorSetCache(Renderer *renderer);
1028 
getBufferSerial()1029     BufferSerial getBufferSerial() const { return mSerial; }
getBlockSerial()1030     BufferSerial getBlockSerial() const
1031     {
1032         ASSERT(mSuballocation.valid());
1033         return mSuballocation.getBlockSerial();
1034     }
getBufferBlock()1035     BufferBlock *getBufferBlock() const { return mSuballocation.getBufferBlock(); }
valid()1036     bool valid() const { return mSuballocation.valid(); }
getBuffer()1037     const Buffer &getBuffer() const { return mSuballocation.getBuffer(); }
getOffset()1038     VkDeviceSize getOffset() const { return mSuballocation.getOffset(); }
getSize()1039     VkDeviceSize getSize() const { return mSuballocation.getSize(); }
getMemoryPropertyFlags()1040     VkMemoryMapFlags getMemoryPropertyFlags() const
1041     {
1042         return mSuballocation.getMemoryPropertyFlags();
1043     }
getMappedMemory()1044     uint8_t *getMappedMemory() const
1045     {
1046         ASSERT(isMapped());
1047         return mSuballocation.getMappedMemory();
1048     }
1049     // Returns the main buffer block's pointer.
getBlockMemory()1050     uint8_t *getBlockMemory() const { return mSuballocation.getBlockMemory(); }
getBlockMemorySize()1051     VkDeviceSize getBlockMemorySize() const { return mSuballocation.getBlockMemorySize(); }
isHostVisible()1052     bool isHostVisible() const { return mSuballocation.isHostVisible(); }
isCoherent()1053     bool isCoherent() const { return mSuballocation.isCoherent(); }
isCached()1054     bool isCached() const { return mSuballocation.isCached(); }
isMapped()1055     bool isMapped() const { return mSuballocation.isMapped(); }
1056 
1057     angle::Result map(Context *context, uint8_t **ptrOut);
1058     angle::Result mapWithOffset(Context *context, uint8_t **ptrOut, size_t offset);
unmap(Renderer * renderer)1059     void unmap(Renderer *renderer) {}
1060     // After a sequence of writes, call flush to ensure the data is visible to the device.
1061     angle::Result flush(Renderer *renderer);
1062     angle::Result flush(Renderer *renderer, VkDeviceSize offset, VkDeviceSize size);
1063     // After a sequence of writes, call invalidate to ensure the data is visible to the host.
1064     angle::Result invalidate(Renderer *renderer);
1065     angle::Result invalidate(Renderer *renderer, VkDeviceSize offset, VkDeviceSize size);
1066 
1067     void changeQueueFamily(uint32_t srcQueueFamilyIndex,
1068                            uint32_t dstQueueFamilyIndex,
1069                            OutsideRenderPassCommandBuffer *commandBuffer);
1070 
1071     // Performs an ownership transfer from an external instance or API.
1072     void acquireFromExternal(DeviceQueueIndex externalQueueIndex,
1073                              DeviceQueueIndex newDeviceQueueIndex,
1074                              OutsideRenderPassCommandBuffer *commandBuffer);
1075 
1076     // Performs an ownership transfer to an external instance or API.
1077     void releaseToExternal(DeviceQueueIndex externalQueueIndex,
1078                            OutsideRenderPassCommandBuffer *commandBuffer);
1079 
1080     // Returns true if the image is owned by an external API or instance.
1081     bool isReleasedToExternal() const;
1082 
1083     void recordReadBarrier(VkAccessFlags readAccessType,
1084                            VkPipelineStageFlags readStage,
1085                            PipelineStage stageIndex,
1086                            PipelineBarrierArray *barriers);
1087 
1088     void recordWriteBarrier(VkAccessFlags writeAccessType,
1089                             VkPipelineStageFlags writeStage,
1090                             PipelineStage stageIndex,
1091                             PipelineBarrierArray *barriers);
1092 
1093     void fillWithColor(const angle::Color<uint8_t> &color,
1094                        const gl::InternalFormat &internalFormat);
1095 
1096     void fillWithPattern(const void *pattern, size_t patternSize, size_t offset, size_t size);
1097 
1098     // Special handling for VertexArray code so that we can create a dedicated VkBuffer for the
1099     // sub-range of memory of the actual buffer data size that user requested (i.e, excluding extra
1100     // paddings that we added for alignment, which will not get zero filled).
1101     const Buffer &getBufferForVertexArray(ContextVk *contextVk,
1102                                           VkDeviceSize actualDataSize,
1103                                           VkDeviceSize *offsetOut);
1104 
onNewDescriptorSet(const SharedDescriptorSetCacheKey & sharedCacheKey)1105     void onNewDescriptorSet(const SharedDescriptorSetCacheKey &sharedCacheKey)
1106     {
1107         mDescriptorSetCacheManager.addKey(sharedCacheKey);
1108     }
1109 
1110     angle::Result initializeNonZeroMemory(Context *context,
1111                                           VkBufferUsageFlags usage,
1112                                           VkDeviceSize size);
1113 
1114     // Buffer's user size and allocation size may be different due to alignment requirement. In
1115     // normal usage we just use the actual allocation size and it is good enough. But when
1116     // robustResourceInit is enabled, mBufferWithUserSize is created to match the exact user
1117     // size. Thus when user size changes, we must clear and recreate this mBufferWithUserSize.
1118     // Returns true if mBufferWithUserSize is released.
1119     bool onBufferUserSizeChange(Renderer *renderer);
1120 
1121     void initializeBarrierTracker(Context *context);
1122 
1123     // Returns the current VkAccessFlags bits
getCurrentWriteAccess()1124     VkAccessFlags getCurrentWriteAccess() const { return mCurrentWriteAccess; }
1125 
1126   private:
1127     // Only called by DynamicBuffer.
1128     friend class DynamicBuffer;
setSuballocationOffsetAndSize(VkDeviceSize offset,VkDeviceSize size)1129     void setSuballocationOffsetAndSize(VkDeviceSize offset, VkDeviceSize size)
1130     {
1131         mSuballocation.setOffsetAndSize(offset, size);
1132     }
1133 
1134     // Suballocation object.
1135     BufferSuballocation mSuballocation;
1136     // This normally is invalid. We always use the BufferBlock's buffer and offset combination. But
1137     // when robust resource init is enabled, we may want to create a dedicated VkBuffer for the
1138     // suballocation so that vulkan driver will ensure no access beyond this sub-range. In that
1139     // case, this VkBuffer will be created lazily as needed.
1140     Buffer mBufferWithUserSize;
1141 
1142     // For memory barriers.
1143     DeviceQueueIndex mCurrentDeviceQueueIndex;
1144     VkFlags mCurrentWriteAccess;
1145     VkFlags mCurrentReadAccess;
1146     VkPipelineStageFlags mCurrentWriteStages;
1147     VkPipelineStageFlags mCurrentReadStages;
1148 
1149     BufferSerial mSerial;
1150     // Manages the descriptorSet cache that created with this BufferHelper object.
1151     DescriptorSetCacheManager mDescriptorSetCacheManager;
1152     // For external buffer
1153     GLeglClientBufferEXT mClientBuffer;
1154 
1155     // Whether ANGLE currently has ownership of this resource or it's released to external.
1156     bool mIsReleasedToExternal;
1157 };
1158 
1159 class BufferPool : angle::NonCopyable
1160 {
1161   public:
1162     BufferPool();
1163     BufferPool(BufferPool &&other);
1164     ~BufferPool();
1165 
1166     // Init that gives the ability to pass in specified memory property flags for the buffer.
1167     void initWithFlags(Renderer *renderer,
1168                        vma::VirtualBlockCreateFlags flags,
1169                        VkBufferUsageFlags usage,
1170                        VkDeviceSize initialSize,
1171                        uint32_t memoryTypeIndex,
1172                        VkMemoryPropertyFlags memoryProperty);
1173 
1174     VkResult allocateBuffer(Context *context,
1175                             VkDeviceSize sizeInBytes,
1176                             VkDeviceSize alignment,
1177                             BufferSuballocation *suballocation);
1178 
1179     // Frees resources immediately, or orphan the non-empty BufferBlocks if allowed. If orphan is
1180     // not allowed, it will assert if BufferBlock is still not empty.
1181     void destroy(Renderer *renderer, bool orphanAllowed);
1182     // Remove and destroy empty BufferBlocks
1183     void pruneEmptyBuffers(Renderer *renderer);
1184 
valid()1185     bool valid() const { return mSize != 0; }
1186 
1187     void addStats(std::ostringstream *out) const;
getBufferCount()1188     size_t getBufferCount() const { return mBufferBlocks.size() + mEmptyBufferBlocks.size(); }
getMemorySize()1189     VkDeviceSize getMemorySize() const { return mTotalMemorySize; }
1190 
1191   private:
1192     VkResult allocateNewBuffer(Context *context, VkDeviceSize sizeInBytes);
1193     VkDeviceSize getTotalEmptyMemorySize() const;
1194 
1195     vma::VirtualBlockCreateFlags mVirtualBlockCreateFlags;
1196     VkBufferUsageFlags mUsage;
1197     bool mHostVisible;
1198     VkDeviceSize mSize;
1199     uint32_t mMemoryTypeIndex;
1200     VkDeviceSize mTotalMemorySize;
1201     BufferBlockPointerVector mBufferBlocks;
1202     BufferBlockPointerVector mEmptyBufferBlocks;
1203     // Tracks the number of new buffers needed for suballocation since last pruneEmptyBuffers call.
1204     // We will use this heuristic information to decide how many empty buffers to keep around.
1205     size_t mNumberOfNewBuffersNeededSinceLastPrune;
1206     // max size to go down the suballocation code path. Any allocation greater or equal this size
1207     // will call into vulkan directly to allocate a dedicated VkDeviceMemory.
1208     static constexpr size_t kMaxBufferSizeForSuballocation = 4 * 1024 * 1024;
1209 };
1210 using BufferPoolPointerArray = std::array<std::unique_ptr<BufferPool>, VK_MAX_MEMORY_TYPES>;
1211 
1212 // Stores clear value In packed attachment index
1213 class PackedClearValuesArray final
1214 {
1215   public:
1216     PackedClearValuesArray();
1217     ~PackedClearValuesArray();
1218 
1219     PackedClearValuesArray(const PackedClearValuesArray &other);
1220     PackedClearValuesArray &operator=(const PackedClearValuesArray &rhs);
1221     void storeColor(PackedAttachmentIndex index, const VkClearValue &clearValue);
1222     // Caller must take care to pack depth and stencil value together.
1223     void storeDepthStencil(PackedAttachmentIndex index, const VkClearValue &clearValue);
1224     const VkClearValue &operator[](PackedAttachmentIndex index) const
1225     {
1226         return mValues[index.get()];
1227     }
data()1228     const VkClearValue *data() const { return mValues.data(); }
1229 
1230   private:
1231     gl::AttachmentArray<VkClearValue> mValues;
1232 };
1233 
1234 class ImageHelper;
1235 using ImageHelperPtr = ImageHelper *;
1236 
1237 // Reference to a render pass attachment (color or depth/stencil) alongside render-pass-related
1238 // tracking such as when the attachment is last written to or invalidated.  This is used to
1239 // determine loadOp and storeOp of the attachment, and enables optimizations that need to know
1240 // how the attachment has been used.
1241 class RenderPassAttachment final
1242 {
1243   public:
1244     RenderPassAttachment();
1245     ~RenderPassAttachment() = default;
1246 
1247     void init(ImageHelper *image,
1248               UniqueSerial imageSiblingSerial,
1249               gl::LevelIndex levelIndex,
1250               uint32_t layerIndex,
1251               uint32_t layerCount,
1252               VkImageAspectFlagBits aspect);
1253     void reset();
1254 
1255     void onAccess(ResourceAccess access, uint32_t currentCmdCount);
1256     void invalidate(const gl::Rectangle &invalidateArea,
1257                     bool isAttachmentEnabled,
1258                     uint32_t currentCmdCount);
1259     void onRenderAreaGrowth(ContextVk *contextVk, const gl::Rectangle &newRenderArea);
1260     void finalizeLoadStore(Context *context,
1261                            uint32_t currentCmdCount,
1262                            bool hasUnresolveAttachment,
1263                            bool hasResolveAttachment,
1264                            RenderPassLoadOp *loadOp,
1265                            RenderPassStoreOp *storeOp,
1266                            bool *isInvalidatedOut);
1267     void restoreContent();
hasAnyAccess()1268     bool hasAnyAccess() const { return mAccess != ResourceAccess::Unused; }
hasWriteAccess()1269     bool hasWriteAccess() const { return HasResourceWriteAccess(mAccess); }
1270 
getImage()1271     ImageHelper *getImage() { return mImage; }
1272 
hasImage(const ImageHelper * image,UniqueSerial imageSiblingSerial)1273     bool hasImage(const ImageHelper *image, UniqueSerial imageSiblingSerial) const
1274     {
1275         // Compare values because we do want that invalid serials compare equal.
1276         return mImage == image && mImageSiblingSerial.getValue() == imageSiblingSerial.getValue();
1277     }
1278 
1279   private:
1280     bool hasWriteAfterInvalidate(uint32_t currentCmdCount) const;
1281     bool isInvalidated(uint32_t currentCmdCount) const;
1282     bool onAccessImpl(ResourceAccess access, uint32_t currentCmdCount);
1283 
1284     // The attachment image itself
1285     ImageHelper *mImage;
1286     // Invalid or serial of EGLImage/Surface sibling target.
1287     UniqueSerial mImageSiblingSerial;
1288     // The subresource used in the render pass
1289     gl::LevelIndex mLevelIndex;
1290     uint32_t mLayerIndex;
1291     uint32_t mLayerCount;
1292     VkImageAspectFlagBits mAspect;
1293     // Tracks the highest access during the entire render pass (Write being the highest), excluding
1294     // clear through loadOp.  This allows loadOp=Clear to be optimized out when we find out that the
1295     // attachment is not used in the render pass at all and storeOp=DontCare, or that a
1296     // mid-render-pass clear could be hoisted to loadOp=Clear.
1297     ResourceAccess mAccess;
1298     // The index of the last draw command after which the attachment is invalidated
1299     uint32_t mInvalidatedCmdCount;
1300     // The index of the last draw command after which the attachment output is disabled
1301     uint32_t mDisabledCmdCount;
1302     // The area that has been invalidated
1303     gl::Rectangle mInvalidateArea;
1304 };
1305 
1306 // Stores RenderPassAttachment In packed attachment index
1307 class PackedRenderPassAttachmentArray final
1308 {
1309   public:
PackedRenderPassAttachmentArray()1310     PackedRenderPassAttachmentArray() : mAttachments{} {}
1311     ~PackedRenderPassAttachmentArray() = default;
1312     RenderPassAttachment &operator[](PackedAttachmentIndex index)
1313     {
1314         return mAttachments[index.get()];
1315     }
reset()1316     void reset()
1317     {
1318         for (RenderPassAttachment &attachment : mAttachments)
1319         {
1320             attachment.reset();
1321         }
1322     }
1323 
1324   private:
1325     gl::AttachmentArray<RenderPassAttachment> mAttachments;
1326 };
1327 
1328 class SecondaryCommandBufferCollector final
1329 {
1330   public:
1331     SecondaryCommandBufferCollector()                                              = default;
1332     SecondaryCommandBufferCollector(const SecondaryCommandBufferCollector &)       = delete;
1333     SecondaryCommandBufferCollector(SecondaryCommandBufferCollector &&)            = default;
1334     void operator=(const SecondaryCommandBufferCollector &)                        = delete;
1335     SecondaryCommandBufferCollector &operator=(SecondaryCommandBufferCollector &&) = default;
~SecondaryCommandBufferCollector()1336     ~SecondaryCommandBufferCollector() { ASSERT(empty()); }
1337 
1338     void collectCommandBuffer(priv::SecondaryCommandBuffer &&commandBuffer);
1339     void collectCommandBuffer(VulkanSecondaryCommandBuffer &&commandBuffer);
1340     void releaseCommandBuffers();
1341 
empty()1342     bool empty() const { return mCollectedCommandBuffers.empty(); }
1343 
1344   private:
1345     std::vector<VulkanSecondaryCommandBuffer> mCollectedCommandBuffers;
1346 };
1347 
1348 struct CommandsState
1349 {
1350     std::vector<VkSemaphore> waitSemaphores;
1351     std::vector<VkPipelineStageFlags> waitSemaphoreStageMasks;
1352     PrimaryCommandBuffer primaryCommands;
1353     SecondaryCommandBufferCollector secondaryCommands;
1354 };
1355 
1356 // How the ImageHelper object is being used by the renderpass
1357 enum class RenderPassUsage
1358 {
1359     // Attached to the render taget of the current renderpass commands. It could be read/write or
1360     // read only access.
1361     RenderTargetAttachment,
1362     // This is special case of RenderTargetAttachment where the render target access is read only.
1363     // Right now it is only tracked for depth stencil attachment
1364     DepthReadOnlyAttachment,
1365     StencilReadOnlyAttachment,
1366     // This is special case of RenderTargetAttachment where the render target access is formed
1367     // feedback loop. Right now it is only tracked for depth stencil attachment
1368     DepthFeedbackLoop,
1369     StencilFeedbackLoop,
1370     // Attached to the texture sampler of the current renderpass commands
1371     ColorTextureSampler,
1372     DepthTextureSampler,
1373     StencilTextureSampler,
1374     // Fragment shading rate attachment
1375     FragmentShadingRateReadOnlyAttachment,
1376 
1377     InvalidEnum,
1378     EnumCount = InvalidEnum,
1379 };
1380 using RenderPassUsageFlags = angle::PackedEnumBitSet<RenderPassUsage, uint16_t>;
1381 constexpr RenderPassUsageFlags kDepthStencilReadOnlyBits = RenderPassUsageFlags(
1382     {RenderPassUsage::DepthReadOnlyAttachment, RenderPassUsage::StencilReadOnlyAttachment});
1383 constexpr RenderPassUsageFlags kDepthStencilFeedbackModeBits = RenderPassUsageFlags(
1384     {RenderPassUsage::DepthFeedbackLoop, RenderPassUsage::StencilFeedbackLoop});
1385 
1386 // The following are used to help track the state of an invalidated attachment.
1387 // This value indicates an "infinite" CmdCount that is not valid for comparing
1388 constexpr uint32_t kInfiniteCmdCount = 0xFFFFFFFF;
1389 
1390 // CommandBufferHelperCommon and derivatives OutsideRenderPassCommandBufferHelper and
1391 // RenderPassCommandBufferHelper wrap the outside/inside render pass secondary command buffers,
1392 // together with other information such as barriers to issue before the command buffer, tracking of
1393 // resource usages, etc.  When the asyncCommandQueue feature is enabled, objects of these classes
1394 // are handed off to the worker thread to be executed on the primary command buffer.
1395 class CommandBufferHelperCommon : angle::NonCopyable
1396 {
1397   public:
1398     void bufferWrite(VkAccessFlags writeAccessType, PipelineStage writeStage, BufferHelper *buffer);
1399 
bufferRead(VkAccessFlags readAccessType,PipelineStage readStage,BufferHelper * buffer)1400     void bufferRead(VkAccessFlags readAccessType, PipelineStage readStage, BufferHelper *buffer)
1401     {
1402         bufferReadImpl(readAccessType, readStage, buffer);
1403         setBufferReadQueueSerial(buffer);
1404     }
1405 
bufferRead(VkAccessFlags readAccessType,const gl::ShaderBitSet & readShaderStages,BufferHelper * buffer)1406     void bufferRead(VkAccessFlags readAccessType,
1407                     const gl::ShaderBitSet &readShaderStages,
1408                     BufferHelper *buffer)
1409     {
1410         bufferReadImpl(readAccessType, readShaderStages, buffer);
1411         setBufferReadQueueSerial(buffer);
1412     }
1413 
usesBuffer(const BufferHelper & buffer)1414     bool usesBuffer(const BufferHelper &buffer) const
1415     {
1416         return buffer.usedByCommandBuffer(mQueueSerial);
1417     }
1418 
usesBufferForWrite(const BufferHelper & buffer)1419     bool usesBufferForWrite(const BufferHelper &buffer) const
1420     {
1421         return buffer.writtenByCommandBuffer(mQueueSerial);
1422     }
1423 
getAndResetHasHostVisibleBufferWrite()1424     bool getAndResetHasHostVisibleBufferWrite()
1425     {
1426         bool hostBufferWrite           = mIsAnyHostVisibleBufferWritten;
1427         mIsAnyHostVisibleBufferWritten = false;
1428         return hostBufferWrite;
1429     }
1430 
1431     void executeBarriers(Renderer *renderer, CommandsState *commandsState);
1432 
1433     // The markOpen and markClosed functions are to aid in proper use of the *CommandBufferHelper.
1434     // saw invalid use due to threading issues that can be easily caught by marking when it's safe
1435     // (open) to write to the command buffer.
1436 #if !defined(ANGLE_ENABLE_ASSERTS)
markOpen()1437     void markOpen() {}
markClosed()1438     void markClosed() {}
1439 #endif
1440 
setHasShaderStorageOutput()1441     void setHasShaderStorageOutput() { mHasShaderStorageOutput = true; }
hasShaderStorageOutput()1442     bool hasShaderStorageOutput() const { return mHasShaderStorageOutput; }
1443 
hasGLMemoryBarrierIssued()1444     bool hasGLMemoryBarrierIssued() const { return mHasGLMemoryBarrierIssued; }
1445 
retainResource(Resource * resource)1446     void retainResource(Resource *resource) { resource->setQueueSerial(mQueueSerial); }
1447 
retainResourceForWrite(ReadWriteResource * writeResource)1448     void retainResourceForWrite(ReadWriteResource *writeResource)
1449     {
1450         writeResource->setWriteQueueSerial(mQueueSerial);
1451     }
1452 
1453     // Update image with this command buffer's queueSerial. If VkEvent is enabled, image's current
1454     // event is also updated with this command's event.
1455     void retainImageWithEvent(Context *context, ImageHelper *image);
1456 
1457     // Returns true if event already existed in this command buffer.
hasSetEventPendingFlush(const RefCountedEvent & event)1458     bool hasSetEventPendingFlush(const RefCountedEvent &event) const
1459     {
1460         ASSERT(event.valid());
1461         return mRefCountedEvents.map[event.getEventStage()] == event;
1462     }
1463 
1464     // Issue VkCmdSetEvent call for events in this command buffer.
1465     template <typename CommandBufferT>
1466     void flushSetEventsImpl(Context *context, CommandBufferT *commandBuffer);
1467 
getQueueSerial()1468     const QueueSerial &getQueueSerial() const { return mQueueSerial; }
1469 
setAcquireNextImageSemaphore(VkSemaphore semaphore)1470     void setAcquireNextImageSemaphore(VkSemaphore semaphore)
1471     {
1472         ASSERT(semaphore != VK_NULL_HANDLE);
1473         ASSERT(!mAcquireNextImageSemaphore.valid());
1474         mAcquireNextImageSemaphore.setHandle(semaphore);
1475     }
1476 
1477   protected:
1478     CommandBufferHelperCommon();
1479     ~CommandBufferHelperCommon();
1480 
1481     void initializeImpl();
1482 
1483     void resetImpl(Context *context);
1484 
1485     template <class DerivedT>
1486     angle::Result attachCommandPoolImpl(Context *context, SecondaryCommandPool *commandPool);
1487     template <class DerivedT, bool kIsRenderPassBuffer>
1488     angle::Result detachCommandPoolImpl(Context *context, SecondaryCommandPool **commandPoolOut);
1489     template <class DerivedT>
1490     void releaseCommandPoolImpl();
1491 
1492     template <class DerivedT>
1493     void attachAllocatorImpl(SecondaryCommandMemoryAllocator *allocator);
1494     template <class DerivedT>
1495     SecondaryCommandMemoryAllocator *detachAllocatorImpl();
1496 
1497     template <class DerivedT>
1498     void assertCanBeRecycledImpl();
1499 
1500     void bufferReadImpl(VkAccessFlags readAccessType,
1501                         PipelineStage readStage,
1502                         BufferHelper *buffer);
bufferReadImpl(VkAccessFlags readAccessType,const gl::ShaderBitSet & readShaderStages,BufferHelper * buffer)1503     void bufferReadImpl(VkAccessFlags readAccessType,
1504                         const gl::ShaderBitSet &readShaderStages,
1505                         BufferHelper *buffer)
1506     {
1507         for (gl::ShaderType shaderType : readShaderStages)
1508         {
1509             const vk::PipelineStage readStage = vk::GetPipelineStage(shaderType);
1510             bufferReadImpl(readAccessType, readStage, buffer);
1511         }
1512     }
1513     void imageReadImpl(Context *context,
1514                        VkImageAspectFlags aspectFlags,
1515                        ImageLayout imageLayout,
1516                        BarrierType barrierType,
1517                        ImageHelper *image);
1518     void imageWriteImpl(Context *context,
1519                         gl::LevelIndex level,
1520                         uint32_t layerStart,
1521                         uint32_t layerCount,
1522                         VkImageAspectFlags aspectFlags,
1523                         ImageLayout imageLayout,
1524                         BarrierType barrierType,
1525                         ImageHelper *image);
1526 
1527     void updateImageLayoutAndBarrier(Context *context,
1528                                      ImageHelper *image,
1529                                      VkImageAspectFlags aspectFlags,
1530                                      ImageLayout imageLayout,
1531                                      BarrierType barrierType);
1532 
1533     void addCommandDiagnosticsCommon(std::ostringstream *out);
1534 
1535     void setBufferReadQueueSerial(BufferHelper *buffer);
1536 
1537     // Allocator used by this class.
1538     SecondaryCommandBlockAllocator mCommandAllocator;
1539 
1540     // Barriers to be executed before the command buffer.
1541     PipelineBarrierArray mPipelineBarriers;
1542     EventBarrierArray mEventBarriers;
1543 
1544     // The command pool *CommandBufferHelper::mCommandBuffer is allocated from.  Only used with
1545     // Vulkan secondary command buffers (as opposed to ANGLE's SecondaryCommandBuffer).
1546     SecondaryCommandPool *mCommandPool;
1547 
1548     // Whether the command buffers contains any draw/dispatch calls that possibly output data
1549     // through storage buffers and images.  This is used to determine whether glMemoryBarrier*
1550     // should flush the command buffer.
1551     bool mHasShaderStorageOutput;
1552     // Whether glMemoryBarrier has been called while commands are recorded in this command buffer.
1553     // This is used to know when to check and potentially flush the command buffer if storage
1554     // buffers and images are used in it.
1555     bool mHasGLMemoryBarrierIssued;
1556 
1557     // Tracks resources used in the command buffer.
1558     QueueSerial mQueueSerial;
1559 
1560     // Only used for swapChain images
1561     Semaphore mAcquireNextImageSemaphore;
1562 
1563     // The list of RefCountedEvents that have be tracked
1564     EventMaps mRefCountedEvents;
1565     // The list of RefCountedEvents that should be garbage collected when it gets reset.
1566     RefCountedEventCollector mRefCountedEventCollector;
1567 
1568     // Check for any buffer write commands recorded for host-visible buffers
1569     bool mIsAnyHostVisibleBufferWritten = false;
1570 };
1571 
1572 class SecondaryCommandBufferCollector;
1573 
1574 class OutsideRenderPassCommandBufferHelper final : public CommandBufferHelperCommon
1575 {
1576   public:
1577     OutsideRenderPassCommandBufferHelper();
1578     ~OutsideRenderPassCommandBufferHelper();
1579 
1580     angle::Result initialize(Context *context);
1581 
1582     angle::Result reset(Context *context, SecondaryCommandBufferCollector *commandBufferCollector);
1583 
ExecutesInline()1584     static constexpr bool ExecutesInline()
1585     {
1586         return OutsideRenderPassCommandBuffer::ExecutesInline();
1587     }
1588 
getCommandBuffer()1589     OutsideRenderPassCommandBuffer &getCommandBuffer() { return mCommandBuffer; }
1590 
empty()1591     bool empty() const { return mCommandBuffer.empty(); }
1592 
1593     angle::Result attachCommandPool(Context *context, SecondaryCommandPool *commandPool);
1594     angle::Result detachCommandPool(Context *context, SecondaryCommandPool **commandPoolOut);
1595     void releaseCommandPool();
1596 
1597     void attachAllocator(SecondaryCommandMemoryAllocator *allocator);
1598     SecondaryCommandMemoryAllocator *detachAllocator();
1599 
1600     void assertCanBeRecycled();
1601 
1602 #if defined(ANGLE_ENABLE_ASSERTS)
markOpen()1603     void markOpen() { mCommandBuffer.open(); }
markClosed()1604     void markClosed() { mCommandBuffer.close(); }
1605 #endif
1606 
1607     void imageRead(Context *context,
1608                    VkImageAspectFlags aspectFlags,
1609                    ImageLayout imageLayout,
1610                    ImageHelper *image);
1611     void imageWrite(Context *context,
1612                     gl::LevelIndex level,
1613                     uint32_t layerStart,
1614                     uint32_t layerCount,
1615                     VkImageAspectFlags aspectFlags,
1616                     ImageLayout imageLayout,
1617                     ImageHelper *image);
1618 
1619     // Update image with this command buffer's queueSerial.
1620     void retainImage(ImageHelper *image);
1621 
1622     // Call SetEvent and have image's current event pointing to it.
1623     void trackImageWithEvent(Context *context, ImageHelper *image);
1624 
1625     // Issues SetEvent calls to the command buffer.
flushSetEvents(Context * context)1626     void flushSetEvents(Context *context) { flushSetEventsImpl(context, &mCommandBuffer); }
1627     // Clean up event garbage. Note that ImageHelper object may still holding reference count to it,
1628     // so the event itself will not gets destroyed until the last refCount goes away.
1629     void collectRefCountedEventsGarbage(RefCountedEventsGarbageRecycler *garbageRecycler);
1630 
getRefCountedEventCollector()1631     RefCountedEventCollector *getRefCountedEventCollector() { return &mRefCountedEventCollector; }
1632 
1633     angle::Result flushToPrimary(Context *context, CommandsState *commandsState);
1634 
setGLMemoryBarrierIssued()1635     void setGLMemoryBarrierIssued()
1636     {
1637         if (!mCommandBuffer.empty())
1638         {
1639             mHasGLMemoryBarrierIssued = true;
1640         }
1641     }
1642 
1643     std::string getCommandDiagnostics();
1644 
setQueueSerial(SerialIndex index,Serial serial)1645     void setQueueSerial(SerialIndex index, Serial serial)
1646     {
1647         mQueueSerial = QueueSerial(index, serial);
1648     }
1649 
1650   private:
1651     angle::Result initializeCommandBuffer(Context *context);
1652     angle::Result endCommandBuffer(Context *context);
1653 
1654     OutsideRenderPassCommandBuffer mCommandBuffer;
1655     bool mIsCommandBufferEnded = false;
1656 
1657     friend class CommandBufferHelperCommon;
1658 };
1659 
1660 enum class ImagelessFramebuffer
1661 {
1662     No,
1663     Yes,
1664 };
1665 
1666 enum class ClearTextureMode
1667 {
1668     FullClear,
1669     PartialClear,
1670 };
1671 
1672 enum class RenderPassSource
1673 {
1674     DefaultFramebuffer,
1675     FramebufferObject,
1676     InternalUtils,
1677 };
1678 
1679 class RenderPassFramebuffer : angle::NonCopyable
1680 {
1681   public:
1682     RenderPassFramebuffer() = default;
~RenderPassFramebuffer()1683     ~RenderPassFramebuffer() { mInitialFramebuffer.release(); }
1684 
1685     RenderPassFramebuffer &operator=(RenderPassFramebuffer &&other)
1686     {
1687         mInitialFramebuffer.setHandle(other.mInitialFramebuffer.release());
1688         std::swap(mImageViews, other.mImageViews);
1689         mWidth       = other.mWidth;
1690         mHeight      = other.mHeight;
1691         mLayers      = other.mLayers;
1692         mIsImageless = other.mIsImageless;
1693         mIsDefault   = other.mIsDefault;
1694         return *this;
1695     }
1696 
1697     void reset();
1698 
setFramebuffer(Context * context,Framebuffer && initialFramebuffer,FramebufferAttachmentsVector<VkImageView> && imageViews,uint32_t width,uint32_t height,uint32_t layers,ImagelessFramebuffer imagelessFramebuffer,RenderPassSource source)1699     void setFramebuffer(Context *context,
1700                         Framebuffer &&initialFramebuffer,
1701                         FramebufferAttachmentsVector<VkImageView> &&imageViews,
1702                         uint32_t width,
1703                         uint32_t height,
1704                         uint32_t layers,
1705                         ImagelessFramebuffer imagelessFramebuffer,
1706                         RenderPassSource source)
1707     {
1708         // Framebuffers are mutually exclusive with dynamic rendering.
1709         ASSERT(initialFramebuffer.valid() != context->getFeatures().preferDynamicRendering.enabled);
1710         mInitialFramebuffer = std::move(initialFramebuffer);
1711         mImageViews         = std::move(imageViews);
1712         mWidth              = width;
1713         mHeight             = height;
1714         mLayers             = layers;
1715         mIsImageless        = imagelessFramebuffer == ImagelessFramebuffer::Yes;
1716         mIsDefault          = source == RenderPassSource::DefaultFramebuffer;
1717     }
1718 
isImageless()1719     bool isImageless() const { return mIsImageless; }
isDefault()1720     bool isDefault() const { return mIsDefault; }
getFramebuffer()1721     const Framebuffer &getFramebuffer() const { return mInitialFramebuffer; }
needsNewFramebufferWithResolveAttachments()1722     bool needsNewFramebufferWithResolveAttachments() const { return !mInitialFramebuffer.valid(); }
getLayers()1723     uint32_t getLayers() const { return mLayers; }
1724 
1725     // Helpers to determine if a resolve attachment already exists
hasColorResolveAttachment(size_t colorIndexGL)1726     bool hasColorResolveAttachment(size_t colorIndexGL)
1727     {
1728         const size_t viewIndex = kColorResolveAttachmentBegin + colorIndexGL;
1729         return viewIndex < mImageViews.size() && mImageViews[viewIndex] != VK_NULL_HANDLE;
1730     }
hasDepthStencilResolveAttachment()1731     bool hasDepthStencilResolveAttachment()
1732     {
1733         return mImageViews[kDepthStencilResolveAttachment] != VK_NULL_HANDLE;
1734     }
1735 
1736     // Add a resolve attachment.  This is only called through glBlitFramebuffer, as other cases
1737     // where resolve attachments are implicitly added already include the resolve attachment when
1738     // initially populating mImageViews.
addColorResolveAttachment(size_t colorIndexGL,VkImageView view)1739     void addColorResolveAttachment(size_t colorIndexGL, VkImageView view)
1740     {
1741         addResolveAttachment(kColorResolveAttachmentBegin + colorIndexGL, view);
1742     }
addDepthStencilResolveAttachment(VkImageView view)1743     void addDepthStencilResolveAttachment(VkImageView view)
1744     {
1745         addResolveAttachment(kDepthStencilResolveAttachment, view);
1746     }
1747 
1748     // Prepare for rendering by creating a new framebuffer because the initial framebuffer is not
1749     // valid (due to added resolve attachments).  This is called when the render pass is finalized.
1750     angle::Result packResolveViewsAndCreateFramebuffer(Context *context,
1751                                                        const RenderPass &renderPass,
1752                                                        Framebuffer *framebufferOut);
1753 
1754     // Prepare for rendering using the initial imageless framebuffer.
1755     void packResolveViewsForRenderPassBegin(VkRenderPassAttachmentBeginInfo *beginInfoOut);
1756 
1757     // For use with dynamic rendering.
getUnpackedImageViews()1758     const FramebufferAttachmentsVector<VkImageView> &getUnpackedImageViews() const
1759     {
1760         return mImageViews;
1761     }
1762 
1763     // Packs views in a contiguous list.
1764     //
1765     // It can be used before creating a framebuffer, or when starting a render pass with an
1766     // imageless framebuffer.
1767     static void PackViews(FramebufferAttachmentsVector<VkImageView> *views);
1768 
1769     static constexpr size_t kColorResolveAttachmentBegin = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 2;
1770     static constexpr size_t kDepthStencilResolveAttachment =
1771         gl::IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 + 2;
1772 
1773   private:
1774     void addResolveAttachment(size_t viewIndex, VkImageView view);
1775     void packResolveViews();
1776 
1777     // The following is the framebuffer object that was used to start the render pass.  If the
1778     // resolve attachments have not been modified, the same framebuffer object can be used.
1779     // Otherwise a temporary framebuffer object is created when the render pass is closed.  This
1780     // inefficiency is removed with VK_KHR_dynamic_rendering when supported.
1781     Framebuffer mInitialFramebuffer;
1782 
1783     // The first gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 2 attachments are laid out as follows:
1784     //
1785     // - Color attachments, if any
1786     // - Depth/stencil attachment, if any
1787     // - Fragment shading rate attachment, if any
1788     // - Padding if needed
1789     //
1790     // Starting from index gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 2, there are potentially another
1791     // gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1 resolve attachments.  However, these are not packed
1792     // (with gaps per missing attachment, and depth/stencil resolve is last).  This allow more
1793     // resolve attachments to be added by optimizing calls to glBlitFramebuffer.  When the render
1794     // pass is closed, the resolve attachments are packed.
1795     FramebufferAttachmentsVector<VkImageView> mImageViews = {};
1796 
1797     uint32_t mWidth  = 0;
1798     uint32_t mHeight = 0;
1799     uint32_t mLayers = 0;
1800 
1801     // Whether this is an imageless framebuffer.  Currently, window surface and UtilsVk framebuffers
1802     // aren't imageless, unless imageless framebuffers aren't supported altogether.
1803     bool mIsImageless = false;
1804     // Whether this is the default framebuffer (i.e. corresponding to the window surface).
1805     bool mIsDefault = false;
1806 };
1807 
1808 class RenderPassCommandBufferHelper final : public CommandBufferHelperCommon
1809 {
1810   public:
1811     RenderPassCommandBufferHelper();
1812     ~RenderPassCommandBufferHelper();
1813 
1814     angle::Result initialize(Context *context);
1815 
1816     angle::Result reset(Context *context, SecondaryCommandBufferCollector *commandBufferCollector);
1817 
ExecutesInline()1818     static constexpr bool ExecutesInline() { return RenderPassCommandBuffer::ExecutesInline(); }
1819 
getCommandBuffer()1820     RenderPassCommandBuffer &getCommandBuffer()
1821     {
1822         return mCommandBuffers[mCurrentSubpassCommandBufferIndex];
1823     }
1824 
empty()1825     bool empty() const { return mCommandBuffers[0].empty(); }
1826 
1827     angle::Result attachCommandPool(Context *context, SecondaryCommandPool *commandPool);
1828     void detachCommandPool(SecondaryCommandPool **commandPoolOut);
1829     void releaseCommandPool();
1830 
1831     void attachAllocator(SecondaryCommandMemoryAllocator *allocator);
1832     SecondaryCommandMemoryAllocator *detachAllocator();
1833 
1834     void assertCanBeRecycled();
1835 
1836 #if defined(ANGLE_ENABLE_ASSERTS)
markOpen()1837     void markOpen() { getCommandBuffer().open(); }
markClosed()1838     void markClosed() { getCommandBuffer().close(); }
1839 #endif
1840 
1841     void imageRead(ContextVk *contextVk,
1842                    VkImageAspectFlags aspectFlags,
1843                    ImageLayout imageLayout,
1844                    ImageHelper *image);
1845     void imageWrite(ContextVk *contextVk,
1846                     gl::LevelIndex level,
1847                     uint32_t layerStart,
1848                     uint32_t layerCount,
1849                     VkImageAspectFlags aspectFlags,
1850                     ImageLayout imageLayout,
1851                     ImageHelper *image);
1852 
1853     void colorImagesDraw(gl::LevelIndex level,
1854                          uint32_t layerStart,
1855                          uint32_t layerCount,
1856                          ImageHelper *image,
1857                          ImageHelper *resolveImage,
1858                          UniqueSerial imageSiblingSerial,
1859                          PackedAttachmentIndex packedAttachmentIndex);
1860     void depthStencilImagesDraw(gl::LevelIndex level,
1861                                 uint32_t layerStart,
1862                                 uint32_t layerCount,
1863                                 ImageHelper *image,
1864                                 ImageHelper *resolveImage,
1865                                 UniqueSerial imageSiblingSerial);
1866     void fragmentShadingRateImageRead(ImageHelper *image);
1867 
1868     bool usesImage(const ImageHelper &image) const;
1869     bool startedAndUsesImageWithBarrier(const ImageHelper &image) const;
1870 
1871     angle::Result flushToPrimary(Context *context,
1872                                  CommandsState *commandsState,
1873                                  const RenderPass &renderPass,
1874                                  VkFramebuffer framebufferOverride);
1875 
started()1876     bool started() const { return mRenderPassStarted; }
1877 
1878     // Finalize the layout if image has any deferred layout transition.
1879     void finalizeImageLayout(Context *context,
1880                              const ImageHelper *image,
1881                              UniqueSerial imageSiblingSerial);
1882 
1883     angle::Result beginRenderPass(ContextVk *contextVk,
1884                                   RenderPassFramebuffer &&framebuffer,
1885                                   const gl::Rectangle &renderArea,
1886                                   const RenderPassDesc &renderPassDesc,
1887                                   const AttachmentOpsArray &renderPassAttachmentOps,
1888                                   const PackedAttachmentCount colorAttachmentCount,
1889                                   const PackedAttachmentIndex depthStencilAttachmentIndex,
1890                                   const PackedClearValuesArray &clearValues,
1891                                   const QueueSerial &queueSerial,
1892                                   RenderPassCommandBuffer **commandBufferOut);
1893 
1894     angle::Result endRenderPass(ContextVk *contextVk);
1895 
1896     angle::Result nextSubpass(ContextVk *contextVk, RenderPassCommandBuffer **commandBufferOut);
1897 
1898     void beginTransformFeedback(size_t validBufferCount,
1899                                 const VkBuffer *counterBuffers,
1900                                 const VkDeviceSize *counterBufferOffsets,
1901                                 bool rebindBuffers);
1902 
1903     void endTransformFeedback();
1904 
1905     void invalidateRenderPassColorAttachment(const gl::State &state,
1906                                              size_t colorIndexGL,
1907                                              PackedAttachmentIndex attachmentIndex,
1908                                              const gl::Rectangle &invalidateArea);
1909     void invalidateRenderPassDepthAttachment(const gl::DepthStencilState &dsState,
1910                                              const gl::Rectangle &invalidateArea);
1911     void invalidateRenderPassStencilAttachment(const gl::DepthStencilState &dsState,
1912                                                GLuint framebufferStencilSize,
1913                                                const gl::Rectangle &invalidateArea);
1914 
1915     void updateRenderPassColorClear(PackedAttachmentIndex colorIndexVk,
1916                                     const VkClearValue &colorClearValue);
1917     void updateRenderPassDepthStencilClear(VkImageAspectFlags aspectFlags,
1918                                            const VkClearValue &clearValue);
1919 
getRenderArea()1920     const gl::Rectangle &getRenderArea() const { return mRenderArea; }
1921 
1922     // If render pass is started with a small render area due to a small scissor, and if a new
1923     // larger scissor is specified, grow the render area to accomodate it.
1924     void growRenderArea(ContextVk *contextVk, const gl::Rectangle &newRenderArea);
1925 
1926     void resumeTransformFeedback();
1927     void pauseTransformFeedback();
isTransformFeedbackStarted()1928     bool isTransformFeedbackStarted() const { return mValidTransformFeedbackBufferCount > 0; }
isTransformFeedbackActiveUnpaused()1929     bool isTransformFeedbackActiveUnpaused() const { return mIsTransformFeedbackActiveUnpaused; }
1930 
getAndResetCounter()1931     uint32_t getAndResetCounter()
1932     {
1933         uint32_t count = mCounter;
1934         mCounter       = 0;
1935         return count;
1936     }
1937 
getFramebuffer()1938     RenderPassFramebuffer &getFramebuffer() { return mFramebuffer; }
getFramebuffer()1939     const RenderPassFramebuffer &getFramebuffer() const { return mFramebuffer; }
1940 
1941     void onColorAccess(PackedAttachmentIndex packedAttachmentIndex, ResourceAccess access);
1942     void onDepthAccess(ResourceAccess access);
1943     void onStencilAccess(ResourceAccess access);
1944 
hasAnyColorAccess(PackedAttachmentIndex packedAttachmentIndex)1945     bool hasAnyColorAccess(PackedAttachmentIndex packedAttachmentIndex)
1946     {
1947         ASSERT(packedAttachmentIndex < mColorAttachmentsCount);
1948         return mColorAttachments[packedAttachmentIndex].hasAnyAccess();
1949     }
hasAnyDepthAccess()1950     bool hasAnyDepthAccess() { return mDepthAttachment.hasAnyAccess(); }
hasAnyStencilAccess()1951     bool hasAnyStencilAccess() { return mStencilAttachment.hasAnyAccess(); }
1952 
1953     void addColorResolveAttachment(size_t colorIndexGL,
1954                                    ImageHelper *image,
1955                                    VkImageView view,
1956                                    gl::LevelIndex level,
1957                                    uint32_t layerStart,
1958                                    uint32_t layerCount,
1959                                    UniqueSerial imageSiblingSerial);
1960     void addDepthStencilResolveAttachment(ImageHelper *image,
1961                                           VkImageView view,
1962                                           VkImageAspectFlags aspects,
1963                                           gl::LevelIndex level,
1964                                           uint32_t layerStart,
1965                                           uint32_t layerCount,
1966                                           UniqueSerial imageSiblingSerial);
1967 
hasDepthWriteOrClear()1968     bool hasDepthWriteOrClear() const
1969     {
1970         return mDepthAttachment.hasWriteAccess() ||
1971                mAttachmentOps[mDepthStencilAttachmentIndex].loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR;
1972     }
1973 
hasStencilWriteOrClear()1974     bool hasStencilWriteOrClear() const
1975     {
1976         return mStencilAttachment.hasWriteAccess() ||
1977                mAttachmentOps[mDepthStencilAttachmentIndex].stencilLoadOp ==
1978                    VK_ATTACHMENT_LOAD_OP_CLEAR;
1979     }
1980 
getRenderPassDesc()1981     const RenderPassDesc &getRenderPassDesc() const { return mRenderPassDesc; }
getAttachmentOps()1982     const AttachmentOpsArray &getAttachmentOps() const { return mAttachmentOps; }
1983 
setFramebufferFetchMode(FramebufferFetchMode framebufferFetchMode)1984     void setFramebufferFetchMode(FramebufferFetchMode framebufferFetchMode)
1985     {
1986         mRenderPassDesc.setFramebufferFetchMode(framebufferFetchMode);
1987     }
1988 
setImageOptimizeForPresent(ImageHelper * image)1989     void setImageOptimizeForPresent(ImageHelper *image) { mImageOptimizeForPresent = image; }
1990 
setGLMemoryBarrierIssued()1991     void setGLMemoryBarrierIssued()
1992     {
1993         if (mRenderPassStarted)
1994         {
1995             mHasGLMemoryBarrierIssued = true;
1996         }
1997     }
1998     std::string getCommandDiagnostics();
1999 
2000     // Readonly depth stencil mode and feedback loop mode
2001     void updateDepthReadOnlyMode(RenderPassUsageFlags dsUsageFlags);
2002     void updateStencilReadOnlyMode(RenderPassUsageFlags dsUsageFlags);
2003     void updateDepthStencilReadOnlyMode(RenderPassUsageFlags dsUsageFlags,
2004                                         VkImageAspectFlags dsAspectFlags);
2005 
2006     void collectRefCountedEventsGarbage(RefCountedEventsGarbageRecycler *garbageRecycler);
2007 
2008     void updatePerfCountersForDynamicRenderingInstance(Context *context,
2009                                                        angle::VulkanPerfCounters *countersOut);
2010 
isDefault()2011     bool isDefault() const { return mFramebuffer.isDefault(); }
2012 
2013   private:
getSubpassCommandBufferCount()2014     uint32_t getSubpassCommandBufferCount() const { return mCurrentSubpassCommandBufferIndex + 1; }
2015 
2016     angle::Result initializeCommandBuffer(Context *context);
2017     angle::Result beginRenderPassCommandBuffer(ContextVk *contextVk);
2018     angle::Result endRenderPassCommandBuffer(ContextVk *contextVk);
2019 
getRenderPassWriteCommandCount()2020     uint32_t getRenderPassWriteCommandCount()
2021     {
2022         // All subpasses are chained (no subpasses running in parallel), so the cmd count can be
2023         // considered continuous among subpasses.
2024         return mPreviousSubpassesCmdCount + getCommandBuffer().getRenderPassWriteCommandCount();
2025     }
2026 
2027     void updateStartedRenderPassWithDepthStencilMode(RenderPassAttachment *resolveAttachment,
2028                                                      bool renderPassHasWriteOrClear,
2029                                                      RenderPassUsageFlags dsUsageFlags,
2030                                                      RenderPassUsage readOnlyAttachmentUsage);
2031 
2032     // We can't determine the image layout at the renderpass start time since their full usage
2033     // aren't known until later time. We finalize the layout when either ImageHelper object is
2034     // released or when renderpass ends.
2035     void finalizeColorImageLayout(Context *context,
2036                                   ImageHelper *image,
2037                                   PackedAttachmentIndex packedAttachmentIndex,
2038                                   bool isResolveImage);
2039     void finalizeColorImageLoadStore(Context *context, PackedAttachmentIndex packedAttachmentIndex);
2040     void finalizeDepthStencilImageLayout(Context *context);
2041     void finalizeDepthStencilResolveImageLayout(Context *context);
2042     void finalizeDepthStencilLoadStore(Context *context);
2043 
2044     void finalizeColorImageLayoutAndLoadStore(Context *context,
2045                                               PackedAttachmentIndex packedAttachmentIndex);
2046     void finalizeDepthStencilImageLayoutAndLoadStore(Context *context);
2047     void finalizeFragmentShadingRateImageLayout(Context *context);
2048 
2049     void executeSetEvents(Context *context, PrimaryCommandBuffer *primary);
2050 
2051     // When using Vulkan secondary command buffers, each subpass must be recorded in a separate
2052     // command buffer.  Currently ANGLE produces render passes with at most 2 subpasses.
2053     static constexpr size_t kMaxSubpassCount = 2;
2054     std::array<RenderPassCommandBuffer, kMaxSubpassCount> mCommandBuffers;
2055     uint32_t mCurrentSubpassCommandBufferIndex;
2056 
2057     // RenderPass state
2058     uint32_t mCounter;
2059     RenderPassDesc mRenderPassDesc;
2060     AttachmentOpsArray mAttachmentOps;
2061     RenderPassFramebuffer mFramebuffer;
2062     gl::Rectangle mRenderArea;
2063     PackedClearValuesArray mClearValues;
2064     bool mRenderPassStarted;
2065 
2066     // Transform feedback state
2067     gl::TransformFeedbackBuffersArray<VkBuffer> mTransformFeedbackCounterBuffers;
2068     gl::TransformFeedbackBuffersArray<VkDeviceSize> mTransformFeedbackCounterBufferOffsets;
2069     uint32_t mValidTransformFeedbackBufferCount;
2070     bool mRebindTransformFeedbackBuffers;
2071     bool mIsTransformFeedbackActiveUnpaused;
2072 
2073     // State tracking for whether to optimize the storeOp to DONT_CARE
2074     uint32_t mPreviousSubpassesCmdCount;
2075 
2076     // Keep track of the depth/stencil attachment index
2077     PackedAttachmentIndex mDepthStencilAttachmentIndex;
2078 
2079     // Array size of mColorAttachments
2080     PackedAttachmentCount mColorAttachmentsCount;
2081     // Attached render target images. Color and depth resolve images always come last.
2082     PackedRenderPassAttachmentArray mColorAttachments;
2083     PackedRenderPassAttachmentArray mColorResolveAttachments;
2084 
2085     RenderPassAttachment mDepthAttachment;
2086     RenderPassAttachment mDepthResolveAttachment;
2087 
2088     RenderPassAttachment mStencilAttachment;
2089     RenderPassAttachment mStencilResolveAttachment;
2090 
2091     RenderPassAttachment mFragmentShadingRateAtachment;
2092 
2093     // This is last renderpass before present and this is the image will be presented. We can use
2094     // final layout of the renderpass to transition it to the presentable layout
2095     ImageHelper *mImageOptimizeForPresent;
2096     ImageLayout mImageOptimizeForPresentOriginalLayout;
2097 
2098     friend class CommandBufferHelperCommon;
2099 };
2100 
2101 // The following class helps support both Vulkan and ANGLE secondary command buffers by
2102 // encapsulating their differences.
2103 template <typename CommandBufferHelperT>
2104 class CommandBufferRecycler
2105 {
2106   public:
2107     CommandBufferRecycler()  = default;
2108     ~CommandBufferRecycler() = default;
2109 
2110     void onDestroy();
2111 
2112     angle::Result getCommandBufferHelper(Context *context,
2113                                          SecondaryCommandPool *commandPool,
2114                                          SecondaryCommandMemoryAllocator *commandsAllocator,
2115                                          CommandBufferHelperT **commandBufferHelperOut);
2116 
2117     void recycleCommandBufferHelper(CommandBufferHelperT **commandBuffer);
2118 
2119   private:
2120     angle::SimpleMutex mMutex;
2121     std::vector<CommandBufferHelperT *> mCommandBufferHelperFreeList;
2122 };
2123 
2124 // The source of update to an ImageHelper
2125 enum class UpdateSource
2126 {
2127     // Clear an image subresource.
2128     Clear,
2129     ClearPartial,
2130     // Clear only the emulated channels of the subresource.  This operation is more expensive than
2131     // Clear, and so is only used for emulated color formats and only for external images.  Color
2132     // only because depth or stencil clear is already per channel, so Clear works for them.
2133     // External only because they may contain data that needs to be preserved.  Additionally, this
2134     // is a one-time only clear.  Once the emulated channels are cleared, ANGLE ensures that they
2135     // remain untouched.
2136     ClearEmulatedChannelsOnly,
2137     // When an image with emulated channels is invalidated, a clear may be restaged to keep the
2138     // contents of the emulated channels defined.  This is given a dedicated enum value, so it can
2139     // be removed if the invalidate is undone at the end of the render pass.
2140     ClearAfterInvalidate,
2141     // The source of the copy is a buffer.
2142     Buffer,
2143     // The source of the copy is an image.
2144     Image,
2145 };
2146 
2147 enum class ApplyImageUpdate
2148 {
2149     ImmediatelyInUnlockedTailCall,
2150     Immediately,
2151     Defer,
2152 };
2153 
2154 constexpr VkImageAspectFlagBits IMAGE_ASPECT_DEPTH_STENCIL =
2155     static_cast<VkImageAspectFlagBits>(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
2156 
2157 bool FormatHasNecessaryFeature(Renderer *renderer,
2158                                angle::FormatID formatID,
2159                                VkImageTiling tilingMode,
2160                                VkFormatFeatureFlags featureBits);
2161 
2162 bool CanCopyWithTransfer(Renderer *renderer,
2163                          angle::FormatID srcFormatID,
2164                          VkImageTiling srcTilingMode,
2165                          angle::FormatID dstFormatID,
2166                          VkImageTiling dstTilingMode);
2167 
2168 class ImageViewHelper;
2169 class ImageHelper final : public Resource, public angle::Subject
2170 {
2171   public:
2172     ImageHelper();
2173     ~ImageHelper() override;
2174 
2175     angle::Result init(Context *context,
2176                        gl::TextureType textureType,
2177                        const VkExtent3D &extents,
2178                        const Format &format,
2179                        GLint samples,
2180                        VkImageUsageFlags usage,
2181                        gl::LevelIndex firstLevel,
2182                        uint32_t mipLevels,
2183                        uint32_t layerCount,
2184                        bool isRobustResourceInitEnabled,
2185                        bool hasProtectedContent);
2186     angle::Result initFromCreateInfo(Context *context,
2187                                      const VkImageCreateInfo &requestedCreateInfo,
2188                                      VkMemoryPropertyFlags memoryPropertyFlags);
2189     angle::Result copyToBufferOneOff(Context *context,
2190                                      BufferHelper *stagingBuffer,
2191                                      VkBufferImageCopy copyRegion);
2192     angle::Result initMSAASwapchain(Context *context,
2193                                     gl::TextureType textureType,
2194                                     const VkExtent3D &extents,
2195                                     bool rotatedAspectRatio,
2196                                     const Format &format,
2197                                     GLint samples,
2198                                     VkImageUsageFlags usage,
2199                                     gl::LevelIndex firstLevel,
2200                                     uint32_t mipLevels,
2201                                     uint32_t layerCount,
2202                                     bool isRobustResourceInitEnabled,
2203                                     bool hasProtectedContent);
2204     angle::Result initExternal(Context *context,
2205                                gl::TextureType textureType,
2206                                const VkExtent3D &extents,
2207                                angle::FormatID intendedFormatID,
2208                                angle::FormatID actualFormatID,
2209                                GLint samples,
2210                                VkImageUsageFlags usage,
2211                                VkImageCreateFlags additionalCreateFlags,
2212                                ImageLayout initialLayout,
2213                                const void *externalImageCreateInfo,
2214                                gl::LevelIndex firstLevel,
2215                                uint32_t mipLevels,
2216                                uint32_t layerCount,
2217                                bool isRobustResourceInitEnabled,
2218                                bool hasProtectedContent,
2219                                YcbcrConversionDesc conversionDesc,
2220                                const void *compressionControl);
2221     VkResult initMemory(Context *context,
2222                         const MemoryProperties &memoryProperties,
2223                         VkMemoryPropertyFlags flags,
2224                         VkMemoryPropertyFlags excludedFlags,
2225                         const VkMemoryRequirements *memoryRequirements,
2226                         const bool allocateDedicatedMemory,
2227                         MemoryAllocationType allocationType,
2228                         VkMemoryPropertyFlags *flagsOut,
2229                         VkDeviceSize *sizeOut);
2230     angle::Result initMemoryAndNonZeroFillIfNeeded(Context *context,
2231                                                    bool hasProtectedContent,
2232                                                    const MemoryProperties &memoryProperties,
2233                                                    VkMemoryPropertyFlags flags,
2234                                                    MemoryAllocationType allocationType);
2235     angle::Result initExternalMemory(Context *context,
2236                                      const MemoryProperties &memoryProperties,
2237                                      const VkMemoryRequirements &memoryRequirements,
2238                                      uint32_t extraAllocationInfoCount,
2239                                      const void **extraAllocationInfo,
2240                                      DeviceQueueIndex currentDeviceQueueIndex,
2241                                      VkMemoryPropertyFlags flags);
2242 
2243     static constexpr VkImageUsageFlags kDefaultImageViewUsageFlags = 0;
2244     angle::Result initLayerImageView(Context *context,
2245                                      gl::TextureType textureType,
2246                                      VkImageAspectFlags aspectMask,
2247                                      const gl::SwizzleState &swizzleMap,
2248                                      ImageView *imageViewOut,
2249                                      LevelIndex baseMipLevelVk,
2250                                      uint32_t levelCount,
2251                                      uint32_t baseArrayLayer,
2252                                      uint32_t layerCount) const;
2253     angle::Result initLayerImageViewWithUsage(Context *context,
2254                                               gl::TextureType textureType,
2255                                               VkImageAspectFlags aspectMask,
2256                                               const gl::SwizzleState &swizzleMap,
2257                                               ImageView *imageViewOut,
2258                                               LevelIndex baseMipLevelVk,
2259                                               uint32_t levelCount,
2260                                               uint32_t baseArrayLayer,
2261                                               uint32_t layerCount,
2262                                               VkImageUsageFlags imageUsageFlags) const;
2263     angle::Result initLayerImageViewWithYuvModeOverride(Context *context,
2264                                                         gl::TextureType textureType,
2265                                                         VkImageAspectFlags aspectMask,
2266                                                         const gl::SwizzleState &swizzleMap,
2267                                                         ImageView *imageViewOut,
2268                                                         LevelIndex baseMipLevelVk,
2269                                                         uint32_t levelCount,
2270                                                         uint32_t baseArrayLayer,
2271                                                         uint32_t layerCount,
2272                                                         gl::YuvSamplingMode yuvSamplingMode,
2273                                                         VkImageUsageFlags imageUsageFlags) const;
2274     angle::Result initReinterpretedLayerImageView(Context *context,
2275                                                   gl::TextureType textureType,
2276                                                   VkImageAspectFlags aspectMask,
2277                                                   const gl::SwizzleState &swizzleMap,
2278                                                   ImageView *imageViewOut,
2279                                                   LevelIndex baseMipLevelVk,
2280                                                   uint32_t levelCount,
2281                                                   uint32_t baseArrayLayer,
2282                                                   uint32_t layerCount,
2283                                                   VkImageUsageFlags imageUsageFlags,
2284                                                   angle::FormatID imageViewFormat) const;
2285     // Create a 2D[Array] for staging purposes.  Used by:
2286     //
2287     // - TextureVk::copySubImageImplWithDraw
2288     // - FramebufferVk::readPixelsImpl
2289     //
2290     angle::Result init2DStaging(Context *context,
2291                                 bool hasProtectedContent,
2292                                 const MemoryProperties &memoryProperties,
2293                                 const gl::Extents &glExtents,
2294                                 angle::FormatID intendedFormatID,
2295                                 angle::FormatID actualFormatID,
2296                                 VkImageUsageFlags usage,
2297                                 uint32_t layerCount);
2298     // Create an image for staging purposes.  Used by:
2299     //
2300     // - TextureVk::copyAndStageImageData
2301     //
2302     angle::Result initStaging(Context *context,
2303                               bool hasProtectedContent,
2304                               const MemoryProperties &memoryProperties,
2305                               VkImageType imageType,
2306                               const VkExtent3D &extents,
2307                               angle::FormatID intendedFormatID,
2308                               angle::FormatID actualFormatID,
2309                               GLint samples,
2310                               VkImageUsageFlags usage,
2311                               uint32_t mipLevels,
2312                               uint32_t layerCount);
2313     // Create a multisampled image for use as the implicit image in multisampled render to texture
2314     // rendering.  If LAZILY_ALLOCATED memory is available, it will prefer that.
2315     angle::Result initImplicitMultisampledRenderToTexture(Context *context,
2316                                                           bool hasProtectedContent,
2317                                                           const MemoryProperties &memoryProperties,
2318                                                           gl::TextureType textureType,
2319                                                           GLint samples,
2320                                                           const ImageHelper &resolveImage,
2321                                                           const VkExtent3D &multisampleImageExtents,
2322                                                           bool isRobustResourceInitEnabled);
2323 
2324     // Helper for initExternal and users to automatically derive the appropriate VkImageCreateInfo
2325     // pNext chain based on the given parameters, and adjust create flags.  In some cases, these
2326     // shouldn't be automatically derived, for example when importing images through
2327     // EXT_external_objects and ANGLE_external_objects_flags.
2328     static constexpr uint32_t kImageListFormatCount = 2;
2329     using ImageListFormats                          = std::array<VkFormat, kImageListFormatCount>;
2330     static const void *DeriveCreateInfoPNext(
2331         Context *context,
2332         angle::FormatID actualFormatID,
2333         const void *pNext,
2334         VkImageFormatListCreateInfoKHR *imageFormatListInfoStorage,
2335         ImageListFormats *imageListFormatsStorage,
2336         VkImageCreateFlags *createFlagsOut);
2337 
2338     // Check whether the given format supports the provided flags.
2339     enum class FormatSupportCheck
2340     {
2341         OnlyQuerySuccess,
2342         RequireMultisampling
2343     };
2344     static bool FormatSupportsUsage(Renderer *renderer,
2345                                     VkFormat format,
2346                                     VkImageType imageType,
2347                                     VkImageTiling tilingMode,
2348                                     VkImageUsageFlags usageFlags,
2349                                     VkImageCreateFlags createFlags,
2350                                     void *formatInfoPNext,
2351                                     void *propertiesPNext,
2352                                     const FormatSupportCheck formatSupportCheck);
2353 
2354     // Image formats used for the creation of imageless framebuffers.
2355     using ImageFormats = angle::FixedVector<VkFormat, kImageListFormatCount>;
getViewFormats()2356     ImageFormats &getViewFormats() { return mViewFormats; }
getViewFormats()2357     const ImageFormats &getViewFormats() const { return mViewFormats; }
2358 
2359     // Helper for initExternal and users to extract the view formats of the image from the pNext
2360     // chain in VkImageCreateInfo.
2361     void deriveImageViewFormatFromCreateInfoPNext(VkImageCreateInfo &imageInfo,
2362                                                   ImageFormats &formatOut);
2363 
2364     // Release the underlying VkImage object for garbage collection.
2365     void releaseImage(Renderer *renderer);
2366     // Similar to releaseImage, but also notify all contexts in the same share group to stop
2367     // accessing to it.
2368     void releaseImageFromShareContexts(Renderer *renderer,
2369                                        ContextVk *contextVk,
2370                                        UniqueSerial imageSiblingSerial);
2371     void finalizeImageLayoutInShareContexts(Renderer *renderer,
2372                                             ContextVk *contextVk,
2373                                             UniqueSerial imageSiblingSerial);
2374 
2375     void releaseStagedUpdates(Renderer *renderer);
2376 
valid()2377     bool valid() const { return mImage.valid(); }
2378 
2379     VkImageAspectFlags getAspectFlags() const;
2380     // True if image contains both depth & stencil aspects
2381     bool isCombinedDepthStencilFormat() const;
2382     void destroy(Renderer *renderer);
release(Renderer * renderer)2383     void release(Renderer *renderer) { releaseImage(renderer); }
2384 
2385     void init2DWeakReference(Context *context,
2386                              VkImage handle,
2387                              const gl::Extents &glExtents,
2388                              bool rotatedAspectRatio,
2389                              angle::FormatID intendedFormatID,
2390                              angle::FormatID actualFormatID,
2391                              VkImageCreateFlags createFlags,
2392                              VkImageUsageFlags usage,
2393                              GLint samples,
2394                              bool isRobustResourceInitEnabled);
2395     void resetImageWeakReference();
2396 
getImage()2397     const Image &getImage() const { return mImage; }
getDeviceMemory()2398     const DeviceMemory &getDeviceMemory() const { return mDeviceMemory; }
getAllocation()2399     const Allocation &getAllocation() const { return mVmaAllocation; }
2400 
getVkImageCreateInfo()2401     const VkImageCreateInfo &getVkImageCreateInfo() const { return mVkImageCreateInfo; }
setTilingMode(VkImageTiling tilingMode)2402     void setTilingMode(VkImageTiling tilingMode) { mTilingMode = tilingMode; }
getTilingMode()2403     VkImageTiling getTilingMode() const { return mTilingMode; }
getCreateFlags()2404     VkImageCreateFlags getCreateFlags() const { return mCreateFlags; }
getUsage()2405     VkImageUsageFlags getUsage() const { return mUsage; }
2406     bool getCompressionFixedRate(VkImageCompressionControlEXT *compressionInfo,
2407                                  VkImageCompressionFixedRateFlagsEXT *compressionRates,
2408                                  GLenum glCompressionRate) const;
getType()2409     VkImageType getType() const { return mImageType; }
getExtents()2410     const VkExtent3D &getExtents() const { return mExtents; }
2411     const VkExtent3D getRotatedExtents() const;
getLayerCount()2412     uint32_t getLayerCount() const
2413     {
2414         ASSERT(valid());
2415         return mLayerCount;
2416     }
getLevelCount()2417     uint32_t getLevelCount() const
2418     {
2419         ASSERT(valid());
2420         return mLevelCount;
2421     }
getIntendedFormatID()2422     angle::FormatID getIntendedFormatID() const
2423     {
2424         ASSERT(valid());
2425         return mIntendedFormatID;
2426     }
getIntendedFormat()2427     const angle::Format &getIntendedFormat() const
2428     {
2429         ASSERT(valid());
2430         return angle::Format::Get(mIntendedFormatID);
2431     }
getActualFormatID()2432     angle::FormatID getActualFormatID() const
2433     {
2434         ASSERT(valid());
2435         return mActualFormatID;
2436     }
getActualVkFormat(const Renderer * renderer)2437     VkFormat getActualVkFormat(const Renderer *renderer) const
2438     {
2439         ASSERT(valid());
2440         return GetVkFormatFromFormatID(renderer, mActualFormatID);
2441     }
getActualFormat()2442     const angle::Format &getActualFormat() const
2443     {
2444         ASSERT(valid());
2445         return angle::Format::Get(mActualFormatID);
2446     }
2447     bool hasEmulatedImageChannels() const;
2448     bool hasEmulatedDepthChannel() const;
2449     bool hasEmulatedStencilChannel() const;
hasEmulatedImageFormat()2450     bool hasEmulatedImageFormat() const { return mActualFormatID != mIntendedFormatID; }
2451     bool hasInefficientlyEmulatedImageFormat() const;
getSamples()2452     GLint getSamples() const { return mSamples; }
2453 
getImageSerial()2454     ImageSerial getImageSerial() const
2455     {
2456         ASSERT(valid() && mImageSerial.valid());
2457         return mImageSerial;
2458     }
2459 
2460     void setCurrentImageLayout(Renderer *renderer, ImageLayout newLayout);
getCurrentImageLayout()2461     ImageLayout getCurrentImageLayout() const { return mCurrentLayout; }
2462     VkImageLayout getCurrentLayout(Renderer *renderer) const;
getBarrierQueueSerial()2463     const QueueSerial &getBarrierQueueSerial() const { return mBarrierQueueSerial; }
2464 
2465     gl::Extents getLevelExtents(LevelIndex levelVk) const;
2466     // Helper function to calculate the extents of a render target created for a certain mip of the
2467     // image.
2468     gl::Extents getLevelExtents2D(LevelIndex levelVk) const;
2469     gl::Extents getRotatedLevelExtents2D(LevelIndex levelVk) const;
2470 
2471     bool isDepthOrStencil() const;
2472 
2473     void setRenderPassUsageFlag(RenderPassUsage flag);
2474     void clearRenderPassUsageFlag(RenderPassUsage flag);
2475     void resetRenderPassUsageFlags();
2476     bool hasRenderPassUsageFlag(RenderPassUsage flag) const;
2477     bool usedByCurrentRenderPassAsAttachmentAndSampler(RenderPassUsage textureSamplerUsage) const;
2478 
2479     static void Copy(Renderer *renderer,
2480                      ImageHelper *srcImage,
2481                      ImageHelper *dstImage,
2482                      const gl::Offset &srcOffset,
2483                      const gl::Offset &dstOffset,
2484                      const gl::Extents &copySize,
2485                      const VkImageSubresourceLayers &srcSubresources,
2486                      const VkImageSubresourceLayers &dstSubresources,
2487                      OutsideRenderPassCommandBuffer *commandBuffer);
2488 
2489     static angle::Result CopyImageSubData(const gl::Context *context,
2490                                           ImageHelper *srcImage,
2491                                           GLint srcLevel,
2492                                           GLint srcX,
2493                                           GLint srcY,
2494                                           GLint srcZ,
2495                                           ImageHelper *dstImage,
2496                                           GLint dstLevel,
2497                                           GLint dstX,
2498                                           GLint dstY,
2499                                           GLint dstZ,
2500                                           GLsizei srcWidth,
2501                                           GLsizei srcHeight,
2502                                           GLsizei srcDepth);
2503 
2504     // Generate mipmap from level 0 into the rest of the levels with blit.
2505     angle::Result generateMipmapsWithBlit(ContextVk *contextVk,
2506                                           LevelIndex baseLevel,
2507                                           LevelIndex maxLevel);
2508 
2509     // Resolve this image into a destination image.  This image should be in the TransferSrc layout.
2510     // The destination image is automatically transitioned into TransferDst.
2511     void resolve(ImageHelper *dst,
2512                  const VkImageResolve &region,
2513                  OutsideRenderPassCommandBuffer *commandBuffer);
2514 
2515     // Data staging
2516     void removeSingleSubresourceStagedUpdates(ContextVk *contextVk,
2517                                               gl::LevelIndex levelIndexGL,
2518                                               uint32_t layerIndex,
2519                                               uint32_t layerCount);
2520     void removeSingleStagedClearAfterInvalidate(gl::LevelIndex levelIndexGL,
2521                                                 uint32_t layerIndex,
2522                                                 uint32_t layerCount);
2523     void removeStagedUpdates(Context *context,
2524                              gl::LevelIndex levelGLStart,
2525                              gl::LevelIndex levelGLEnd);
2526 
2527     angle::Result stagePartialClear(ContextVk *contextVk,
2528                                     const gl::Box &clearArea,
2529                                     const ClearTextureMode clearMode,
2530                                     gl::TextureType textureType,
2531                                     uint32_t levelIndex,
2532                                     uint32_t layerIndex,
2533                                     uint32_t layerCount,
2534                                     GLenum type,
2535                                     const gl::InternalFormat &formatInfo,
2536                                     const Format &vkFormat,
2537                                     ImageAccess access,
2538                                     const uint8_t *data);
2539 
2540     angle::Result stageSubresourceUpdateImpl(ContextVk *contextVk,
2541                                              const gl::ImageIndex &index,
2542                                              const gl::Extents &glExtents,
2543                                              const gl::Offset &offset,
2544                                              const gl::InternalFormat &formatInfo,
2545                                              const gl::PixelUnpackState &unpack,
2546                                              GLenum type,
2547                                              const uint8_t *pixels,
2548                                              const Format &vkFormat,
2549                                              ImageAccess access,
2550                                              const GLuint inputRowPitch,
2551                                              const GLuint inputDepthPitch,
2552                                              const GLuint inputSkipBytes,
2553                                              ApplyImageUpdate applyUpdate,
2554                                              bool *updateAppliedImmediatelyOut);
2555 
2556     angle::Result stageSubresourceUpdate(ContextVk *contextVk,
2557                                          const gl::ImageIndex &index,
2558                                          const gl::Extents &glExtents,
2559                                          const gl::Offset &offset,
2560                                          const gl::InternalFormat &formatInfo,
2561                                          const gl::PixelUnpackState &unpack,
2562                                          GLenum type,
2563                                          const uint8_t *pixels,
2564                                          const Format &vkFormat,
2565                                          ImageAccess access,
2566                                          ApplyImageUpdate applyUpdate,
2567                                          bool *updateAppliedImmediatelyOut);
2568 
2569     angle::Result stageSubresourceUpdateAndGetData(ContextVk *contextVk,
2570                                                    size_t allocationSize,
2571                                                    const gl::ImageIndex &imageIndex,
2572                                                    const gl::Extents &glExtents,
2573                                                    const gl::Offset &offset,
2574                                                    uint8_t **destData,
2575                                                    angle::FormatID formatID);
2576 
2577     angle::Result stageSubresourceUpdateFromFramebuffer(const gl::Context *context,
2578                                                         const gl::ImageIndex &index,
2579                                                         const gl::Rectangle &sourceArea,
2580                                                         const gl::Offset &dstOffset,
2581                                                         const gl::Extents &dstExtent,
2582                                                         const gl::InternalFormat &formatInfo,
2583                                                         ImageAccess access,
2584                                                         FramebufferVk *framebufferVk);
2585 
2586     void stageSubresourceUpdateFromImage(RefCounted<ImageHelper> *image,
2587                                          const gl::ImageIndex &index,
2588                                          LevelIndex srcMipLevel,
2589                                          const gl::Offset &destOffset,
2590                                          const gl::Extents &glExtents,
2591                                          const VkImageType imageType);
2592 
2593     // Takes an image and stages a subresource update for each level of it, including its full
2594     // extent and all its layers, at the specified GL level.
2595     void stageSubresourceUpdatesFromAllImageLevels(RefCounted<ImageHelper> *image,
2596                                                    gl::LevelIndex baseLevel);
2597 
2598     // Stage a clear to an arbitrary value.
2599     void stageClear(const gl::ImageIndex &index,
2600                     VkImageAspectFlags aspectFlags,
2601                     const VkClearValue &clearValue);
2602 
2603     // Stage a clear based on robust resource init.
2604     angle::Result stageRobustResourceClearWithFormat(ContextVk *contextVk,
2605                                                      const gl::ImageIndex &index,
2606                                                      const gl::Extents &glExtents,
2607                                                      const angle::Format &intendedFormat,
2608                                                      const angle::Format &imageFormat);
2609     void stageRobustResourceClear(const gl::ImageIndex &index);
2610 
2611     angle::Result stageResourceClearWithFormat(ContextVk *contextVk,
2612                                                const gl::ImageIndex &index,
2613                                                const gl::Extents &glExtents,
2614                                                const angle::Format &intendedFormat,
2615                                                const angle::Format &imageFormat,
2616                                                const VkClearValue &clearValue);
2617 
2618     // Stage the currently allocated image as updates to base level and on, making this !valid().
2619     // This is used for:
2620     //
2621     // - Mipmap generation, where levelCount is 1 so only the base level is retained
2622     // - Image respecification, where every level (other than those explicitly skipped) is staged
2623     void stageSelfAsSubresourceUpdates(ContextVk *contextVk,
2624                                        uint32_t levelCount,
2625                                        gl::TextureType textureType,
2626                                        const gl::CubeFaceArray<gl::TexLevelMask> &skipLevels);
2627 
2628     // Flush staged updates for a single subresource. Can optionally take a parameter to defer
2629     // clears to a subsequent RenderPass load op.
2630     angle::Result flushSingleSubresourceStagedUpdates(ContextVk *contextVk,
2631                                                       gl::LevelIndex levelGL,
2632                                                       uint32_t layer,
2633                                                       uint32_t layerCount,
2634                                                       ClearValuesArray *deferredClears,
2635                                                       uint32_t deferredClearIndex);
2636 
2637     // Flushes staged updates to a range of levels and layers from start to (but not including) end.
2638     // Due to the nature of updates (done wholly to a VkImageSubresourceLayers), some unsolicited
2639     // layers may also be updated.
2640     angle::Result flushStagedUpdates(ContextVk *contextVk,
2641                                      gl::LevelIndex levelGLStart,
2642                                      gl::LevelIndex levelGLEnd,
2643                                      uint32_t layerStart,
2644                                      uint32_t layerEnd,
2645                                      const gl::CubeFaceArray<gl::TexLevelMask> &skipLevels);
2646 
2647     // Creates a command buffer and flushes all staged updates.  This is used for one-time
2648     // initialization of resources that we don't expect to accumulate further staged updates, such
2649     // as with renderbuffers or surface images.
2650     angle::Result flushAllStagedUpdates(ContextVk *contextVk);
2651 
2652     bool hasStagedUpdatesForSubresource(gl::LevelIndex levelGL,
2653                                         uint32_t layer,
2654                                         uint32_t layerCount) const;
2655     bool hasStagedUpdatesInAllocatedLevels() const;
2656     bool hasBufferSourcedStagedUpdatesInAllLevels() const;
2657 
2658     bool removeStagedClearUpdatesAndReturnColor(gl::LevelIndex levelGL,
2659                                                 const VkClearColorValue **color);
2660 
2661     void recordWriteBarrier(Context *context,
2662                             VkImageAspectFlags aspectMask,
2663                             ImageLayout newLayout,
2664                             gl::LevelIndex levelStart,
2665                             uint32_t levelCount,
2666                             uint32_t layerStart,
2667                             uint32_t layerCount,
2668                             OutsideRenderPassCommandBufferHelper *commands);
2669 
2670     void recordReadSubresourceBarrier(Context *context,
2671                                       VkImageAspectFlags aspectMask,
2672                                       ImageLayout newLayout,
2673                                       gl::LevelIndex levelStart,
2674                                       uint32_t levelCount,
2675                                       uint32_t layerStart,
2676                                       uint32_t layerCount,
2677                                       OutsideRenderPassCommandBufferHelper *commands);
2678 
recordWriteBarrierOneOff(Context * context,ImageLayout newLayout,PrimaryCommandBuffer * commandBuffer,VkSemaphore * acquireNextImageSemaphoreOut)2679     void recordWriteBarrierOneOff(Context *context,
2680                                   ImageLayout newLayout,
2681                                   PrimaryCommandBuffer *commandBuffer,
2682                                   VkSemaphore *acquireNextImageSemaphoreOut)
2683     {
2684         if (mCurrentEvent.valid())
2685         {
2686             mCurrentEvent.release(context->getRenderer());
2687         }
2688 
2689         barrierImpl(context, getAspectFlags(), newLayout, mCurrentDeviceQueueIndex, nullptr,
2690                     commandBuffer, acquireNextImageSemaphoreOut);
2691     }
2692 
2693     // This function can be used to prevent issuing redundant layout transition commands.
2694     bool isReadBarrierNecessary(Renderer *renderer, ImageLayout newLayout) const;
2695     bool isReadSubresourceBarrierNecessary(ImageLayout newLayout,
2696                                            gl::LevelIndex levelStart,
2697                                            uint32_t levelCount,
2698                                            uint32_t layerStart,
2699                                            uint32_t layerCount) const;
2700     bool isWriteBarrierNecessary(ImageLayout newLayout,
2701                                  gl::LevelIndex levelStart,
2702                                  uint32_t levelCount,
2703                                  uint32_t layerStart,
2704                                  uint32_t layerCount) const;
2705 
2706     void recordReadBarrier(Context *context,
2707                            VkImageAspectFlags aspectMask,
2708                            ImageLayout newLayout,
2709                            OutsideRenderPassCommandBufferHelper *commands);
2710 
isQueueFamilyChangeNeccesary(DeviceQueueIndex newDeviceQueueIndex)2711     bool isQueueFamilyChangeNeccesary(DeviceQueueIndex newDeviceQueueIndex) const
2712     {
2713         return mCurrentDeviceQueueIndex.familyIndex() != newDeviceQueueIndex.familyIndex();
2714     }
2715 
2716     void changeLayoutAndQueue(Context *context,
2717                               VkImageAspectFlags aspectMask,
2718                               ImageLayout newLayout,
2719                               DeviceQueueIndex newDeviceQueueIndex,
2720                               OutsideRenderPassCommandBuffer *commandBuffer);
2721 
2722     // Returns true if barrier has been generated
2723     void updateLayoutAndBarrier(Context *context,
2724                                 VkImageAspectFlags aspectMask,
2725                                 ImageLayout newLayout,
2726                                 BarrierType barrierType,
2727                                 const QueueSerial &queueSerial,
2728                                 PipelineBarrierArray *pipelineBarriers,
2729                                 EventBarrierArray *eventBarriers,
2730                                 RefCountedEventCollector *eventCollector,
2731                                 VkSemaphore *semaphoreOut);
2732 
2733     // Performs an ownership transfer from an external instance or API.
2734     void acquireFromExternal(Context *context,
2735                              DeviceQueueIndex externalQueueIndex,
2736                              DeviceQueueIndex newDeviceQueueIndex,
2737                              ImageLayout currentLayout,
2738                              OutsideRenderPassCommandBuffer *commandBuffer);
2739 
2740     // Performs an ownership transfer to an external instance or API.
2741     void releaseToExternal(Context *context,
2742                            DeviceQueueIndex externalQueueIndex,
2743                            ImageLayout desiredLayout,
2744                            OutsideRenderPassCommandBuffer *commandBuffer);
2745 
2746     // Returns true if the image is owned by an external API or instance.
2747     bool isReleasedToExternal() const;
2748 
getFirstAllocatedLevel()2749     gl::LevelIndex getFirstAllocatedLevel() const
2750     {
2751         ASSERT(valid());
2752         return mFirstAllocatedLevel;
2753     }
2754     gl::LevelIndex getLastAllocatedLevel() const;
2755     LevelIndex toVkLevel(gl::LevelIndex levelIndexGL) const;
2756     gl::LevelIndex toGLLevel(LevelIndex levelIndexVk) const;
2757 
2758     angle::Result copyImageDataToBuffer(ContextVk *contextVk,
2759                                         gl::LevelIndex sourceLevelGL,
2760                                         uint32_t layerCount,
2761                                         uint32_t baseLayer,
2762                                         const gl::Box &sourceArea,
2763                                         BufferHelper *dstBuffer,
2764                                         uint8_t **outDataPtr);
2765 
2766     angle::Result copySurfaceImageToBuffer(DisplayVk *displayVk,
2767                                            gl::LevelIndex sourceLevelGL,
2768                                            uint32_t layerCount,
2769                                            uint32_t baseLayer,
2770                                            const gl::Box &sourceArea,
2771                                            vk::BufferHelper *bufferHelperOut);
2772 
2773     angle::Result copyBufferToSurfaceImage(DisplayVk *displayVk,
2774                                            gl::LevelIndex destLevelGL,
2775                                            uint32_t layerCount,
2776                                            uint32_t baseLayer,
2777                                            const gl::Box &destArea,
2778                                            vk::BufferHelper *bufferHelper);
2779 
2780     static angle::Result GetReadPixelsParams(ContextVk *contextVk,
2781                                              const gl::PixelPackState &packState,
2782                                              gl::Buffer *packBuffer,
2783                                              GLenum format,
2784                                              GLenum type,
2785                                              const gl::Rectangle &area,
2786                                              const gl::Rectangle &clippedArea,
2787                                              PackPixelsParams *paramsOut,
2788                                              GLuint *skipBytesOut);
2789 
2790     angle::Result readPixelsForGetImage(ContextVk *contextVk,
2791                                         const gl::PixelPackState &packState,
2792                                         gl::Buffer *packBuffer,
2793                                         gl::LevelIndex levelGL,
2794                                         uint32_t layer,
2795                                         uint32_t layerCount,
2796                                         GLenum format,
2797                                         GLenum type,
2798                                         void *pixels);
2799 
2800     angle::Result readPixelsForCompressedGetImage(ContextVk *contextVk,
2801                                                   const gl::PixelPackState &packState,
2802                                                   gl::Buffer *packBuffer,
2803                                                   gl::LevelIndex levelGL,
2804                                                   uint32_t layer,
2805                                                   uint32_t layerCount,
2806                                                   void *pixels);
2807 
2808     angle::Result readPixelsWithCompute(ContextVk *contextVk,
2809                                         ImageHelper *src,
2810                                         const PackPixelsParams &packPixelsParams,
2811                                         const VkOffset3D &srcOffset,
2812                                         const VkExtent3D &srcExtent,
2813                                         ptrdiff_t pixelsOffset,
2814                                         const VkImageSubresourceLayers &srcSubresource);
2815 
2816     angle::Result readPixels(ContextVk *contextVk,
2817                              const gl::Rectangle &area,
2818                              const PackPixelsParams &packPixelsParams,
2819                              VkImageAspectFlagBits copyAspectFlags,
2820                              gl::LevelIndex levelGL,
2821                              uint32_t layer,
2822                              void *pixels);
2823 
2824     angle::Result CalculateBufferInfo(ContextVk *contextVk,
2825                                       const gl::Extents &glExtents,
2826                                       const gl::InternalFormat &formatInfo,
2827                                       const gl::PixelUnpackState &unpack,
2828                                       GLenum type,
2829                                       bool is3D,
2830                                       GLuint *inputRowPitch,
2831                                       GLuint *inputDepthPitch,
2832                                       GLuint *inputSkipBytes);
2833 
2834     void onRenderPassAttach(const QueueSerial &queueSerial);
2835 
2836     // Mark a given subresource as written to.  The subresource is identified by [levelStart,
2837     // levelStart + levelCount) and [layerStart, layerStart + layerCount).
2838     void onWrite(gl::LevelIndex levelStart,
2839                  uint32_t levelCount,
2840                  uint32_t layerStart,
2841                  uint32_t layerCount,
2842                  VkImageAspectFlags aspectFlags);
hasImmutableSampler()2843     bool hasImmutableSampler() const { return mYcbcrConversionDesc.valid(); }
getExternalFormat()2844     uint64_t getExternalFormat() const { return mYcbcrConversionDesc.getExternalFormat(); }
isYuvResolve()2845     bool isYuvResolve() const { return mYcbcrConversionDesc.getExternalFormat() != 0; }
updateChromaFilter(Renderer * renderer,VkFilter filter)2846     bool updateChromaFilter(Renderer *renderer, VkFilter filter)
2847     {
2848         return mYcbcrConversionDesc.updateChromaFilter(renderer, filter);
2849     }
getYcbcrConversionDesc()2850     const YcbcrConversionDesc &getYcbcrConversionDesc() const { return mYcbcrConversionDesc; }
getY2YConversionDesc()2851     const YcbcrConversionDesc getY2YConversionDesc() const
2852     {
2853         YcbcrConversionDesc y2yDesc = mYcbcrConversionDesc;
2854         y2yDesc.updateConversionModel(VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY);
2855         return y2yDesc;
2856     }
2857 
2858     static YcbcrConversionDesc deriveConversionDesc(Context *context,
2859                                                     angle::FormatID actualFormatID,
2860                                                     angle::FormatID intendedFormatID);
2861 
2862     // Used by framebuffer and render pass functions to decide loadOps and invalidate/un-invalidate
2863     // render target contents.
2864     bool hasSubresourceDefinedContent(gl::LevelIndex level,
2865                                       uint32_t layerIndex,
2866                                       uint32_t layerCount) const;
2867     bool hasSubresourceDefinedStencilContent(gl::LevelIndex level,
2868                                              uint32_t layerIndex,
2869                                              uint32_t layerCount) const;
2870     void invalidateSubresourceContent(ContextVk *contextVk,
2871                                       gl::LevelIndex level,
2872                                       uint32_t layerIndex,
2873                                       uint32_t layerCount,
2874                                       bool *preferToKeepContentsDefinedOut);
2875     void invalidateSubresourceStencilContent(ContextVk *contextVk,
2876                                              gl::LevelIndex level,
2877                                              uint32_t layerIndex,
2878                                              uint32_t layerCount,
2879                                              bool *preferToKeepContentsDefinedOut);
2880     void restoreSubresourceContent(gl::LevelIndex level, uint32_t layerIndex, uint32_t layerCount);
2881     void restoreSubresourceStencilContent(gl::LevelIndex level,
2882                                           uint32_t layerIndex,
2883                                           uint32_t layerCount);
2884     angle::Result reformatStagedBufferUpdates(ContextVk *contextVk,
2885                                               angle::FormatID srcFormatID,
2886                                               angle::FormatID dstFormatID);
2887     bool hasStagedImageUpdatesWithMismatchedFormat(gl::LevelIndex levelStart,
2888                                                    gl::LevelIndex levelEnd,
2889                                                    angle::FormatID formatID) const;
2890 
setAcquireNextImageSemaphore(VkSemaphore semaphore)2891     void setAcquireNextImageSemaphore(VkSemaphore semaphore)
2892     {
2893         ASSERT(semaphore != VK_NULL_HANDLE);
2894         ASSERT(!mAcquireNextImageSemaphore.valid());
2895         mAcquireNextImageSemaphore.setHandle(semaphore);
2896     }
getAcquireNextImageSemaphore()2897     const Semaphore &getAcquireNextImageSemaphore() const { return mAcquireNextImageSemaphore; }
resetAcquireNextImageSemaphore()2898     void resetAcquireNextImageSemaphore() { mAcquireNextImageSemaphore.release(); }
isBackedByExternalMemory()2899     bool isBackedByExternalMemory() const
2900     {
2901         return mMemoryAllocationType == MemoryAllocationType::ImageExternal;
2902     }
2903 
2904     angle::Result initializeNonZeroMemory(Context *context,
2905                                           bool hasProtectedContent,
2906                                           VkMemoryPropertyFlags flags,
2907                                           VkDeviceSize size);
2908 
2909     size_t getLevelUpdateCount(gl::LevelIndex level) const;
2910 
2911     // Create event if needed and record the event in ImageHelper::mCurrentEvent.
2912     void setCurrentRefCountedEvent(Context *context, EventMaps &eventMaps);
2913 
2914     void updatePipelineStageAccessHistory();
2915 
2916   private:
2917     ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
2918     struct ClearUpdate
2919     {
2920         bool operator==(const ClearUpdate &rhs) const
2921         {
2922             return memcmp(this, &rhs, sizeof(ClearUpdate)) == 0;
2923         }
2924         VkImageAspectFlags aspectFlags;
2925         VkClearValue value;
2926         uint32_t levelIndex;
2927         uint32_t layerIndex;
2928         uint32_t layerCount;
2929         // For ClearEmulatedChannelsOnly, mask of which channels to clear.
2930         VkColorComponentFlags colorMaskFlags;
2931     };
2932     ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
2933     ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
2934     struct ClearPartialUpdate
2935     {
2936         bool operator==(const ClearPartialUpdate &rhs) const
2937         {
2938             return memcmp(this, &rhs, sizeof(ClearPartialUpdate)) == 0;
2939         }
2940         VkImageAspectFlags aspectFlags;
2941         VkClearValue clearValue;
2942         uint32_t levelIndex;
2943         uint32_t layerIndex;
2944         uint32_t layerCount;
2945         VkOffset3D offset;
2946         VkExtent3D extent;
2947         gl::TextureType textureType;
2948         uint8_t _padding[3];
2949     };
2950     ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
2951     struct BufferUpdate
2952     {
2953         BufferHelper *bufferHelper;
2954         VkBufferImageCopy copyRegion;
2955         angle::FormatID formatID;
2956     };
2957     struct ImageUpdate
2958     {
2959         VkImageCopy copyRegion;
2960         angle::FormatID formatID;
2961     };
2962 
2963     struct SubresourceUpdate : angle::NonCopyable
2964     {
2965         SubresourceUpdate();
2966         ~SubresourceUpdate();
2967         SubresourceUpdate(RefCounted<BufferHelper> *bufferIn,
2968                           BufferHelper *bufferHelperIn,
2969                           const VkBufferImageCopy &copyRegion,
2970                           angle::FormatID formatID);
2971         SubresourceUpdate(RefCounted<ImageHelper> *imageIn,
2972                           const VkImageCopy &copyRegion,
2973                           angle::FormatID formatID);
2974         SubresourceUpdate(VkImageAspectFlags aspectFlags,
2975                           const VkClearValue &clearValue,
2976                           const gl::ImageIndex &imageIndex);
2977         SubresourceUpdate(const VkImageAspectFlags aspectFlags,
2978                           const VkClearValue &clearValue,
2979                           const gl::TextureType textureType,
2980                           const uint32_t levelIndex,
2981                           const uint32_t layerIndex,
2982                           const uint32_t layerCount,
2983                           const gl::Box &clearArea);
2984         SubresourceUpdate(VkImageAspectFlags aspectFlags,
2985                           const VkClearValue &clearValue,
2986                           gl::LevelIndex level,
2987                           uint32_t layerIndex,
2988                           uint32_t layerCount);
2989         SubresourceUpdate(VkColorComponentFlags colorMaskFlags,
2990                           const VkClearColorValue &clearValue,
2991                           const gl::ImageIndex &imageIndex);
2992         SubresourceUpdate(SubresourceUpdate &&other);
2993 
2994         SubresourceUpdate &operator=(SubresourceUpdate &&other);
2995 
2996         void release(Renderer *renderer);
2997 
2998         // Returns true if the update's layer range exact matches [layerIndex,
2999         // layerIndex+layerCount) range
3000         bool matchesLayerRange(uint32_t layerIndex, uint32_t layerCount) const;
3001         // Returns true if the update is to any layer within range of [layerIndex,
3002         // layerIndex+layerCount)
3003         bool intersectsLayerRange(uint32_t layerIndex, uint32_t layerCount) const;
3004         void getDestSubresource(uint32_t imageLayerCount,
3005                                 uint32_t *baseLayerOut,
3006                                 uint32_t *layerCountOut) const;
3007         VkImageAspectFlags getDestAspectFlags() const;
3008 
3009         UpdateSource updateSource;
3010         union
3011         {
3012             ClearUpdate clear;
3013             ClearPartialUpdate clearPartial;
3014             BufferUpdate buffer;
3015             ImageUpdate image;
3016         } data;
3017         union
3018         {
3019             RefCounted<ImageHelper> *image;
3020             RefCounted<BufferHelper> *buffer;
3021         } refCounted;
3022     };
3023 
3024     // Up to 8 layers are tracked per level for whether contents are defined, above which the
3025     // contents are considered unconditionally defined.  This handles the more likely scenarios of:
3026     //
3027     // - Single layer framebuffer attachments,
3028     // - Cube map framebuffer attachments,
3029     // - Multi-view rendering.
3030     //
3031     // If there arises a need to optimize an application that invalidates layer >= 8, this can
3032     // easily be raised to 32 to 64 bits.  Beyond that, an additional hash map can be used to track
3033     // such subresources.
3034     static constexpr uint32_t kMaxContentDefinedLayerCount = 8;
3035     using LevelContentDefinedMask = angle::BitSet8<kMaxContentDefinedLayerCount>;
3036 
3037     void deriveExternalImageTiling(const void *createInfoChain);
3038 
3039     // Used to initialize ImageFormats from actual format, with no pNext from a VkImageCreateInfo
3040     // object.
3041     void setImageFormatsFromActualFormat(VkFormat actualFormat, ImageFormats &imageFormatsOut);
3042 
3043     // Called from flushStagedUpdates, removes updates that are later superseded by another.  This
3044     // cannot be done at the time the updates were staged, as the image is not created (and thus the
3045     // extents are not known).
3046     void removeSupersededUpdates(ContextVk *contextVk, const gl::TexLevelMask skipLevelsAllFaces);
3047 
3048     void initImageMemoryBarrierStruct(Renderer *renderer,
3049                                       VkImageAspectFlags aspectMask,
3050                                       ImageLayout newLayout,
3051                                       uint32_t newQueueFamilyIndex,
3052                                       VkImageMemoryBarrier *imageMemoryBarrier) const;
3053 
3054     // Generalized to accept both "primary" and "secondary" command buffers.
3055     template <typename CommandBufferT>
3056     void barrierImpl(Context *context,
3057                      VkImageAspectFlags aspectMask,
3058                      ImageLayout newLayout,
3059                      DeviceQueueIndex newDeviceQueueIndex,
3060                      RefCountedEventCollector *eventCollector,
3061                      CommandBufferT *commandBuffer,
3062                      VkSemaphore *acquireNextImageSemaphoreOut);
3063 
3064     void setSubresourcesWrittenSinceBarrier(gl::LevelIndex levelStart,
3065                                             uint32_t levelCount,
3066                                             uint32_t layerStart,
3067                                             uint32_t layerCount);
3068 
3069     void resetSubresourcesWrittenSinceBarrier();
areLevelSubresourcesWrittenWithinMaskRange(uint32_t level,ImageLayerWriteMask & layerMask)3070     bool areLevelSubresourcesWrittenWithinMaskRange(uint32_t level,
3071                                                     ImageLayerWriteMask &layerMask) const
3072     {
3073         return (mSubresourcesWrittenSinceBarrier[level] & layerMask) != 0;
3074     }
3075 
3076     // If the image has emulated channels, we clear them once so as not to leave garbage on those
3077     // channels.
3078     VkColorComponentFlags getEmulatedChannelsMask() const;
3079     void stageClearIfEmulatedFormat(bool isRobustResourceInitEnabled, bool isExternalImage);
3080     bool verifyEmulatedClearsAreBeforeOtherUpdates(const std::vector<SubresourceUpdate> &updates);
3081 
3082     // Clear either color or depth/stencil based on image format.
3083     void clear(Renderer *renderer,
3084                VkImageAspectFlags aspectFlags,
3085                const VkClearValue &value,
3086                LevelIndex mipLevel,
3087                uint32_t baseArrayLayer,
3088                uint32_t layerCount,
3089                OutsideRenderPassCommandBuffer *commandBuffer);
3090 
3091     void clearColor(Renderer *renderer,
3092                     const VkClearColorValue &color,
3093                     LevelIndex baseMipLevelVk,
3094                     uint32_t levelCount,
3095                     uint32_t baseArrayLayer,
3096                     uint32_t layerCount,
3097                     OutsideRenderPassCommandBuffer *commandBuffer);
3098 
3099     void clearDepthStencil(Renderer *renderer,
3100                            VkImageAspectFlags clearAspectFlags,
3101                            const VkClearDepthStencilValue &depthStencil,
3102                            LevelIndex baseMipLevelVk,
3103                            uint32_t levelCount,
3104                            uint32_t baseArrayLayer,
3105                            uint32_t layerCount,
3106                            OutsideRenderPassCommandBuffer *commandBuffer);
3107 
3108     angle::Result clearEmulatedChannels(ContextVk *contextVk,
3109                                         VkColorComponentFlags colorMaskFlags,
3110                                         const VkClearValue &value,
3111                                         LevelIndex mipLevel,
3112                                         uint32_t baseArrayLayer,
3113                                         uint32_t layerCount);
3114 
3115     angle::Result updateSubresourceOnHost(Context *context,
3116                                           ApplyImageUpdate applyUpdate,
3117                                           const gl::ImageIndex &index,
3118                                           const gl::Extents &glExtents,
3119                                           const gl::Offset &offset,
3120                                           const uint8_t *source,
3121                                           const GLuint rowPitch,
3122                                           const GLuint depthPitch,
3123                                           bool *copiedOut);
3124 
3125     // ClearEmulatedChannels updates are expected in the beginning of the level update list. They
3126     // can be processed first and removed. By doing so, if this is the only update for the image,
3127     // an unnecessary layout transition can be avoided.
3128     angle::Result flushStagedClearEmulatedChannelsUpdates(ContextVk *contextVk,
3129                                                           gl::LevelIndex levelGLStart,
3130                                                           gl::LevelIndex levelGLLimit,
3131                                                           bool *otherUpdatesToFlushOut);
3132 
3133     // Flushes staged updates to a range of levels and layers from start to end. The updates do not
3134     // include ClearEmulatedChannelsOnly, which are processed in a separate function.
3135     angle::Result flushStagedUpdatesImpl(ContextVk *contextVk,
3136                                          gl::LevelIndex levelGLStart,
3137                                          gl::LevelIndex levelGLEnd,
3138                                          uint32_t layerStart,
3139                                          uint32_t layerEnd,
3140                                          const gl::TexLevelMask &skipLevelsAllFaces);
3141 
3142     // Limit the input level to the number of levels in subresource update list.
3143     void clipLevelToUpdateListUpperLimit(gl::LevelIndex *level) const;
3144 
3145     std::vector<SubresourceUpdate> *getLevelUpdates(gl::LevelIndex level);
3146     const std::vector<SubresourceUpdate> *getLevelUpdates(gl::LevelIndex level) const;
3147 
3148     void appendSubresourceUpdate(gl::LevelIndex level, SubresourceUpdate &&update);
3149     void prependSubresourceUpdate(gl::LevelIndex level, SubresourceUpdate &&update);
3150 
3151     enum class PruneReason
3152     {
3153         MemoryOptimization,
3154         MinimizeWorkBeforeFlush
3155     };
3156     void pruneSupersededUpdatesForLevel(ContextVk *contextVk,
3157                                         const gl::LevelIndex level,
3158                                         const PruneReason reason);
3159 
3160     // Whether there are any updates in [start, end).
3161     bool hasStagedUpdatesInLevels(gl::LevelIndex levelStart, gl::LevelIndex levelEnd) const;
3162 
3163     // Used only for assertions, these functions verify that
3164     // SubresourceUpdate::refcountedObject::image or buffer references have the correct ref count.
3165     // This is to prevent accidental leaks.
3166     bool validateSubresourceUpdateImageRefConsistent(RefCounted<ImageHelper> *image) const;
3167     bool validateSubresourceUpdateBufferRefConsistent(RefCounted<BufferHelper> *buffer) const;
3168     bool validateSubresourceUpdateRefCountsConsistent() const;
3169 
3170     void resetCachedProperties();
3171     void setEntireContentDefined();
3172     void setEntireContentUndefined();
3173     void setContentDefined(LevelIndex levelStart,
3174                            uint32_t levelCount,
3175                            uint32_t layerStart,
3176                            uint32_t layerCount,
3177                            VkImageAspectFlags aspectFlags);
3178     void invalidateSubresourceContentImpl(ContextVk *contextVk,
3179                                           gl::LevelIndex level,
3180                                           uint32_t layerIndex,
3181                                           uint32_t layerCount,
3182                                           VkImageAspectFlagBits aspect,
3183                                           LevelContentDefinedMask *contentDefinedMask,
3184                                           bool *preferToKeepContentsDefinedOut);
3185     void restoreSubresourceContentImpl(gl::LevelIndex level,
3186                                        uint32_t layerIndex,
3187                                        uint32_t layerCount,
3188                                        VkImageAspectFlagBits aspect,
3189                                        LevelContentDefinedMask *contentDefinedMask);
3190 
3191     // Use the following functions to access m*ContentDefined to make sure the correct level index
3192     // is used (i.e. vk::LevelIndex and not gl::LevelIndex).
3193     LevelContentDefinedMask &getLevelContentDefined(LevelIndex level);
3194     LevelContentDefinedMask &getLevelStencilContentDefined(LevelIndex level);
3195     const LevelContentDefinedMask &getLevelContentDefined(LevelIndex level) const;
3196     const LevelContentDefinedMask &getLevelStencilContentDefined(LevelIndex level) const;
3197 
3198     angle::Result initLayerImageViewImpl(Context *context,
3199                                          gl::TextureType textureType,
3200                                          VkImageAspectFlags aspectMask,
3201                                          const gl::SwizzleState &swizzleMap,
3202                                          ImageView *imageViewOut,
3203                                          LevelIndex baseMipLevelVk,
3204                                          uint32_t levelCount,
3205                                          uint32_t baseArrayLayer,
3206                                          uint32_t layerCount,
3207                                          VkFormat imageFormat,
3208                                          VkImageUsageFlags usageFlags,
3209                                          gl::YuvSamplingMode yuvSamplingMode) const;
3210 
3211     angle::Result readPixelsImpl(ContextVk *contextVk,
3212                                  const gl::Rectangle &area,
3213                                  const PackPixelsParams &packPixelsParams,
3214                                  VkImageAspectFlagBits copyAspectFlags,
3215                                  gl::LevelIndex levelGL,
3216                                  uint32_t layer,
3217                                  void *pixels);
3218 
3219     angle::Result packReadPixelBuffer(ContextVk *contextVk,
3220                                       const gl::Rectangle &area,
3221                                       const PackPixelsParams &packPixelsParams,
3222                                       const angle::Format &readFormat,
3223                                       const angle::Format &aspectFormat,
3224                                       const uint8_t *readPixelBuffer,
3225                                       gl::LevelIndex levelGL,
3226                                       void *pixels);
3227 
3228     bool canCopyWithTransformForReadPixels(const PackPixelsParams &packPixelsParams,
3229                                            const VkExtent3D &srcExtent,
3230                                            const angle::Format *readFormat,
3231                                            ptrdiff_t pixelsOffset);
3232     bool canCopyWithComputeForReadPixels(const PackPixelsParams &packPixelsParams,
3233                                          const VkExtent3D &srcExtent,
3234                                          const angle::Format *readFormat,
3235                                          ptrdiff_t pixelsOffset);
3236 
3237     // Returns true if source data and actual image format matches except color space differences.
isDataFormatMatchForCopy(angle::FormatID srcDataFormatID)3238     bool isDataFormatMatchForCopy(angle::FormatID srcDataFormatID) const
3239     {
3240         if (mActualFormatID == srcDataFormatID)
3241         {
3242             return true;
3243         }
3244         angle::FormatID actualFormatLinear =
3245             getActualFormat().isSRGB ? ConvertToLinear(mActualFormatID) : mActualFormatID;
3246         angle::FormatID srcDataFormatIDLinear = angle::Format::Get(srcDataFormatID).isSRGB
3247                                                     ? ConvertToLinear(srcDataFormatID)
3248                                                     : srcDataFormatID;
3249         return actualFormatLinear == srcDataFormatIDLinear;
3250     }
3251 
3252     static constexpr int kThreadholdForComputeTransCoding = 4096;
shouldUseComputeForTransCoding(LevelIndex level)3253     bool shouldUseComputeForTransCoding(LevelIndex level)
3254     {
3255         // Using texture size instead of extent size to simplify the problem.
3256         gl::Extents ext = getLevelExtents2D(level);
3257         return ext.width * ext.height > kThreadholdForComputeTransCoding;
3258     }
3259 
3260     void adjustLayerRange(const std::vector<SubresourceUpdate> &levelUpdates,
3261                           uint32_t *layerStart,
3262                           uint32_t *layerEnd);
3263 
3264     // Vulkan objects.
3265     Image mImage;
3266     DeviceMemory mDeviceMemory;
3267     Allocation mVmaAllocation;
3268 
3269     // Image properties.
3270     VkImageCreateInfo mVkImageCreateInfo;
3271     VkImageType mImageType;
3272     VkImageTiling mTilingMode;
3273     VkImageCreateFlags mCreateFlags;
3274     VkImageUsageFlags mUsage;
3275     // For Android swapchain images, the Vulkan VkImage must be "rotated".  However, most of ANGLE
3276     // uses non-rotated extents (i.e. the way the application views the extents--see "Introduction
3277     // to Android rotation and pre-rotation" in "SurfaceVk.cpp").  Thus, mExtents are non-rotated.
3278     // The rotated extents are also stored along with a bool that indicates if the aspect ratio is
3279     // different between the rotated and non-rotated extents.
3280     VkExtent3D mExtents;
3281     bool mRotatedAspectRatio;
3282     angle::FormatID mIntendedFormatID;
3283     angle::FormatID mActualFormatID;
3284     GLint mSamples;
3285     ImageSerial mImageSerial;
3286 
3287     // Current state.
3288     ImageLayout mCurrentLayout;
3289     DeviceQueueIndex mCurrentDeviceQueueIndex;
3290     // For optimizing transition between different shader readonly layouts
3291     ImageLayout mLastNonShaderReadOnlyLayout;
3292     VkPipelineStageFlags mCurrentShaderReadStageMask;
3293     // Track how it is being used by current open renderpass.
3294     RenderPassUsageFlags mRenderPassUsageFlags;
3295     // The QueueSerial that associated with the last barrier.
3296     QueueSerial mBarrierQueueSerial;
3297 
3298     // The current refCounted event. When barrier or layout change is needed, we should wait for
3299     // this event.
3300     RefCountedEvent mCurrentEvent;
3301     RefCountedEvent mLastNonShaderReadOnlyEvent;
3302     // Track history of pipeline stages being used. Each bit represents the fragment or
3303     // attachment usage, i.e, a bit is set if the layout indicates a fragment or colorAttachment
3304     // pipeline stages, and bit is 0 if used by other stages like vertex shader or compute or
3305     // transfer. Every use of image update the usage history by shifting the bitfields left and new
3306     // bit that represents the new pipeline usage is added to the right most bit. This way we track
3307     // if there is any non-fragment pipeline usage during the past usages (i.e., the window of
3308     // usage history is number of bits in mPipelineStageAccessHeuristic). This information provides
3309     // heuristic for making decisions if a VkEvent should be used to track the operation.
3310     PipelineStageAccessHeuristic mPipelineStageAccessHeuristic;
3311 
3312     // Whether ANGLE currently has ownership of this resource or it's released to external.
3313     bool mIsReleasedToExternal;
3314 
3315     // For imported images
3316     YcbcrConversionDesc mYcbcrConversionDesc;
3317 
3318     // The first level that has been allocated. For mutable textures, this should be same as
3319     // mBaseLevel since we always reallocate VkImage based on mBaseLevel change. But for immutable
3320     // textures, we always allocate from level 0 regardless of mBaseLevel change.
3321     gl::LevelIndex mFirstAllocatedLevel;
3322 
3323     // Cached properties.
3324     uint32_t mLayerCount;
3325     uint32_t mLevelCount;
3326 
3327     // Image formats used for imageless framebuffers.
3328     ImageFormats mViewFormats;
3329 
3330     std::vector<std::vector<SubresourceUpdate>> mSubresourceUpdates;
3331     VkDeviceSize mTotalStagedBufferUpdateSize;
3332 
3333     // Optimization for repeated clear with the same value. If this pointer is not null, the entire
3334     // image it has been cleared to the specified clear value. If another clear call is made with
3335     // the exact same clear value, we will detect and skip the clear call.
3336     Optional<ClearUpdate> mCurrentSingleClearValue;
3337 
3338     // Track whether each subresource has defined contents.  Up to 8 layers are tracked per level,
3339     // above which the contents are considered unconditionally defined.
3340     gl::TexLevelArray<LevelContentDefinedMask> mContentDefined;
3341     gl::TexLevelArray<LevelContentDefinedMask> mStencilContentDefined;
3342 
3343     // Used for memory allocation tracking.
3344     // Memory size allocated for the image in the memory during the initialization.
3345     VkDeviceSize mAllocationSize;
3346     // Type of the memory allocation for the image (Image or ImageExternal).
3347     MemoryAllocationType mMemoryAllocationType;
3348     // Memory type index used for the allocation. It can be used to determine the heap index.
3349     uint32_t mMemoryTypeIndex;
3350 
3351     // Only used for swapChain images. This is set when an image is acquired and is waited on
3352     // by the next submission (which uses this image), at which point it is released.
3353     Semaphore mAcquireNextImageSemaphore;
3354 
3355     // Used to track subresource writes per level/layer. This can help parallelize writes to
3356     // different levels or layers of the image, such as data uploads.
3357     // See comment on kMaxParallelLayerWrites.
3358     gl::TexLevelArray<ImageLayerWriteMask> mSubresourcesWrittenSinceBarrier;
3359 };
3360 
usesImage(const ImageHelper & image)3361 ANGLE_INLINE bool RenderPassCommandBufferHelper::usesImage(const ImageHelper &image) const
3362 {
3363     return image.usedByCommandBuffer(mQueueSerial);
3364 }
3365 
startedAndUsesImageWithBarrier(const ImageHelper & image)3366 ANGLE_INLINE bool RenderPassCommandBufferHelper::startedAndUsesImageWithBarrier(
3367     const ImageHelper &image) const
3368 {
3369     return mRenderPassStarted && image.getBarrierQueueSerial() == mQueueSerial;
3370 }
3371 
3372 // A vector of image views, such as one per level or one per layer.
3373 using ImageViewVector = std::vector<ImageView>;
3374 
3375 // A vector of vector of image views.  Primary index is layer, secondary index is level.
3376 using LayerLevelImageViewVector = std::vector<ImageViewVector>;
3377 
3378 using SubresourceImageViewMap = angle::HashMap<ImageSubresourceRange, std::unique_ptr<ImageView>>;
3379 
3380 // Address mode for layers: only possible to access either all layers, or up to
3381 // IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS layers.  This enum uses 0 for all layers and the rest of
3382 // the values conveniently alias the number of layers.
3383 enum LayerMode
3384 {
3385     All,
3386     _1,
3387     _2,
3388     _3,
3389     _4,
3390 };
3391 static_assert(gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS == 4, "Update LayerMode");
3392 
3393 LayerMode GetLayerMode(const vk::ImageHelper &image, uint32_t layerCount);
3394 
3395 // The colorspace of image views derived from angle::ColorspaceState
3396 enum class ImageViewColorspace
3397 {
3398     Invalid = 0,
3399     Linear,
3400     SRGB,
3401 };
3402 
3403 class ImageViewHelper final : angle::NonCopyable
3404 {
3405   public:
3406     ImageViewHelper();
3407     ImageViewHelper(ImageViewHelper &&other);
3408     ~ImageViewHelper();
3409 
3410     void init(Renderer *renderer);
3411     void destroy(VkDevice device);
3412 
getLinearReadImageView()3413     const ImageView &getLinearReadImageView() const
3414     {
3415         return getValidReadViewImpl(mPerLevelRangeLinearReadImageViews);
3416     }
getSRGBReadImageView()3417     const ImageView &getSRGBReadImageView() const
3418     {
3419         return getValidReadViewImpl(mPerLevelRangeSRGBReadImageViews);
3420     }
getLinearCopyImageView()3421     const ImageView &getLinearCopyImageView() const
3422     {
3423         return getValidReadViewImpl(mPerLevelRangeLinearCopyImageViews);
3424     }
getSRGBCopyImageView()3425     const ImageView &getSRGBCopyImageView() const
3426     {
3427         return getValidReadViewImpl(mPerLevelRangeSRGBCopyImageViews);
3428     }
getStencilReadImageView()3429     const ImageView &getStencilReadImageView() const
3430     {
3431         return getValidReadViewImpl(mPerLevelRangeStencilReadImageViews);
3432     }
3433 
getReadImageView()3434     const ImageView &getReadImageView() const
3435     {
3436         return mReadColorspace == ImageViewColorspace::Linear
3437                    ? getReadViewImpl(mPerLevelRangeLinearReadImageViews)
3438                    : getReadViewImpl(mPerLevelRangeSRGBReadImageViews);
3439     }
3440 
getCopyImageView()3441     const ImageView &getCopyImageView() const
3442     {
3443         return mReadColorspace == ImageViewColorspace::Linear
3444                    ? getReadViewImpl(mPerLevelRangeLinearCopyImageViews)
3445                    : getReadViewImpl(mPerLevelRangeSRGBCopyImageViews);
3446     }
3447 
getSamplerExternal2DY2YEXTImageView()3448     ImageView &getSamplerExternal2DY2YEXTImageView()
3449     {
3450         return getReadViewImpl(mPerLevelRangeSamplerExternal2DY2YEXTImageViews);
3451     }
3452 
getSamplerExternal2DY2YEXTImageView()3453     const ImageView &getSamplerExternal2DY2YEXTImageView() const
3454     {
3455         return getValidReadViewImpl(mPerLevelRangeSamplerExternal2DY2YEXTImageViews);
3456     }
3457 
getFragmentShadingRateImageView()3458     const ImageView &getFragmentShadingRateImageView() const
3459     {
3460         return mFragmentShadingRateImageView;
3461     }
3462 
3463     // Used when initialized RenderTargets.
hasStencilReadImageView()3464     bool hasStencilReadImageView() const
3465     {
3466         return mCurrentBaseMaxLevelHash < mPerLevelRangeStencilReadImageViews.size()
3467                    ? mPerLevelRangeStencilReadImageViews[mCurrentBaseMaxLevelHash].valid()
3468                    : false;
3469     }
3470 
hasCopyImageView()3471     bool hasCopyImageView() const
3472     {
3473         if ((mReadColorspace == ImageViewColorspace::Linear &&
3474              mCurrentBaseMaxLevelHash < mPerLevelRangeLinearCopyImageViews.size()) ||
3475             (mReadColorspace == ImageViewColorspace::SRGB &&
3476              mCurrentBaseMaxLevelHash < mPerLevelRangeSRGBCopyImageViews.size()))
3477         {
3478             return getCopyImageView().valid();
3479         }
3480         else
3481         {
3482             return false;
3483         }
3484     }
3485 
3486     // For applications that frequently switch a texture's max level, and make no other changes to
3487     // the texture, change the currently-used max level, and potentially create new "read views"
3488     // for the new max-level
3489     angle::Result initReadViews(ContextVk *contextVk,
3490                                 gl::TextureType viewType,
3491                                 const ImageHelper &image,
3492                                 const gl::SwizzleState &formatSwizzle,
3493                                 const gl::SwizzleState &readSwizzle,
3494                                 LevelIndex baseLevel,
3495                                 uint32_t levelCount,
3496                                 uint32_t baseLayer,
3497                                 uint32_t layerCount,
3498                                 bool requiresSRGBViews,
3499                                 VkImageUsageFlags imageUsageFlags);
3500 
3501     // Creates a storage view with all layers of the level.
3502     angle::Result getLevelStorageImageView(Context *context,
3503                                            gl::TextureType viewType,
3504                                            const ImageHelper &image,
3505                                            LevelIndex levelVk,
3506                                            uint32_t layer,
3507                                            VkImageUsageFlags imageUsageFlags,
3508                                            angle::FormatID formatID,
3509                                            const ImageView **imageViewOut);
3510 
3511     // Creates a storage view with a single layer of the level.
3512     angle::Result getLevelLayerStorageImageView(Context *context,
3513                                                 const ImageHelper &image,
3514                                                 LevelIndex levelVk,
3515                                                 uint32_t layer,
3516                                                 VkImageUsageFlags imageUsageFlags,
3517                                                 angle::FormatID formatID,
3518                                                 const ImageView **imageViewOut);
3519 
3520     // Creates a draw view with a range of layers of the level.
3521     angle::Result getLevelDrawImageView(Context *context,
3522                                         const ImageHelper &image,
3523                                         LevelIndex levelVk,
3524                                         uint32_t layer,
3525                                         uint32_t layerCount,
3526                                         const ImageView **imageViewOut);
3527 
3528     // Creates a draw view with a single layer of the level.
3529     angle::Result getLevelLayerDrawImageView(Context *context,
3530                                              const ImageHelper &image,
3531                                              LevelIndex levelVk,
3532                                              uint32_t layer,
3533                                              const ImageView **imageViewOut);
3534 
3535     // Creates a depth-xor-stencil view with a range of layers of the level.
3536     angle::Result getLevelDepthOrStencilImageView(Context *context,
3537                                                   const ImageHelper &image,
3538                                                   LevelIndex levelVk,
3539                                                   uint32_t layer,
3540                                                   uint32_t layerCount,
3541                                                   VkImageAspectFlagBits aspect,
3542                                                   const ImageView **imageViewOut);
3543 
3544     // Creates a  depth-xor-stencil view with a single layer of the level.
3545     angle::Result getLevelLayerDepthOrStencilImageView(Context *context,
3546                                                        const ImageHelper &image,
3547                                                        LevelIndex levelVk,
3548                                                        uint32_t layer,
3549                                                        VkImageAspectFlagBits aspect,
3550                                                        const ImageView **imageViewOut);
3551 
3552     // Creates a fragment shading rate view.
3553     angle::Result initFragmentShadingRateView(ContextVk *contextVk, ImageHelper *image);
3554 
3555     // Return unique Serial for an imageView.
3556     ImageOrBufferViewSubresourceSerial getSubresourceSerial(gl::LevelIndex levelGL,
3557                                                             uint32_t levelCount,
3558                                                             uint32_t layer,
3559                                                             LayerMode layerMode) const;
3560 
3561     // Return unique Serial for an imageView for a specific colorspace.
3562     ImageOrBufferViewSubresourceSerial getSubresourceSerialForColorspace(
3563         gl::LevelIndex levelGL,
3564         uint32_t levelCount,
3565         uint32_t layer,
3566         LayerMode layerMode,
3567         ImageViewColorspace readColorspace) const;
3568 
3569     ImageSubresourceRange getSubresourceDrawRange(gl::LevelIndex level,
3570                                                   uint32_t layer,
3571                                                   LayerMode layerMode) const;
3572 
3573     bool isImageViewGarbageEmpty() const;
3574 
3575     void release(Renderer *renderer, const ResourceUse &use);
3576 
3577     // Helpers for colorspace state
getColorspaceForRead()3578     ImageViewColorspace getColorspaceForRead() const { return mReadColorspace; }
hasColorspaceOverrideForRead(const ImageHelper & image)3579     bool hasColorspaceOverrideForRead(const ImageHelper &image) const
3580     {
3581         ASSERT(image.valid());
3582         return (!image.getActualFormat().isSRGB &&
3583                 mReadColorspace == vk::ImageViewColorspace::SRGB) ||
3584                (image.getActualFormat().isSRGB &&
3585                 mReadColorspace == vk::ImageViewColorspace::Linear);
3586     }
3587 
hasColorspaceOverrideForWrite(const ImageHelper & image)3588     bool hasColorspaceOverrideForWrite(const ImageHelper &image) const
3589     {
3590         ASSERT(image.valid());
3591         return (!image.getActualFormat().isSRGB &&
3592                 mWriteColorspace == vk::ImageViewColorspace::SRGB) ||
3593                (image.getActualFormat().isSRGB &&
3594                 mWriteColorspace == vk::ImageViewColorspace::Linear);
3595     }
3596     angle::FormatID getColorspaceOverrideFormatForWrite(angle::FormatID format) const;
updateStaticTexelFetch(const ImageHelper & image,bool staticTexelFetchAccess)3597     void updateStaticTexelFetch(const ImageHelper &image, bool staticTexelFetchAccess) const
3598     {
3599         if (mColorspaceState.hasStaticTexelFetchAccess != staticTexelFetchAccess)
3600         {
3601             mColorspaceState.hasStaticTexelFetchAccess = staticTexelFetchAccess;
3602             updateColorspace(image);
3603         }
3604     }
updateSrgbDecode(const ImageHelper & image,gl::SrgbDecode srgbDecode)3605     void updateSrgbDecode(const ImageHelper &image, gl::SrgbDecode srgbDecode) const
3606     {
3607         if (mColorspaceState.srgbDecode != srgbDecode)
3608         {
3609             mColorspaceState.srgbDecode = srgbDecode;
3610             updateColorspace(image);
3611         }
3612     }
updateSrgbOverride(const ImageHelper & image,gl::SrgbOverride srgbOverride)3613     void updateSrgbOverride(const ImageHelper &image, gl::SrgbOverride srgbOverride) const
3614     {
3615         if (mColorspaceState.srgbOverride != srgbOverride)
3616         {
3617             mColorspaceState.srgbOverride = srgbOverride;
3618             updateColorspace(image);
3619         }
3620     }
updateSrgbWiteControlMode(const ImageHelper & image,gl::SrgbWriteControlMode srgbWriteControl)3621     void updateSrgbWiteControlMode(const ImageHelper &image,
3622                                    gl::SrgbWriteControlMode srgbWriteControl) const
3623     {
3624         if (mColorspaceState.srgbWriteControl != srgbWriteControl)
3625         {
3626             mColorspaceState.srgbWriteControl = srgbWriteControl;
3627             updateColorspace(image);
3628         }
3629     }
updateEglImageColorspace(const ImageHelper & image,egl::ImageColorspace eglImageColorspace)3630     void updateEglImageColorspace(const ImageHelper &image,
3631                                   egl::ImageColorspace eglImageColorspace) const
3632     {
3633         if (mColorspaceState.eglImageColorspace != eglImageColorspace)
3634         {
3635             mColorspaceState.eglImageColorspace = eglImageColorspace;
3636             updateColorspace(image);
3637         }
3638     }
3639 
3640   private:
getReadImageView()3641     ImageView &getReadImageView()
3642     {
3643         return mReadColorspace == ImageViewColorspace::Linear
3644                    ? getReadViewImpl(mPerLevelRangeLinearReadImageViews)
3645                    : getReadViewImpl(mPerLevelRangeSRGBReadImageViews);
3646     }
getCopyImageView()3647     ImageView &getCopyImageView()
3648     {
3649         return mReadColorspace == ImageViewColorspace::Linear
3650                    ? getReadViewImpl(mPerLevelRangeLinearCopyImageViews)
3651                    : getReadViewImpl(mPerLevelRangeSRGBCopyImageViews);
3652     }
3653 
3654     // Used by public get*ImageView() methods to do proper assert based on vector size and validity
getValidReadViewImpl(const ImageViewVector & imageViewVector)3655     inline const ImageView &getValidReadViewImpl(const ImageViewVector &imageViewVector) const
3656     {
3657         ASSERT(mCurrentBaseMaxLevelHash < imageViewVector.size() &&
3658                imageViewVector[mCurrentBaseMaxLevelHash].valid());
3659         return imageViewVector[mCurrentBaseMaxLevelHash];
3660     }
3661 
3662     // Used by public get*ImageView() methods to do proper assert based on vector size
getReadViewImpl(const ImageViewVector & imageViewVector)3663     inline const ImageView &getReadViewImpl(const ImageViewVector &imageViewVector) const
3664     {
3665         ASSERT(mCurrentBaseMaxLevelHash < imageViewVector.size());
3666         return imageViewVector[mCurrentBaseMaxLevelHash];
3667     }
3668 
3669     // Used by private get*ImageView() methods to do proper assert based on vector size
getReadViewImpl(ImageViewVector & imageViewVector)3670     inline ImageView &getReadViewImpl(ImageViewVector &imageViewVector)
3671     {
3672         ASSERT(mCurrentBaseMaxLevelHash < imageViewVector.size());
3673         return imageViewVector[mCurrentBaseMaxLevelHash];
3674     }
3675 
3676     angle::Result getLevelLayerDrawImageViewImpl(Context *context,
3677                                                  const ImageHelper &image,
3678                                                  LevelIndex levelVk,
3679                                                  uint32_t layer,
3680                                                  uint32_t layerCount,
3681                                                  ImageView *imageViewOut);
3682     angle::Result getLevelLayerDepthOrStencilImageViewImpl(Context *context,
3683                                                            const ImageHelper &image,
3684                                                            LevelIndex levelVk,
3685                                                            uint32_t layer,
3686                                                            uint32_t layerCount,
3687                                                            VkImageAspectFlagBits aspect,
3688                                                            ImageView *imageViewOut);
3689 
3690     // Creates views with multiple layers and levels.
3691     angle::Result initReadViewsImpl(ContextVk *contextVk,
3692                                     gl::TextureType viewType,
3693                                     const ImageHelper &image,
3694                                     const gl::SwizzleState &formatSwizzle,
3695                                     const gl::SwizzleState &readSwizzle,
3696                                     LevelIndex baseLevel,
3697                                     uint32_t levelCount,
3698                                     uint32_t baseLayer,
3699                                     uint32_t layerCount,
3700                                     VkImageUsageFlags imageUsageFlags);
3701 
3702     // Create linear and srgb read views
3703     angle::Result initLinearAndSrgbReadViewsImpl(ContextVk *contextVk,
3704                                                  gl::TextureType viewType,
3705                                                  const ImageHelper &image,
3706                                                  const gl::SwizzleState &formatSwizzle,
3707                                                  const gl::SwizzleState &readSwizzle,
3708                                                  LevelIndex baseLevel,
3709                                                  uint32_t levelCount,
3710                                                  uint32_t baseLayer,
3711                                                  uint32_t layerCount,
3712                                                  VkImageUsageFlags imageUsageFlags);
3713 
3714     void updateColorspace(const ImageHelper &image) const;
3715 
3716     // For applications that frequently switch a texture's base/max level, and make no other changes
3717     // to the texture, keep track of the currently-used base and max levels, and keep one "read
3718     // view" per each combination.  The value stored here is base<<4|max, used to look up the view
3719     // in a vector.
3720     static_assert(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS <= 16,
3721                   "Not enough bits in mCurrentBaseMaxLevelHash");
3722     uint8_t mCurrentBaseMaxLevelHash;
3723 
3724     mutable ImageViewColorspace mReadColorspace;
3725     mutable ImageViewColorspace mWriteColorspace;
3726     mutable angle::ColorspaceState mColorspaceState;
3727 
3728     // Read views (one per [base, max] level range)
3729     ImageViewVector mPerLevelRangeLinearReadImageViews;
3730     ImageViewVector mPerLevelRangeSRGBReadImageViews;
3731     ImageViewVector mPerLevelRangeLinearCopyImageViews;
3732     ImageViewVector mPerLevelRangeSRGBCopyImageViews;
3733     ImageViewVector mPerLevelRangeStencilReadImageViews;
3734     ImageViewVector mPerLevelRangeSamplerExternal2DY2YEXTImageViews;
3735 
3736     // Draw views
3737     LayerLevelImageViewVector mLayerLevelDrawImageViews;
3738     LayerLevelImageViewVector mLayerLevelDrawImageViewsLinear;
3739     SubresourceImageViewMap mSubresourceDrawImageViews;
3740 
3741     // Depth- or stencil-only input attachment views
3742     LayerLevelImageViewVector mLayerLevelDepthOnlyImageViews;
3743     LayerLevelImageViewVector mLayerLevelStencilOnlyImageViews;
3744     SubresourceImageViewMap mSubresourceDepthOnlyImageViews;
3745     SubresourceImageViewMap mSubresourceStencilOnlyImageViews;
3746 
3747     // Storage views
3748     ImageViewVector mLevelStorageImageViews;
3749     LayerLevelImageViewVector mLayerLevelStorageImageViews;
3750 
3751     // Fragment shading rate view
3752     ImageView mFragmentShadingRateImageView;
3753 
3754     // Serial for the image view set. getSubresourceSerial combines it with subresource info.
3755     ImageOrBufferViewSerial mImageViewSerial;
3756 };
3757 
3758 class BufferViewHelper final : public Resource
3759 {
3760   public:
3761     BufferViewHelper();
3762     BufferViewHelper(BufferViewHelper &&other);
3763     ~BufferViewHelper() override;
3764 
3765     void init(Renderer *renderer, VkDeviceSize offset, VkDeviceSize size);
isInitialized()3766     bool isInitialized() const { return mInitialized; }
3767     void release(ContextVk *contextVk);
3768     void release(Renderer *renderer);
3769     void destroy(VkDevice device);
3770 
3771     angle::Result getView(Context *context,
3772                           const BufferHelper &buffer,
3773                           VkDeviceSize bufferOffset,
3774                           const Format &format,
3775                           const BufferView **viewOut);
3776 
3777     // Return unique Serial for a bufferView.
3778     ImageOrBufferViewSubresourceSerial getSerial() const;
3779 
3780   private:
3781     bool mInitialized;
3782 
3783     // To support format reinterpretation, additional views for formats other than the one specified
3784     // to glTexBuffer may need to be created.  On draw/dispatch, the format layout qualifier of the
3785     // imageBuffer is used (if provided) to create a potentially different view of the buffer.
3786     angle::HashMap<VkFormat, BufferView> mViews;
3787 
3788     // View properties:
3789     //
3790     // Offset and size specified to glTexBufferRange
3791     VkDeviceSize mOffset;
3792     VkDeviceSize mSize;
3793 
3794     // Serial for the buffer view.  An ImageOrBufferViewSerial is used for texture buffers so that
3795     // they fit together with the other texture types.
3796     ImageOrBufferViewSerial mViewSerial;
3797 };
3798 
3799 // Context state that can affect a compute pipeline
3800 union ComputePipelineOptions final
3801 {
3802     struct
3803     {
3804         // Whether VK_EXT_pipeline_robustness should be used to make the pipeline robust.  Note that
3805         // programs are allowed to be shared between robust and non-robust contexts, so different
3806         // pipelines can be created for the same compute program.
3807         uint8_t robustness : 1;
3808         // Whether VK_EXT_pipeline_protected_access should be used to make the pipeline
3809         // protected-only. Similar to robustness, EGL allows protected and unprotected to be in the
3810         // same share group.
3811         uint8_t protectedAccess : 1;
3812         uint8_t reserved : 6;  // must initialize to zero
3813     };
3814     uint8_t permutationIndex;
3815     static constexpr uint32_t kPermutationCount = 0x1 << 2;
3816 };
3817 static_assert(sizeof(ComputePipelineOptions) == 1, "Size check failed");
3818 ComputePipelineOptions GetComputePipelineOptions(vk::PipelineRobustness robustness,
3819                                                  vk::PipelineProtectedAccess protectedAccess);
3820 using ComputePipelineCache = std::array<PipelineHelper, ComputePipelineOptions::kPermutationCount>;
3821 
3822 class ShaderProgramHelper : angle::NonCopyable
3823 {
3824   public:
3825     ShaderProgramHelper();
3826     ~ShaderProgramHelper();
3827 
3828     bool valid(const gl::ShaderType shaderType) const;
3829     void destroy(Renderer *renderer);
3830     void release(ContextVk *contextVk);
3831 
3832     void setShader(gl::ShaderType shaderType, const ShaderModulePtr &shader);
3833 
3834     // Create a graphics pipeline and place it in the cache.  Must not be called if the pipeline
3835     // exists in cache.
3836     template <typename PipelineHash>
createGraphicsPipeline(vk::Context * context,GraphicsPipelineCache<PipelineHash> * graphicsPipelines,PipelineCacheAccess * pipelineCache,const RenderPass & compatibleRenderPass,const PipelineLayout & pipelineLayout,PipelineSource source,const GraphicsPipelineDesc & pipelineDesc,const SpecializationConstants & specConsts,const GraphicsPipelineDesc ** descPtrOut,PipelineHelper ** pipelineOut)3837     ANGLE_INLINE angle::Result createGraphicsPipeline(
3838         vk::Context *context,
3839         GraphicsPipelineCache<PipelineHash> *graphicsPipelines,
3840         PipelineCacheAccess *pipelineCache,
3841         const RenderPass &compatibleRenderPass,
3842         const PipelineLayout &pipelineLayout,
3843         PipelineSource source,
3844         const GraphicsPipelineDesc &pipelineDesc,
3845         const SpecializationConstants &specConsts,
3846         const GraphicsPipelineDesc **descPtrOut,
3847         PipelineHelper **pipelineOut) const
3848     {
3849         return graphicsPipelines->createPipeline(context, pipelineCache, compatibleRenderPass,
3850                                                  pipelineLayout, mShaders, specConsts, source,
3851                                                  pipelineDesc, descPtrOut, pipelineOut);
3852     }
3853 
3854     void createMonolithicPipelineCreationTask(vk::Context *context,
3855                                               PipelineCacheAccess *pipelineCache,
3856                                               const GraphicsPipelineDesc &desc,
3857                                               const PipelineLayout &pipelineLayout,
3858                                               const SpecializationConstants &specConsts,
3859                                               PipelineHelper *pipeline) const;
3860 
3861     angle::Result getOrCreateComputePipeline(vk::Context *context,
3862                                              ComputePipelineCache *computePipelines,
3863                                              PipelineCacheAccess *pipelineCache,
3864                                              const PipelineLayout &pipelineLayout,
3865                                              ComputePipelineOptions pipelineOptions,
3866                                              PipelineSource source,
3867                                              PipelineHelper **pipelineOut,
3868                                              const char *shaderName,
3869                                              VkSpecializationInfo *specializationInfo) const;
3870 
3871   private:
3872     ShaderModuleMap mShaders;
3873 };
3874 
3875 // Tracks current handle allocation counts in the back-end. Useful for debugging and profiling.
3876 // Note: not all handle types are currently implemented.
3877 class ActiveHandleCounter final : angle::NonCopyable
3878 {
3879   public:
3880     ActiveHandleCounter();
3881     ~ActiveHandleCounter();
3882 
onAllocate(HandleType handleType)3883     void onAllocate(HandleType handleType)
3884     {
3885         mActiveCounts[handleType]++;
3886         mAllocatedCounts[handleType]++;
3887     }
3888 
onDeallocate(HandleType handleType,uint32_t count)3889     void onDeallocate(HandleType handleType, uint32_t count) { mActiveCounts[handleType] -= count; }
3890 
getActive(HandleType handleType)3891     uint32_t getActive(HandleType handleType) const { return mActiveCounts[handleType]; }
getAllocated(HandleType handleType)3892     uint32_t getAllocated(HandleType handleType) const { return mAllocatedCounts[handleType]; }
3893 
3894   private:
3895     angle::PackedEnumMap<HandleType, uint32_t> mActiveCounts;
3896     angle::PackedEnumMap<HandleType, uint32_t> mAllocatedCounts;
3897 };
3898 
3899 // Sometimes ANGLE issues a command internally, such as copies, draws and dispatches that do not
3900 // directly correspond to the application draw/dispatch call.  Before the command is recorded in the
3901 // command buffer, the render pass may need to be broken and/or appropriate barriers may need to be
3902 // inserted.  The following struct aggregates all resources that such internal commands need.
3903 struct CommandBufferBufferAccess
3904 {
3905     BufferHelper *buffer;
3906     VkAccessFlags accessType;
3907     PipelineStage stage;
3908 };
3909 struct CommandBufferImageAccess
3910 {
3911     ImageHelper *image;
3912     VkImageAspectFlags aspectFlags;
3913     ImageLayout imageLayout;
3914 };
3915 struct CommandBufferImageSubresourceAccess
3916 {
3917     CommandBufferImageAccess access;
3918     gl::LevelIndex levelStart;
3919     uint32_t levelCount;
3920     uint32_t layerStart;
3921     uint32_t layerCount;
3922 };
3923 struct CommandBufferBufferExternalAcquireRelease
3924 {
3925     BufferHelper *buffer;
3926 };
3927 struct CommandBufferResourceAccess
3928 {
3929     Resource *resource;
3930 };
3931 class CommandBufferAccess : angle::NonCopyable
3932 {
3933   public:
3934     CommandBufferAccess();
3935     ~CommandBufferAccess();
3936 
onBufferTransferRead(BufferHelper * buffer)3937     void onBufferTransferRead(BufferHelper *buffer)
3938     {
3939         onBufferRead(VK_ACCESS_TRANSFER_READ_BIT, PipelineStage::Transfer, buffer);
3940     }
onBufferTransferWrite(BufferHelper * buffer)3941     void onBufferTransferWrite(BufferHelper *buffer)
3942     {
3943         onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, PipelineStage::Transfer, buffer);
3944     }
onBufferSelfCopy(BufferHelper * buffer)3945     void onBufferSelfCopy(BufferHelper *buffer)
3946     {
3947         onBufferWrite(VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
3948                       PipelineStage::Transfer, buffer);
3949     }
onBufferComputeShaderRead(BufferHelper * buffer)3950     void onBufferComputeShaderRead(BufferHelper *buffer)
3951     {
3952         onBufferRead(VK_ACCESS_SHADER_READ_BIT, PipelineStage::ComputeShader, buffer);
3953     }
onBufferComputeShaderWrite(BufferHelper * buffer)3954     void onBufferComputeShaderWrite(BufferHelper *buffer)
3955     {
3956         onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT,
3957                       PipelineStage::ComputeShader, buffer);
3958     }
3959 
onImageTransferRead(VkImageAspectFlags aspectFlags,ImageHelper * image)3960     void onImageTransferRead(VkImageAspectFlags aspectFlags, ImageHelper *image)
3961     {
3962         onImageRead(aspectFlags, ImageLayout::TransferSrc, image);
3963     }
onImageTransferWrite(gl::LevelIndex levelStart,uint32_t levelCount,uint32_t layerStart,uint32_t layerCount,VkImageAspectFlags aspectFlags,ImageHelper * image)3964     void onImageTransferWrite(gl::LevelIndex levelStart,
3965                               uint32_t levelCount,
3966                               uint32_t layerStart,
3967                               uint32_t layerCount,
3968                               VkImageAspectFlags aspectFlags,
3969                               ImageHelper *image)
3970     {
3971         onImageWrite(levelStart, levelCount, layerStart, layerCount, aspectFlags,
3972                      ImageLayout::TransferDst, image);
3973     }
onImageSelfCopy(gl::LevelIndex readLevelStart,uint32_t readLevelCount,uint32_t readLayerStart,uint32_t readLayerCount,gl::LevelIndex writeLevelStart,uint32_t writeLevelCount,uint32_t writeLayerStart,uint32_t writeLayerCount,VkImageAspectFlags aspectFlags,ImageHelper * image)3974     void onImageSelfCopy(gl::LevelIndex readLevelStart,
3975                          uint32_t readLevelCount,
3976                          uint32_t readLayerStart,
3977                          uint32_t readLayerCount,
3978                          gl::LevelIndex writeLevelStart,
3979                          uint32_t writeLevelCount,
3980                          uint32_t writeLayerStart,
3981                          uint32_t writeLayerCount,
3982                          VkImageAspectFlags aspectFlags,
3983                          ImageHelper *image)
3984     {
3985         onImageReadSubresources(readLevelStart, readLevelCount, readLayerStart, readLayerCount,
3986                                 aspectFlags, ImageLayout::TransferSrcDst, image);
3987         onImageWrite(writeLevelStart, writeLevelCount, writeLayerStart, writeLayerCount,
3988                      aspectFlags, ImageLayout::TransferSrcDst, image);
3989     }
onImageDrawMipmapGenerationWrite(gl::LevelIndex levelStart,uint32_t levelCount,uint32_t layerStart,uint32_t layerCount,VkImageAspectFlags aspectFlags,ImageHelper * image)3990     void onImageDrawMipmapGenerationWrite(gl::LevelIndex levelStart,
3991                                           uint32_t levelCount,
3992                                           uint32_t layerStart,
3993                                           uint32_t layerCount,
3994                                           VkImageAspectFlags aspectFlags,
3995                                           ImageHelper *image)
3996     {
3997         onImageWrite(levelStart, levelCount, layerStart, layerCount, aspectFlags,
3998                      ImageLayout::ColorWrite, image);
3999     }
onImageComputeShaderRead(VkImageAspectFlags aspectFlags,ImageHelper * image)4000     void onImageComputeShaderRead(VkImageAspectFlags aspectFlags, ImageHelper *image)
4001     {
4002         onImageRead(aspectFlags, ImageLayout::ComputeShaderReadOnly, image);
4003     }
onImageComputeMipmapGenerationRead(gl::LevelIndex levelStart,uint32_t levelCount,uint32_t layerStart,uint32_t layerCount,VkImageAspectFlags aspectFlags,ImageHelper * image)4004     void onImageComputeMipmapGenerationRead(gl::LevelIndex levelStart,
4005                                             uint32_t levelCount,
4006                                             uint32_t layerStart,
4007                                             uint32_t layerCount,
4008                                             VkImageAspectFlags aspectFlags,
4009                                             ImageHelper *image)
4010     {
4011         onImageReadSubresources(levelStart, levelCount, layerStart, layerCount, aspectFlags,
4012                                 ImageLayout::ComputeShaderWrite, image);
4013     }
onImageComputeShaderWrite(gl::LevelIndex levelStart,uint32_t levelCount,uint32_t layerStart,uint32_t layerCount,VkImageAspectFlags aspectFlags,ImageHelper * image)4014     void onImageComputeShaderWrite(gl::LevelIndex levelStart,
4015                                    uint32_t levelCount,
4016                                    uint32_t layerStart,
4017                                    uint32_t layerCount,
4018                                    VkImageAspectFlags aspectFlags,
4019                                    ImageHelper *image)
4020     {
4021         onImageWrite(levelStart, levelCount, layerStart, layerCount, aspectFlags,
4022                      ImageLayout::ComputeShaderWrite, image);
4023     }
onImageTransferDstAndComputeWrite(gl::LevelIndex levelStart,uint32_t levelCount,uint32_t layerStart,uint32_t layerCount,VkImageAspectFlags aspectFlags,ImageHelper * image)4024     void onImageTransferDstAndComputeWrite(gl::LevelIndex levelStart,
4025                                            uint32_t levelCount,
4026                                            uint32_t layerStart,
4027                                            uint32_t layerCount,
4028                                            VkImageAspectFlags aspectFlags,
4029                                            ImageHelper *image)
4030     {
4031         onImageWrite(levelStart, levelCount, layerStart, layerCount, aspectFlags,
4032                      ImageLayout::TransferDstAndComputeWrite, image);
4033     }
onExternalAcquireRelease(ImageHelper * image)4034     void onExternalAcquireRelease(ImageHelper *image) { onResourceAccess(image); }
onQueryAccess(QueryHelper * query)4035     void onQueryAccess(QueryHelper *query) { onResourceAccess(query); }
4036     void onBufferExternalAcquireRelease(BufferHelper *buffer);
4037 
4038     // The limits reflect the current maximum concurrent usage of each resource type.  ASSERTs will
4039     // fire if this limit is exceeded in the future.
4040     using ReadBuffers           = angle::FixedVector<CommandBufferBufferAccess, 2>;
4041     using WriteBuffers          = angle::FixedVector<CommandBufferBufferAccess, 2>;
4042     using ReadImages            = angle::FixedVector<CommandBufferImageAccess, 2>;
4043     using WriteImages           = angle::FixedVector<CommandBufferImageSubresourceAccess,
4044                                                      gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>;
4045     using ReadImageSubresources = angle::FixedVector<CommandBufferImageSubresourceAccess, 1>;
4046 
4047     using ExternalAcquireReleaseBuffers =
4048         angle::FixedVector<CommandBufferBufferExternalAcquireRelease, 1>;
4049     using AccessResources = angle::FixedVector<CommandBufferResourceAccess, 1>;
4050 
getReadBuffers()4051     const ReadBuffers &getReadBuffers() const { return mReadBuffers; }
getWriteBuffers()4052     const WriteBuffers &getWriteBuffers() const { return mWriteBuffers; }
getReadImages()4053     const ReadImages &getReadImages() const { return mReadImages; }
getWriteImages()4054     const WriteImages &getWriteImages() const { return mWriteImages; }
getReadImageSubresources()4055     const ReadImageSubresources &getReadImageSubresources() const { return mReadImageSubresources; }
getExternalAcquireReleaseBuffers()4056     const ExternalAcquireReleaseBuffers &getExternalAcquireReleaseBuffers() const
4057     {
4058         return mExternalAcquireReleaseBuffers;
4059     }
getAccessResources()4060     const AccessResources &getAccessResources() const { return mAccessResources; }
4061 
4062   private:
4063     void onBufferRead(VkAccessFlags readAccessType, PipelineStage readStage, BufferHelper *buffer);
4064     void onBufferWrite(VkAccessFlags writeAccessType,
4065                        PipelineStage writeStage,
4066                        BufferHelper *buffer);
4067 
4068     void onImageRead(VkImageAspectFlags aspectFlags, ImageLayout imageLayout, ImageHelper *image);
4069     void onImageWrite(gl::LevelIndex levelStart,
4070                       uint32_t levelCount,
4071                       uint32_t layerStart,
4072                       uint32_t layerCount,
4073                       VkImageAspectFlags aspectFlags,
4074                       ImageLayout imageLayout,
4075                       ImageHelper *image);
4076 
4077     void onImageReadSubresources(gl::LevelIndex levelStart,
4078                                  uint32_t levelCount,
4079                                  uint32_t layerStart,
4080                                  uint32_t layerCount,
4081                                  VkImageAspectFlags aspectFlags,
4082                                  ImageLayout imageLayout,
4083                                  ImageHelper *image);
4084 
4085     void onResourceAccess(Resource *resource);
4086 
4087     ReadBuffers mReadBuffers;
4088     WriteBuffers mWriteBuffers;
4089     ReadImages mReadImages;
4090     WriteImages mWriteImages;
4091     ReadImageSubresources mReadImageSubresources;
4092     ExternalAcquireReleaseBuffers mExternalAcquireReleaseBuffers;
4093     AccessResources mAccessResources;
4094 };
4095 
4096 enum class PresentMode
4097 {
4098     ImmediateKHR               = VK_PRESENT_MODE_IMMEDIATE_KHR,
4099     MailboxKHR                 = VK_PRESENT_MODE_MAILBOX_KHR,
4100     FifoKHR                    = VK_PRESENT_MODE_FIFO_KHR,
4101     FifoRelaxedKHR             = VK_PRESENT_MODE_FIFO_RELAXED_KHR,
4102     SharedDemandRefreshKHR     = VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR,
4103     SharedContinuousRefreshKHR = VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR,
4104 
4105     InvalidEnum,
4106     EnumCount = InvalidEnum,
4107 };
4108 
4109 VkPresentModeKHR ConvertPresentModeToVkPresentMode(PresentMode presentMode);
4110 PresentMode ConvertVkPresentModeToPresentMode(VkPresentModeKHR vkPresentMode);
4111 }  // namespace vk
4112 }  // namespace rx
4113 
4114 #endif  // LIBANGLE_RENDERER_VULKAN_VK_HELPERS_H_
4115