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