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