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