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 ©Size,
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 ®ion,
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 ©Region,
2816 angle::FormatID formatID);
2817 SubresourceUpdate(RefCounted<ImageHelper> *imageIn,
2818 const VkImageCopy ©Region,
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