1 //
2 // Copyright 2019 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_wrapper:
7 // Wrapper classes around Vulkan objects. In an ideal world we could generate this
8 // from vk.xml. Or reuse the generator in the vkhpp tool. For now this is manually
9 // generated and we must add missing functions and objects as we need them.
10
11 #ifndef LIBANGLE_RENDERER_VULKAN_VK_WRAPPER_H_
12 #define LIBANGLE_RENDERER_VULKAN_VK_WRAPPER_H_
13
14 #include "common/vulkan/vk_headers.h"
15 #include "libANGLE/renderer/renderer_utils.h"
16 #include "libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.h"
17 #include "libANGLE/trace.h"
18
19 namespace rx
20 {
21 enum class DescriptorSetIndex : uint32_t;
22
23 namespace vk
24 {
25 // Helper macros that apply to all the wrapped object types.
26 // Unimplemented handle types:
27 // Instance
28 // PhysicalDevice
29 // Device
30 // Queue
31 // DescriptorSet
32
33 #define ANGLE_HANDLE_TYPES_X(FUNC) \
34 FUNC(Allocation) \
35 FUNC(Allocator) \
36 FUNC(Buffer) \
37 FUNC(BufferView) \
38 FUNC(CommandPool) \
39 FUNC(DescriptorPool) \
40 FUNC(DescriptorSetLayout) \
41 FUNC(DeviceMemory) \
42 FUNC(Event) \
43 FUNC(Fence) \
44 FUNC(Framebuffer) \
45 FUNC(Image) \
46 FUNC(ImageView) \
47 FUNC(Pipeline) \
48 FUNC(PipelineCache) \
49 FUNC(PipelineLayout) \
50 FUNC(QueryPool) \
51 FUNC(RenderPass) \
52 FUNC(Sampler) \
53 FUNC(SamplerYcbcrConversion) \
54 FUNC(Semaphore) \
55 FUNC(ShaderModule)
56
57 #define ANGLE_COMMA_SEP_FUNC(TYPE) TYPE,
58
59 enum class HandleType
60 {
61 Invalid,
62 CommandBuffer,
63 ANGLE_HANDLE_TYPES_X(ANGLE_COMMA_SEP_FUNC) EnumCount
64 };
65
66 #undef ANGLE_COMMA_SEP_FUNC
67
68 #define ANGLE_PRE_DECLARE_CLASS_FUNC(TYPE) class TYPE;
ANGLE_HANDLE_TYPES_X(ANGLE_PRE_DECLARE_CLASS_FUNC)69 ANGLE_HANDLE_TYPES_X(ANGLE_PRE_DECLARE_CLASS_FUNC)
70 namespace priv
71 {
72 class CommandBuffer;
73 } // namespace priv
74 #undef ANGLE_PRE_DECLARE_CLASS_FUNC
75
76 // Returns the HandleType of a Vk Handle.
77 template <typename T>
78 struct HandleTypeHelper;
79
80 #define ANGLE_HANDLE_TYPE_HELPER_FUNC(TYPE) \
81 template <> \
82 struct HandleTypeHelper<TYPE> \
83 { \
84 constexpr static HandleType kHandleType = HandleType::TYPE; \
85 };
86
87 ANGLE_HANDLE_TYPES_X(ANGLE_HANDLE_TYPE_HELPER_FUNC)
88 template <>
89 struct HandleTypeHelper<priv::CommandBuffer>
90 {
91 constexpr static HandleType kHandleType = HandleType::CommandBuffer;
92 };
93
94 #undef ANGLE_HANDLE_TYPE_HELPER_FUNC
95
96 // Base class for all wrapped vulkan objects. Implements several common helper routines.
97 template <typename DerivedT, typename HandleT>
98 class WrappedObject : angle::NonCopyable
99 {
100 public:
101 HandleT getHandle() const { return mHandle; }
102 void setHandle(HandleT handle) { mHandle = handle; }
103 bool valid() const { return (mHandle != VK_NULL_HANDLE); }
104
105 const HandleT *ptr() const { return &mHandle; }
106
107 HandleT release()
108 {
109 HandleT handle = mHandle;
110 mHandle = VK_NULL_HANDLE;
111 return handle;
112 }
113
114 protected:
115 WrappedObject() : mHandle(VK_NULL_HANDLE) {}
116 ~WrappedObject() { ASSERT(!valid()); }
117
118 WrappedObject(WrappedObject &&other) : mHandle(other.mHandle)
119 {
120 other.mHandle = VK_NULL_HANDLE;
121 }
122
123 // Only works to initialize empty objects, since we don't have the device handle.
124 WrappedObject &operator=(WrappedObject &&other)
125 {
126 ASSERT(!valid());
127 std::swap(mHandle, other.mHandle);
128 return *this;
129 }
130
131 HandleT mHandle;
132 };
133
134 class CommandPool final : public WrappedObject<CommandPool, VkCommandPool>
135 {
136 public:
137 CommandPool() = default;
138
139 void destroy(VkDevice device);
140 VkResult reset(VkDevice device, VkCommandPoolResetFlags flags);
141 void freeCommandBuffers(VkDevice device,
142 uint32_t commandBufferCount,
143 const VkCommandBuffer *commandBuffers);
144
145 VkResult init(VkDevice device, const VkCommandPoolCreateInfo &createInfo);
146 };
147
148 class Pipeline final : public WrappedObject<Pipeline, VkPipeline>
149 {
150 public:
151 Pipeline() = default;
152 void destroy(VkDevice device);
153
154 VkResult initGraphics(VkDevice device,
155 const VkGraphicsPipelineCreateInfo &createInfo,
156 const PipelineCache &pipelineCacheVk);
157 VkResult initCompute(VkDevice device,
158 const VkComputePipelineCreateInfo &createInfo,
159 const PipelineCache &pipelineCacheVk);
160 };
161
162 namespace priv
163 {
164
165 // Helper class that wraps a Vulkan command buffer.
166 class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
167 {
168 public:
169 CommandBuffer() = default;
170
171 VkCommandBuffer releaseHandle();
172
173 // This is used for normal pool allocated command buffers. It reset the handle.
174 void destroy(VkDevice device);
175
176 // This is used in conjunction with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT.
177 void destroy(VkDevice device, const CommandPool &commandPool);
178
179 VkResult init(VkDevice device, const VkCommandBufferAllocateInfo &createInfo);
180
181 using WrappedObject::operator=;
182
183 static bool SupportsQueries(const VkPhysicalDeviceFeatures &features)
184 {
185 return (features.inheritedQueries == VK_TRUE);
186 }
187
188 // Vulkan command buffers are executed as secondary command buffers within a primary command
189 // buffer.
190 static constexpr bool ExecutesInline() { return false; }
191
192 VkResult begin(const VkCommandBufferBeginInfo &info);
193
194 void beginQuery(const QueryPool &queryPool, uint32_t query, VkQueryControlFlags flags);
195
196 void beginRenderPass(const VkRenderPassBeginInfo &beginInfo, VkSubpassContents subpassContents);
197
198 void bindDescriptorSets(const PipelineLayout &layout,
199 VkPipelineBindPoint pipelineBindPoint,
200 DescriptorSetIndex firstSet,
201 uint32_t descriptorSetCount,
202 const VkDescriptorSet *descriptorSets,
203 uint32_t dynamicOffsetCount,
204 const uint32_t *dynamicOffsets);
205 void bindGraphicsPipeline(const Pipeline &pipeline);
206 void bindComputePipeline(const Pipeline &pipeline);
207 void bindPipeline(VkPipelineBindPoint pipelineBindPoint, const Pipeline &pipeline);
208
209 void bindIndexBuffer(const Buffer &buffer, VkDeviceSize offset, VkIndexType indexType);
210 void bindVertexBuffers(uint32_t firstBinding,
211 uint32_t bindingCount,
212 const VkBuffer *buffers,
213 const VkDeviceSize *offsets);
214
215 void blitImage(const Image &srcImage,
216 VkImageLayout srcImageLayout,
217 const Image &dstImage,
218 VkImageLayout dstImageLayout,
219 uint32_t regionCount,
220 const VkImageBlit *regions,
221 VkFilter filter);
222
223 void clearColorImage(const Image &image,
224 VkImageLayout imageLayout,
225 const VkClearColorValue &color,
226 uint32_t rangeCount,
227 const VkImageSubresourceRange *ranges);
228 void clearDepthStencilImage(const Image &image,
229 VkImageLayout imageLayout,
230 const VkClearDepthStencilValue &depthStencil,
231 uint32_t rangeCount,
232 const VkImageSubresourceRange *ranges);
233
234 void clearAttachments(uint32_t attachmentCount,
235 const VkClearAttachment *attachments,
236 uint32_t rectCount,
237 const VkClearRect *rects);
238
239 void copyBuffer(const Buffer &srcBuffer,
240 const Buffer &destBuffer,
241 uint32_t regionCount,
242 const VkBufferCopy *regions);
243
244 void copyBufferToImage(VkBuffer srcBuffer,
245 const Image &dstImage,
246 VkImageLayout dstImageLayout,
247 uint32_t regionCount,
248 const VkBufferImageCopy *regions);
249 void copyImageToBuffer(const Image &srcImage,
250 VkImageLayout srcImageLayout,
251 VkBuffer dstBuffer,
252 uint32_t regionCount,
253 const VkBufferImageCopy *regions);
254 void copyImage(const Image &srcImage,
255 VkImageLayout srcImageLayout,
256 const Image &dstImage,
257 VkImageLayout dstImageLayout,
258 uint32_t regionCount,
259 const VkImageCopy *regions);
260
261 void dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
262 void dispatchIndirect(const Buffer &buffer, VkDeviceSize offset);
263
264 void draw(uint32_t vertexCount,
265 uint32_t instanceCount,
266 uint32_t firstVertex,
267 uint32_t firstInstance);
268 void drawIndexed(uint32_t indexCount,
269 uint32_t instanceCount,
270 uint32_t firstIndex,
271 int32_t vertexOffset,
272 uint32_t firstInstance);
273 void drawIndexedIndirect(const Buffer &buffer,
274 VkDeviceSize offset,
275 uint32_t drawCount,
276 uint32_t stride);
277 void drawIndirect(const Buffer &buffer,
278 VkDeviceSize offset,
279 uint32_t drawCount,
280 uint32_t stride);
281
282 VkResult end();
283 void endQuery(const QueryPool &queryPool, uint32_t query);
284 void endRenderPass();
285 void executeCommands(uint32_t commandBufferCount, const CommandBuffer *commandBuffers);
286
287 void getMemoryUsageStats(size_t *usedMemoryOut, size_t *allocatedMemoryOut) const;
288
289 void fillBuffer(const Buffer &dstBuffer,
290 VkDeviceSize dstOffset,
291 VkDeviceSize size,
292 uint32_t data);
293
294 void imageBarrier(VkPipelineStageFlags srcStageMask,
295 VkPipelineStageFlags dstStageMask,
296 const VkImageMemoryBarrier &imageMemoryBarrier);
297
298 void nextSubpass(VkSubpassContents subpassContents);
299
300 void memoryBarrier(VkPipelineStageFlags srcStageMask,
301 VkPipelineStageFlags dstStageMask,
302 const VkMemoryBarrier *memoryBarrier);
303
304 void pipelineBarrier(VkPipelineStageFlags srcStageMask,
305 VkPipelineStageFlags dstStageMask,
306 VkDependencyFlags dependencyFlags,
307 uint32_t memoryBarrierCount,
308 const VkMemoryBarrier *memoryBarriers,
309 uint32_t bufferMemoryBarrierCount,
310 const VkBufferMemoryBarrier *bufferMemoryBarriers,
311 uint32_t imageMemoryBarrierCount,
312 const VkImageMemoryBarrier *imageMemoryBarriers);
313
314 void pushConstants(const PipelineLayout &layout,
315 VkShaderStageFlags flag,
316 uint32_t offset,
317 uint32_t size,
318 const void *data);
319
320 void setEvent(VkEvent event, VkPipelineStageFlags stageMask);
321 void setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *viewports);
322 void setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *scissors);
323 VkResult reset();
324 void resetEvent(VkEvent event, VkPipelineStageFlags stageMask);
325 void resetQueryPool(const QueryPool &queryPool, uint32_t firstQuery, uint32_t queryCount);
326 void resolveImage(const Image &srcImage,
327 VkImageLayout srcImageLayout,
328 const Image &dstImage,
329 VkImageLayout dstImageLayout,
330 uint32_t regionCount,
331 const VkImageResolve *regions);
332 void waitEvents(uint32_t eventCount,
333 const VkEvent *events,
334 VkPipelineStageFlags srcStageMask,
335 VkPipelineStageFlags dstStageMask,
336 uint32_t memoryBarrierCount,
337 const VkMemoryBarrier *memoryBarriers,
338 uint32_t bufferMemoryBarrierCount,
339 const VkBufferMemoryBarrier *bufferMemoryBarriers,
340 uint32_t imageMemoryBarrierCount,
341 const VkImageMemoryBarrier *imageMemoryBarriers);
342
343 void writeTimestamp(VkPipelineStageFlagBits pipelineStage,
344 const QueryPool &queryPool,
345 uint32_t query);
346
347 // VK_EXT_transform_feedback
348 void beginTransformFeedback(uint32_t firstCounterBuffer,
349 uint32_t counterBufferCount,
350 const VkBuffer *counterBuffers,
351 const VkDeviceSize *counterBufferOffsets);
352 void endTransformFeedback(uint32_t firstCounterBuffer,
353 uint32_t counterBufferCount,
354 const VkBuffer *counterBuffers,
355 const VkDeviceSize *counterBufferOffsets);
356 void bindTransformFeedbackBuffers(uint32_t firstBinding,
357 uint32_t bindingCount,
358 const VkBuffer *buffers,
359 const VkDeviceSize *offsets,
360 const VkDeviceSize *sizes);
361
362 // VK_EXT_debug_utils
363 void beginDebugUtilsLabelEXT(const VkDebugUtilsLabelEXT &labelInfo);
364 void endDebugUtilsLabelEXT();
365 void insertDebugUtilsLabelEXT(const VkDebugUtilsLabelEXT &labelInfo);
366 };
367 } // namespace priv
368
369 using PrimaryCommandBuffer = priv::CommandBuffer;
370
371 class Image final : public WrappedObject<Image, VkImage>
372 {
373 public:
374 Image() = default;
375
376 // Use this method if the lifetime of the image is not controlled by ANGLE. (SwapChain)
377 void setHandle(VkImage handle);
378
379 // Called on shutdown when the helper class *doesn't* own the handle to the image resource.
380 void reset();
381
382 // Called on shutdown when the helper class *does* own the handle to the image resource.
383 void destroy(VkDevice device);
384
385 VkResult init(VkDevice device, const VkImageCreateInfo &createInfo);
386
387 void getMemoryRequirements(VkDevice device, VkMemoryRequirements *requirementsOut) const;
388 VkResult bindMemory(VkDevice device, const DeviceMemory &deviceMemory);
389 VkResult bindMemory2(VkDevice device, const VkBindImageMemoryInfoKHR &bindInfo);
390
391 void getSubresourceLayout(VkDevice device,
392 VkImageAspectFlagBits aspectMask,
393 uint32_t mipLevel,
394 uint32_t arrayLayer,
395 VkSubresourceLayout *outSubresourceLayout) const;
396 };
397
398 class ImageView final : public WrappedObject<ImageView, VkImageView>
399 {
400 public:
401 ImageView() = default;
402 void destroy(VkDevice device);
403
404 VkResult init(VkDevice device, const VkImageViewCreateInfo &createInfo);
405 };
406
407 class Semaphore final : public WrappedObject<Semaphore, VkSemaphore>
408 {
409 public:
410 Semaphore() = default;
411 void destroy(VkDevice device);
412
413 VkResult init(VkDevice device);
414 VkResult init(VkDevice device, const VkSemaphoreCreateInfo &createInfo);
415 VkResult importFd(VkDevice device, const VkImportSemaphoreFdInfoKHR &importFdInfo) const;
416 };
417
418 class Framebuffer final : public WrappedObject<Framebuffer, VkFramebuffer>
419 {
420 public:
421 Framebuffer() = default;
422 void destroy(VkDevice device);
423
424 // Use this method only in necessary cases. (RenderPass)
425 void setHandle(VkFramebuffer handle);
426
427 VkResult init(VkDevice device, const VkFramebufferCreateInfo &createInfo);
428 };
429
430 class DeviceMemory final : public WrappedObject<DeviceMemory, VkDeviceMemory>
431 {
432 public:
433 DeviceMemory() = default;
434 void destroy(VkDevice device);
435
436 VkResult allocate(VkDevice device, const VkMemoryAllocateInfo &allocInfo);
437 VkResult map(VkDevice device,
438 VkDeviceSize offset,
439 VkDeviceSize size,
440 VkMemoryMapFlags flags,
441 uint8_t **mapPointer) const;
442 void unmap(VkDevice device) const;
443 void flush(VkDevice device, VkMappedMemoryRange &memRange);
444 void invalidate(VkDevice device, VkMappedMemoryRange &memRange);
445 };
446
447 class Allocator : public WrappedObject<Allocator, VmaAllocator>
448 {
449 public:
450 Allocator() = default;
451 void destroy();
452
453 VkResult init(VkPhysicalDevice physicalDevice,
454 VkDevice device,
455 VkInstance instance,
456 uint32_t apiVersion,
457 VkDeviceSize preferredLargeHeapBlockSize);
458
459 void buildStatsString(char **statsString, VkBool32 detailedMap);
460 void freeStatsString(char *statsString);
461 };
462
463 class Allocation final : public WrappedObject<Allocation, VmaAllocation>
464 {
465 public:
466 Allocation() = default;
467 void destroy(const Allocator &allocator);
468
469 VkResult map(const Allocator &allocator, uint8_t **mapPointer) const;
470 void unmap(const Allocator &allocator) const;
471 void flush(const Allocator &allocator, VkDeviceSize offset, VkDeviceSize size);
472 void invalidate(const Allocator &allocator, VkDeviceSize offset, VkDeviceSize size);
473
474 private:
475 friend class BufferMemoryAllocator;
476 };
477
478 class RenderPass final : public WrappedObject<RenderPass, VkRenderPass>
479 {
480 public:
481 RenderPass() = default;
482 void destroy(VkDevice device);
483
484 VkResult init(VkDevice device, const VkRenderPassCreateInfo &createInfo);
485 VkResult init2(VkDevice device, const VkRenderPassCreateInfo2 &createInfo);
486 };
487
488 enum class StagingUsage
489 {
490 Read,
491 Write,
492 Both,
493 };
494
495 class Buffer final : public WrappedObject<Buffer, VkBuffer>
496 {
497 public:
498 Buffer() = default;
499 void destroy(VkDevice device);
500
501 VkResult init(VkDevice device, const VkBufferCreateInfo &createInfo);
502 VkResult bindMemory(VkDevice device, const DeviceMemory &deviceMemory);
503 void getMemoryRequirements(VkDevice device, VkMemoryRequirements *memoryRequirementsOut);
504
505 private:
506 friend class BufferMemoryAllocator;
507 };
508
509 class BufferView final : public WrappedObject<BufferView, VkBufferView>
510 {
511 public:
512 BufferView() = default;
513 void destroy(VkDevice device);
514
515 VkResult init(VkDevice device, const VkBufferViewCreateInfo &createInfo);
516 };
517
518 class ShaderModule final : public WrappedObject<ShaderModule, VkShaderModule>
519 {
520 public:
521 ShaderModule() = default;
522 void destroy(VkDevice device);
523
524 VkResult init(VkDevice device, const VkShaderModuleCreateInfo &createInfo);
525 };
526
527 class PipelineLayout final : public WrappedObject<PipelineLayout, VkPipelineLayout>
528 {
529 public:
530 PipelineLayout() = default;
531 void destroy(VkDevice device);
532
533 VkResult init(VkDevice device, const VkPipelineLayoutCreateInfo &createInfo);
534 };
535
536 class PipelineCache final : public WrappedObject<PipelineCache, VkPipelineCache>
537 {
538 public:
539 PipelineCache() = default;
540 void destroy(VkDevice device);
541
542 VkResult init(VkDevice device, const VkPipelineCacheCreateInfo &createInfo);
543 VkResult getCacheData(VkDevice device, size_t *cacheSize, void *cacheData);
544 VkResult merge(VkDevice device,
545 VkPipelineCache dstCache,
546 uint32_t srcCacheCount,
547 const VkPipelineCache *srcCaches);
548 };
549
550 class DescriptorSetLayout final : public WrappedObject<DescriptorSetLayout, VkDescriptorSetLayout>
551 {
552 public:
553 DescriptorSetLayout() = default;
554 void destroy(VkDevice device);
555
556 VkResult init(VkDevice device, const VkDescriptorSetLayoutCreateInfo &createInfo);
557 };
558
559 class DescriptorPool final : public WrappedObject<DescriptorPool, VkDescriptorPool>
560 {
561 public:
562 DescriptorPool() = default;
563 void destroy(VkDevice device);
564
565 VkResult init(VkDevice device, const VkDescriptorPoolCreateInfo &createInfo);
566
567 VkResult allocateDescriptorSets(VkDevice device,
568 const VkDescriptorSetAllocateInfo &allocInfo,
569 VkDescriptorSet *descriptorSetsOut);
570 VkResult freeDescriptorSets(VkDevice device,
571 uint32_t descriptorSetCount,
572 const VkDescriptorSet *descriptorSets);
573 };
574
575 class Sampler final : public WrappedObject<Sampler, VkSampler>
576 {
577 public:
578 Sampler() = default;
579 void destroy(VkDevice device);
580 VkResult init(VkDevice device, const VkSamplerCreateInfo &createInfo);
581 };
582
583 class SamplerYcbcrConversion final
584 : public WrappedObject<SamplerYcbcrConversion, VkSamplerYcbcrConversion>
585 {
586 public:
587 SamplerYcbcrConversion() = default;
588 void destroy(VkDevice device);
589 VkResult init(VkDevice device, const VkSamplerYcbcrConversionCreateInfo &createInfo);
590 };
591
592 class Event final : public WrappedObject<Event, VkEvent>
593 {
594 public:
595 Event() = default;
596 void destroy(VkDevice device);
597 using WrappedObject::operator=;
598
599 VkResult init(VkDevice device, const VkEventCreateInfo &createInfo);
600 VkResult getStatus(VkDevice device) const;
601 VkResult set(VkDevice device) const;
602 VkResult reset(VkDevice device) const;
603 };
604
605 class Fence final : public WrappedObject<Fence, VkFence>
606 {
607 public:
608 Fence() = default;
609 void destroy(VkDevice device);
610 using WrappedObject::operator=;
611
612 VkResult init(VkDevice device, const VkFenceCreateInfo &createInfo);
613 VkResult reset(VkDevice device);
614 VkResult getStatus(VkDevice device) const;
615 VkResult wait(VkDevice device, uint64_t timeout) const;
616 VkResult importFd(VkDevice device, const VkImportFenceFdInfoKHR &importFenceFdInfo) const;
617 VkResult exportFd(VkDevice device, const VkFenceGetFdInfoKHR &fenceGetFdInfo, int *outFd) const;
618 };
619
620 class QueryPool final : public WrappedObject<QueryPool, VkQueryPool>
621 {
622 public:
623 QueryPool() = default;
624 void destroy(VkDevice device);
625
626 VkResult init(VkDevice device, const VkQueryPoolCreateInfo &createInfo);
627 VkResult getResults(VkDevice device,
628 uint32_t firstQuery,
629 uint32_t queryCount,
630 size_t dataSize,
631 void *data,
632 VkDeviceSize stride,
633 VkQueryResultFlags flags) const;
634 };
635
636 // CommandPool implementation.
637 ANGLE_INLINE void CommandPool::destroy(VkDevice device)
638 {
639 if (valid())
640 {
641 vkDestroyCommandPool(device, mHandle, nullptr);
642 mHandle = VK_NULL_HANDLE;
643 }
644 }
645
646 ANGLE_INLINE VkResult CommandPool::reset(VkDevice device, VkCommandPoolResetFlags flags)
647 {
648 ASSERT(valid());
649 return vkResetCommandPool(device, mHandle, flags);
650 }
651
652 ANGLE_INLINE void CommandPool::freeCommandBuffers(VkDevice device,
653 uint32_t commandBufferCount,
654 const VkCommandBuffer *commandBuffers)
655 {
656 ASSERT(valid());
657 vkFreeCommandBuffers(device, mHandle, commandBufferCount, commandBuffers);
658 }
659
660 ANGLE_INLINE VkResult CommandPool::init(VkDevice device, const VkCommandPoolCreateInfo &createInfo)
661 {
662 ASSERT(!valid());
663 return vkCreateCommandPool(device, &createInfo, nullptr, &mHandle);
664 }
665
666 namespace priv
667 {
668
669 // CommandBuffer implementation.
670 ANGLE_INLINE VkCommandBuffer CommandBuffer::releaseHandle()
671 {
672 VkCommandBuffer handle = mHandle;
673 mHandle = nullptr;
674 return handle;
675 }
676
677 ANGLE_INLINE VkResult CommandBuffer::init(VkDevice device,
678 const VkCommandBufferAllocateInfo &createInfo)
679 {
680 ASSERT(!valid());
681 return vkAllocateCommandBuffers(device, &createInfo, &mHandle);
682 }
683
684 ANGLE_INLINE void CommandBuffer::blitImage(const Image &srcImage,
685 VkImageLayout srcImageLayout,
686 const Image &dstImage,
687 VkImageLayout dstImageLayout,
688 uint32_t regionCount,
689 const VkImageBlit *regions,
690 VkFilter filter)
691 {
692 ASSERT(valid() && srcImage.valid() && dstImage.valid());
693 ASSERT(regionCount == 1);
694 vkCmdBlitImage(mHandle, srcImage.getHandle(), srcImageLayout, dstImage.getHandle(),
695 dstImageLayout, 1, regions, filter);
696 }
697
698 ANGLE_INLINE VkResult CommandBuffer::begin(const VkCommandBufferBeginInfo &info)
699 {
700 ANGLE_TRACE_EVENT0("gpu.angle", "CommandBuffer::begin");
701 ASSERT(valid());
702 return vkBeginCommandBuffer(mHandle, &info);
703 }
704
705 ANGLE_INLINE VkResult CommandBuffer::end()
706 {
707 ANGLE_TRACE_EVENT0("gpu.angle", "CommandBuffer::end");
708 ASSERT(valid());
709 return vkEndCommandBuffer(mHandle);
710 }
711
712 ANGLE_INLINE VkResult CommandBuffer::reset()
713 {
714 ANGLE_TRACE_EVENT0("gpu.angle", "CommandBuffer::reset");
715 ASSERT(valid());
716 return vkResetCommandBuffer(mHandle, 0);
717 }
718
719 ANGLE_INLINE void CommandBuffer::nextSubpass(VkSubpassContents subpassContents)
720 {
721 ASSERT(valid());
722 vkCmdNextSubpass(mHandle, subpassContents);
723 }
724
725 ANGLE_INLINE void CommandBuffer::memoryBarrier(VkPipelineStageFlags srcStageMask,
726 VkPipelineStageFlags dstStageMask,
727 const VkMemoryBarrier *memoryBarrier)
728 {
729 ASSERT(valid());
730 vkCmdPipelineBarrier(mHandle, srcStageMask, dstStageMask, 0, 1, memoryBarrier, 0, nullptr, 0,
731 nullptr);
732 }
733
734 ANGLE_INLINE void CommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMask,
735 VkPipelineStageFlags dstStageMask,
736 VkDependencyFlags dependencyFlags,
737 uint32_t memoryBarrierCount,
738 const VkMemoryBarrier *memoryBarriers,
739 uint32_t bufferMemoryBarrierCount,
740 const VkBufferMemoryBarrier *bufferMemoryBarriers,
741 uint32_t imageMemoryBarrierCount,
742 const VkImageMemoryBarrier *imageMemoryBarriers)
743 {
744 ASSERT(valid());
745 vkCmdPipelineBarrier(mHandle, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount,
746 memoryBarriers, bufferMemoryBarrierCount, bufferMemoryBarriers,
747 imageMemoryBarrierCount, imageMemoryBarriers);
748 }
749
750 ANGLE_INLINE void CommandBuffer::imageBarrier(VkPipelineStageFlags srcStageMask,
751 VkPipelineStageFlags dstStageMask,
752 const VkImageMemoryBarrier &imageMemoryBarrier)
753 {
754 ASSERT(valid());
755 vkCmdPipelineBarrier(mHandle, srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1,
756 &imageMemoryBarrier);
757 }
758
759 ANGLE_INLINE void CommandBuffer::destroy(VkDevice device)
760 {
761 releaseHandle();
762 }
763
764 ANGLE_INLINE void CommandBuffer::destroy(VkDevice device, const vk::CommandPool &commandPool)
765 {
766 if (valid())
767 {
768 ASSERT(commandPool.valid());
769 vkFreeCommandBuffers(device, commandPool.getHandle(), 1, &mHandle);
770 mHandle = VK_NULL_HANDLE;
771 }
772 }
773
774 ANGLE_INLINE void CommandBuffer::copyBuffer(const Buffer &srcBuffer,
775 const Buffer &destBuffer,
776 uint32_t regionCount,
777 const VkBufferCopy *regions)
778 {
779 ASSERT(valid() && srcBuffer.valid() && destBuffer.valid());
780 vkCmdCopyBuffer(mHandle, srcBuffer.getHandle(), destBuffer.getHandle(), regionCount, regions);
781 }
782
783 ANGLE_INLINE void CommandBuffer::copyBufferToImage(VkBuffer srcBuffer,
784 const Image &dstImage,
785 VkImageLayout dstImageLayout,
786 uint32_t regionCount,
787 const VkBufferImageCopy *regions)
788 {
789 ASSERT(valid() && dstImage.valid());
790 ASSERT(srcBuffer != VK_NULL_HANDLE);
791 ASSERT(regionCount == 1);
792 vkCmdCopyBufferToImage(mHandle, srcBuffer, dstImage.getHandle(), dstImageLayout, 1, regions);
793 }
794
795 ANGLE_INLINE void CommandBuffer::copyImageToBuffer(const Image &srcImage,
796 VkImageLayout srcImageLayout,
797 VkBuffer dstBuffer,
798 uint32_t regionCount,
799 const VkBufferImageCopy *regions)
800 {
801 ASSERT(valid() && srcImage.valid());
802 ASSERT(dstBuffer != VK_NULL_HANDLE);
803 ASSERT(regionCount == 1);
804 vkCmdCopyImageToBuffer(mHandle, srcImage.getHandle(), srcImageLayout, dstBuffer, 1, regions);
805 }
806
807 ANGLE_INLINE void CommandBuffer::clearColorImage(const Image &image,
808 VkImageLayout imageLayout,
809 const VkClearColorValue &color,
810 uint32_t rangeCount,
811 const VkImageSubresourceRange *ranges)
812 {
813 ASSERT(valid());
814 ASSERT(rangeCount == 1);
815 vkCmdClearColorImage(mHandle, image.getHandle(), imageLayout, &color, 1, ranges);
816 }
817
818 ANGLE_INLINE void CommandBuffer::clearDepthStencilImage(
819 const Image &image,
820 VkImageLayout imageLayout,
821 const VkClearDepthStencilValue &depthStencil,
822 uint32_t rangeCount,
823 const VkImageSubresourceRange *ranges)
824 {
825 ASSERT(valid());
826 ASSERT(rangeCount == 1);
827 vkCmdClearDepthStencilImage(mHandle, image.getHandle(), imageLayout, &depthStencil, 1, ranges);
828 }
829
830 ANGLE_INLINE void CommandBuffer::clearAttachments(uint32_t attachmentCount,
831 const VkClearAttachment *attachments,
832 uint32_t rectCount,
833 const VkClearRect *rects)
834 {
835 ASSERT(valid());
836 vkCmdClearAttachments(mHandle, attachmentCount, attachments, rectCount, rects);
837 }
838
839 ANGLE_INLINE void CommandBuffer::copyImage(const Image &srcImage,
840 VkImageLayout srcImageLayout,
841 const Image &dstImage,
842 VkImageLayout dstImageLayout,
843 uint32_t regionCount,
844 const VkImageCopy *regions)
845 {
846 ASSERT(valid() && srcImage.valid() && dstImage.valid());
847 ASSERT(regionCount == 1);
848 vkCmdCopyImage(mHandle, srcImage.getHandle(), srcImageLayout, dstImage.getHandle(),
849 dstImageLayout, 1, regions);
850 }
851
852 ANGLE_INLINE void CommandBuffer::beginRenderPass(const VkRenderPassBeginInfo &beginInfo,
853 VkSubpassContents subpassContents)
854 {
855 ASSERT(valid());
856 vkCmdBeginRenderPass(mHandle, &beginInfo, subpassContents);
857 }
858
859 ANGLE_INLINE void CommandBuffer::endRenderPass()
860 {
861 ASSERT(mHandle != VK_NULL_HANDLE);
862 vkCmdEndRenderPass(mHandle);
863 }
864
865 ANGLE_INLINE void CommandBuffer::bindIndexBuffer(const Buffer &buffer,
866 VkDeviceSize offset,
867 VkIndexType indexType)
868 {
869 ASSERT(valid());
870 vkCmdBindIndexBuffer(mHandle, buffer.getHandle(), offset, indexType);
871 }
872
873 ANGLE_INLINE void CommandBuffer::bindDescriptorSets(const PipelineLayout &layout,
874 VkPipelineBindPoint pipelineBindPoint,
875 DescriptorSetIndex firstSet,
876 uint32_t descriptorSetCount,
877 const VkDescriptorSet *descriptorSets,
878 uint32_t dynamicOffsetCount,
879 const uint32_t *dynamicOffsets)
880 {
881 ASSERT(valid() && layout.valid());
882 vkCmdBindDescriptorSets(this->mHandle, pipelineBindPoint, layout.getHandle(),
883 ToUnderlying(firstSet), descriptorSetCount, descriptorSets,
884 dynamicOffsetCount, dynamicOffsets);
885 }
886
887 ANGLE_INLINE void CommandBuffer::executeCommands(uint32_t commandBufferCount,
888 const CommandBuffer *commandBuffers)
889 {
890 ASSERT(valid());
891 vkCmdExecuteCommands(mHandle, commandBufferCount, commandBuffers[0].ptr());
892 }
893
894 ANGLE_INLINE void CommandBuffer::getMemoryUsageStats(size_t *usedMemoryOut,
895 size_t *allocatedMemoryOut) const
896 {
897 // No data available.
898 *usedMemoryOut = 0;
899 *allocatedMemoryOut = 1;
900 }
901
902 ANGLE_INLINE void CommandBuffer::fillBuffer(const Buffer &dstBuffer,
903 VkDeviceSize dstOffset,
904 VkDeviceSize size,
905 uint32_t data)
906 {
907 ASSERT(valid());
908 vkCmdFillBuffer(mHandle, dstBuffer.getHandle(), dstOffset, size, data);
909 }
910
911 ANGLE_INLINE void CommandBuffer::pushConstants(const PipelineLayout &layout,
912 VkShaderStageFlags flag,
913 uint32_t offset,
914 uint32_t size,
915 const void *data)
916 {
917 ASSERT(valid() && layout.valid());
918 ASSERT(offset == 0);
919 vkCmdPushConstants(mHandle, layout.getHandle(), flag, 0, size, data);
920 }
921
922 ANGLE_INLINE void CommandBuffer::setEvent(VkEvent event, VkPipelineStageFlags stageMask)
923 {
924 ASSERT(valid() && event != VK_NULL_HANDLE);
925 vkCmdSetEvent(mHandle, event, stageMask);
926 }
927
928 ANGLE_INLINE void CommandBuffer::setViewport(uint32_t firstViewport,
929 uint32_t viewportCount,
930 const VkViewport *viewports)
931 {
932 ASSERT(valid() && viewports != nullptr);
933 vkCmdSetViewport(mHandle, firstViewport, viewportCount, viewports);
934 }
935
936 ANGLE_INLINE void CommandBuffer::setScissor(uint32_t firstScissor,
937 uint32_t scissorCount,
938 const VkRect2D *scissors)
939 {
940 ASSERT(valid() && scissors != nullptr);
941 vkCmdSetScissor(mHandle, firstScissor, scissorCount, scissors);
942 }
943
944 ANGLE_INLINE void CommandBuffer::resetEvent(VkEvent event, VkPipelineStageFlags stageMask)
945 {
946 ASSERT(valid() && event != VK_NULL_HANDLE);
947 vkCmdResetEvent(mHandle, event, stageMask);
948 }
949
950 ANGLE_INLINE void CommandBuffer::waitEvents(uint32_t eventCount,
951 const VkEvent *events,
952 VkPipelineStageFlags srcStageMask,
953 VkPipelineStageFlags dstStageMask,
954 uint32_t memoryBarrierCount,
955 const VkMemoryBarrier *memoryBarriers,
956 uint32_t bufferMemoryBarrierCount,
957 const VkBufferMemoryBarrier *bufferMemoryBarriers,
958 uint32_t imageMemoryBarrierCount,
959 const VkImageMemoryBarrier *imageMemoryBarriers)
960 {
961 ASSERT(valid());
962 vkCmdWaitEvents(mHandle, eventCount, events, srcStageMask, dstStageMask, memoryBarrierCount,
963 memoryBarriers, bufferMemoryBarrierCount, bufferMemoryBarriers,
964 imageMemoryBarrierCount, imageMemoryBarriers);
965 }
966
967 ANGLE_INLINE void CommandBuffer::resetQueryPool(const QueryPool &queryPool,
968 uint32_t firstQuery,
969 uint32_t queryCount)
970 {
971 ASSERT(valid() && queryPool.valid());
972 vkCmdResetQueryPool(mHandle, queryPool.getHandle(), firstQuery, queryCount);
973 }
974
975 ANGLE_INLINE void CommandBuffer::resolveImage(const Image &srcImage,
976 VkImageLayout srcImageLayout,
977 const Image &dstImage,
978 VkImageLayout dstImageLayout,
979 uint32_t regionCount,
980 const VkImageResolve *regions)
981 {
982 ASSERT(valid() && srcImage.valid() && dstImage.valid());
983 vkCmdResolveImage(mHandle, srcImage.getHandle(), srcImageLayout, dstImage.getHandle(),
984 dstImageLayout, regionCount, regions);
985 }
986
987 ANGLE_INLINE void CommandBuffer::beginQuery(const QueryPool &queryPool,
988 uint32_t query,
989 VkQueryControlFlags flags)
990 {
991 ASSERT(valid() && queryPool.valid());
992 vkCmdBeginQuery(mHandle, queryPool.getHandle(), query, flags);
993 }
994
995 ANGLE_INLINE void CommandBuffer::endQuery(const QueryPool &queryPool, uint32_t query)
996 {
997 ASSERT(valid() && queryPool.valid());
998 vkCmdEndQuery(mHandle, queryPool.getHandle(), query);
999 }
1000
1001 ANGLE_INLINE void CommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStage,
1002 const QueryPool &queryPool,
1003 uint32_t query)
1004 {
1005 ASSERT(valid());
1006 vkCmdWriteTimestamp(mHandle, pipelineStage, queryPool.getHandle(), query);
1007 }
1008
1009 ANGLE_INLINE void CommandBuffer::draw(uint32_t vertexCount,
1010 uint32_t instanceCount,
1011 uint32_t firstVertex,
1012 uint32_t firstInstance)
1013 {
1014 ASSERT(valid());
1015 vkCmdDraw(mHandle, vertexCount, instanceCount, firstVertex, firstInstance);
1016 }
1017
1018 ANGLE_INLINE void CommandBuffer::drawIndexed(uint32_t indexCount,
1019 uint32_t instanceCount,
1020 uint32_t firstIndex,
1021 int32_t vertexOffset,
1022 uint32_t firstInstance)
1023 {
1024 ASSERT(valid());
1025 vkCmdDrawIndexed(mHandle, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
1026 }
1027
1028 ANGLE_INLINE void CommandBuffer::drawIndexedIndirect(const Buffer &buffer,
1029 VkDeviceSize offset,
1030 uint32_t drawCount,
1031 uint32_t stride)
1032 {
1033 ASSERT(valid());
1034 vkCmdDrawIndexedIndirect(mHandle, buffer.getHandle(), offset, drawCount, stride);
1035 }
1036
1037 ANGLE_INLINE void CommandBuffer::drawIndirect(const Buffer &buffer,
1038 VkDeviceSize offset,
1039 uint32_t drawCount,
1040 uint32_t stride)
1041 {
1042 ASSERT(valid());
1043 vkCmdDrawIndirect(mHandle, buffer.getHandle(), offset, drawCount, stride);
1044 }
1045
1046 ANGLE_INLINE void CommandBuffer::dispatch(uint32_t groupCountX,
1047 uint32_t groupCountY,
1048 uint32_t groupCountZ)
1049 {
1050 ASSERT(valid());
1051 vkCmdDispatch(mHandle, groupCountX, groupCountY, groupCountZ);
1052 }
1053
1054 ANGLE_INLINE void CommandBuffer::dispatchIndirect(const Buffer &buffer, VkDeviceSize offset)
1055 {
1056 ASSERT(valid());
1057 vkCmdDispatchIndirect(mHandle, buffer.getHandle(), offset);
1058 }
1059
1060 ANGLE_INLINE void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint,
1061 const Pipeline &pipeline)
1062 {
1063 ASSERT(valid() && pipeline.valid());
1064 vkCmdBindPipeline(mHandle, pipelineBindPoint, pipeline.getHandle());
1065 }
1066
1067 ANGLE_INLINE void CommandBuffer::bindGraphicsPipeline(const Pipeline &pipeline)
1068 {
1069 ASSERT(valid() && pipeline.valid());
1070 vkCmdBindPipeline(mHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getHandle());
1071 }
1072
1073 ANGLE_INLINE void CommandBuffer::bindComputePipeline(const Pipeline &pipeline)
1074 {
1075 ASSERT(valid() && pipeline.valid());
1076 vkCmdBindPipeline(mHandle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.getHandle());
1077 }
1078
1079 ANGLE_INLINE void CommandBuffer::bindVertexBuffers(uint32_t firstBinding,
1080 uint32_t bindingCount,
1081 const VkBuffer *buffers,
1082 const VkDeviceSize *offsets)
1083 {
1084 ASSERT(valid());
1085 vkCmdBindVertexBuffers(mHandle, firstBinding, bindingCount, buffers, offsets);
1086 }
1087
1088 ANGLE_INLINE void CommandBuffer::beginTransformFeedback(uint32_t firstCounterBuffer,
1089 uint32_t counterBufferCount,
1090 const VkBuffer *counterBuffers,
1091 const VkDeviceSize *counterBufferOffsets)
1092 {
1093 ASSERT(valid());
1094 ASSERT(vkCmdBeginTransformFeedbackEXT);
1095 vkCmdBeginTransformFeedbackEXT(mHandle, firstCounterBuffer, counterBufferCount, counterBuffers,
1096 counterBufferOffsets);
1097 }
1098
1099 ANGLE_INLINE void CommandBuffer::endTransformFeedback(uint32_t firstCounterBuffer,
1100 uint32_t counterBufferCount,
1101 const VkBuffer *counterBuffers,
1102 const VkDeviceSize *counterBufferOffsets)
1103 {
1104 ASSERT(valid());
1105 ASSERT(vkCmdEndTransformFeedbackEXT);
1106 vkCmdEndTransformFeedbackEXT(mHandle, firstCounterBuffer, counterBufferCount, counterBuffers,
1107 counterBufferOffsets);
1108 }
1109
1110 ANGLE_INLINE void CommandBuffer::bindTransformFeedbackBuffers(uint32_t firstBinding,
1111 uint32_t bindingCount,
1112 const VkBuffer *buffers,
1113 const VkDeviceSize *offsets,
1114 const VkDeviceSize *sizes)
1115 {
1116 ASSERT(valid());
1117 ASSERT(vkCmdBindTransformFeedbackBuffersEXT);
1118 vkCmdBindTransformFeedbackBuffersEXT(mHandle, firstBinding, bindingCount, buffers, offsets,
1119 sizes);
1120 }
1121
1122 ANGLE_INLINE void CommandBuffer::beginDebugUtilsLabelEXT(const VkDebugUtilsLabelEXT &labelInfo)
1123 {
1124 ASSERT(valid());
1125 {
1126 #if !defined(ANGLE_SHARED_LIBVULKAN)
1127 // When the vulkan-loader is statically linked, we need to use the extension
1128 // functions defined in ANGLE's rx namespace. When it's dynamically linked
1129 // with volk, this will default to the function definitions with no namespace
1130 using rx::vkCmdBeginDebugUtilsLabelEXT;
1131 #endif // !defined(ANGLE_SHARED_LIBVULKAN)
1132 ASSERT(vkCmdBeginDebugUtilsLabelEXT);
1133 vkCmdBeginDebugUtilsLabelEXT(mHandle, &labelInfo);
1134 }
1135 }
1136
1137 ANGLE_INLINE void CommandBuffer::endDebugUtilsLabelEXT()
1138 {
1139 ASSERT(valid());
1140 ASSERT(vkCmdEndDebugUtilsLabelEXT);
1141 vkCmdEndDebugUtilsLabelEXT(mHandle);
1142 }
1143
1144 ANGLE_INLINE void CommandBuffer::insertDebugUtilsLabelEXT(const VkDebugUtilsLabelEXT &labelInfo)
1145 {
1146 ASSERT(valid());
1147 ASSERT(vkCmdInsertDebugUtilsLabelEXT);
1148 vkCmdInsertDebugUtilsLabelEXT(mHandle, &labelInfo);
1149 }
1150 } // namespace priv
1151
1152 // Image implementation.
1153 ANGLE_INLINE void Image::setHandle(VkImage handle)
1154 {
1155 mHandle = handle;
1156 }
1157
1158 ANGLE_INLINE void Image::reset()
1159 {
1160 mHandle = VK_NULL_HANDLE;
1161 }
1162
1163 ANGLE_INLINE void Image::destroy(VkDevice device)
1164 {
1165 if (valid())
1166 {
1167 vkDestroyImage(device, mHandle, nullptr);
1168 mHandle = VK_NULL_HANDLE;
1169 }
1170 }
1171
1172 ANGLE_INLINE VkResult Image::init(VkDevice device, const VkImageCreateInfo &createInfo)
1173 {
1174 ASSERT(!valid());
1175 return vkCreateImage(device, &createInfo, nullptr, &mHandle);
1176 }
1177
1178 ANGLE_INLINE void Image::getMemoryRequirements(VkDevice device,
1179 VkMemoryRequirements *requirementsOut) const
1180 {
1181 ASSERT(valid());
1182 vkGetImageMemoryRequirements(device, mHandle, requirementsOut);
1183 }
1184
1185 ANGLE_INLINE VkResult Image::bindMemory(VkDevice device, const vk::DeviceMemory &deviceMemory)
1186 {
1187 ASSERT(valid() && deviceMemory.valid());
1188 return vkBindImageMemory(device, mHandle, deviceMemory.getHandle(), 0);
1189 }
1190
1191 ANGLE_INLINE VkResult Image::bindMemory2(VkDevice device, const VkBindImageMemoryInfoKHR &bindInfo)
1192 {
1193 ASSERT(valid());
1194 return vkBindImageMemory2KHR(device, 1, &bindInfo);
1195 }
1196
1197 ANGLE_INLINE void Image::getSubresourceLayout(VkDevice device,
1198 VkImageAspectFlagBits aspectMask,
1199 uint32_t mipLevel,
1200 uint32_t arrayLayer,
1201 VkSubresourceLayout *outSubresourceLayout) const
1202 {
1203 VkImageSubresource subresource = {};
1204 subresource.aspectMask = aspectMask;
1205 subresource.mipLevel = mipLevel;
1206 subresource.arrayLayer = arrayLayer;
1207
1208 vkGetImageSubresourceLayout(device, getHandle(), &subresource, outSubresourceLayout);
1209 }
1210
1211 // ImageView implementation.
1212 ANGLE_INLINE void ImageView::destroy(VkDevice device)
1213 {
1214 if (valid())
1215 {
1216 vkDestroyImageView(device, mHandle, nullptr);
1217 mHandle = VK_NULL_HANDLE;
1218 }
1219 }
1220
1221 ANGLE_INLINE VkResult ImageView::init(VkDevice device, const VkImageViewCreateInfo &createInfo)
1222 {
1223 return vkCreateImageView(device, &createInfo, nullptr, &mHandle);
1224 }
1225
1226 // Semaphore implementation.
1227 ANGLE_INLINE void Semaphore::destroy(VkDevice device)
1228 {
1229 if (valid())
1230 {
1231 vkDestroySemaphore(device, mHandle, nullptr);
1232 mHandle = VK_NULL_HANDLE;
1233 }
1234 }
1235
1236 ANGLE_INLINE VkResult Semaphore::init(VkDevice device)
1237 {
1238 ASSERT(!valid());
1239
1240 VkSemaphoreCreateInfo semaphoreInfo = {};
1241 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
1242 semaphoreInfo.flags = 0;
1243
1244 return vkCreateSemaphore(device, &semaphoreInfo, nullptr, &mHandle);
1245 }
1246
1247 ANGLE_INLINE VkResult Semaphore::init(VkDevice device, const VkSemaphoreCreateInfo &createInfo)
1248 {
1249 ASSERT(valid());
1250 return vkCreateSemaphore(device, &createInfo, nullptr, &mHandle);
1251 }
1252
1253 ANGLE_INLINE VkResult Semaphore::importFd(VkDevice device,
1254 const VkImportSemaphoreFdInfoKHR &importFdInfo) const
1255 {
1256 ASSERT(valid());
1257 return vkImportSemaphoreFdKHR(device, &importFdInfo);
1258 }
1259
1260 // Framebuffer implementation.
1261 ANGLE_INLINE void Framebuffer::destroy(VkDevice device)
1262 {
1263 if (valid())
1264 {
1265 vkDestroyFramebuffer(device, mHandle, nullptr);
1266 mHandle = VK_NULL_HANDLE;
1267 }
1268 }
1269
1270 ANGLE_INLINE VkResult Framebuffer::init(VkDevice device, const VkFramebufferCreateInfo &createInfo)
1271 {
1272 ASSERT(!valid());
1273 return vkCreateFramebuffer(device, &createInfo, nullptr, &mHandle);
1274 }
1275
1276 ANGLE_INLINE void Framebuffer::setHandle(VkFramebuffer handle)
1277 {
1278 mHandle = handle;
1279 }
1280
1281 // DeviceMemory implementation.
1282 ANGLE_INLINE void DeviceMemory::destroy(VkDevice device)
1283 {
1284 if (valid())
1285 {
1286 vkFreeMemory(device, mHandle, nullptr);
1287 mHandle = VK_NULL_HANDLE;
1288 }
1289 }
1290
1291 ANGLE_INLINE VkResult DeviceMemory::allocate(VkDevice device, const VkMemoryAllocateInfo &allocInfo)
1292 {
1293 ASSERT(!valid());
1294 return vkAllocateMemory(device, &allocInfo, nullptr, &mHandle);
1295 }
1296
1297 ANGLE_INLINE VkResult DeviceMemory::map(VkDevice device,
1298 VkDeviceSize offset,
1299 VkDeviceSize size,
1300 VkMemoryMapFlags flags,
1301 uint8_t **mapPointer) const
1302 {
1303 ANGLE_TRACE_EVENT0("gpu.angle", "DeviceMemory::map");
1304 ASSERT(valid());
1305 return vkMapMemory(device, mHandle, offset, size, flags, reinterpret_cast<void **>(mapPointer));
1306 }
1307
1308 ANGLE_INLINE void DeviceMemory::unmap(VkDevice device) const
1309 {
1310 ASSERT(valid());
1311 vkUnmapMemory(device, mHandle);
1312 }
1313
1314 ANGLE_INLINE void DeviceMemory::flush(VkDevice device, VkMappedMemoryRange &memRange)
1315 {
1316 vkFlushMappedMemoryRanges(device, 1, &memRange);
1317 }
1318
1319 ANGLE_INLINE void DeviceMemory::invalidate(VkDevice device, VkMappedMemoryRange &memRange)
1320 {
1321 vkInvalidateMappedMemoryRanges(device, 1, &memRange);
1322 }
1323
1324 // Allocator implementation.
1325 ANGLE_INLINE void Allocator::destroy()
1326 {
1327 if (valid())
1328 {
1329 vma::DestroyAllocator(mHandle);
1330 mHandle = VK_NULL_HANDLE;
1331 }
1332 }
1333
1334 ANGLE_INLINE VkResult Allocator::init(VkPhysicalDevice physicalDevice,
1335 VkDevice device,
1336 VkInstance instance,
1337 uint32_t apiVersion,
1338 VkDeviceSize preferredLargeHeapBlockSize)
1339 {
1340 ASSERT(!valid());
1341 return vma::InitAllocator(physicalDevice, device, instance, apiVersion,
1342 preferredLargeHeapBlockSize, &mHandle);
1343 }
1344
1345 ANGLE_INLINE void Allocator::buildStatsString(char **statsString, VkBool32 detailedMap)
1346 {
1347 ASSERT(valid());
1348 vma::BuildStatsString(mHandle, statsString, detailedMap);
1349 }
1350
1351 ANGLE_INLINE void Allocator::freeStatsString(char *statsString)
1352 {
1353 ASSERT(valid());
1354 vma::FreeStatsString(mHandle, statsString);
1355 }
1356
1357 // Allocation implementation.
1358 ANGLE_INLINE void Allocation::destroy(const Allocator &allocator)
1359 {
1360 if (valid())
1361 {
1362 vma::FreeMemory(allocator.getHandle(), mHandle);
1363 mHandle = VK_NULL_HANDLE;
1364 }
1365 }
1366
1367 ANGLE_INLINE VkResult Allocation::map(const Allocator &allocator, uint8_t **mapPointer) const
1368 {
1369 ASSERT(valid());
1370 return vma::MapMemory(allocator.getHandle(), mHandle, (void **)mapPointer);
1371 }
1372
1373 ANGLE_INLINE void Allocation::unmap(const Allocator &allocator) const
1374 {
1375 ASSERT(valid());
1376 vma::UnmapMemory(allocator.getHandle(), mHandle);
1377 }
1378
1379 ANGLE_INLINE void Allocation::flush(const Allocator &allocator,
1380 VkDeviceSize offset,
1381 VkDeviceSize size)
1382 {
1383 ASSERT(valid());
1384 vma::FlushAllocation(allocator.getHandle(), mHandle, offset, size);
1385 }
1386
1387 ANGLE_INLINE void Allocation::invalidate(const Allocator &allocator,
1388 VkDeviceSize offset,
1389 VkDeviceSize size)
1390 {
1391 ASSERT(valid());
1392 vma::InvalidateAllocation(allocator.getHandle(), mHandle, offset, size);
1393 }
1394
1395 // RenderPass implementation.
1396 ANGLE_INLINE void RenderPass::destroy(VkDevice device)
1397 {
1398 if (valid())
1399 {
1400 vkDestroyRenderPass(device, mHandle, nullptr);
1401 mHandle = VK_NULL_HANDLE;
1402 }
1403 }
1404
1405 ANGLE_INLINE VkResult RenderPass::init(VkDevice device, const VkRenderPassCreateInfo &createInfo)
1406 {
1407 ASSERT(!valid());
1408 return vkCreateRenderPass(device, &createInfo, nullptr, &mHandle);
1409 }
1410
1411 ANGLE_INLINE VkResult RenderPass::init2(VkDevice device, const VkRenderPassCreateInfo2 &createInfo)
1412 {
1413 ASSERT(!valid());
1414 return vkCreateRenderPass2KHR(device, &createInfo, nullptr, &mHandle);
1415 }
1416
1417 // Buffer implementation.
1418 ANGLE_INLINE void Buffer::destroy(VkDevice device)
1419 {
1420 if (valid())
1421 {
1422 vkDestroyBuffer(device, mHandle, nullptr);
1423 mHandle = VK_NULL_HANDLE;
1424 }
1425 }
1426
1427 ANGLE_INLINE VkResult Buffer::init(VkDevice device, const VkBufferCreateInfo &createInfo)
1428 {
1429 ASSERT(!valid());
1430 return vkCreateBuffer(device, &createInfo, nullptr, &mHandle);
1431 }
1432
1433 ANGLE_INLINE VkResult Buffer::bindMemory(VkDevice device, const DeviceMemory &deviceMemory)
1434 {
1435 ASSERT(valid() && deviceMemory.valid());
1436 return vkBindBufferMemory(device, mHandle, deviceMemory.getHandle(), 0);
1437 }
1438
1439 ANGLE_INLINE void Buffer::getMemoryRequirements(VkDevice device,
1440 VkMemoryRequirements *memoryRequirementsOut)
1441 {
1442 ASSERT(valid());
1443 vkGetBufferMemoryRequirements(device, mHandle, memoryRequirementsOut);
1444 }
1445
1446 // BufferView implementation.
1447 ANGLE_INLINE void BufferView::destroy(VkDevice device)
1448 {
1449 if (valid())
1450 {
1451 vkDestroyBufferView(device, mHandle, nullptr);
1452 mHandle = VK_NULL_HANDLE;
1453 }
1454 }
1455
1456 ANGLE_INLINE VkResult BufferView::init(VkDevice device, const VkBufferViewCreateInfo &createInfo)
1457 {
1458 ASSERT(!valid());
1459 return vkCreateBufferView(device, &createInfo, nullptr, &mHandle);
1460 }
1461
1462 // ShaderModule implementation.
1463 ANGLE_INLINE void ShaderModule::destroy(VkDevice device)
1464 {
1465 if (mHandle != VK_NULL_HANDLE)
1466 {
1467 vkDestroyShaderModule(device, mHandle, nullptr);
1468 mHandle = VK_NULL_HANDLE;
1469 }
1470 }
1471
1472 ANGLE_INLINE VkResult ShaderModule::init(VkDevice device,
1473 const VkShaderModuleCreateInfo &createInfo)
1474 {
1475 ASSERT(!valid());
1476 return vkCreateShaderModule(device, &createInfo, nullptr, &mHandle);
1477 }
1478
1479 // PipelineLayout implementation.
1480 ANGLE_INLINE void PipelineLayout::destroy(VkDevice device)
1481 {
1482 if (valid())
1483 {
1484 vkDestroyPipelineLayout(device, mHandle, nullptr);
1485 mHandle = VK_NULL_HANDLE;
1486 }
1487 }
1488
1489 ANGLE_INLINE VkResult PipelineLayout::init(VkDevice device,
1490 const VkPipelineLayoutCreateInfo &createInfo)
1491 {
1492 ASSERT(!valid());
1493 return vkCreatePipelineLayout(device, &createInfo, nullptr, &mHandle);
1494 }
1495
1496 // PipelineCache implementation.
1497 ANGLE_INLINE void PipelineCache::destroy(VkDevice device)
1498 {
1499 if (valid())
1500 {
1501 vkDestroyPipelineCache(device, mHandle, nullptr);
1502 mHandle = VK_NULL_HANDLE;
1503 }
1504 }
1505
1506 ANGLE_INLINE VkResult PipelineCache::init(VkDevice device,
1507 const VkPipelineCacheCreateInfo &createInfo)
1508 {
1509 ASSERT(!valid());
1510 // Note: if we are concerned with memory usage of this cache, we should give it custom
1511 // allocators. Also, failure of this function is of little importance.
1512 return vkCreatePipelineCache(device, &createInfo, nullptr, &mHandle);
1513 }
1514
1515 ANGLE_INLINE VkResult PipelineCache::merge(VkDevice device,
1516 VkPipelineCache dstCache,
1517 uint32_t srcCacheCount,
1518 const VkPipelineCache *srcCaches)
1519 {
1520 ASSERT(valid());
1521 return vkMergePipelineCaches(device, dstCache, srcCacheCount, srcCaches);
1522 }
1523
1524 ANGLE_INLINE VkResult PipelineCache::getCacheData(VkDevice device,
1525 size_t *cacheSize,
1526 void *cacheData)
1527 {
1528 ASSERT(valid());
1529
1530 // Note: vkGetPipelineCacheData can return VK_INCOMPLETE if cacheSize is smaller than actual
1531 // size. There are two usages of this function. One is with *cacheSize == 0 to query the size
1532 // of the cache, and one is with an appropriate buffer to retrieve the cache contents.
1533 // VK_INCOMPLETE in the first case is an expected output. In the second case, VK_INCOMPLETE is
1534 // also acceptable and the resulting buffer will contain valid value by spec. Angle currently
1535 // ensures *cacheSize to be either 0 or of enough size, therefore VK_INCOMPLETE is not expected.
1536 return vkGetPipelineCacheData(device, mHandle, cacheSize, cacheData);
1537 }
1538
1539 // Pipeline implementation.
1540 ANGLE_INLINE void Pipeline::destroy(VkDevice device)
1541 {
1542 if (valid())
1543 {
1544 vkDestroyPipeline(device, mHandle, nullptr);
1545 mHandle = VK_NULL_HANDLE;
1546 }
1547 }
1548
1549 ANGLE_INLINE VkResult Pipeline::initGraphics(VkDevice device,
1550 const VkGraphicsPipelineCreateInfo &createInfo,
1551 const PipelineCache &pipelineCacheVk)
1552 {
1553 ASSERT(!valid());
1554 return vkCreateGraphicsPipelines(device, pipelineCacheVk.getHandle(), 1, &createInfo, nullptr,
1555 &mHandle);
1556 }
1557
1558 ANGLE_INLINE VkResult Pipeline::initCompute(VkDevice device,
1559 const VkComputePipelineCreateInfo &createInfo,
1560 const PipelineCache &pipelineCacheVk)
1561 {
1562 ASSERT(!valid());
1563 return vkCreateComputePipelines(device, pipelineCacheVk.getHandle(), 1, &createInfo, nullptr,
1564 &mHandle);
1565 }
1566
1567 // DescriptorSetLayout implementation.
1568 ANGLE_INLINE void DescriptorSetLayout::destroy(VkDevice device)
1569 {
1570 if (valid())
1571 {
1572 vkDestroyDescriptorSetLayout(device, mHandle, nullptr);
1573 mHandle = VK_NULL_HANDLE;
1574 }
1575 }
1576
1577 ANGLE_INLINE VkResult DescriptorSetLayout::init(VkDevice device,
1578 const VkDescriptorSetLayoutCreateInfo &createInfo)
1579 {
1580 ASSERT(!valid());
1581 return vkCreateDescriptorSetLayout(device, &createInfo, nullptr, &mHandle);
1582 }
1583
1584 // DescriptorPool implementation.
1585 ANGLE_INLINE void DescriptorPool::destroy(VkDevice device)
1586 {
1587 if (valid())
1588 {
1589 vkDestroyDescriptorPool(device, mHandle, nullptr);
1590 mHandle = VK_NULL_HANDLE;
1591 }
1592 }
1593
1594 ANGLE_INLINE VkResult DescriptorPool::init(VkDevice device,
1595 const VkDescriptorPoolCreateInfo &createInfo)
1596 {
1597 ASSERT(!valid());
1598 return vkCreateDescriptorPool(device, &createInfo, nullptr, &mHandle);
1599 }
1600
1601 ANGLE_INLINE VkResult
1602 DescriptorPool::allocateDescriptorSets(VkDevice device,
1603 const VkDescriptorSetAllocateInfo &allocInfo,
1604 VkDescriptorSet *descriptorSetsOut)
1605 {
1606 ASSERT(valid());
1607 return vkAllocateDescriptorSets(device, &allocInfo, descriptorSetsOut);
1608 }
1609
1610 ANGLE_INLINE VkResult DescriptorPool::freeDescriptorSets(VkDevice device,
1611 uint32_t descriptorSetCount,
1612 const VkDescriptorSet *descriptorSets)
1613 {
1614 ASSERT(valid());
1615 ASSERT(descriptorSetCount > 0);
1616 return vkFreeDescriptorSets(device, mHandle, descriptorSetCount, descriptorSets);
1617 }
1618
1619 // Sampler implementation.
1620 ANGLE_INLINE void Sampler::destroy(VkDevice device)
1621 {
1622 if (valid())
1623 {
1624 vkDestroySampler(device, mHandle, nullptr);
1625 mHandle = VK_NULL_HANDLE;
1626 }
1627 }
1628
1629 ANGLE_INLINE VkResult Sampler::init(VkDevice device, const VkSamplerCreateInfo &createInfo)
1630 {
1631 ASSERT(!valid());
1632 return vkCreateSampler(device, &createInfo, nullptr, &mHandle);
1633 }
1634
1635 // SamplerYuvConversion implementation.
1636 ANGLE_INLINE void SamplerYcbcrConversion::destroy(VkDevice device)
1637 {
1638 if (valid())
1639 {
1640 vkDestroySamplerYcbcrConversionKHR(device, mHandle, nullptr);
1641 mHandle = VK_NULL_HANDLE;
1642 }
1643 }
1644
1645 ANGLE_INLINE VkResult
1646 SamplerYcbcrConversion::init(VkDevice device, const VkSamplerYcbcrConversionCreateInfo &createInfo)
1647 {
1648 ASSERT(!valid());
1649 return vkCreateSamplerYcbcrConversionKHR(device, &createInfo, nullptr, &mHandle);
1650 }
1651
1652 // Event implementation.
1653 ANGLE_INLINE void Event::destroy(VkDevice device)
1654 {
1655 if (valid())
1656 {
1657 vkDestroyEvent(device, mHandle, nullptr);
1658 mHandle = VK_NULL_HANDLE;
1659 }
1660 }
1661
1662 ANGLE_INLINE VkResult Event::init(VkDevice device, const VkEventCreateInfo &createInfo)
1663 {
1664 ASSERT(!valid());
1665 return vkCreateEvent(device, &createInfo, nullptr, &mHandle);
1666 }
1667
1668 ANGLE_INLINE VkResult Event::getStatus(VkDevice device) const
1669 {
1670 ASSERT(valid());
1671 return vkGetEventStatus(device, mHandle);
1672 }
1673
1674 ANGLE_INLINE VkResult Event::set(VkDevice device) const
1675 {
1676 ASSERT(valid());
1677 return vkSetEvent(device, mHandle);
1678 }
1679
1680 ANGLE_INLINE VkResult Event::reset(VkDevice device) const
1681 {
1682 ASSERT(valid());
1683 return vkResetEvent(device, mHandle);
1684 }
1685
1686 // Fence implementation.
1687 ANGLE_INLINE void Fence::destroy(VkDevice device)
1688 {
1689 if (valid())
1690 {
1691 vkDestroyFence(device, mHandle, nullptr);
1692 mHandle = VK_NULL_HANDLE;
1693 }
1694 }
1695
1696 ANGLE_INLINE VkResult Fence::init(VkDevice device, const VkFenceCreateInfo &createInfo)
1697 {
1698 ASSERT(!valid());
1699 return vkCreateFence(device, &createInfo, nullptr, &mHandle);
1700 }
1701
1702 ANGLE_INLINE VkResult Fence::reset(VkDevice device)
1703 {
1704 ASSERT(valid());
1705 return vkResetFences(device, 1, &mHandle);
1706 }
1707
1708 ANGLE_INLINE VkResult Fence::getStatus(VkDevice device) const
1709 {
1710 ASSERT(valid());
1711 return vkGetFenceStatus(device, mHandle);
1712 }
1713
1714 ANGLE_INLINE VkResult Fence::wait(VkDevice device, uint64_t timeout) const
1715 {
1716 ASSERT(valid());
1717 return vkWaitForFences(device, 1, &mHandle, true, timeout);
1718 }
1719
1720 ANGLE_INLINE VkResult Fence::importFd(VkDevice device,
1721 const VkImportFenceFdInfoKHR &importFenceFdInfo) const
1722 {
1723 ASSERT(valid());
1724 return vkImportFenceFdKHR(device, &importFenceFdInfo);
1725 }
1726
1727 ANGLE_INLINE VkResult Fence::exportFd(VkDevice device,
1728 const VkFenceGetFdInfoKHR &fenceGetFdInfo,
1729 int *fdOut) const
1730 {
1731 ASSERT(valid());
1732 return vkGetFenceFdKHR(device, &fenceGetFdInfo, fdOut);
1733 }
1734
1735 // QueryPool implementation.
1736 ANGLE_INLINE void QueryPool::destroy(VkDevice device)
1737 {
1738 if (valid())
1739 {
1740 vkDestroyQueryPool(device, mHandle, nullptr);
1741 mHandle = VK_NULL_HANDLE;
1742 }
1743 }
1744
1745 ANGLE_INLINE VkResult QueryPool::init(VkDevice device, const VkQueryPoolCreateInfo &createInfo)
1746 {
1747 ASSERT(!valid());
1748 return vkCreateQueryPool(device, &createInfo, nullptr, &mHandle);
1749 }
1750
1751 ANGLE_INLINE VkResult QueryPool::getResults(VkDevice device,
1752 uint32_t firstQuery,
1753 uint32_t queryCount,
1754 size_t dataSize,
1755 void *data,
1756 VkDeviceSize stride,
1757 VkQueryResultFlags flags) const
1758 {
1759 ASSERT(valid());
1760 return vkGetQueryPoolResults(device, mHandle, firstQuery, queryCount, dataSize, data, stride,
1761 flags);
1762 }
1763 } // namespace vk
1764 } // namespace rx
1765
1766 #endif // LIBANGLE_RENDERER_VULKAN_VK_WRAPPER_H_
1767