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