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