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