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 utilitiy 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/ResourceVk.h"
14 #include "libANGLE/renderer/vulkan/vk_cache_utils.h"
15 
16 namespace gl
17 {
18 class ImageIndex;
19 }  // namespace gl
20 
21 namespace rx
22 {
23 namespace vk
24 {
25 constexpr VkBufferUsageFlags kVertexBufferUsageFlags =
26     VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
27 constexpr VkBufferUsageFlags kIndexBufferUsageFlags =
28     VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
29 constexpr VkBufferUsageFlags kIndirectBufferUsageFlags =
30     VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
31 constexpr size_t kVertexBufferAlignment   = 4;
32 constexpr size_t kIndexBufferAlignment    = 4;
33 constexpr size_t kIndirectBufferAlignment = 4;
34 
35 constexpr VkBufferUsageFlags kStagingBufferFlags =
36     VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
37 constexpr size_t kStagingBufferSize = 1024 * 16;
38 
39 constexpr VkImageCreateFlags kVkImageCreateFlagsNone = 0;
40 
41 using StagingBufferOffsetArray = std::array<VkDeviceSize, 2>;
42 
43 struct TextureUnit final
44 {
45     TextureVk *texture;
46     const SamplerHelper *sampler;
47     GLenum srgbDecode;
48 };
49 
50 // A dynamic buffer is conceptually an infinitely long buffer. Each time you write to the buffer,
51 // you will always write to a previously unused portion. After a series of writes, you must flush
52 // the buffer data to the device. Buffer lifetime currently assumes that each new allocation will
53 // last as long or longer than each prior allocation.
54 //
55 // Dynamic buffers are used to implement a variety of data streaming operations in Vulkan, such
56 // as for immediate vertex array and element array data, uniform updates, and other dynamic data.
57 //
58 // Internally dynamic buffers keep a collection of VkBuffers. When we write past the end of a
59 // currently active VkBuffer we keep it until it is no longer in use. We then mark it available
60 // for future allocations in a free list.
61 class BufferHelper;
62 using BufferHelperPointerVector = std::vector<std::unique_ptr<BufferHelper>>;
63 
64 enum class DynamicBufferPolicy
65 {
66     // Used where future allocations from the dynamic buffer are unlikely, so it's best to free the
67     // memory when the allocated buffers are no longer in use.
68     OneShotUse,
69     // Used where multiple small allocations are made every frame, so it's worth keeping the free
70     // buffers around to avoid release/reallocation.
71     FrequentSmallAllocations,
72     // Used where bursts of allocation happen occasionally, but the steady state may make
73     // allocations every now and then.  In that case, a limited number of buffers are retained.
74     SporadicTextureUpload,
75 };
76 
77 class DynamicBuffer : angle::NonCopyable
78 {
79   public:
80     DynamicBuffer();
81     DynamicBuffer(DynamicBuffer &&other);
82     ~DynamicBuffer();
83 
84     // Init is called after the buffer creation so that the alignment can be specified later.
85     void init(RendererVk *renderer,
86               VkBufferUsageFlags usage,
87               size_t alignment,
88               size_t initialSize,
89               bool hostVisible,
90               DynamicBufferPolicy policy);
91 
92     // Init that gives the ability to pass in specified memory property flags for the buffer.
93     void initWithFlags(RendererVk *renderer,
94                        VkBufferUsageFlags usage,
95                        size_t alignment,
96                        size_t initialSize,
97                        VkMemoryPropertyFlags memoryProperty,
98                        DynamicBufferPolicy policy);
99 
100     // This call will allocate a new region at the end of the current buffer. If it can't find
101     // enough space in the current buffer, it returns false. This gives caller a chance to deal with
102     // buffer switch that may occur with allocate call.
103     bool allocateFromCurrentBuffer(size_t sizeInBytes, uint8_t **ptrOut, VkDeviceSize *offsetOut);
104 
105     // This call will allocate a new region at the end of the buffer. It internally may trigger
106     // a new buffer to be created (which is returned in the optional parameter
107     // `newBufferAllocatedOut`).  The new region will be in the returned buffer at given offset. If
108     // a memory pointer is given, the buffer will be automatically map()ed.
109     angle::Result allocateWithAlignment(ContextVk *contextVk,
110                                         size_t sizeInBytes,
111                                         size_t alignment,
112                                         uint8_t **ptrOut,
113                                         VkBuffer *bufferOut,
114                                         VkDeviceSize *offsetOut,
115                                         bool *newBufferAllocatedOut);
116 
117     // Allocate with default alignment
allocate(ContextVk * contextVk,size_t sizeInBytes,uint8_t ** ptrOut,VkBuffer * bufferOut,VkDeviceSize * offsetOut,bool * newBufferAllocatedOut)118     angle::Result allocate(ContextVk *contextVk,
119                            size_t sizeInBytes,
120                            uint8_t **ptrOut,
121                            VkBuffer *bufferOut,
122                            VkDeviceSize *offsetOut,
123                            bool *newBufferAllocatedOut)
124     {
125         return allocateWithAlignment(contextVk, sizeInBytes, mAlignment, ptrOut, bufferOut,
126                                      offsetOut, newBufferAllocatedOut);
127     }
128 
129     // After a sequence of writes, call flush to ensure the data is visible to the device.
130     angle::Result flush(ContextVk *contextVk);
131 
132     // After a sequence of writes, call invalidate to ensure the data is visible to the host.
133     angle::Result invalidate(ContextVk *contextVk);
134 
135     // This releases resources when they might currently be in use.
136     void release(RendererVk *renderer);
137 
138     // This releases all the buffers that have been allocated since this was last called.
139     void releaseInFlightBuffers(ContextVk *contextVk);
140 
141     // This adds inflight buffers to the context's mResourceUseList and then releases them
142     void releaseInFlightBuffersToResourceUseList(ContextVk *contextVk);
143 
144     // This frees resources immediately.
145     void destroy(RendererVk *renderer);
146 
getCurrentBuffer()147     BufferHelper *getCurrentBuffer() const { return mBuffer.get(); }
148 
149     // **Accumulate** an alignment requirement.  A dynamic buffer is used as the staging buffer for
150     // image uploads, which can contain updates to unrelated mips, possibly with different formats.
151     // The staging buffer should have an alignment that can satisfy all those formats, i.e. it's the
152     // lcm of all alignments set in its lifetime.
153     void requireAlignment(RendererVk *renderer, size_t alignment);
getAlignment()154     size_t getAlignment() const { return mAlignment; }
155 
156     // For testing only!
157     void setMinimumSizeForTesting(size_t minSize);
158 
isCoherent()159     bool isCoherent() const
160     {
161         return (mMemoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0;
162     }
163 
valid()164     bool valid() const { return mSize != 0; }
165 
166   private:
167     void reset();
168     angle::Result allocateNewBuffer(ContextVk *contextVk);
169 
170     VkBufferUsageFlags mUsage;
171     bool mHostVisible;
172     DynamicBufferPolicy mPolicy;
173     size_t mInitialSize;
174     std::unique_ptr<BufferHelper> mBuffer;
175     uint32_t mNextAllocationOffset;
176     uint32_t mLastFlushOrInvalidateOffset;
177     size_t mSize;
178     size_t mAlignment;
179     VkMemoryPropertyFlags mMemoryPropertyFlags;
180 
181     BufferHelperPointerVector mInFlightBuffers;
182     BufferHelperPointerVector mBufferFreeList;
183 };
184 
185 // Based off of the DynamicBuffer class, DynamicShadowBuffer provides
186 // a similar conceptually infinitely long buffer that will only be written
187 // to and read by the CPU. This can be used to provide CPU cached copies of
188 // GPU-read only buffers. The value add here is that when an app requests
189 // CPU access to a buffer we can fullfil such a request in O(1) time since
190 // we don't need to wait for GPU to be done with in-flight commands.
191 //
192 // The hidden cost here is that any operation that updates a buffer, either
193 // through a buffer sub data update or a buffer-to-buffer copy will have an
194 // additional overhead of having to update its CPU only buffer
195 class DynamicShadowBuffer : public angle::NonCopyable
196 {
197   public:
198     DynamicShadowBuffer();
199     DynamicShadowBuffer(DynamicShadowBuffer &&other);
200     ~DynamicShadowBuffer();
201 
202     // Initialize the DynamicShadowBuffer.
203     void init(size_t initialSize);
204 
205     // Returns whether this DynamicShadowBuffer is active
valid()206     ANGLE_INLINE bool valid() { return (mSize != 0); }
207 
208     // This call will actually allocate a new CPU only memory from the heap.
209     // The size can be different than the one specified during `init`.
210     angle::Result allocate(size_t sizeInBytes);
211 
updateData(const uint8_t * data,size_t size,size_t offset)212     ANGLE_INLINE void updateData(const uint8_t *data, size_t size, size_t offset)
213     {
214         ASSERT(!mBuffer.empty());
215         // Memcopy data into the buffer
216         memcpy((mBuffer.data() + offset), data, size);
217     }
218 
219     // Map the CPU only buffer and return the pointer. We map the entire buffer for now.
map(size_t offset,void ** mapPtr)220     ANGLE_INLINE void map(size_t offset, void **mapPtr)
221     {
222         ASSERT(mapPtr);
223         ASSERT(!mBuffer.empty());
224         *mapPtr = mBuffer.data() + offset;
225     }
226 
227     // Unmap the CPU only buffer, NOOP for now
unmap()228     ANGLE_INLINE void unmap() {}
229 
230     // This releases resources when they might currently be in use.
231     void release();
232 
233     // This frees resources immediately.
234     void destroy(VkDevice device);
235 
getCurrentBuffer()236     ANGLE_INLINE uint8_t *getCurrentBuffer()
237     {
238         ASSERT(!mBuffer.empty());
239         return mBuffer.data();
240     }
241 
getCurrentBuffer()242     ANGLE_INLINE const uint8_t *getCurrentBuffer() const
243     {
244         ASSERT(!mBuffer.empty());
245         return mBuffer.data();
246     }
247 
248   private:
249     void reset();
250 
251     size_t mInitialSize;
252     size_t mSize;
253     angle::MemoryBuffer mBuffer;
254 };
255 
256 // Uses DescriptorPool to allocate descriptor sets as needed. If a descriptor pool becomes full, we
257 // allocate new pools internally as needed. RendererVk takes care of the lifetime of the discarded
258 // pools. Note that we used a fixed layout for descriptor pools in ANGLE.
259 
260 // Shared handle to a descriptor pool. Each helper is allocated from the dynamic descriptor pool.
261 // Can be used to share descriptor pools between multiple ProgramVks and the ContextVk.
262 class DescriptorPoolHelper : public Resource
263 {
264   public:
265     DescriptorPoolHelper();
266     ~DescriptorPoolHelper() override;
267 
valid()268     bool valid() { return mDescriptorPool.valid(); }
269 
270     bool hasCapacity(uint32_t descriptorSetCount) const;
271     angle::Result init(ContextVk *contextVk,
272                        const std::vector<VkDescriptorPoolSize> &poolSizesIn,
273                        uint32_t maxSets);
274     void destroy(VkDevice device);
275     void release(ContextVk *contextVk);
276 
277     angle::Result allocateSets(ContextVk *contextVk,
278                                const VkDescriptorSetLayout *descriptorSetLayout,
279                                uint32_t descriptorSetCount,
280                                VkDescriptorSet *descriptorSetsOut);
281 
282   private:
283     uint32_t mFreeDescriptorSets;
284     DescriptorPool mDescriptorPool;
285 };
286 
287 using RefCountedDescriptorPoolHelper  = RefCounted<DescriptorPoolHelper>;
288 using RefCountedDescriptorPoolBinding = BindingPointer<DescriptorPoolHelper>;
289 
290 class DynamicDescriptorPool final : angle::NonCopyable
291 {
292   public:
293     DynamicDescriptorPool();
294     ~DynamicDescriptorPool();
295 
296     // The DynamicDescriptorPool only handles one pool size at this time.
297     // Note that setSizes[i].descriptorCount is expected to be the number of descriptors in
298     // an individual set.  The pool size will be calculated accordingly.
299     angle::Result init(ContextVk *contextVk,
300                        const VkDescriptorPoolSize *setSizes,
301                        size_t setSizeCount,
302                        VkDescriptorSetLayout descriptorSetLayout);
303     void destroy(VkDevice device);
304     void release(ContextVk *contextVk);
305 
306     // We use the descriptor type to help count the number of free sets.
307     // By convention, sets are indexed according to the constants in vk_cache_utils.h.
allocateSets(ContextVk * contextVk,const VkDescriptorSetLayout * descriptorSetLayout,uint32_t descriptorSetCount,RefCountedDescriptorPoolBinding * bindingOut,VkDescriptorSet * descriptorSetsOut)308     ANGLE_INLINE angle::Result allocateSets(ContextVk *contextVk,
309                                             const VkDescriptorSetLayout *descriptorSetLayout,
310                                             uint32_t descriptorSetCount,
311                                             RefCountedDescriptorPoolBinding *bindingOut,
312                                             VkDescriptorSet *descriptorSetsOut)
313     {
314         bool ignoreNewPoolAllocated;
315         return allocateSetsAndGetInfo(contextVk, descriptorSetLayout, descriptorSetCount,
316                                       bindingOut, descriptorSetsOut, &ignoreNewPoolAllocated);
317     }
318 
319     // We use the descriptor type to help count the number of free sets.
320     // By convention, sets are indexed according to the constants in vk_cache_utils.h.
321     angle::Result allocateSetsAndGetInfo(ContextVk *contextVk,
322                                          const VkDescriptorSetLayout *descriptorSetLayout,
323                                          uint32_t descriptorSetCount,
324                                          RefCountedDescriptorPoolBinding *bindingOut,
325                                          VkDescriptorSet *descriptorSetsOut,
326                                          bool *newPoolAllocatedOut);
327 
328     // For testing only!
329     static uint32_t GetMaxSetsPerPoolForTesting();
330     static void SetMaxSetsPerPoolForTesting(uint32_t maxSetsPerPool);
331     static uint32_t GetMaxSetsPerPoolMultiplierForTesting();
332     static void SetMaxSetsPerPoolMultiplierForTesting(uint32_t maxSetsPerPool);
333 
334   private:
335     angle::Result allocateNewPool(ContextVk *contextVk);
336 
337     static constexpr uint32_t kMaxSetsPerPoolMax = 512;
338     static uint32_t mMaxSetsPerPool;
339     static uint32_t mMaxSetsPerPoolMultiplier;
340     size_t mCurrentPoolIndex;
341     std::vector<RefCountedDescriptorPoolHelper *> mDescriptorPools;
342     std::vector<VkDescriptorPoolSize> mPoolSizes;
343     // This cached handle is used for verifying the layout being used to allocate descriptor sets
344     // from the pool matches the layout that the pool was created for, to ensure that the free
345     // descriptor count is accurate and new pools are created appropriately.
346     VkDescriptorSetLayout mCachedDescriptorSetLayout;
347 };
348 
349 template <typename Pool>
350 class DynamicallyGrowingPool : angle::NonCopyable
351 {
352   public:
353     DynamicallyGrowingPool();
354     virtual ~DynamicallyGrowingPool();
355 
isValid()356     bool isValid() { return mPoolSize > 0; }
357 
358   protected:
359     angle::Result initEntryPool(Context *contextVk, uint32_t poolSize);
360     void destroyEntryPool();
361 
362     // Checks to see if any pool is already free, in which case it sets it as current pool and
363     // returns true.
364     bool findFreeEntryPool(ContextVk *contextVk);
365 
366     // Allocates a new entry and initializes it with the given pool.
367     angle::Result allocateNewEntryPool(ContextVk *contextVk, Pool &&pool);
368 
369     // Called by the implementation whenever an entry is freed.
370     void onEntryFreed(ContextVk *contextVk, size_t poolIndex);
371 
372     // The pool size, to know when a pool is completely freed.
373     uint32_t mPoolSize;
374 
375     std::vector<Pool> mPools;
376 
377     struct PoolStats
378     {
379         // A count corresponding to each pool indicating how many of its allocated entries
380         // have been freed. Once that value reaches mPoolSize for each pool, that pool is considered
381         // free and reusable.  While keeping a bitset would allow allocation of each index, the
382         // slight runtime overhead of finding free indices is not worth the slight memory overhead
383         // of creating new pools when unnecessary.
384         uint32_t freedCount;
385         // The serial of the renderer is stored on each object free to make sure no
386         // new allocations are made from the pool until it's not in use.
387         Serial serial;
388     };
389     std::vector<PoolStats> mPoolStats;
390 
391     // Index into mPools indicating pool we are currently allocating from.
392     size_t mCurrentPool;
393     // Index inside mPools[mCurrentPool] indicating which index can be allocated next.
394     uint32_t mCurrentFreeEntry;
395 };
396 
397 // DynamicQueryPool allocates indices out of QueryPool as needed.  Once a QueryPool is exhausted,
398 // another is created.  The query pools live permanently, but are recycled as indices get freed.
399 
400 // These are arbitrary default sizes for query pools.
401 constexpr uint32_t kDefaultOcclusionQueryPoolSize           = 64;
402 constexpr uint32_t kDefaultTimestampQueryPoolSize           = 64;
403 constexpr uint32_t kDefaultTransformFeedbackQueryPoolSize   = 128;
404 constexpr uint32_t kDefaultPrimitivesGeneratedQueryPoolSize = 128;
405 
406 class QueryHelper;
407 
408 class DynamicQueryPool final : public DynamicallyGrowingPool<QueryPool>
409 {
410   public:
411     DynamicQueryPool();
412     ~DynamicQueryPool() override;
413 
414     angle::Result init(ContextVk *contextVk, VkQueryType type, uint32_t poolSize);
415     void destroy(VkDevice device);
416 
417     angle::Result allocateQuery(ContextVk *contextVk, QueryHelper *queryOut, uint32_t queryCount);
418     void freeQuery(ContextVk *contextVk, QueryHelper *query);
419 
getQueryPool(size_t index)420     const QueryPool &getQueryPool(size_t index) const { return mPools[index]; }
421 
422   private:
423     angle::Result allocateNewPool(ContextVk *contextVk);
424 
425     // Information required to create new query pools
426     VkQueryType mQueryType;
427 };
428 
429 // Stores the result of a Vulkan query call. XFB queries in particular store two result values.
430 class QueryResult final
431 {
432   public:
QueryResult(uint32_t intsPerResult)433     QueryResult(uint32_t intsPerResult) : mIntsPerResult(intsPerResult), mResults{} {}
434 
435     void operator+=(const QueryResult &rhs)
436     {
437         mResults[0] += rhs.mResults[0];
438         mResults[1] += rhs.mResults[1];
439     }
440 
getDataSize()441     size_t getDataSize() const { return mIntsPerResult * sizeof(uint64_t); }
442     void setResults(uint64_t *results, uint32_t queryCount);
getResult(size_t index)443     uint64_t getResult(size_t index) const
444     {
445         ASSERT(index < mIntsPerResult);
446         return mResults[index];
447     }
448 
449     static constexpr size_t kDefaultResultIndex                      = 0;
450     static constexpr size_t kTransformFeedbackPrimitivesWrittenIndex = 0;
451     static constexpr size_t kPrimitivesGeneratedIndex                = 1;
452 
453   private:
454     uint32_t mIntsPerResult;
455     std::array<uint64_t, 2> mResults;
456 };
457 
458 // Queries in Vulkan are identified by the query pool and an index for a query within that pool.
459 // Unlike other pools, such as descriptor pools where an allocation returns an independent object
460 // from the pool, the query allocations are not done through a Vulkan function and are only an
461 // integer index.
462 //
463 // Furthermore, to support arbitrarily large number of queries, DynamicQueryPool creates query pools
464 // of a fixed size as needed and allocates indices within those pools.
465 //
466 // The QueryHelper class below keeps the pool and index pair together.  For multiview, multiple
467 // consecutive query indices are implicitly written to by the driver, so the query count is
468 // additionally kept.
469 class QueryHelper final : public Resource
470 {
471   public:
472     QueryHelper();
473     ~QueryHelper() override;
474     QueryHelper(QueryHelper &&rhs);
475     QueryHelper &operator=(QueryHelper &&rhs);
476     void init(const DynamicQueryPool *dynamicQueryPool,
477               const size_t queryPoolIndex,
478               uint32_t query,
479               uint32_t queryCount);
480     void deinit();
481 
valid()482     bool valid() const { return mDynamicQueryPool != nullptr; }
483 
484     // Begin/end queries.  These functions break the render pass.
485     angle::Result beginQuery(ContextVk *contextVk);
486     angle::Result endQuery(ContextVk *contextVk);
487     // Begin/end queries within a started render pass.
488     angle::Result beginRenderPassQuery(ContextVk *contextVk);
489     void endRenderPassQuery(ContextVk *contextVk);
490 
491     angle::Result flushAndWriteTimestamp(ContextVk *contextVk);
492     // When syncing gpu/cpu time, main thread accesses primary directly
493     void writeTimestampToPrimary(ContextVk *contextVk, PrimaryCommandBuffer *primary);
494     // All other timestamp accesses should be made on outsideRenderPassCommandBuffer
495     void writeTimestamp(ContextVk *contextVk, CommandBuffer *outsideRenderPassCommandBuffer);
496 
497     // Whether this query helper has generated and submitted any commands.
498     bool hasSubmittedCommands() const;
499 
500     angle::Result getUint64ResultNonBlocking(ContextVk *contextVk,
501                                              QueryResult *resultOut,
502                                              bool *availableOut);
503     angle::Result getUint64Result(ContextVk *contextVk, QueryResult *resultOut);
504 
505   private:
506     friend class DynamicQueryPool;
getQueryPool()507     const QueryPool &getQueryPool() const
508     {
509         ASSERT(valid());
510         return mDynamicQueryPool->getQueryPool(mQueryPoolIndex);
511     }
512 
513     // Reset needs to always be done outside a render pass, which may be different from the
514     // passed-in command buffer (which could be the render pass').
515     void beginQueryImpl(ContextVk *contextVk,
516                         CommandBuffer *resetCommandBuffer,
517                         CommandBuffer *commandBuffer);
518     void endQueryImpl(ContextVk *contextVk, CommandBuffer *commandBuffer);
519     VkResult getResultImpl(ContextVk *contextVk,
520                            const VkQueryResultFlags flags,
521                            QueryResult *resultOut);
522 
523     const DynamicQueryPool *mDynamicQueryPool;
524     size_t mQueryPoolIndex;
525     uint32_t mQuery;
526     uint32_t mQueryCount;
527 };
528 
529 // DynamicSemaphorePool allocates semaphores as needed.  It uses a std::vector
530 // as a pool to allocate many semaphores at once.  The pools live permanently,
531 // but are recycled as semaphores get freed.
532 
533 // These are arbitrary default sizes for semaphore pools.
534 constexpr uint32_t kDefaultSemaphorePoolSize = 64;
535 
536 class SemaphoreHelper;
537 
538 class DynamicSemaphorePool final : public DynamicallyGrowingPool<std::vector<Semaphore>>
539 {
540   public:
541     DynamicSemaphorePool();
542     ~DynamicSemaphorePool() override;
543 
544     angle::Result init(ContextVk *contextVk, uint32_t poolSize);
545     void destroy(VkDevice device);
546 
isValid()547     bool isValid() { return mPoolSize > 0; }
548 
549     // autoFree can be used to allocate a semaphore that's expected to be freed at the end of the
550     // frame.  This renders freeSemaphore unnecessary and saves an eventual search.
551     angle::Result allocateSemaphore(ContextVk *contextVk, SemaphoreHelper *semaphoreOut);
552     void freeSemaphore(ContextVk *contextVk, SemaphoreHelper *semaphore);
553 
554   private:
555     angle::Result allocateNewPool(ContextVk *contextVk);
556 };
557 
558 // Semaphores that are allocated from the semaphore pool are encapsulated in a helper object,
559 // keeping track of where in the pool they are allocated from.
560 class SemaphoreHelper final : angle::NonCopyable
561 {
562   public:
563     SemaphoreHelper();
564     ~SemaphoreHelper();
565 
566     SemaphoreHelper(SemaphoreHelper &&other);
567     SemaphoreHelper &operator=(SemaphoreHelper &&other);
568 
569     void init(const size_t semaphorePoolIndex, const Semaphore *semaphore);
570     void deinit();
571 
getSemaphore()572     const Semaphore *getSemaphore() const { return mSemaphore; }
573 
574     // Used only by DynamicSemaphorePool.
getSemaphorePoolIndex()575     size_t getSemaphorePoolIndex() const { return mSemaphorePoolIndex; }
576 
577   private:
578     size_t mSemaphorePoolIndex;
579     const Semaphore *mSemaphore;
580 };
581 
582 // This class' responsibility is to create index buffers needed to support line loops in Vulkan.
583 // In the setup phase of drawing, the createIndexBuffer method should be called with the
584 // current draw call parameters. If an element array buffer is bound for an indexed draw, use
585 // createIndexBufferFromElementArrayBuffer.
586 //
587 // If the user wants to draw a loop between [v1, v2, v3], we will create an indexed buffer with
588 // these indexes: [0, 1, 2, 3, 0] to emulate the loop.
589 class LineLoopHelper final : angle::NonCopyable
590 {
591   public:
592     LineLoopHelper(RendererVk *renderer);
593     ~LineLoopHelper();
594 
595     angle::Result getIndexBufferForDrawArrays(ContextVk *contextVk,
596                                               uint32_t clampedVertexCount,
597                                               GLint firstVertex,
598                                               BufferHelper **bufferOut,
599                                               VkDeviceSize *offsetOut);
600 
601     angle::Result getIndexBufferForElementArrayBuffer(ContextVk *contextVk,
602                                                       BufferVk *elementArrayBufferVk,
603                                                       gl::DrawElementsType glIndexType,
604                                                       int indexCount,
605                                                       intptr_t elementArrayOffset,
606                                                       BufferHelper **bufferOut,
607                                                       VkDeviceSize *bufferOffsetOut,
608                                                       uint32_t *indexCountOut);
609 
610     angle::Result streamIndices(ContextVk *contextVk,
611                                 gl::DrawElementsType glIndexType,
612                                 GLsizei indexCount,
613                                 const uint8_t *srcPtr,
614                                 BufferHelper **bufferOut,
615                                 VkDeviceSize *bufferOffsetOut,
616                                 uint32_t *indexCountOut);
617 
618     angle::Result streamIndicesIndirect(ContextVk *contextVk,
619                                         gl::DrawElementsType glIndexType,
620                                         BufferHelper *indexBuffer,
621                                         VkDeviceSize indexBufferOffset,
622                                         BufferHelper *indirectBuffer,
623                                         VkDeviceSize indirectBufferOffset,
624                                         BufferHelper **indexBufferOut,
625                                         VkDeviceSize *indexBufferOffsetOut,
626                                         BufferHelper **indirectBufferOut,
627                                         VkDeviceSize *indirectBufferOffsetOut);
628 
629     angle::Result streamArrayIndirect(ContextVk *contextVk,
630                                       size_t vertexCount,
631                                       BufferHelper *arrayIndirectBuffer,
632                                       VkDeviceSize arrayIndirectBufferOffset,
633                                       BufferHelper **indexBufferOut,
634                                       VkDeviceSize *indexBufferOffsetOut,
635                                       BufferHelper **indexIndirectBufferOut,
636                                       VkDeviceSize *indexIndirectBufferOffsetOut);
637 
638     void release(ContextVk *contextVk);
639     void destroy(RendererVk *renderer);
640 
641     static void Draw(uint32_t count, uint32_t baseVertex, CommandBuffer *commandBuffer);
642 
643   private:
644     DynamicBuffer mDynamicIndexBuffer;
645     DynamicBuffer mDynamicIndirectBuffer;
646 };
647 
648 // This defines enum for VkPipelineStageFlagBits so that we can use it to compare and index into
649 // array.
650 enum class PipelineStage : uint16_t
651 {
652     // Bellow are ordered based on Graphics Pipeline Stages
653     TopOfPipe             = 0,
654     DrawIndirect          = 1,
655     VertexInput           = 2,
656     VertexShader          = 3,
657     GeometryShader        = 4,
658     TransformFeedback     = 5,
659     EarlyFragmentTest     = 6,
660     FragmentShader        = 7,
661     LateFragmentTest      = 8,
662     ColorAttachmentOutput = 9,
663 
664     // Compute specific pipeline Stage
665     ComputeShader = 10,
666 
667     // Transfer specific pipeline Stage
668     Transfer     = 11,
669     BottomOfPipe = 12,
670 
671     // Host specific pipeline stage
672     Host = 13,
673 
674     InvalidEnum = 14,
675     EnumCount   = InvalidEnum,
676 };
677 using PipelineStagesMask = angle::PackedEnumBitSet<PipelineStage, uint16_t>;
678 
679 PipelineStage GetPipelineStage(gl::ShaderType stage);
680 
681 // This wraps data and API for vkCmdPipelineBarrier call
682 class PipelineBarrier : angle::NonCopyable
683 {
684   public:
PipelineBarrier()685     PipelineBarrier()
686         : mSrcStageMask(0),
687           mDstStageMask(0),
688           mMemoryBarrierSrcAccess(0),
689           mMemoryBarrierDstAccess(0),
690           mImageMemoryBarriers()
691     {}
692     ~PipelineBarrier() = default;
693 
isEmpty()694     bool isEmpty() const { return mImageMemoryBarriers.empty() && mMemoryBarrierDstAccess == 0; }
695 
execute(PrimaryCommandBuffer * primary)696     void execute(PrimaryCommandBuffer *primary)
697     {
698         if (isEmpty())
699         {
700             return;
701         }
702 
703         // Issue vkCmdPipelineBarrier call
704         VkMemoryBarrier memoryBarrier = {};
705         uint32_t memoryBarrierCount   = 0;
706         if (mMemoryBarrierDstAccess != 0)
707         {
708             memoryBarrier.sType         = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
709             memoryBarrier.srcAccessMask = mMemoryBarrierSrcAccess;
710             memoryBarrier.dstAccessMask = mMemoryBarrierDstAccess;
711             memoryBarrierCount++;
712         }
713         primary->pipelineBarrier(
714             mSrcStageMask, mDstStageMask, 0, memoryBarrierCount, &memoryBarrier, 0, nullptr,
715             static_cast<uint32_t>(mImageMemoryBarriers.size()), mImageMemoryBarriers.data());
716 
717         reset();
718     }
719 
executeIndividually(PrimaryCommandBuffer * primary)720     void executeIndividually(PrimaryCommandBuffer *primary)
721     {
722         if (isEmpty())
723         {
724             return;
725         }
726 
727         // Issue vkCmdPipelineBarrier call
728         VkMemoryBarrier memoryBarrier = {};
729         uint32_t memoryBarrierCount   = 0;
730         if (mMemoryBarrierDstAccess != 0)
731         {
732             memoryBarrier.sType         = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
733             memoryBarrier.srcAccessMask = mMemoryBarrierSrcAccess;
734             memoryBarrier.dstAccessMask = mMemoryBarrierDstAccess;
735             memoryBarrierCount++;
736         }
737 
738         for (const VkImageMemoryBarrier &imageBarrier : mImageMemoryBarriers)
739         {
740             primary->pipelineBarrier(mSrcStageMask, mDstStageMask, 0, memoryBarrierCount,
741                                      &memoryBarrier, 0, nullptr, 1, &imageBarrier);
742         }
743 
744         reset();
745     }
746 
747     // merge two barriers into one
merge(PipelineBarrier * other)748     void merge(PipelineBarrier *other)
749     {
750         mSrcStageMask |= other->mSrcStageMask;
751         mDstStageMask |= other->mDstStageMask;
752         mMemoryBarrierSrcAccess |= other->mMemoryBarrierSrcAccess;
753         mMemoryBarrierDstAccess |= other->mMemoryBarrierDstAccess;
754         mImageMemoryBarriers.insert(mImageMemoryBarriers.end(), other->mImageMemoryBarriers.begin(),
755                                     other->mImageMemoryBarriers.end());
756         other->reset();
757     }
758 
mergeMemoryBarrier(VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,VkFlags srcAccess,VkFlags dstAccess)759     void mergeMemoryBarrier(VkPipelineStageFlags srcStageMask,
760                             VkPipelineStageFlags dstStageMask,
761                             VkFlags srcAccess,
762                             VkFlags dstAccess)
763     {
764         mSrcStageMask |= srcStageMask;
765         mDstStageMask |= dstStageMask;
766         mMemoryBarrierSrcAccess |= srcAccess;
767         mMemoryBarrierDstAccess |= dstAccess;
768     }
769 
mergeImageBarrier(VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,const VkImageMemoryBarrier & imageMemoryBarrier)770     void mergeImageBarrier(VkPipelineStageFlags srcStageMask,
771                            VkPipelineStageFlags dstStageMask,
772                            const VkImageMemoryBarrier &imageMemoryBarrier)
773     {
774         ASSERT(imageMemoryBarrier.pNext == nullptr);
775         mSrcStageMask |= srcStageMask;
776         mDstStageMask |= dstStageMask;
777         mImageMemoryBarriers.push_back(imageMemoryBarrier);
778     }
779 
reset()780     void reset()
781     {
782         mSrcStageMask           = 0;
783         mDstStageMask           = 0;
784         mMemoryBarrierSrcAccess = 0;
785         mMemoryBarrierDstAccess = 0;
786         mImageMemoryBarriers.clear();
787     }
788 
789     void addDiagnosticsString(std::ostringstream &out) const;
790 
791   private:
792     VkPipelineStageFlags mSrcStageMask;
793     VkPipelineStageFlags mDstStageMask;
794     VkFlags mMemoryBarrierSrcAccess;
795     VkFlags mMemoryBarrierDstAccess;
796     std::vector<VkImageMemoryBarrier> mImageMemoryBarriers;
797 };
798 using PipelineBarrierArray = angle::PackedEnumMap<PipelineStage, PipelineBarrier>;
799 
800 class FramebufferHelper;
801 
802 class BufferMemory : angle::NonCopyable
803 {
804   public:
805     BufferMemory();
806     ~BufferMemory();
807     angle::Result initExternal(GLeglClientBufferEXT clientBuffer);
808     angle::Result init();
809 
810     void destroy(RendererVk *renderer);
811 
map(ContextVk * contextVk,VkDeviceSize size,uint8_t ** ptrOut)812     angle::Result map(ContextVk *contextVk, VkDeviceSize size, uint8_t **ptrOut)
813     {
814         if (mMappedMemory == nullptr)
815         {
816             ANGLE_TRY(mapImpl(contextVk, size));
817         }
818         *ptrOut = mMappedMemory;
819         return angle::Result::Continue;
820     }
821     void unmap(RendererVk *renderer);
822     void flush(RendererVk *renderer,
823                VkMemoryMapFlags memoryPropertyFlags,
824                VkDeviceSize offset,
825                VkDeviceSize size);
826     void invalidate(RendererVk *renderer,
827                     VkMemoryMapFlags memoryPropertyFlags,
828                     VkDeviceSize offset,
829                     VkDeviceSize size);
830 
isExternalBuffer()831     bool isExternalBuffer() const { return mClientBuffer != nullptr; }
832 
getMappedMemory()833     uint8_t *getMappedMemory() const { return mMappedMemory; }
getExternalMemoryObject()834     DeviceMemory *getExternalMemoryObject() { return &mExternalMemory; }
getMemoryObject()835     Allocation *getMemoryObject() { return &mAllocation; }
836 
837   private:
838     angle::Result mapImpl(ContextVk *contextVk, VkDeviceSize size);
839 
840     Allocation mAllocation;        // use mAllocation if isExternalBuffer() is false
841     DeviceMemory mExternalMemory;  // use mExternalMemory if isExternalBuffer() is true
842 
843     GLeglClientBufferEXT mClientBuffer;
844     uint8_t *mMappedMemory;
845 };
846 
847 class BufferHelper final : public Resource
848 {
849   public:
850     BufferHelper();
851     ~BufferHelper() override;
852 
853     angle::Result init(ContextVk *contextVk,
854                        const VkBufferCreateInfo &createInfo,
855                        VkMemoryPropertyFlags memoryPropertyFlags);
856     angle::Result initExternal(ContextVk *contextVk,
857                                VkMemoryPropertyFlags memoryProperties,
858                                const VkBufferCreateInfo &requestedCreateInfo,
859                                GLeglClientBufferEXT clientBuffer);
860     void destroy(RendererVk *renderer);
861 
862     void release(RendererVk *renderer);
863 
getBufferSerial()864     BufferSerial getBufferSerial() const { return mSerial; }
valid()865     bool valid() const { return mBuffer.valid(); }
getBuffer()866     const Buffer &getBuffer() const { return mBuffer; }
getSize()867     VkDeviceSize getSize() const { return mSize; }
getMappedMemory()868     uint8_t *getMappedMemory() const
869     {
870         ASSERT(isMapped());
871         return mMemory.getMappedMemory();
872     }
isHostVisible()873     bool isHostVisible() const
874     {
875         return (mMemoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;
876     }
isCoherent()877     bool isCoherent() const
878     {
879         return (mMemoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0;
880     }
881 
isMapped()882     bool isMapped() const { return mMemory.getMappedMemory() != nullptr; }
isExternalBuffer()883     bool isExternalBuffer() const { return mMemory.isExternalBuffer(); }
884 
885     // Also implicitly sets up the correct barriers.
886     angle::Result copyFromBuffer(ContextVk *contextVk,
887                                  BufferHelper *srcBuffer,
888                                  uint32_t regionCount,
889                                  const VkBufferCopy *copyRegions);
890 
map(ContextVk * contextVk,uint8_t ** ptrOut)891     angle::Result map(ContextVk *contextVk, uint8_t **ptrOut)
892     {
893         return mMemory.map(contextVk, mSize, ptrOut);
894     }
895 
mapWithOffset(ContextVk * contextVk,uint8_t ** ptrOut,size_t offset)896     angle::Result mapWithOffset(ContextVk *contextVk, uint8_t **ptrOut, size_t offset)
897     {
898         uint8_t *mapBufPointer;
899         ANGLE_TRY(mMemory.map(contextVk, mSize, &mapBufPointer));
900         *ptrOut = mapBufPointer + offset;
901         return angle::Result::Continue;
902     }
903 
904     void unmap(RendererVk *renderer);
905 
906     // After a sequence of writes, call flush to ensure the data is visible to the device.
907     angle::Result flush(RendererVk *renderer, VkDeviceSize offset, VkDeviceSize size);
908 
909     // After a sequence of writes, call invalidate to ensure the data is visible to the host.
910     angle::Result invalidate(RendererVk *renderer, VkDeviceSize offset, VkDeviceSize size);
911 
912     void changeQueue(uint32_t newQueueFamilyIndex, CommandBuffer *commandBuffer);
913 
914     // Performs an ownership transfer from an external instance or API.
915     void acquireFromExternal(ContextVk *contextVk,
916                              uint32_t externalQueueFamilyIndex,
917                              uint32_t rendererQueueFamilyIndex,
918                              CommandBuffer *commandBuffer);
919 
920     // Performs an ownership transfer to an external instance or API.
921     void releaseToExternal(ContextVk *contextVk,
922                            uint32_t rendererQueueFamilyIndex,
923                            uint32_t externalQueueFamilyIndex,
924                            CommandBuffer *commandBuffer);
925 
926     // Returns true if the image is owned by an external API or instance.
927     bool isReleasedToExternal() const;
928 
929     bool recordReadBarrier(VkAccessFlags readAccessType,
930                            VkPipelineStageFlags readStage,
931                            PipelineBarrier *barrier);
932 
933     bool recordWriteBarrier(VkAccessFlags writeAccessType,
934                             VkPipelineStageFlags writeStage,
935                             PipelineBarrier *barrier);
936 
937   private:
938     angle::Result initializeNonZeroMemory(Context *context, VkDeviceSize size);
939 
940     // Vulkan objects.
941     Buffer mBuffer;
942     BufferMemory mMemory;
943 
944     // Cached properties.
945     VkMemoryPropertyFlags mMemoryPropertyFlags;
946     VkDeviceSize mSize;
947     uint32_t mCurrentQueueFamilyIndex;
948 
949     // For memory barriers.
950     VkFlags mCurrentWriteAccess;
951     VkFlags mCurrentReadAccess;
952     VkPipelineStageFlags mCurrentWriteStages;
953     VkPipelineStageFlags mCurrentReadStages;
954 
955     BufferSerial mSerial;
956 };
957 
958 enum class BufferAccess
959 {
960     Read,
961     Write,
962 };
963 
964 enum class AliasingMode
965 {
966     Allowed,
967     Disallowed,
968 };
969 
970 // Stores clear value In packed attachment index
971 class PackedClearValuesArray final
972 {
973   public:
974     PackedClearValuesArray();
975     ~PackedClearValuesArray();
976 
977     PackedClearValuesArray(const PackedClearValuesArray &other);
978     PackedClearValuesArray &operator=(const PackedClearValuesArray &rhs);
979     void store(PackedAttachmentIndex index,
980                VkImageAspectFlags aspectFlags,
981                const VkClearValue &clearValue);
982     void storeNoDepthStencil(PackedAttachmentIndex index, const VkClearValue &clearValue);
983     const VkClearValue &operator[](PackedAttachmentIndex index) const
984     {
985         return mValues[index.get()];
986     }
data()987     const VkClearValue *data() const { return mValues.data(); }
988 
989   private:
990     gl::AttachmentArray<VkClearValue> mValues;
991 };
992 
993 // Stores ImageHelpers In packed attachment index
994 class PackedImageAttachmentArray final
995 {
996   public:
PackedImageAttachmentArray()997     PackedImageAttachmentArray() : mImages{} {}
998     ~PackedImageAttachmentArray() = default;
999     ImageHelper *&operator[](PackedAttachmentIndex index) { return mImages[index.get()]; }
reset()1000     void reset() { mImages.fill(nullptr); }
1001 
1002   private:
1003     gl::AttachmentArray<ImageHelper *> mImages;
1004 };
1005 
1006 // The following are used to help track the state of an invalidated attachment.
1007 
1008 // This value indicates an "infinite" CmdSize that is not valid for comparing
1009 constexpr uint32_t kInfiniteCmdSize = 0xFFFFFFFF;
1010 
1011 // CommandBufferHelper (CBH) class wraps ANGLE's custom command buffer
1012 //  class, SecondaryCommandBuffer. This provides a way to temporarily
1013 //  store Vulkan commands that be can submitted in-line to a primary
1014 //  command buffer at a later time.
1015 // The current plan is for the main ANGLE thread to record commands
1016 //  into the CBH and then pass the CBH off to a worker thread that will
1017 //  process the commands into a primary command buffer and then submit
1018 //  those commands to the queue.
1019 class CommandBufferHelper : angle::NonCopyable
1020 {
1021   public:
1022     CommandBufferHelper();
1023     ~CommandBufferHelper();
1024 
1025     // General Functions (non-renderPass specific)
1026     void initialize(bool isRenderPassCommandBuffer);
1027 
1028     void bufferRead(ContextVk *contextVk,
1029                     VkAccessFlags readAccessType,
1030                     PipelineStage readStage,
1031                     BufferHelper *buffer);
1032     void bufferWrite(ContextVk *contextVk,
1033                      VkAccessFlags writeAccessType,
1034                      PipelineStage writeStage,
1035                      AliasingMode aliasingMode,
1036                      BufferHelper *buffer);
1037 
1038     void imageRead(ContextVk *contextVk,
1039                    VkImageAspectFlags aspectFlags,
1040                    ImageLayout imageLayout,
1041                    ImageHelper *image);
1042     void imageWrite(ContextVk *contextVk,
1043                     gl::LevelIndex level,
1044                     uint32_t layerStart,
1045                     uint32_t layerCount,
1046                     VkImageAspectFlags aspectFlags,
1047                     ImageLayout imageLayout,
1048                     AliasingMode aliasingMode,
1049                     ImageHelper *image);
1050 
1051     void colorImagesDraw(ResourceUseList *resourceUseList,
1052                          ImageHelper *image,
1053                          ImageHelper *resolveImage,
1054                          PackedAttachmentIndex packedAttachmentIndex);
1055     void depthStencilImagesDraw(ResourceUseList *resourceUseList,
1056                                 gl::LevelIndex level,
1057                                 uint32_t layerStart,
1058                                 uint32_t layerCount,
1059                                 ImageHelper *image,
1060                                 ImageHelper *resolveImage);
1061 
getCommandBuffer()1062     CommandBuffer &getCommandBuffer() { return mCommandBuffer; }
1063 
1064     angle::Result flushToPrimary(const angle::FeaturesVk &features,
1065                                  PrimaryCommandBuffer *primary,
1066                                  const RenderPass *renderPass);
1067 
1068     void executeBarriers(const angle::FeaturesVk &features, PrimaryCommandBuffer *primary);
1069 
setHasRenderPass(bool hasRenderPass)1070     void setHasRenderPass(bool hasRenderPass) { mIsRenderPassCommandBuffer = hasRenderPass; }
1071 
1072     // The markOpen and markClosed functions are to aid in proper use of the CommandBufferHelper.
1073     // saw invalid use due to threading issues that can be easily caught by marking when it's safe
1074     // (open) to write to the commandbuffer.
1075 #if defined(ANGLE_ENABLE_ASSERTS)
markOpen()1076     void markOpen() { mCommandBuffer.open(); }
markClosed()1077     void markClosed() { mCommandBuffer.close(); }
1078 #else
markOpen()1079     void markOpen() {}
markClosed()1080     void markClosed() {}
1081 #endif
1082 
1083     void reset();
1084 
1085     // Returns true if we have no work to execute. For renderpass command buffer, even if the
1086     // underlying command buffer is empty, we may still have a renderpass with an empty command
1087     // buffer just to do the clear.
empty()1088     bool empty() const
1089     {
1090         return mIsRenderPassCommandBuffer ? !mRenderPassStarted : mCommandBuffer.empty();
1091     }
1092     // RenderPass related functions. This is equivalent to !empty(), but only when you know this is
1093     // a RenderPass command buffer
started()1094     bool started() const
1095     {
1096         ASSERT(mIsRenderPassCommandBuffer);
1097         return mRenderPassStarted;
1098     }
1099 
1100     // Finalize the layout if image has any deferred layout transition.
1101     void finalizeImageLayout(Context *context, const ImageHelper *image);
1102 
1103     void beginRenderPass(const Framebuffer &framebuffer,
1104                          const gl::Rectangle &renderArea,
1105                          const RenderPassDesc &renderPassDesc,
1106                          const AttachmentOpsArray &renderPassAttachmentOps,
1107                          const vk::PackedAttachmentCount colorAttachmentCount,
1108                          const PackedAttachmentIndex depthStencilAttachmentIndex,
1109                          const PackedClearValuesArray &clearValues,
1110                          CommandBuffer **commandBufferOut);
1111 
1112     void endRenderPass(ContextVk *contextVk);
1113 
1114     void updateStartedRenderPassWithDepthMode(bool readOnlyDepthStencilMode);
1115 
1116     void beginTransformFeedback(size_t validBufferCount,
1117                                 const VkBuffer *counterBuffers,
1118                                 bool rebindBuffers);
1119 
1120     void endTransformFeedback();
1121 
1122     void invalidateRenderPassColorAttachment(PackedAttachmentIndex attachmentIndex);
1123     void invalidateRenderPassDepthAttachment(const gl::DepthStencilState &dsState,
1124                                              const gl::Rectangle &invalidateArea);
1125     void invalidateRenderPassStencilAttachment(const gl::DepthStencilState &dsState,
1126                                                const gl::Rectangle &invalidateArea);
1127 
hasWriteAfterInvalidate(uint32_t cmdCountInvalidated,uint32_t cmdCountDisabled)1128     bool hasWriteAfterInvalidate(uint32_t cmdCountInvalidated, uint32_t cmdCountDisabled)
1129     {
1130         ASSERT(mIsRenderPassCommandBuffer);
1131         return (cmdCountInvalidated != kInfiniteCmdSize &&
1132                 std::min(cmdCountDisabled, mCommandBuffer.getCommandSize()) != cmdCountInvalidated);
1133     }
1134 
isInvalidated(uint32_t cmdCountInvalidated,uint32_t cmdCountDisabled)1135     bool isInvalidated(uint32_t cmdCountInvalidated, uint32_t cmdCountDisabled)
1136     {
1137         ASSERT(mIsRenderPassCommandBuffer);
1138         return cmdCountInvalidated != kInfiniteCmdSize &&
1139                std::min(cmdCountDisabled, mCommandBuffer.getCommandSize()) == cmdCountInvalidated;
1140     }
1141 
1142     void updateRenderPassColorClear(PackedAttachmentIndex colorIndex,
1143                                     const VkClearValue &colorClearValue);
1144     void updateRenderPassDepthStencilClear(VkImageAspectFlags aspectFlags,
1145                                            const VkClearValue &clearValue);
1146 
getRenderArea()1147     const gl::Rectangle &getRenderArea() const
1148     {
1149         ASSERT(mIsRenderPassCommandBuffer);
1150         return mRenderArea;
1151     }
1152 
1153     // If render pass is started with a small render area due to a small scissor, and if a new
1154     // larger scissor is specified, grow the render area to accomodate it.
1155     void growRenderArea(ContextVk *contextVk, const gl::Rectangle &newRenderArea);
1156 
1157     void resumeTransformFeedback();
1158     void pauseTransformFeedback();
isTransformFeedbackStarted()1159     bool isTransformFeedbackStarted() const { return mValidTransformFeedbackBufferCount > 0; }
isTransformFeedbackActiveUnpaused()1160     bool isTransformFeedbackActiveUnpaused() const { return mIsTransformFeedbackActiveUnpaused; }
1161 
getAndResetCounter()1162     uint32_t getAndResetCounter()
1163     {
1164         ASSERT(mIsRenderPassCommandBuffer);
1165         uint32_t count = mCounter;
1166         mCounter       = 0;
1167         return count;
1168     }
1169 
getFramebufferHandle()1170     VkFramebuffer getFramebufferHandle() const
1171     {
1172         ASSERT(mIsRenderPassCommandBuffer);
1173         return mFramebuffer.getHandle();
1174     }
1175 
1176     bool usesBuffer(const BufferHelper &buffer) const;
1177     bool usesBufferForWrite(const BufferHelper &buffer) const;
1178     bool usesImageInRenderPass(const ImageHelper &image) const;
getUsedBuffersCount()1179     size_t getUsedBuffersCount() const { return mUsedBuffers.size(); }
1180 
1181     // Dumping the command stream is disabled by default.
1182     static constexpr bool kEnableCommandStreamDiagnostics = false;
1183 
1184     void onDepthAccess(ResourceAccess access);
1185     void onStencilAccess(ResourceAccess access);
1186 
1187     void updateRenderPassForResolve(ContextVk *contextVk,
1188                                     Framebuffer *newFramebuffer,
1189                                     const RenderPassDesc &renderPassDesc);
1190 
hasDepthStencilWriteOrClear()1191     bool hasDepthStencilWriteOrClear() const
1192     {
1193         return mDepthAccess == ResourceAccess::Write || mStencilAccess == ResourceAccess::Write ||
1194                mAttachmentOps[mDepthStencilAttachmentIndex].loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ||
1195                mAttachmentOps[mDepthStencilAttachmentIndex].stencilLoadOp ==
1196                    VK_ATTACHMENT_LOAD_OP_CLEAR;
1197     }
1198 
1199     void addCommandDiagnostics(ContextVk *contextVk);
1200 
getRenderPassDesc()1201     const RenderPassDesc &getRenderPassDesc() const { return mRenderPassDesc; }
getAttachmentOps()1202     const AttachmentOpsArray &getAttachmentOps() const { return mAttachmentOps; }
1203 
hasRenderPass()1204     bool hasRenderPass() const { return mIsRenderPassCommandBuffer; }
1205 
setHasShaderStorageOutput()1206     void setHasShaderStorageOutput() { mHasShaderStorageOutput = true; }
hasShaderStorageOutput()1207     bool hasShaderStorageOutput() const { return mHasShaderStorageOutput; }
1208 
setGLMemoryBarrierIssued()1209     void setGLMemoryBarrierIssued()
1210     {
1211         if (!empty())
1212         {
1213             mHasGLMemoryBarrierIssued = true;
1214         }
1215     }
hasGLMemoryBarrierIssued()1216     bool hasGLMemoryBarrierIssued() const { return mHasGLMemoryBarrierIssued; }
setImageOptimizeForPresent(ImageHelper * image)1217     void setImageOptimizeForPresent(ImageHelper *image) { mImageOptimizeForPresent = image; }
1218 
1219   private:
1220     bool onDepthStencilAccess(ResourceAccess access,
1221                               uint32_t *cmdCountInvalidated,
1222                               uint32_t *cmdCountDisabled);
1223     void restoreDepthContent();
1224     void restoreStencilContent();
1225 
1226     // We can't determine the image layout at the renderpass start time since their full usage
1227     // aren't known until later time. We finalize the layout when either ImageHelper object is
1228     // released or when renderpass ends.
1229     void finalizeColorImageLayout(Context *context,
1230                                   ImageHelper *image,
1231                                   PackedAttachmentIndex packedAttachmentIndex,
1232                                   bool isResolveImage);
1233     void finalizeDepthStencilImageLayout(Context *context);
1234     void finalizeDepthStencilResolveImageLayout(Context *context);
1235     void finalizeDepthStencilLoadStore(Context *context);
1236     void finalizeDepthStencilImageLayoutAndLoadStore(Context *context);
1237 
1238     void updateImageLayoutAndBarrier(Context *context,
1239                                      ImageHelper *image,
1240                                      VkImageAspectFlags aspectFlags,
1241                                      ImageLayout imageLayout);
1242 
1243     // Allocator used by this class. Using a pool allocator per CBH to avoid threading issues
1244     //  that occur w/ shared allocator between multiple CBHs.
1245     angle::PoolAllocator mAllocator;
1246 
1247     // General state (non-renderPass related)
1248     PipelineBarrierArray mPipelineBarriers;
1249     PipelineStagesMask mPipelineBarrierMask;
1250     CommandBuffer mCommandBuffer;
1251 
1252     // RenderPass state
1253     uint32_t mCounter;
1254     RenderPassDesc mRenderPassDesc;
1255     AttachmentOpsArray mAttachmentOps;
1256     Framebuffer mFramebuffer;
1257     gl::Rectangle mRenderArea;
1258     PackedClearValuesArray mClearValues;
1259     bool mRenderPassStarted;
1260 
1261     // Transform feedback state
1262     gl::TransformFeedbackBuffersArray<VkBuffer> mTransformFeedbackCounterBuffers;
1263     uint32_t mValidTransformFeedbackBufferCount;
1264     bool mRebindTransformFeedbackBuffers;
1265     bool mIsTransformFeedbackActiveUnpaused;
1266 
1267     bool mIsRenderPassCommandBuffer;
1268 
1269     // Whether the command buffers contains any draw/dispatch calls that possibly output data
1270     // through storage buffers and images.  This is used to determine whether glMemoryBarrier*
1271     // should flush the command buffer.
1272     bool mHasShaderStorageOutput;
1273     // Whether glMemoryBarrier has been called while commands are recorded in this command buffer.
1274     // This is used to know when to check and potentially flush the command buffer if storage
1275     // buffers and images are used in it.
1276     bool mHasGLMemoryBarrierIssued;
1277 
1278     // State tracking for the maximum (Write been the highest) depth access during the entire
1279     // renderpass. Note that this does not include VK_ATTACHMENT_LOAD_OP_CLEAR which is tracked
1280     // separately. This is done this way to allow clear op to being optimized out when we find out
1281     // that the depth buffer is not being used during the entire renderpass and store op is
1282     // VK_ATTACHMENT_STORE_OP_DONTCARE.
1283     ResourceAccess mDepthAccess;
1284     // Similar tracking to mDepthAccess but for the stencil aspect.
1285     ResourceAccess mStencilAccess;
1286 
1287     // State tracking for whether to optimize the storeOp to DONT_CARE
1288     uint32_t mDepthCmdSizeInvalidated;
1289     uint32_t mDepthCmdSizeDisabled;
1290     uint32_t mStencilCmdSizeInvalidated;
1291     uint32_t mStencilCmdSizeDisabled;
1292     gl::Rectangle mDepthInvalidateArea;
1293     gl::Rectangle mStencilInvalidateArea;
1294 
1295     // Keep track of the depth/stencil attachment index
1296     PackedAttachmentIndex mDepthStencilAttachmentIndex;
1297 
1298     // Tracks resources used in the command buffer.
1299     // For Buffers, we track the read/write access type so we can enable simultaneous reads.
1300     // Images have unique layouts unlike buffers therefore we don't support multi-read.
1301     angle::FastIntegerMap<BufferAccess> mUsedBuffers;
1302     angle::FastIntegerSet mRenderPassUsedImages;
1303 
1304     ImageHelper *mDepthStencilImage;
1305     ImageHelper *mDepthStencilResolveImage;
1306     gl::LevelIndex mDepthStencilLevelIndex;
1307     uint32_t mDepthStencilLayerIndex;
1308     uint32_t mDepthStencilLayerCount;
1309 
1310     // Array size of mColorImages
1311     PackedAttachmentCount mColorImagesCount;
1312     // Attached render target images. Color and depth resolve images are always come last.
1313     PackedImageAttachmentArray mColorImages;
1314     PackedImageAttachmentArray mColorResolveImages;
1315     // This is last renderpass before present and this is the image will be presented. We can use
1316     // final layout of the renderpass to transit it to the presentable layout
1317     ImageHelper *mImageOptimizeForPresent;
1318 };
1319 
1320 // Imagine an image going through a few layout transitions:
1321 //
1322 //           srcStage 1    dstStage 2          srcStage 2     dstStage 3
1323 //  Layout 1 ------Transition 1-----> Layout 2 ------Transition 2------> Layout 3
1324 //           srcAccess 1  dstAccess 2          srcAccess 2   dstAccess 3
1325 //   \_________________  ___________________/
1326 //                     \/
1327 //               A transition
1328 //
1329 // Every transition requires 6 pieces of information: from/to layouts, src/dst stage masks and
1330 // src/dst access masks.  At the moment we decide to transition the image to Layout 2 (i.e.
1331 // Transition 1), we need to have Layout 1, srcStage 1 and srcAccess 1 stored as history of the
1332 // image.  To perform the transition, we need to know Layout 2, dstStage 2 and dstAccess 2.
1333 // Additionally, we need to know srcStage 2 and srcAccess 2 to retain them for the next transition.
1334 //
1335 // That is, with the history kept, on every new transition we need 5 pieces of new information:
1336 // layout/dstStage/dstAccess to transition into the layout, and srcStage/srcAccess for the future
1337 // transition out from it.  Given the small number of possible combinations of these values, an
1338 // enum is used were each value encapsulates these 5 pieces of information:
1339 //
1340 //                       +--------------------------------+
1341 //           srcStage 1  | dstStage 2          srcStage 2 |   dstStage 3
1342 //  Layout 1 ------Transition 1-----> Layout 2 ------Transition 2------> Layout 3
1343 //           srcAccess 1 |dstAccess 2          srcAccess 2|  dstAccess 3
1344 //                       +---------------  ---------------+
1345 //                                       \/
1346 //                                 One enum value
1347 //
1348 // Note that, while generally dstStage for the to-transition and srcStage for the from-transition
1349 // are the same, they may occasionally be BOTTOM_OF_PIPE and TOP_OF_PIPE respectively.
1350 enum class ImageLayout
1351 {
1352     Undefined = 0,
1353     // Framebuffer attachment layouts are placed first, so they can fit in fewer bits in
1354     // PackedAttachmentOpsDesc.
1355     ColorAttachment,
1356     ColorAttachmentAndFragmentShaderRead,
1357     ColorAttachmentAndAllShadersRead,
1358     DSAttachmentWriteAndFragmentShaderRead,
1359     DSAttachmentWriteAndAllShadersRead,
1360     DSAttachmentReadAndFragmentShaderRead,
1361     DSAttachmentReadAndAllShadersRead,
1362     DepthStencilAttachmentReadOnly,
1363     DepthStencilAttachment,
1364     DepthStencilResolveAttachment,
1365     Present,
1366     // The rest of the layouts.
1367     ExternalPreInitialized,
1368     ExternalShadersReadOnly,
1369     ExternalShadersWrite,
1370     TransferSrc,
1371     TransferDst,
1372     VertexShaderReadOnly,
1373     VertexShaderWrite,
1374     // PreFragment == Vertex, Tessellation and Geometry stages
1375     PreFragmentShadersReadOnly,
1376     PreFragmentShadersWrite,
1377     FragmentShaderReadOnly,
1378     FragmentShaderWrite,
1379     ComputeShaderReadOnly,
1380     ComputeShaderWrite,
1381     AllGraphicsShadersReadOnly,
1382     AllGraphicsShadersWrite,
1383 
1384     InvalidEnum,
1385     EnumCount = InvalidEnum,
1386 };
1387 
1388 VkImageLayout ConvertImageLayoutToVkImageLayout(ImageLayout imageLayout);
1389 
1390 // How the ImageHelper object is being used by the renderpass
1391 enum class RenderPassUsage
1392 {
1393     // Attached to the render taget of the current renderpass commands. It could be read/write or
1394     // read only access.
1395     RenderTargetAttachment,
1396     // This is special case of RenderTargetAttachment where the render target access is read only.
1397     // Right now it is only tracked for depth stencil attachment
1398     ReadOnlyAttachment,
1399     // Attached to the texture sampler of the current renderpass commands
1400     TextureSampler,
1401 
1402     InvalidEnum,
1403     EnumCount = InvalidEnum,
1404 };
1405 using RenderPassUsageFlags = angle::PackedEnumBitSet<RenderPassUsage, uint16_t>;
1406 
1407 bool FormatHasNecessaryFeature(RendererVk *renderer,
1408                                angle::FormatID formatID,
1409                                VkImageTiling tilingMode,
1410                                VkFormatFeatureFlags featureBits);
1411 
1412 bool CanCopyWithTransfer(RendererVk *renderer,
1413                          const Format &srcFormat,
1414                          VkImageTiling srcTilingMode,
1415                          const Format &destFormat,
1416                          VkImageTiling destTilingMode);
1417 
1418 class ImageHelper final : public Resource, public angle::Subject
1419 {
1420   public:
1421     ImageHelper();
1422     ImageHelper(ImageHelper &&other);
1423     ~ImageHelper() override;
1424 
1425     void initStagingBuffer(RendererVk *renderer,
1426                            size_t imageCopyBufferAlignment,
1427                            VkBufferUsageFlags usageFlags,
1428                            size_t initialSize);
1429 
1430     angle::Result init(Context *context,
1431                        gl::TextureType textureType,
1432                        const VkExtent3D &extents,
1433                        const Format &format,
1434                        GLint samples,
1435                        VkImageUsageFlags usage,
1436                        gl::LevelIndex firstLevel,
1437                        uint32_t mipLevels,
1438                        uint32_t layerCount,
1439                        bool isRobustResourceInitEnabled,
1440                        bool hasProtectedContent);
1441     angle::Result initMSAASwapchain(Context *context,
1442                                     gl::TextureType textureType,
1443                                     const VkExtent3D &extents,
1444                                     bool rotatedAspectRatio,
1445                                     const Format &format,
1446                                     GLint samples,
1447                                     VkImageUsageFlags usage,
1448                                     gl::LevelIndex firstLevel,
1449                                     uint32_t mipLevels,
1450                                     uint32_t layerCount,
1451                                     bool isRobustResourceInitEnabled,
1452                                     bool hasProtectedContent);
1453     angle::Result initExternal(Context *context,
1454                                gl::TextureType textureType,
1455                                const VkExtent3D &extents,
1456                                const Format &format,
1457                                GLint samples,
1458                                VkImageUsageFlags usage,
1459                                VkImageCreateFlags additionalCreateFlags,
1460                                ImageLayout initialLayout,
1461                                const void *externalImageCreateInfo,
1462                                gl::LevelIndex firstLevel,
1463                                uint32_t mipLevels,
1464                                uint32_t layerCount,
1465                                bool isRobustResourceInitEnabled,
1466                                bool *imageFormatListEnabledOut,
1467                                bool hasProtectedContent);
1468     angle::Result initMemory(Context *context,
1469                              bool hasProtectedContent,
1470                              const MemoryProperties &memoryProperties,
1471                              VkMemoryPropertyFlags flags);
1472     angle::Result initExternalMemory(
1473         Context *context,
1474         const MemoryProperties &memoryProperties,
1475         const VkMemoryRequirements &memoryRequirements,
1476         const VkSamplerYcbcrConversionCreateInfo *samplerYcbcrConversionCreateInfo,
1477         const void *extraAllocationInfo,
1478         uint32_t currentQueueFamilyIndex,
1479         VkMemoryPropertyFlags flags);
1480     angle::Result initLayerImageView(Context *context,
1481                                      gl::TextureType textureType,
1482                                      VkImageAspectFlags aspectMask,
1483                                      const gl::SwizzleState &swizzleMap,
1484                                      ImageView *imageViewOut,
1485                                      LevelIndex baseMipLevelVk,
1486                                      uint32_t levelCount,
1487                                      uint32_t baseArrayLayer,
1488                                      uint32_t layerCount,
1489                                      gl::SrgbWriteControlMode mode) const;
1490     angle::Result initLayerImageViewWithFormat(Context *context,
1491                                                gl::TextureType textureType,
1492                                                const Format &format,
1493                                                VkImageAspectFlags aspectMask,
1494                                                const gl::SwizzleState &swizzleMap,
1495                                                ImageView *imageViewOut,
1496                                                LevelIndex baseMipLevelVk,
1497                                                uint32_t levelCount,
1498                                                uint32_t baseArrayLayer,
1499                                                uint32_t layerCount) const;
1500     angle::Result initReinterpretedLayerImageView(Context *context,
1501                                                   gl::TextureType textureType,
1502                                                   VkImageAspectFlags aspectMask,
1503                                                   const gl::SwizzleState &swizzleMap,
1504                                                   ImageView *imageViewOut,
1505                                                   LevelIndex baseMipLevelVk,
1506                                                   uint32_t levelCount,
1507                                                   uint32_t baseArrayLayer,
1508                                                   uint32_t layerCount,
1509                                                   VkImageUsageFlags imageUsageFlags,
1510                                                   angle::FormatID imageViewFormat) const;
1511     angle::Result initImageView(Context *context,
1512                                 gl::TextureType textureType,
1513                                 VkImageAspectFlags aspectMask,
1514                                 const gl::SwizzleState &swizzleMap,
1515                                 ImageView *imageViewOut,
1516                                 LevelIndex baseMipLevelVk,
1517                                 uint32_t levelCount);
1518     // Create a 2D[Array] for staging purposes.  Used by:
1519     //
1520     // - TextureVk::copySubImageImplWithDraw
1521     // - FramebufferVk::readPixelsImpl
1522     //
1523     angle::Result init2DStaging(Context *context,
1524                                 bool hasProtectedContent,
1525                                 const MemoryProperties &memoryProperties,
1526                                 const gl::Extents &glExtents,
1527                                 const Format &format,
1528                                 VkImageUsageFlags usage,
1529                                 uint32_t layerCount);
1530     // Create an image for staging purposes.  Used by:
1531     //
1532     // - TextureVk::copyAndStageImageData
1533     //
1534     angle::Result initStaging(Context *context,
1535                               bool hasProtectedContent,
1536                               const MemoryProperties &memoryProperties,
1537                               VkImageType imageType,
1538                               const VkExtent3D &extents,
1539                               const Format &format,
1540                               GLint samples,
1541                               VkImageUsageFlags usage,
1542                               uint32_t mipLevels,
1543                               uint32_t layerCount);
1544     // Create a multisampled image for use as the implicit image in multisampled render to texture
1545     // rendering.  If LAZILY_ALLOCATED memory is available, it will prefer that.
1546     angle::Result initImplicitMultisampledRenderToTexture(Context *context,
1547                                                           bool hasProtectedContent,
1548                                                           const MemoryProperties &memoryProperties,
1549                                                           gl::TextureType textureType,
1550                                                           GLint samples,
1551                                                           const ImageHelper &resolveImage,
1552                                                           bool isRobustResourceInitEnabled);
1553     // Release the underlining VkImage object for garbage collection.
1554     void releaseImage(RendererVk *renderer);
1555     // Similar to releaseImage, but also notify all contexts in the same share group to stop
1556     // accessing to it.
1557     void releaseImageFromShareContexts(RendererVk *renderer, ContextVk *contextVk);
1558     void releaseStagingBuffer(RendererVk *renderer);
1559 
valid()1560     bool valid() const { return mImage.valid(); }
1561 
1562     VkImageAspectFlags getAspectFlags() const;
1563     // True if image contains both depth & stencil aspects
1564     bool isCombinedDepthStencilFormat() const;
1565     void destroy(RendererVk *renderer);
release(RendererVk * renderer)1566     void release(RendererVk *renderer) { destroy(renderer); }
1567 
1568     void init2DWeakReference(Context *context,
1569                              VkImage handle,
1570                              const gl::Extents &glExtents,
1571                              bool rotatedAspectRatio,
1572                              const Format &format,
1573                              GLint samples,
1574                              bool isRobustResourceInitEnabled);
1575     void resetImageWeakReference();
1576 
getImage()1577     const Image &getImage() const { return mImage; }
getDeviceMemory()1578     const DeviceMemory &getDeviceMemory() const { return mDeviceMemory; }
1579 
setTilingMode(VkImageTiling tilingMode)1580     void setTilingMode(VkImageTiling tilingMode) { mTilingMode = tilingMode; }
getTilingMode()1581     VkImageTiling getTilingMode() const { return mTilingMode; }
getCreateFlags()1582     VkImageCreateFlags getCreateFlags() const { return mCreateFlags; }
getUsage()1583     VkImageUsageFlags getUsage() const { return mUsage; }
getType()1584     VkImageType getType() const { return mImageType; }
getExtents()1585     const VkExtent3D &getExtents() const { return mExtents; }
1586     const VkExtent3D getRotatedExtents() const;
getLayerCount()1587     uint32_t getLayerCount() const { return mLayerCount; }
getLevelCount()1588     uint32_t getLevelCount() const { return mLevelCount; }
getFormat()1589     const Format &getFormat() const { return *mFormat; }
getSamples()1590     GLint getSamples() const { return mSamples; }
1591 
getImageSerial()1592     ImageSerial getImageSerial() const
1593     {
1594         ASSERT(valid() && mImageSerial.valid());
1595         return mImageSerial;
1596     }
1597 
setCurrentImageLayout(ImageLayout newLayout)1598     void setCurrentImageLayout(ImageLayout newLayout) { mCurrentLayout = newLayout; }
getCurrentImageLayout()1599     ImageLayout getCurrentImageLayout() const { return mCurrentLayout; }
1600     VkImageLayout getCurrentLayout() const;
1601 
1602     gl::Extents getLevelExtents(LevelIndex levelVk) const;
1603     // Helper function to calculate the extents of a render target created for a certain mip of the
1604     // image.
1605     gl::Extents getLevelExtents2D(LevelIndex levelVk) const;
1606     gl::Extents getRotatedLevelExtents2D(LevelIndex levelVk) const;
1607 
1608     bool isDepthOrStencil() const;
1609 
1610     void setRenderPassUsageFlag(RenderPassUsage flag);
1611     void clearRenderPassUsageFlag(RenderPassUsage flag);
1612     void resetRenderPassUsageFlags();
1613     bool hasRenderPassUsageFlag(RenderPassUsage flag) const;
1614     bool usedByCurrentRenderPassAsAttachmentAndSampler() const;
1615 
1616     // Clear either color or depth/stencil based on image format.
1617     void clear(VkImageAspectFlags aspectFlags,
1618                const VkClearValue &value,
1619                LevelIndex mipLevel,
1620                uint32_t baseArrayLayer,
1621                uint32_t layerCount,
1622                CommandBuffer *commandBuffer);
1623 
1624     static void Copy(ImageHelper *srcImage,
1625                      ImageHelper *dstImage,
1626                      const gl::Offset &srcOffset,
1627                      const gl::Offset &dstOffset,
1628                      const gl::Extents &copySize,
1629                      const VkImageSubresourceLayers &srcSubresources,
1630                      const VkImageSubresourceLayers &dstSubresources,
1631                      CommandBuffer *commandBuffer);
1632 
1633     static angle::Result CopyImageSubData(const gl::Context *context,
1634                                           ImageHelper *srcImage,
1635                                           GLint srcLevel,
1636                                           GLint srcX,
1637                                           GLint srcY,
1638                                           GLint srcZ,
1639                                           ImageHelper *dstImage,
1640                                           GLint dstLevel,
1641                                           GLint dstX,
1642                                           GLint dstY,
1643                                           GLint dstZ,
1644                                           GLsizei srcWidth,
1645                                           GLsizei srcHeight,
1646                                           GLsizei srcDepth);
1647 
1648     // Generate mipmap from level 0 into the rest of the levels with blit.
1649     angle::Result generateMipmapsWithBlit(ContextVk *contextVk,
1650                                           LevelIndex baseLevel,
1651                                           LevelIndex maxLevel);
1652 
1653     // Resolve this image into a destination image.  This image should be in the TransferSrc layout.
1654     // The destination image is automatically transitioned into TransferDst.
1655     void resolve(ImageHelper *dest, const VkImageResolve &region, CommandBuffer *commandBuffer);
1656 
1657     // Data staging
1658     void removeSingleSubresourceStagedUpdates(ContextVk *contextVk,
1659                                               gl::LevelIndex levelIndexGL,
1660                                               uint32_t layerIndex,
1661                                               uint32_t layerCount);
1662     void removeStagedUpdates(Context *context,
1663                              gl::LevelIndex levelGLStart,
1664                              gl::LevelIndex levelGLEnd);
1665 
1666     angle::Result stageSubresourceUpdateImpl(ContextVk *contextVk,
1667                                              const gl::ImageIndex &index,
1668                                              const gl::Extents &glExtents,
1669                                              const gl::Offset &offset,
1670                                              const gl::InternalFormat &formatInfo,
1671                                              const gl::PixelUnpackState &unpack,
1672                                              DynamicBuffer *stagingBufferOverride,
1673                                              GLenum type,
1674                                              const uint8_t *pixels,
1675                                              const Format &vkFormat,
1676                                              const GLuint inputRowPitch,
1677                                              const GLuint inputDepthPitch,
1678                                              const GLuint inputSkipBytes);
1679 
1680     angle::Result stageSubresourceUpdate(ContextVk *contextVk,
1681                                          const gl::ImageIndex &index,
1682                                          const gl::Extents &glExtents,
1683                                          const gl::Offset &offset,
1684                                          const gl::InternalFormat &formatInfo,
1685                                          const gl::PixelUnpackState &unpack,
1686                                          DynamicBuffer *stagingBufferOverride,
1687                                          GLenum type,
1688                                          const uint8_t *pixels,
1689                                          const Format &vkFormat);
1690 
1691     angle::Result stageSubresourceUpdateAndGetData(ContextVk *contextVk,
1692                                                    size_t allocationSize,
1693                                                    const gl::ImageIndex &imageIndex,
1694                                                    const gl::Extents &glExtents,
1695                                                    const gl::Offset &offset,
1696                                                    uint8_t **destData,
1697                                                    DynamicBuffer *stagingBufferOverride);
1698 
1699     angle::Result stageSubresourceUpdateFromFramebuffer(const gl::Context *context,
1700                                                         const gl::ImageIndex &index,
1701                                                         const gl::Rectangle &sourceArea,
1702                                                         const gl::Offset &dstOffset,
1703                                                         const gl::Extents &dstExtent,
1704                                                         const gl::InternalFormat &formatInfo,
1705                                                         FramebufferVk *framebufferVk,
1706                                                         DynamicBuffer *stagingBufferOverride);
1707 
1708     void stageSubresourceUpdateFromImage(RefCounted<ImageHelper> *image,
1709                                          const gl::ImageIndex &index,
1710                                          LevelIndex srcMipLevel,
1711                                          const gl::Offset &destOffset,
1712                                          const gl::Extents &glExtents,
1713                                          const VkImageType imageType);
1714 
1715     // Takes an image and stages a subresource update for each level of it, including its full
1716     // extent and all its layers, at the specified GL level.
1717     void stageSubresourceUpdatesFromAllImageLevels(RefCounted<ImageHelper> *image,
1718                                                    gl::LevelIndex baseLevel);
1719 
1720     // Stage a clear to an arbitrary value.
1721     void stageClear(const gl::ImageIndex &index,
1722                     VkImageAspectFlags aspectFlags,
1723                     const VkClearValue &clearValue);
1724 
1725     // Stage a clear based on robust resource init.
1726     angle::Result stageRobustResourceClearWithFormat(ContextVk *contextVk,
1727                                                      const gl::ImageIndex &index,
1728                                                      const gl::Extents &glExtents,
1729                                                      const Format &format);
1730     void stageRobustResourceClear(const gl::ImageIndex &index);
1731 
1732     // Stage the currently allocated image as updates to base level and on, making this !valid().
1733     // This is used for:
1734     //
1735     // - Mipmap generation, where levelCount is 1 so only the base level is retained
1736     // - Image respecification, where every level (other than those explicitly skipped) is staged
1737     void stageSelfAsSubresourceUpdates(ContextVk *contextVk,
1738                                        uint32_t levelCount,
1739                                        gl::TexLevelMask skipLevelsMask);
1740 
1741     // Flush staged updates for a single subresource. Can optionally take a parameter to defer
1742     // clears to a subsequent RenderPass load op.
1743     angle::Result flushSingleSubresourceStagedUpdates(ContextVk *contextVk,
1744                                                       gl::LevelIndex levelGL,
1745                                                       uint32_t layer,
1746                                                       uint32_t layerCount,
1747                                                       ClearValuesArray *deferredClears,
1748                                                       uint32_t deferredClearIndex);
1749 
1750     // Flushes staged updates to a range of levels and layers from start to (but not including) end.
1751     // Due to the nature of updates (done wholly to a VkImageSubresourceLayers), some unsolicited
1752     // layers may also be updated.
1753     angle::Result flushStagedUpdates(ContextVk *contextVk,
1754                                      gl::LevelIndex levelGLStart,
1755                                      gl::LevelIndex levelGLEnd,
1756                                      uint32_t layerStart,
1757                                      uint32_t layerEnd,
1758                                      gl::TexLevelMask skipLevelsMask);
1759 
1760     // Creates a command buffer and flushes all staged updates.  This is used for one-time
1761     // initialization of resources that we don't expect to accumulate further staged updates, such
1762     // as with renderbuffers or surface images.
1763     angle::Result flushAllStagedUpdates(ContextVk *contextVk);
1764 
1765     bool hasStagedUpdatesForSubresource(gl::LevelIndex levelGL,
1766                                         uint32_t layer,
1767                                         uint32_t layerCount) const;
1768     bool hasStagedUpdatesInAllocatedLevels() const;
1769 
recordWriteBarrier(Context * context,VkImageAspectFlags aspectMask,ImageLayout newLayout,CommandBuffer * commandBuffer)1770     void recordWriteBarrier(Context *context,
1771                             VkImageAspectFlags aspectMask,
1772                             ImageLayout newLayout,
1773                             CommandBuffer *commandBuffer)
1774     {
1775         barrierImpl(context, aspectMask, newLayout, mCurrentQueueFamilyIndex, commandBuffer);
1776     }
1777 
1778     // This function can be used to prevent issuing redundant layout transition commands.
1779     bool isReadBarrierNecessary(ImageLayout newLayout) const;
1780 
recordReadBarrier(Context * context,VkImageAspectFlags aspectMask,ImageLayout newLayout,CommandBuffer * commandBuffer)1781     void recordReadBarrier(Context *context,
1782                            VkImageAspectFlags aspectMask,
1783                            ImageLayout newLayout,
1784                            CommandBuffer *commandBuffer)
1785     {
1786         if (!isReadBarrierNecessary(newLayout))
1787         {
1788             return;
1789         }
1790 
1791         barrierImpl(context, aspectMask, newLayout, mCurrentQueueFamilyIndex, commandBuffer);
1792     }
1793 
isQueueChangeNeccesary(uint32_t newQueueFamilyIndex)1794     bool isQueueChangeNeccesary(uint32_t newQueueFamilyIndex) const
1795     {
1796         return mCurrentQueueFamilyIndex != newQueueFamilyIndex;
1797     }
1798 
1799     void changeLayoutAndQueue(Context *context,
1800                               VkImageAspectFlags aspectMask,
1801                               ImageLayout newLayout,
1802                               uint32_t newQueueFamilyIndex,
1803                               CommandBuffer *commandBuffer);
1804 
1805     // Returns true if barrier has been generated
1806     bool updateLayoutAndBarrier(Context *context,
1807                                 VkImageAspectFlags aspectMask,
1808                                 ImageLayout newLayout,
1809                                 PipelineBarrier *barrier);
1810 
1811     // Performs an ownership transfer from an external instance or API.
1812     void acquireFromExternal(ContextVk *contextVk,
1813                              uint32_t externalQueueFamilyIndex,
1814                              uint32_t rendererQueueFamilyIndex,
1815                              ImageLayout currentLayout,
1816                              CommandBuffer *commandBuffer);
1817 
1818     // Performs an ownership transfer to an external instance or API.
1819     void releaseToExternal(ContextVk *contextVk,
1820                            uint32_t rendererQueueFamilyIndex,
1821                            uint32_t externalQueueFamilyIndex,
1822                            ImageLayout desiredLayout,
1823                            CommandBuffer *commandBuffer);
1824 
1825     // Returns true if the image is owned by an external API or instance.
1826     bool isReleasedToExternal() const;
1827 
getFirstAllocatedLevel()1828     gl::LevelIndex getFirstAllocatedLevel() const { return mFirstAllocatedLevel; }
1829     void setFirstAllocatedLevel(gl::LevelIndex firstLevel);
1830     gl::LevelIndex getLastAllocatedLevel() const;
1831     LevelIndex toVkLevel(gl::LevelIndex levelIndexGL) const;
1832     gl::LevelIndex toGLLevel(LevelIndex levelIndexVk) const;
1833 
1834     angle::Result copyImageDataToBuffer(ContextVk *contextVk,
1835                                         gl::LevelIndex sourceLevelGL,
1836                                         uint32_t layerCount,
1837                                         uint32_t baseLayer,
1838                                         const gl::Box &sourceArea,
1839                                         BufferHelper **bufferOut,
1840                                         size_t *bufferSize,
1841                                         StagingBufferOffsetArray *bufferOffsetsOut,
1842                                         uint8_t **outDataPtr);
1843 
1844     static angle::Result GetReadPixelsParams(ContextVk *contextVk,
1845                                              const gl::PixelPackState &packState,
1846                                              gl::Buffer *packBuffer,
1847                                              GLenum format,
1848                                              GLenum type,
1849                                              const gl::Rectangle &area,
1850                                              const gl::Rectangle &clippedArea,
1851                                              PackPixelsParams *paramsOut,
1852                                              GLuint *skipBytesOut);
1853 
1854     angle::Result readPixelsForGetImage(ContextVk *contextVk,
1855                                         const gl::PixelPackState &packState,
1856                                         gl::Buffer *packBuffer,
1857                                         gl::LevelIndex levelGL,
1858                                         uint32_t layer,
1859                                         GLenum format,
1860                                         GLenum type,
1861                                         void *pixels);
1862 
1863     angle::Result readPixels(ContextVk *contextVk,
1864                              const gl::Rectangle &area,
1865                              const PackPixelsParams &packPixelsParams,
1866                              VkImageAspectFlagBits copyAspectFlags,
1867                              gl::LevelIndex levelGL,
1868                              uint32_t layer,
1869                              void *pixels,
1870                              DynamicBuffer *stagingBuffer);
1871 
1872     angle::Result CalculateBufferInfo(ContextVk *contextVk,
1873                                       const gl::Extents &glExtents,
1874                                       const gl::InternalFormat &formatInfo,
1875                                       const gl::PixelUnpackState &unpack,
1876                                       GLenum type,
1877                                       bool is3D,
1878                                       GLuint *inputRowPitch,
1879                                       GLuint *inputDepthPitch,
1880                                       GLuint *inputSkipBytes);
1881 
1882     // Mark a given subresource as written to.  The subresource is identified by [levelStart,
1883     // levelStart + levelCount) and [layerStart, layerStart + layerCount).
1884     void onWrite(gl::LevelIndex levelStart,
1885                  uint32_t levelCount,
1886                  uint32_t layerStart,
1887                  uint32_t layerCount,
1888                  VkImageAspectFlags aspectFlags);
1889     bool hasImmutableSampler() const;
getExternalFormat()1890     uint64_t getExternalFormat() const { return mExternalFormat; }
1891 
1892     // Used by framebuffer and render pass functions to decide loadOps and invalidate/un-invalidate
1893     // render target contents.
1894     bool hasSubresourceDefinedContent(gl::LevelIndex level,
1895                                       uint32_t layerIndex,
1896                                       uint32_t layerCount) const;
1897     bool hasSubresourceDefinedStencilContent(gl::LevelIndex level,
1898                                              uint32_t layerIndex,
1899                                              uint32_t layerCount) const;
1900     void invalidateSubresourceContent(ContextVk *contextVk,
1901                                       gl::LevelIndex level,
1902                                       uint32_t layerIndex,
1903                                       uint32_t layerCount);
1904     void invalidateSubresourceStencilContent(ContextVk *contextVk,
1905                                              gl::LevelIndex level,
1906                                              uint32_t layerIndex,
1907                                              uint32_t layerCount);
1908     void restoreSubresourceContent(gl::LevelIndex level, uint32_t layerIndex, uint32_t layerCount);
1909     void restoreSubresourceStencilContent(gl::LevelIndex level,
1910                                           uint32_t layerIndex,
1911                                           uint32_t layerCount);
1912 
1913   private:
1914     enum class UpdateSource
1915     {
1916         Clear,
1917         Buffer,
1918         Image,
1919     };
1920     ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
1921     struct ClearUpdate
1922     {
1923         bool operator==(const ClearUpdate &rhs)
1924         {
1925             return memcmp(this, &rhs, sizeof(ClearUpdate)) == 0;
1926         }
1927         VkImageAspectFlags aspectFlags;
1928         VkClearValue value;
1929         uint32_t levelIndex;
1930         uint32_t layerIndex;
1931         uint32_t layerCount;
1932     };
1933     ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
1934     struct BufferUpdate
1935     {
1936         BufferHelper *bufferHelper;
1937         VkBufferImageCopy copyRegion;
1938     };
1939     struct ImageUpdate
1940     {
1941         VkImageCopy copyRegion;
1942     };
1943 
1944     struct SubresourceUpdate : angle::NonCopyable
1945     {
1946         SubresourceUpdate();
1947         ~SubresourceUpdate();
1948         SubresourceUpdate(BufferHelper *bufferHelperIn, const VkBufferImageCopy &copyRegion);
1949         SubresourceUpdate(RefCounted<ImageHelper> *imageIn, const VkImageCopy &copyRegion);
1950         SubresourceUpdate(VkImageAspectFlags aspectFlags,
1951                           const VkClearValue &clearValue,
1952                           const gl::ImageIndex &imageIndex);
1953         SubresourceUpdate(SubresourceUpdate &&other);
1954 
1955         SubresourceUpdate &operator=(SubresourceUpdate &&other);
1956 
1957         void release(RendererVk *renderer);
1958 
1959         bool isUpdateToLayers(uint32_t layerIndex, uint32_t layerCount) const;
1960         void getDestSubresource(uint32_t imageLayerCount,
1961                                 uint32_t *baseLayerOut,
1962                                 uint32_t *layerCountOut) const;
1963         VkImageAspectFlags getDestAspectFlags() const;
1964 
1965         UpdateSource updateSource;
1966         union
1967         {
1968             ClearUpdate clear;
1969             BufferUpdate buffer;
1970             ImageUpdate image;
1971         } data;
1972         RefCounted<ImageHelper> *image;
1973     };
1974 
1975     // Called from flushStagedUpdates, removes updates that are later superseded by another.  This
1976     // cannot be done at the time the updates were staged, as the image is not created (and thus the
1977     // extents are not known).
1978     void removeSupersededUpdates(ContextVk *contextVk, gl::TexLevelMask skipLevelsMask);
1979 
1980     void initImageMemoryBarrierStruct(VkImageAspectFlags aspectMask,
1981                                       ImageLayout newLayout,
1982                                       uint32_t newQueueFamilyIndex,
1983                                       VkImageMemoryBarrier *imageMemoryBarrier) const;
1984 
1985     // Generalized to accept both "primary" and "secondary" command buffers.
1986     template <typename CommandBufferT>
1987     void barrierImpl(Context *context,
1988                      VkImageAspectFlags aspectMask,
1989                      ImageLayout newLayout,
1990                      uint32_t newQueueFamilyIndex,
1991                      CommandBufferT *commandBuffer);
1992 
1993     // If the image has emulated channels, we clear them once so as not to leave garbage on those
1994     // channels.
1995     void stageClearIfEmulatedFormat(bool isRobustResourceInitEnabled);
1996 
1997     void clearColor(const VkClearColorValue &color,
1998                     LevelIndex baseMipLevelVk,
1999                     uint32_t levelCount,
2000                     uint32_t baseArrayLayer,
2001                     uint32_t layerCount,
2002                     CommandBuffer *commandBuffer);
2003 
2004     void clearDepthStencil(VkImageAspectFlags clearAspectFlags,
2005                            const VkClearDepthStencilValue &depthStencil,
2006                            LevelIndex baseMipLevelVk,
2007                            uint32_t levelCount,
2008                            uint32_t baseArrayLayer,
2009                            uint32_t layerCount,
2010                            CommandBuffer *commandBuffer);
2011 
2012     angle::Result initializeNonZeroMemory(Context *context,
2013                                           bool hasProtectedContent,
2014                                           VkDeviceSize size);
2015 
2016     std::vector<SubresourceUpdate> *getLevelUpdates(gl::LevelIndex level);
2017     const std::vector<SubresourceUpdate> *getLevelUpdates(gl::LevelIndex level) const;
2018 
2019     void appendSubresourceUpdate(gl::LevelIndex level, SubresourceUpdate &&update);
2020     void prependSubresourceUpdate(gl::LevelIndex level, SubresourceUpdate &&update);
2021     // Whether there are any updates in [start, end).
2022     bool hasStagedUpdatesInLevels(gl::LevelIndex levelStart, gl::LevelIndex levelEnd) const;
2023 
2024     // Used only for assertions, these functions verify that SubresourceUpdate::image references
2025     // have the correct ref count.  This is to prevent accidental leaks.
2026     bool validateSubresourceUpdateImageRefConsistent(RefCounted<ImageHelper> *image) const;
2027     bool validateSubresourceUpdateImageRefsConsistent() const;
2028 
2029     void resetCachedProperties();
2030     void setEntireContentDefined();
2031     void setEntireContentUndefined();
2032     void setContentDefined(LevelIndex levelStart,
2033                            uint32_t levelCount,
2034                            uint32_t layerStart,
2035                            uint32_t layerCount,
2036                            VkImageAspectFlags aspectFlags);
2037 
2038     // Up to 8 layers are tracked per level for whether contents are defined, above which the
2039     // contents are considered unconditionally defined.  This handles the more likely scenarios of:
2040     //
2041     // - Single layer framebuffer attachments,
2042     // - Cube map framebuffer attachments,
2043     // - Multi-view rendering.
2044     //
2045     // If there arises a need to optimize an application that invalidates layer >= 8, an additional
2046     // hash map can be used to track such subresources.
2047     static constexpr uint32_t kMaxContentDefinedLayerCount = 8;
2048     using LevelContentDefinedMask = angle::BitSet8<kMaxContentDefinedLayerCount>;
2049 
2050     // Use the following functions to access m*ContentDefined to make sure the correct level index
2051     // is used (i.e. vk::LevelIndex and not gl::LevelIndex).
2052     LevelContentDefinedMask &getLevelContentDefined(LevelIndex level);
2053     LevelContentDefinedMask &getLevelStencilContentDefined(LevelIndex level);
2054     const LevelContentDefinedMask &getLevelContentDefined(LevelIndex level) const;
2055     const LevelContentDefinedMask &getLevelStencilContentDefined(LevelIndex level) const;
2056 
2057     angle::Result initLayerImageViewImpl(
2058         Context *context,
2059         gl::TextureType textureType,
2060         VkImageAspectFlags aspectMask,
2061         const gl::SwizzleState &swizzleMap,
2062         ImageView *imageViewOut,
2063         LevelIndex baseMipLevelVk,
2064         uint32_t levelCount,
2065         uint32_t baseArrayLayer,
2066         uint32_t layerCount,
2067         VkFormat imageFormat,
2068         const VkImageViewUsageCreateInfo *imageViewUsageCreateInfo) const;
2069 
2070     // Vulkan objects.
2071     Image mImage;
2072     DeviceMemory mDeviceMemory;
2073 
2074     // Image properties.
2075     VkImageType mImageType;
2076     VkImageTiling mTilingMode;
2077     VkImageCreateFlags mCreateFlags;
2078     VkImageUsageFlags mUsage;
2079     // For Android swapchain images, the Vulkan VkImage must be "rotated".  However, most of ANGLE
2080     // uses non-rotated extents (i.e. the way the application views the extents--see "Introduction
2081     // to Android rotation and pre-rotation" in "SurfaceVk.cpp").  Thus, mExtents are non-rotated.
2082     // The rotated extents are also stored along with a bool that indicates if the aspect ratio is
2083     // different between the rotated and non-rotated extents.
2084     VkExtent3D mExtents;
2085     bool mRotatedAspectRatio;
2086     const Format *mFormat;
2087     GLint mSamples;
2088     ImageSerial mImageSerial;
2089 
2090     // Current state.
2091     ImageLayout mCurrentLayout;
2092     uint32_t mCurrentQueueFamilyIndex;
2093     // For optimizing transition between different shader readonly layouts
2094     ImageLayout mLastNonShaderReadOnlyLayout;
2095     VkPipelineStageFlags mCurrentShaderReadStageMask;
2096     // Track how it is being used by current open renderpass.
2097     RenderPassUsageFlags mRenderPassUsageFlags;
2098 
2099     // For imported images
2100     BindingPointer<SamplerYcbcrConversion> mYuvConversionSampler;
2101     uint64_t mExternalFormat;
2102 
2103     // The first level that has been allocated. For mutable textures, this should be same as
2104     // mBaseLevel since we always reallocate VkImage based on mBaseLevel change. But for immutable
2105     // textures, we always allocate from level 0 regardless of mBaseLevel change.
2106     gl::LevelIndex mFirstAllocatedLevel;
2107 
2108     // Cached properties.
2109     uint32_t mLayerCount;
2110     uint32_t mLevelCount;
2111 
2112     // Staging buffer
2113     DynamicBuffer mStagingBuffer;
2114     std::vector<std::vector<SubresourceUpdate>> mSubresourceUpdates;
2115 
2116     // Optimization for repeated clear with the same value. If this pointer is not null, the entire
2117     // image it has been cleared to the specified clear value. If another clear call is made with
2118     // the exact same clear value, we will detect and skip the clear call.
2119     Optional<ClearUpdate> mCurrentSingleClearValue;
2120 
2121     // Track whether each subresource has defined contents.  Up to 8 layers are tracked per level,
2122     // above which the contents are considered unconditionally defined.
2123     gl::TexLevelArray<LevelContentDefinedMask> mContentDefined;
2124     gl::TexLevelArray<LevelContentDefinedMask> mStencilContentDefined;
2125 };
2126 
2127 // A vector of image views, such as one per level or one per layer.
2128 using ImageViewVector = std::vector<ImageView>;
2129 
2130 // A vector of vector of image views.  Primary index is layer, secondary index is level.
2131 using LayerLevelImageViewVector = std::vector<ImageViewVector>;
2132 
2133 // Address mode for layers: only possible to access either all layers, or up to
2134 // IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS layers.  This enum uses 0 for all layers and the rest of
2135 // the values conveniently alias the number of layers.
2136 enum LayerMode
2137 {
2138     All,
2139     _1,
2140     _2,
2141     _3,
2142     _4,
2143 };
2144 static_assert(gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS == 4, "Update LayerMode");
2145 
2146 LayerMode GetLayerMode(const vk::ImageHelper &image, uint32_t layerCount);
2147 
2148 // Sampler decode mode indicating if an attachment needs to be decoded in linear colorspace or sRGB
2149 enum class SrgbDecodeMode
2150 {
2151     SkipDecode,
2152     SrgbDecode
2153 };
2154 
2155 class ImageViewHelper final : public Resource
2156 {
2157   public:
2158     ImageViewHelper();
2159     ImageViewHelper(ImageViewHelper &&other);
2160     ~ImageViewHelper() override;
2161 
2162     void init(RendererVk *renderer);
2163     void release(RendererVk *renderer);
2164     void destroy(VkDevice device);
2165 
getLinearReadImageView()2166     const ImageView &getLinearReadImageView() const
2167     {
2168         return getValidReadViewImpl(mPerLevelLinearReadImageViews);
2169     }
getSRGBReadImageView()2170     const ImageView &getSRGBReadImageView() const
2171     {
2172         return getValidReadViewImpl(mPerLevelSRGBReadImageViews);
2173     }
getLinearFetchImageView()2174     const ImageView &getLinearFetchImageView() const
2175     {
2176         return getValidReadViewImpl(mPerLevelLinearFetchImageViews);
2177     }
getSRGBFetchImageView()2178     const ImageView &getSRGBFetchImageView() const
2179     {
2180         return getValidReadViewImpl(mPerLevelSRGBFetchImageViews);
2181     }
getLinearCopyImageView()2182     const ImageView &getLinearCopyImageView() const
2183     {
2184         return getValidReadViewImpl(mPerLevelLinearCopyImageViews);
2185     }
getSRGBCopyImageView()2186     const ImageView &getSRGBCopyImageView() const
2187     {
2188         return getValidReadViewImpl(mPerLevelSRGBCopyImageViews);
2189     }
getStencilReadImageView()2190     const ImageView &getStencilReadImageView() const
2191     {
2192         return getValidReadViewImpl(mPerLevelStencilReadImageViews);
2193     }
2194 
getReadImageView()2195     const ImageView &getReadImageView() const
2196     {
2197         return mLinearColorspace ? getReadViewImpl(mPerLevelLinearReadImageViews)
2198                                  : getReadViewImpl(mPerLevelSRGBReadImageViews);
2199     }
2200 
getFetchImageView()2201     const ImageView &getFetchImageView() const
2202     {
2203         return mLinearColorspace ? getReadViewImpl(mPerLevelLinearFetchImageViews)
2204                                  : getReadViewImpl(mPerLevelSRGBFetchImageViews);
2205     }
2206 
getCopyImageView()2207     const ImageView &getCopyImageView() const
2208     {
2209         return mLinearColorspace ? getReadViewImpl(mPerLevelLinearCopyImageViews)
2210                                  : getReadViewImpl(mPerLevelSRGBCopyImageViews);
2211     }
2212 
2213     // Used when initialized RenderTargets.
hasStencilReadImageView()2214     bool hasStencilReadImageView() const
2215     {
2216         return mCurrentMaxLevel.get() < mPerLevelStencilReadImageViews.size()
2217                    ? mPerLevelStencilReadImageViews[mCurrentMaxLevel.get()].valid()
2218                    : false;
2219     }
2220 
hasFetchImageView()2221     bool hasFetchImageView() const
2222     {
2223         if ((mLinearColorspace && mCurrentMaxLevel.get() < mPerLevelLinearFetchImageViews.size()) ||
2224             (!mLinearColorspace && mCurrentMaxLevel.get() < mPerLevelSRGBFetchImageViews.size()))
2225         {
2226             return getFetchImageView().valid();
2227         }
2228         else
2229         {
2230             return false;
2231         }
2232     }
2233 
hasCopyImageView()2234     bool hasCopyImageView() const
2235     {
2236         if ((mLinearColorspace && mCurrentMaxLevel.get() < mPerLevelLinearCopyImageViews.size()) ||
2237             (!mLinearColorspace && mCurrentMaxLevel.get() < mPerLevelSRGBCopyImageViews.size()))
2238         {
2239             return getCopyImageView().valid();
2240         }
2241         else
2242         {
2243             return false;
2244         }
2245     }
2246 
2247     // For applications that frequently switch a texture's max level, and make no other changes to
2248     // the texture, change the currently-used max level, and potentially create new "read views"
2249     // for the new max-level
2250     angle::Result initReadViews(ContextVk *contextVk,
2251                                 gl::TextureType viewType,
2252                                 const ImageHelper &image,
2253                                 const Format &format,
2254                                 const gl::SwizzleState &formatSwizzle,
2255                                 const gl::SwizzleState &readSwizzle,
2256                                 LevelIndex baseLevel,
2257                                 uint32_t levelCount,
2258                                 uint32_t baseLayer,
2259                                 uint32_t layerCount,
2260                                 bool requiresSRGBViews,
2261                                 VkImageUsageFlags imageUsageFlags);
2262 
2263     // Creates a storage view with all layers of the level.
2264     angle::Result getLevelStorageImageView(ContextVk *contextVk,
2265                                            gl::TextureType viewType,
2266                                            const ImageHelper &image,
2267                                            LevelIndex levelVk,
2268                                            uint32_t layer,
2269                                            VkImageUsageFlags imageUsageFlags,
2270                                            angle::FormatID formatID,
2271                                            const ImageView **imageViewOut);
2272 
2273     // Creates a storage view with a single layer of the level.
2274     angle::Result getLevelLayerStorageImageView(ContextVk *contextVk,
2275                                                 const ImageHelper &image,
2276                                                 LevelIndex levelVk,
2277                                                 uint32_t layer,
2278                                                 VkImageUsageFlags imageUsageFlags,
2279                                                 angle::FormatID formatID,
2280                                                 const ImageView **imageViewOut);
2281 
2282     // Creates a draw view with a range of layers of the level.
2283     angle::Result getLevelDrawImageView(ContextVk *contextVk,
2284                                         const ImageHelper &image,
2285                                         LevelIndex levelVk,
2286                                         uint32_t layer,
2287                                         uint32_t layerCount,
2288                                         gl::SrgbWriteControlMode mode,
2289                                         const ImageView **imageViewOut);
2290 
2291     // Creates a draw view with a single layer of the level.
2292     angle::Result getLevelLayerDrawImageView(ContextVk *contextVk,
2293                                              const ImageHelper &image,
2294                                              LevelIndex levelVk,
2295                                              uint32_t layer,
2296                                              gl::SrgbWriteControlMode mode,
2297                                              const ImageView **imageViewOut);
2298 
2299     // Return unique Serial for an imageView.
2300     ImageOrBufferViewSubresourceSerial getSubresourceSerial(
2301         gl::LevelIndex levelGL,
2302         uint32_t levelCount,
2303         uint32_t layer,
2304         LayerMode layerMode,
2305         SrgbDecodeMode srgbDecodeMode,
2306         gl::SrgbOverride srgbOverrideMode) const;
2307 
2308   private:
getReadImageView()2309     ImageView &getReadImageView()
2310     {
2311         return mLinearColorspace ? getReadViewImpl(mPerLevelLinearReadImageViews)
2312                                  : getReadViewImpl(mPerLevelSRGBReadImageViews);
2313     }
getFetchImageView()2314     ImageView &getFetchImageView()
2315     {
2316         return mLinearColorspace ? getReadViewImpl(mPerLevelLinearFetchImageViews)
2317                                  : getReadViewImpl(mPerLevelSRGBFetchImageViews);
2318     }
getCopyImageView()2319     ImageView &getCopyImageView()
2320     {
2321         return mLinearColorspace ? getReadViewImpl(mPerLevelLinearCopyImageViews)
2322                                  : getReadViewImpl(mPerLevelSRGBCopyImageViews);
2323     }
2324 
2325     // Used by public get*ImageView() methods to do proper assert based on vector size and validity
getValidReadViewImpl(const ImageViewVector & imageViewVector)2326     inline const ImageView &getValidReadViewImpl(const ImageViewVector &imageViewVector) const
2327     {
2328         ASSERT(mCurrentMaxLevel.get() < imageViewVector.size() &&
2329                imageViewVector[mCurrentMaxLevel.get()].valid());
2330         return imageViewVector[mCurrentMaxLevel.get()];
2331     }
2332 
2333     // Used by public get*ImageView() methods to do proper assert based on vector size
getReadViewImpl(const ImageViewVector & imageViewVector)2334     inline const ImageView &getReadViewImpl(const ImageViewVector &imageViewVector) const
2335     {
2336         ASSERT(mCurrentMaxLevel.get() < imageViewVector.size());
2337         return imageViewVector[mCurrentMaxLevel.get()];
2338     }
2339 
2340     // Used by private get*ImageView() methods to do proper assert based on vector size
getReadViewImpl(ImageViewVector & imageViewVector)2341     inline ImageView &getReadViewImpl(ImageViewVector &imageViewVector)
2342     {
2343         ASSERT(mCurrentMaxLevel.get() < imageViewVector.size());
2344         return imageViewVector[mCurrentMaxLevel.get()];
2345     }
2346 
2347     // Creates views with multiple layers and levels.
2348     angle::Result initReadViewsImpl(ContextVk *contextVk,
2349                                     gl::TextureType viewType,
2350                                     const ImageHelper &image,
2351                                     const Format &format,
2352                                     const gl::SwizzleState &formatSwizzle,
2353                                     const gl::SwizzleState &readSwizzle,
2354                                     LevelIndex baseLevel,
2355                                     uint32_t levelCount,
2356                                     uint32_t baseLayer,
2357                                     uint32_t layerCount);
2358 
2359     // Create SRGB-reinterpreted read views
2360     angle::Result initSRGBReadViewsImpl(ContextVk *contextVk,
2361                                         gl::TextureType viewType,
2362                                         const ImageHelper &image,
2363                                         const Format &format,
2364                                         const gl::SwizzleState &formatSwizzle,
2365                                         const gl::SwizzleState &readSwizzle,
2366                                         LevelIndex baseLevel,
2367                                         uint32_t levelCount,
2368                                         uint32_t baseLayer,
2369                                         uint32_t layerCount,
2370                                         VkImageUsageFlags imageUsageFlags);
2371 
2372     // For applications that frequently switch a texture's max level, and make no other changes to
2373     // the texture, keep track of the currently-used max level, and keep one "read view" per
2374     // max-level
2375     LevelIndex mCurrentMaxLevel;
2376 
2377     // Read views (one per max-level)
2378     ImageViewVector mPerLevelLinearReadImageViews;
2379     ImageViewVector mPerLevelSRGBReadImageViews;
2380     ImageViewVector mPerLevelLinearFetchImageViews;
2381     ImageViewVector mPerLevelSRGBFetchImageViews;
2382     ImageViewVector mPerLevelLinearCopyImageViews;
2383     ImageViewVector mPerLevelSRGBCopyImageViews;
2384     ImageViewVector mPerLevelStencilReadImageViews;
2385 
2386     bool mLinearColorspace;
2387 
2388     // Draw views
2389     LayerLevelImageViewVector mLayerLevelDrawImageViews;
2390     LayerLevelImageViewVector mLayerLevelDrawImageViewsLinear;
2391     angle::HashMap<ImageSubresourceRange, std::unique_ptr<ImageView>> mSubresourceDrawImageViews;
2392 
2393     // Storage views
2394     ImageViewVector mLevelStorageImageViews;
2395     LayerLevelImageViewVector mLayerLevelStorageImageViews;
2396 
2397     // Serial for the image view set. getSubresourceSerial combines it with subresource info.
2398     ImageOrBufferViewSerial mImageViewSerial;
2399 };
2400 
2401 ImageSubresourceRange MakeImageSubresourceReadRange(gl::LevelIndex level,
2402                                                     uint32_t levelCount,
2403                                                     uint32_t layer,
2404                                                     LayerMode layerMode,
2405                                                     SrgbDecodeMode srgbDecodeMode,
2406                                                     gl::SrgbOverride srgbOverrideMode);
2407 ImageSubresourceRange MakeImageSubresourceDrawRange(gl::LevelIndex level,
2408                                                     uint32_t layer,
2409                                                     LayerMode layerMode,
2410                                                     gl::SrgbWriteControlMode srgbWriteControlMode);
2411 
2412 class BufferViewHelper final : public Resource
2413 {
2414   public:
2415     BufferViewHelper();
2416     BufferViewHelper(BufferViewHelper &&other);
2417     ~BufferViewHelper() override;
2418 
2419     void init(RendererVk *renderer, VkDeviceSize offset, VkDeviceSize size);
2420     void release(RendererVk *renderer);
2421     void destroy(VkDevice device);
2422 
2423     angle::Result getView(ContextVk *contextVk,
2424                           const BufferHelper &buffer,
2425                           VkDeviceSize bufferOffset,
2426                           const Format &format,
2427                           const BufferView **viewOut);
2428 
2429     // Return unique Serial for a bufferView.
2430     ImageOrBufferViewSubresourceSerial getSerial() const;
2431 
2432   private:
2433     // To support format reinterpretation, additional views for formats other than the one specified
2434     // to glTexBuffer may need to be created.  On draw/dispatch, the format layout qualifier of the
2435     // imageBuffer is used (if provided) to create a potentially different view of the buffer.
2436     angle::HashMap<VkFormat, BufferView> mViews;
2437 
2438     // View properties:
2439     //
2440     // Offset and size specified to glTexBufferRange
2441     VkDeviceSize mOffset;
2442     VkDeviceSize mSize;
2443 
2444     // Serial for the buffer view.  An ImageOrBufferViewSerial is used for texture buffers so that
2445     // they fit together with the other texture types.
2446     ImageOrBufferViewSerial mViewSerial;
2447 };
2448 
2449 class FramebufferHelper : public Resource
2450 {
2451   public:
2452     FramebufferHelper();
2453     ~FramebufferHelper() override;
2454 
2455     FramebufferHelper(FramebufferHelper &&other);
2456     FramebufferHelper &operator=(FramebufferHelper &&other);
2457 
2458     angle::Result init(ContextVk *contextVk, const VkFramebufferCreateInfo &createInfo);
2459     void release(ContextVk *contextVk);
2460 
valid()2461     bool valid() { return mFramebuffer.valid(); }
2462 
getFramebuffer()2463     const Framebuffer &getFramebuffer() const
2464     {
2465         ASSERT(mFramebuffer.valid());
2466         return mFramebuffer;
2467     }
2468 
getFramebuffer()2469     Framebuffer &getFramebuffer()
2470     {
2471         ASSERT(mFramebuffer.valid());
2472         return mFramebuffer;
2473     }
2474 
2475   private:
2476     // Vulkan object.
2477     Framebuffer mFramebuffer;
2478 };
2479 
2480 class ShaderProgramHelper : angle::NonCopyable
2481 {
2482   public:
2483     ShaderProgramHelper();
2484     ~ShaderProgramHelper();
2485 
2486     bool valid(const gl::ShaderType shaderType) const;
2487     void destroy(RendererVk *rendererVk);
2488     void release(ContextVk *contextVk);
2489 
getShader(gl::ShaderType shaderType)2490     ShaderAndSerial &getShader(gl::ShaderType shaderType) { return mShaders[shaderType].get(); }
2491 
2492     void setShader(gl::ShaderType shaderType, RefCounted<ShaderAndSerial> *shader);
2493     void setSpecializationConstant(sh::vk::SpecializationConstantId id, uint32_t value);
2494 
2495     // For getting a Pipeline and from the pipeline cache.
getGraphicsPipeline(ContextVk * contextVk,RenderPassCache * renderPassCache,const PipelineCache & pipelineCache,const PipelineLayout & pipelineLayout,const GraphicsPipelineDesc & pipelineDesc,const gl::AttributesMask & activeAttribLocationsMask,const gl::ComponentTypeMask & programAttribsTypeMask,const GraphicsPipelineDesc ** descPtrOut,PipelineHelper ** pipelineOut)2496     ANGLE_INLINE angle::Result getGraphicsPipeline(
2497         ContextVk *contextVk,
2498         RenderPassCache *renderPassCache,
2499         const PipelineCache &pipelineCache,
2500         const PipelineLayout &pipelineLayout,
2501         const GraphicsPipelineDesc &pipelineDesc,
2502         const gl::AttributesMask &activeAttribLocationsMask,
2503         const gl::ComponentTypeMask &programAttribsTypeMask,
2504         const GraphicsPipelineDesc **descPtrOut,
2505         PipelineHelper **pipelineOut)
2506     {
2507         // Pull in a compatible RenderPass.
2508         RenderPass *compatibleRenderPass = nullptr;
2509         ANGLE_TRY(renderPassCache->getCompatibleRenderPass(
2510             contextVk, pipelineDesc.getRenderPassDesc(), &compatibleRenderPass));
2511 
2512         ShaderModule *vertexShader   = &mShaders[gl::ShaderType::Vertex].get().get();
2513         ShaderModule *fragmentShader = mShaders[gl::ShaderType::Fragment].valid()
2514                                            ? &mShaders[gl::ShaderType::Fragment].get().get()
2515                                            : nullptr;
2516         ShaderModule *geometryShader = mShaders[gl::ShaderType::Geometry].valid()
2517                                            ? &mShaders[gl::ShaderType::Geometry].get().get()
2518                                            : nullptr;
2519         ShaderModule *tessControlShader = mShaders[gl::ShaderType::TessControl].valid()
2520                                               ? &mShaders[gl::ShaderType::TessControl].get().get()
2521                                               : nullptr;
2522         ShaderModule *tessEvaluationShader =
2523             mShaders[gl::ShaderType::TessEvaluation].valid()
2524                 ? &mShaders[gl::ShaderType::TessEvaluation].get().get()
2525                 : nullptr;
2526 
2527         return mGraphicsPipelines.getPipeline(
2528             contextVk, pipelineCache, *compatibleRenderPass, pipelineLayout,
2529             activeAttribLocationsMask, programAttribsTypeMask, vertexShader, fragmentShader,
2530             geometryShader, tessControlShader, tessEvaluationShader, mSpecializationConstants,
2531             pipelineDesc, descPtrOut, pipelineOut);
2532     }
2533 
2534     angle::Result getComputePipeline(Context *context,
2535                                      const PipelineLayout &pipelineLayout,
2536                                      PipelineAndSerial **pipelineOut);
2537 
2538   private:
2539     gl::ShaderMap<BindingPointer<ShaderAndSerial>> mShaders;
2540     GraphicsPipelineCache mGraphicsPipelines;
2541 
2542     // We should probably use PipelineHelper here so we can remove PipelineAndSerial.
2543     PipelineAndSerial mComputePipeline;
2544 
2545     // Specialization constants, currently only used by the graphics queue.
2546     SpecializationConstants mSpecializationConstants;
2547 };
2548 
2549 // Tracks current handle allocation counts in the back-end. Useful for debugging and profiling.
2550 // Note: not all handle types are currently implemented.
2551 class ActiveHandleCounter final : angle::NonCopyable
2552 {
2553   public:
2554     ActiveHandleCounter();
2555     ~ActiveHandleCounter();
2556 
onAllocate(HandleType handleType)2557     void onAllocate(HandleType handleType)
2558     {
2559         mActiveCounts[handleType]++;
2560         mAllocatedCounts[handleType]++;
2561     }
2562 
onDeallocate(HandleType handleType)2563     void onDeallocate(HandleType handleType) { mActiveCounts[handleType]--; }
2564 
getActive(HandleType handleType)2565     uint32_t getActive(HandleType handleType) const { return mActiveCounts[handleType]; }
getAllocated(HandleType handleType)2566     uint32_t getAllocated(HandleType handleType) const { return mAllocatedCounts[handleType]; }
2567 
2568   private:
2569     angle::PackedEnumMap<HandleType, uint32_t> mActiveCounts;
2570     angle::PackedEnumMap<HandleType, uint32_t> mAllocatedCounts;
2571 };
2572 
usesImageInRenderPass(const ImageHelper & image)2573 ANGLE_INLINE bool CommandBufferHelper::usesImageInRenderPass(const ImageHelper &image) const
2574 {
2575     ASSERT(mIsRenderPassCommandBuffer);
2576     return mRenderPassUsedImages.contains(image.getImageSerial().getValue());
2577 }
2578 
2579 // Sometimes ANGLE issues a command internally, such as copies, draws and dispatches that do not
2580 // directly correspond to the application draw/dispatch call.  Before the command is recorded in the
2581 // command buffer, the render pass may need to be broken and/or appropriate barriers may need to be
2582 // inserted.  The following struct aggregates all resources that such internal commands need.
2583 struct CommandBufferBufferAccess
2584 {
2585     BufferHelper *buffer;
2586     VkAccessFlags accessType;
2587     PipelineStage stage;
2588 };
2589 struct CommandBufferImageAccess
2590 {
2591     ImageHelper *image;
2592     VkImageAspectFlags aspectFlags;
2593     ImageLayout imageLayout;
2594 };
2595 struct CommandBufferImageWrite
2596 {
2597     CommandBufferImageAccess access;
2598     gl::LevelIndex levelStart;
2599     uint32_t levelCount;
2600     uint32_t layerStart;
2601     uint32_t layerCount;
2602 };
2603 class CommandBufferAccess : angle::NonCopyable
2604 {
2605   public:
2606     CommandBufferAccess();
2607     ~CommandBufferAccess();
2608 
onBufferTransferRead(BufferHelper * buffer)2609     void onBufferTransferRead(BufferHelper *buffer)
2610     {
2611         onBufferRead(VK_ACCESS_TRANSFER_READ_BIT, PipelineStage::Transfer, buffer);
2612     }
onBufferTransferWrite(BufferHelper * buffer)2613     void onBufferTransferWrite(BufferHelper *buffer)
2614     {
2615         onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, PipelineStage::Transfer, buffer);
2616     }
onBufferSelfCopy(BufferHelper * buffer)2617     void onBufferSelfCopy(BufferHelper *buffer)
2618     {
2619         onBufferWrite(VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
2620                       PipelineStage::Transfer, buffer);
2621     }
onBufferComputeShaderRead(BufferHelper * buffer)2622     void onBufferComputeShaderRead(BufferHelper *buffer)
2623     {
2624         onBufferRead(VK_ACCESS_SHADER_READ_BIT, PipelineStage::ComputeShader, buffer);
2625     }
onBufferComputeShaderWrite(BufferHelper * buffer)2626     void onBufferComputeShaderWrite(BufferHelper *buffer)
2627     {
2628         onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, PipelineStage::ComputeShader, buffer);
2629     }
2630 
onImageTransferRead(VkImageAspectFlags aspectFlags,ImageHelper * image)2631     void onImageTransferRead(VkImageAspectFlags aspectFlags, ImageHelper *image)
2632     {
2633         onImageRead(aspectFlags, ImageLayout::TransferSrc, image);
2634     }
onImageTransferWrite(gl::LevelIndex levelStart,uint32_t levelCount,uint32_t layerStart,uint32_t layerCount,VkImageAspectFlags aspectFlags,ImageHelper * image)2635     void onImageTransferWrite(gl::LevelIndex levelStart,
2636                               uint32_t levelCount,
2637                               uint32_t layerStart,
2638                               uint32_t layerCount,
2639                               VkImageAspectFlags aspectFlags,
2640                               ImageHelper *image)
2641     {
2642         onImageWrite(levelStart, levelCount, layerStart, layerCount, aspectFlags,
2643                      ImageLayout::TransferDst, image);
2644     }
onImageComputeShaderRead(VkImageAspectFlags aspectFlags,ImageHelper * image)2645     void onImageComputeShaderRead(VkImageAspectFlags aspectFlags, ImageHelper *image)
2646     {
2647         onImageRead(aspectFlags, ImageLayout::ComputeShaderReadOnly, image);
2648     }
onImageComputeShaderWrite(gl::LevelIndex levelStart,uint32_t levelCount,uint32_t layerStart,uint32_t layerCount,VkImageAspectFlags aspectFlags,ImageHelper * image)2649     void onImageComputeShaderWrite(gl::LevelIndex levelStart,
2650                                    uint32_t levelCount,
2651                                    uint32_t layerStart,
2652                                    uint32_t layerCount,
2653                                    VkImageAspectFlags aspectFlags,
2654                                    ImageHelper *image)
2655     {
2656         onImageWrite(levelStart, levelCount, layerStart, layerCount, aspectFlags,
2657                      ImageLayout::ComputeShaderWrite, image);
2658     }
2659 
2660     // The limits reflect the current maximum concurrent usage of each resource type.  ASSERTs will
2661     // fire if this limit is exceeded in the future.
2662     using ReadBuffers  = angle::FixedVector<CommandBufferBufferAccess, 2>;
2663     using WriteBuffers = angle::FixedVector<CommandBufferBufferAccess, 2>;
2664     using ReadImages   = angle::FixedVector<CommandBufferImageAccess, 2>;
2665     using WriteImages  = angle::FixedVector<CommandBufferImageWrite, 1>;
2666 
getReadBuffers()2667     const ReadBuffers &getReadBuffers() const { return mReadBuffers; }
getWriteBuffers()2668     const WriteBuffers &getWriteBuffers() const { return mWriteBuffers; }
getReadImages()2669     const ReadImages &getReadImages() const { return mReadImages; }
getWriteImages()2670     const WriteImages &getWriteImages() const { return mWriteImages; }
2671 
2672   private:
2673     void onBufferRead(VkAccessFlags readAccessType, PipelineStage readStage, BufferHelper *buffer);
2674     void onBufferWrite(VkAccessFlags writeAccessType,
2675                        PipelineStage writeStage,
2676                        BufferHelper *buffer);
2677 
2678     void onImageRead(VkImageAspectFlags aspectFlags, ImageLayout imageLayout, ImageHelper *image);
2679     void onImageWrite(gl::LevelIndex levelStart,
2680                       uint32_t levelCount,
2681                       uint32_t layerStart,
2682                       uint32_t layerCount,
2683                       VkImageAspectFlags aspectFlags,
2684                       ImageLayout imageLayout,
2685                       ImageHelper *image);
2686 
2687     ReadBuffers mReadBuffers;
2688     WriteBuffers mWriteBuffers;
2689     ReadImages mReadImages;
2690     WriteImages mWriteImages;
2691 };
2692 }  // namespace vk
2693 }  // namespace rx
2694 
2695 #endif  // LIBANGLE_RENDERER_VULKAN_VK_HELPERS_H_
2696