• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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