blob: c9fe77bd4a1f0812eb5d6f311d2cd9fcd367c099 [file] [log] [blame]
//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// vk_wrapper:
// Wrapper classes around Vulkan objects. In an ideal world we could generate this
// from vk.xml. Or reuse the generator in the vkhpp tool. For now this is manually
// generated and we must add missing functions and objects as we need them.
#ifndef LIBANGLE_RENDERER_VULKAN_VK_WRAPPER_H_
#define LIBANGLE_RENDERER_VULKAN_VK_WRAPPER_H_
#include <vulkan/vulkan.h>
#include "libANGLE/renderer/renderer_utils.h"
namespace rx
{
namespace vk
{
// Helper macros that apply to all the wrapped object types.
// Unimplemented handle types:
// Instance
// PhysicalDevice
// Device
// Queue
// DescriptorSet
#define ANGLE_HANDLE_TYPES_X(FUNC) \
FUNC(Buffer) \
FUNC(BufferView) \
FUNC(CommandPool) \
FUNC(DescriptorPool) \
FUNC(DescriptorSetLayout) \
FUNC(DeviceMemory) \
FUNC(Event) \
FUNC(Fence) \
FUNC(Framebuffer) \
FUNC(Image) \
FUNC(ImageView) \
FUNC(Pipeline) \
FUNC(PipelineCache) \
FUNC(PipelineLayout) \
FUNC(QueryPool) \
FUNC(RenderPass) \
FUNC(Sampler) \
FUNC(Semaphore) \
FUNC(ShaderModule)
#define ANGLE_COMMA_SEP_FUNC(TYPE) TYPE,
enum class HandleType
{
Invalid,
CommandBuffer,
ANGLE_HANDLE_TYPES_X(ANGLE_COMMA_SEP_FUNC)
};
#undef ANGLE_COMMA_SEP_FUNC
#define ANGLE_PRE_DECLARE_CLASS_FUNC(TYPE) class TYPE;
ANGLE_HANDLE_TYPES_X(ANGLE_PRE_DECLARE_CLASS_FUNC)
namespace priv
{
class CommandBuffer;
} // namespace priv
#undef ANGLE_PRE_DECLARE_CLASS_FUNC
// Returns the HandleType of a Vk Handle.
template <typename T>
struct HandleTypeHelper;
#define ANGLE_HANDLE_TYPE_HELPER_FUNC(TYPE) \
template <> \
struct HandleTypeHelper<TYPE> \
{ \
constexpr static HandleType kHandleType = HandleType::TYPE; \
};
ANGLE_HANDLE_TYPES_X(ANGLE_HANDLE_TYPE_HELPER_FUNC)
template <>
struct HandleTypeHelper<priv::CommandBuffer>
{
constexpr static HandleType kHandleType = HandleType::CommandBuffer;
};
#undef ANGLE_HANDLE_TYPE_HELPER_FUNC
// Base class for all wrapped vulkan objects. Implements several common helper routines.
template <typename DerivedT, typename HandleT>
class WrappedObject : angle::NonCopyable
{
public:
HandleT getHandle() const { return mHandle; }
bool valid() const { return (mHandle != VK_NULL_HANDLE); }
const HandleT *ptr() const { return &mHandle; }
HandleT release()
{
HandleT handle = mHandle;
mHandle = VK_NULL_HANDLE;
return handle;
}
protected:
WrappedObject() : mHandle(VK_NULL_HANDLE) {}
~WrappedObject() { ASSERT(!valid()); }
WrappedObject(WrappedObject &&other) : mHandle(other.mHandle)
{
other.mHandle = VK_NULL_HANDLE;
}
// Only works to initialize empty objects, since we don't have the device handle.
WrappedObject &operator=(WrappedObject &&other)
{
ASSERT(!valid());
std::swap(mHandle, other.mHandle);
return *this;
}
HandleT mHandle;
};
class CommandPool final : public WrappedObject<CommandPool, VkCommandPool>
{
public:
CommandPool() = default;
void destroy(VkDevice device);
VkResult reset(VkDevice device, VkCommandPoolResetFlags flags);
VkResult init(VkDevice device, const VkCommandPoolCreateInfo &createInfo);
};
class Pipeline final : public WrappedObject<Pipeline, VkPipeline>
{
public:
Pipeline() = default;
void destroy(VkDevice device);
VkResult initGraphics(VkDevice device,
const VkGraphicsPipelineCreateInfo &createInfo,
const PipelineCache &pipelineCacheVk);
VkResult initCompute(VkDevice device,
const VkComputePipelineCreateInfo &createInfo,
const PipelineCache &pipelineCacheVk);
};
namespace priv
{
// Helper class that wraps a Vulkan command buffer.
class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
{
public:
CommandBuffer() = default;
VkCommandBuffer releaseHandle();
// This is used for normal pool allocated command buffers. It reset the handle.
void destroy(VkDevice device);
// This is used in conjunction with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT.
void destroy(VkDevice device, const CommandPool &commandPool);
VkResult init(VkDevice device, const VkCommandBufferAllocateInfo &createInfo);
// There is no way to know if the command buffer contains any commands.
static bool CanKnowIfEmpty() { return false; }
bool empty() const { return false; }
using WrappedObject::operator=;
static bool SupportsQueries(const VkPhysicalDeviceFeatures &features)
{
return (features.inheritedQueries == VK_TRUE);
}
// Vulkan command buffers are executed as secondary command buffers within a primary command
// buffer.
static constexpr bool ExecutesInline() { return false; }
VkResult begin(const VkCommandBufferBeginInfo &info);
void beginQuery(VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags);
void beginRenderPass(const VkRenderPassBeginInfo &beginInfo, VkSubpassContents subpassContents);
void bindDescriptorSets(const PipelineLayout &layout,
VkPipelineBindPoint pipelineBindPoint,
uint32_t firstSet,
uint32_t descriptorSetCount,
const VkDescriptorSet *descriptorSets,
uint32_t dynamicOffsetCount,
const uint32_t *dynamicOffsets);
void bindGraphicsPipeline(const Pipeline &pipeline);
void bindComputePipeline(const Pipeline &pipeline);
void bindPipeline(VkPipelineBindPoint pipelineBindPoint, const Pipeline &pipeline);
void bindIndexBuffer(const Buffer &buffer, VkDeviceSize offset, VkIndexType indexType);
void bindVertexBuffers(uint32_t firstBinding,
uint32_t bindingCount,
const VkBuffer *buffers,
const VkDeviceSize *offsets);
void blitImage(const Image &srcImage,
VkImageLayout srcImageLayout,
const Image &dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageBlit *regions,
VkFilter filter);
void clearColorImage(const Image &image,
VkImageLayout imageLayout,
const VkClearColorValue &color,
uint32_t rangeCount,
const VkImageSubresourceRange *ranges);
void clearDepthStencilImage(const Image &image,
VkImageLayout imageLayout,
const VkClearDepthStencilValue &depthStencil,
uint32_t rangeCount,
const VkImageSubresourceRange *ranges);
void clearAttachments(uint32_t attachmentCount,
const VkClearAttachment *attachments,
uint32_t rectCount,
const VkClearRect *rects);
void copyBuffer(const Buffer &srcBuffer,
const Buffer &destBuffer,
uint32_t regionCount,
const VkBufferCopy *regions);
void copyBufferToImage(VkBuffer srcBuffer,
const Image &dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkBufferImageCopy *regions);
void copyImageToBuffer(const Image &srcImage,
VkImageLayout srcImageLayout,
VkBuffer dstBuffer,
uint32_t regionCount,
const VkBufferImageCopy *regions);
void copyImage(const Image &srcImage,
VkImageLayout srcImageLayout,
const Image &dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageCopy *regions);
void dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
void dispatchIndirect(const Buffer &buffer, VkDeviceSize offset);
void draw(uint32_t vertexCount,
uint32_t instanceCount,
uint32_t firstVertex,
uint32_t firstInstance);
void draw(uint32_t vertexCount, uint32_t firstVertex);
void drawInstanced(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex);
void drawInstancedBaseInstance(uint32_t vertexCount,
uint32_t instanceCount,
uint32_t firstVertex,
uint32_t firstInstance);
void drawIndexed(uint32_t indexCount,
uint32_t instanceCount,
uint32_t firstIndex,
int32_t vertexOffset,
uint32_t firstInstance);
void drawIndexed(uint32_t indexCount);
void drawIndexedInstanced(uint32_t indexCount, uint32_t instanceCount);
void drawIndexedInstancedBaseVertexBaseInstance(uint32_t indexCount,
uint32_t instanceCount,
uint32_t firstIndex,
int32_t vertexOffset,
uint32_t firstInstance);
void drawIndexedIndirect(const Buffer &buffer,
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride);
void drawIndirect(const Buffer &buffer,
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride);
VkResult end();
void endQuery(VkQueryPool queryPool, uint32_t query);
void endRenderPass();
void executeCommands(uint32_t commandBufferCount, const CommandBuffer *commandBuffers);
void getMemoryUsageStats(size_t *usedMemoryOut, size_t *allocatedMemoryOut) const;
void executionBarrier(VkPipelineStageFlags stageMask);
void fillBuffer(const Buffer &dstBuffer,
VkDeviceSize dstOffset,
VkDeviceSize size,
uint32_t data);
void imageBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
const VkImageMemoryBarrier *imageMemoryBarrier);
void memoryBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
const VkMemoryBarrier *memoryBarrier);
void pipelineBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
VkDependencyFlags dependencyFlags,
uint32_t memoryBarrierCount,
const VkMemoryBarrier *memoryBarriers,
uint32_t bufferMemoryBarrierCount,
const VkBufferMemoryBarrier *bufferMemoryBarriers,
uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier *imageMemoryBarriers);
void pushConstants(const PipelineLayout &layout,
VkShaderStageFlags flag,
uint32_t offset,
uint32_t size,
const void *data);
void setEvent(VkEvent event, VkPipelineStageFlags stageMask);
VkResult reset();
void resetEvent(VkEvent event, VkPipelineStageFlags stageMask);
void resetQueryPool(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount);
void resolveImage(const Image &srcImage,
VkImageLayout srcImageLayout,
const Image &dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageResolve *regions);
void waitEvents(uint32_t eventCount,
const VkEvent *events,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
uint32_t memoryBarrierCount,
const VkMemoryBarrier *memoryBarriers,
uint32_t bufferMemoryBarrierCount,
const VkBufferMemoryBarrier *bufferMemoryBarriers,
uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier *imageMemoryBarriers);
void writeTimestamp(VkPipelineStageFlagBits pipelineStage,
VkQueryPool queryPool,
uint32_t query);
};
} // namespace priv
class Image final : public WrappedObject<Image, VkImage>
{
public:
Image() = default;
// Use this method if the lifetime of the image is not controlled by ANGLE. (SwapChain)
void setHandle(VkImage handle);
// Called on shutdown when the helper class *doesn't* own the handle to the image resource.
void reset();
// Called on shutdown when the helper class *does* own the handle to the image resource.
void destroy(VkDevice device);
VkResult init(VkDevice device, const VkImageCreateInfo &createInfo);
void getMemoryRequirements(VkDevice device, VkMemoryRequirements *requirementsOut) const;
VkResult bindMemory(VkDevice device, const DeviceMemory &deviceMemory);
void getSubresourceLayout(VkDevice device,
VkImageAspectFlagBits aspectMask,
uint32_t mipLevel,
uint32_t arrayLayer,
VkSubresourceLayout *outSubresourceLayout) const;
};
class ImageView final : public WrappedObject<ImageView, VkImageView>
{
public:
ImageView() = default;
void destroy(VkDevice device);
VkResult init(VkDevice device, const VkImageViewCreateInfo &createInfo);
};
class Semaphore final : public WrappedObject<Semaphore, VkSemaphore>
{
public:
Semaphore() = default;
void destroy(VkDevice device);
VkResult init(VkDevice device);
};
class Framebuffer final : public WrappedObject<Framebuffer, VkFramebuffer>
{
public:
Framebuffer() = default;
void destroy(VkDevice device);
// Use this method only in necessary cases. (RenderPass)
void setHandle(VkFramebuffer handle);
VkResult init(VkDevice device, const VkFramebufferCreateInfo &createInfo);
};
class DeviceMemory final : public WrappedObject<DeviceMemory, VkDeviceMemory>
{
public:
DeviceMemory() = default;
void destroy(VkDevice device);
VkResult allocate(VkDevice device, const VkMemoryAllocateInfo &allocInfo);
VkResult map(VkDevice device,
VkDeviceSize offset,
VkDeviceSize size,
VkMemoryMapFlags flags,
uint8_t **mapPointer) const;
void unmap(VkDevice device) const;
};
class RenderPass final : public WrappedObject<RenderPass, VkRenderPass>
{
public:
RenderPass() = default;
void destroy(VkDevice device);
VkResult init(VkDevice device, const VkRenderPassCreateInfo &createInfo);
};
enum class StagingUsage
{
Read,
Write,
Both,
};
class Buffer final : public WrappedObject<Buffer, VkBuffer>
{
public:
Buffer() = default;
void destroy(VkDevice device);
VkResult init(VkDevice device, const VkBufferCreateInfo &createInfo);
VkResult bindMemory(VkDevice device, const DeviceMemory &deviceMemory);
void getMemoryRequirements(VkDevice device, VkMemoryRequirements *memoryRequirementsOut);
};
class BufferView final : public WrappedObject<BufferView, VkBufferView>
{
public:
BufferView() = default;
void destroy(VkDevice device);
VkResult init(VkDevice device, const VkBufferViewCreateInfo &createInfo);
};
class ShaderModule final : public WrappedObject<ShaderModule, VkShaderModule>
{
public:
ShaderModule() = default;
void destroy(VkDevice device);
VkResult init(VkDevice device, const VkShaderModuleCreateInfo &createInfo);
};
class PipelineLayout final : public WrappedObject<PipelineLayout, VkPipelineLayout>
{
public:
PipelineLayout() = default;
void destroy(VkDevice device);
VkResult init(VkDevice device, const VkPipelineLayoutCreateInfo &createInfo);
};
class PipelineCache final : public WrappedObject<PipelineCache, VkPipelineCache>
{
public:
PipelineCache() = default;
void destroy(VkDevice device);
VkResult init(VkDevice device, const VkPipelineCacheCreateInfo &createInfo);
VkResult getCacheData(VkDevice device, size_t *cacheSize, void *cacheData);
VkResult merge(VkDevice device,
VkPipelineCache dstCache,
uint32_t srcCacheCount,
const VkPipelineCache *srcCaches);
};
class DescriptorSetLayout final : public WrappedObject<DescriptorSetLayout, VkDescriptorSetLayout>
{
public:
DescriptorSetLayout() = default;
void destroy(VkDevice device);
VkResult init(VkDevice device, const VkDescriptorSetLayoutCreateInfo &createInfo);
};
class DescriptorPool final : public WrappedObject<DescriptorPool, VkDescriptorPool>
{
public:
DescriptorPool() = default;
void destroy(VkDevice device);
VkResult init(VkDevice device, const VkDescriptorPoolCreateInfo &createInfo);
VkResult allocateDescriptorSets(VkDevice device,
const VkDescriptorSetAllocateInfo &allocInfo,
VkDescriptorSet *descriptorSetsOut);
VkResult freeDescriptorSets(VkDevice device,
uint32_t descriptorSetCount,
const VkDescriptorSet *descriptorSets);
};
class Sampler final : public WrappedObject<Sampler, VkSampler>
{
public:
Sampler() = default;
void destroy(VkDevice device);
VkResult init(VkDevice device, const VkSamplerCreateInfo &createInfo);
};
class Event final : public WrappedObject<Event, VkEvent>
{
public:
Event() = default;
void destroy(VkDevice device);
using WrappedObject::operator=;
VkResult init(VkDevice device, const VkEventCreateInfo &createInfo);
VkResult getStatus(VkDevice device) const;
VkResult set(VkDevice device) const;
VkResult reset(VkDevice device) const;
};
class Fence final : public WrappedObject<Fence, VkFence>
{
public:
Fence() = default;
void destroy(VkDevice device);
using WrappedObject::operator=;
VkResult init(VkDevice device, const VkFenceCreateInfo &createInfo);
VkResult reset(VkDevice device);
VkResult getStatus(VkDevice device) const;
VkResult wait(VkDevice device, uint64_t timeout) const;
};
class QueryPool final : public WrappedObject<QueryPool, VkQueryPool>
{
public:
QueryPool() = default;
void destroy(VkDevice device);
VkResult init(VkDevice device, const VkQueryPoolCreateInfo &createInfo);
VkResult getResults(VkDevice device,
uint32_t firstQuery,
uint32_t queryCount,
size_t dataSize,
void *data,
VkDeviceSize stride,
VkQueryResultFlags flags) const;
};
// CommandPool implementation.
ANGLE_INLINE void CommandPool::destroy(VkDevice device)
{
if (valid())
{
vkDestroyCommandPool(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult CommandPool::reset(VkDevice device, VkCommandPoolResetFlags flags)
{
ASSERT(valid());
return vkResetCommandPool(device, mHandle, flags);
}
ANGLE_INLINE VkResult CommandPool::init(VkDevice device, const VkCommandPoolCreateInfo &createInfo)
{
ASSERT(!valid());
return vkCreateCommandPool(device, &createInfo, nullptr, &mHandle);
}
namespace priv
{
// CommandBuffer implementation.
ANGLE_INLINE VkCommandBuffer CommandBuffer::releaseHandle()
{
VkCommandBuffer handle = mHandle;
mHandle = nullptr;
return handle;
}
ANGLE_INLINE VkResult CommandBuffer::init(VkDevice device,
const VkCommandBufferAllocateInfo &createInfo)
{
ASSERT(!valid());
return vkAllocateCommandBuffers(device, &createInfo, &mHandle);
}
ANGLE_INLINE void CommandBuffer::blitImage(const Image &srcImage,
VkImageLayout srcImageLayout,
const Image &dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageBlit *regions,
VkFilter filter)
{
ASSERT(valid() && srcImage.valid() && dstImage.valid());
ASSERT(regionCount == 1);
vkCmdBlitImage(mHandle, srcImage.getHandle(), srcImageLayout, dstImage.getHandle(),
dstImageLayout, 1, regions, filter);
}
ANGLE_INLINE VkResult CommandBuffer::begin(const VkCommandBufferBeginInfo &info)
{
ASSERT(valid());
return vkBeginCommandBuffer(mHandle, &info);
}
ANGLE_INLINE VkResult CommandBuffer::end()
{
ASSERT(valid());
return vkEndCommandBuffer(mHandle);
}
ANGLE_INLINE VkResult CommandBuffer::reset()
{
ASSERT(valid());
return vkResetCommandBuffer(mHandle, 0);
}
ANGLE_INLINE void CommandBuffer::memoryBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
const VkMemoryBarrier *memoryBarrier)
{
ASSERT(valid());
vkCmdPipelineBarrier(mHandle, srcStageMask, dstStageMask, 0, 1, memoryBarrier, 0, nullptr, 0,
nullptr);
}
ANGLE_INLINE void CommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
VkDependencyFlags dependencyFlags,
uint32_t memoryBarrierCount,
const VkMemoryBarrier *memoryBarriers,
uint32_t bufferMemoryBarrierCount,
const VkBufferMemoryBarrier *bufferMemoryBarriers,
uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier *imageMemoryBarriers)
{
ASSERT(valid());
vkCmdPipelineBarrier(mHandle, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount,
memoryBarriers, bufferMemoryBarrierCount, bufferMemoryBarriers,
imageMemoryBarrierCount, imageMemoryBarriers);
}
ANGLE_INLINE void CommandBuffer::executionBarrier(VkPipelineStageFlags stageMask)
{
ASSERT(valid());
vkCmdPipelineBarrier(mHandle, stageMask, stageMask, 0, 0, nullptr, 0, nullptr, 0, nullptr);
}
ANGLE_INLINE void CommandBuffer::imageBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
const VkImageMemoryBarrier *imageMemoryBarrier)
{
ASSERT(valid());
vkCmdPipelineBarrier(mHandle, srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1,
imageMemoryBarrier);
}
ANGLE_INLINE void CommandBuffer::destroy(VkDevice device)
{
releaseHandle();
}
ANGLE_INLINE void CommandBuffer::destroy(VkDevice device, const vk::CommandPool &commandPool)
{
if (valid())
{
ASSERT(commandPool.valid());
vkFreeCommandBuffers(device, commandPool.getHandle(), 1, &mHandle);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE void CommandBuffer::copyBuffer(const Buffer &srcBuffer,
const Buffer &destBuffer,
uint32_t regionCount,
const VkBufferCopy *regions)
{
ASSERT(valid() && srcBuffer.valid() && destBuffer.valid());
vkCmdCopyBuffer(mHandle, srcBuffer.getHandle(), destBuffer.getHandle(), regionCount, regions);
}
ANGLE_INLINE void CommandBuffer::copyBufferToImage(VkBuffer srcBuffer,
const Image &dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkBufferImageCopy *regions)
{
ASSERT(valid() && dstImage.valid());
ASSERT(srcBuffer != VK_NULL_HANDLE);
ASSERT(regionCount == 1);
vkCmdCopyBufferToImage(mHandle, srcBuffer, dstImage.getHandle(), dstImageLayout, 1, regions);
}
ANGLE_INLINE void CommandBuffer::copyImageToBuffer(const Image &srcImage,
VkImageLayout srcImageLayout,
VkBuffer dstBuffer,
uint32_t regionCount,
const VkBufferImageCopy *regions)
{
ASSERT(valid() && srcImage.valid());
ASSERT(dstBuffer != VK_NULL_HANDLE);
ASSERT(regionCount == 1);
vkCmdCopyImageToBuffer(mHandle, srcImage.getHandle(), srcImageLayout, dstBuffer, 1, regions);
}
ANGLE_INLINE void CommandBuffer::clearColorImage(const Image &image,
VkImageLayout imageLayout,
const VkClearColorValue &color,
uint32_t rangeCount,
const VkImageSubresourceRange *ranges)
{
ASSERT(valid());
ASSERT(rangeCount == 1);
vkCmdClearColorImage(mHandle, image.getHandle(), imageLayout, &color, 1, ranges);
}
ANGLE_INLINE void CommandBuffer::clearDepthStencilImage(
const Image &image,
VkImageLayout imageLayout,
const VkClearDepthStencilValue &depthStencil,
uint32_t rangeCount,
const VkImageSubresourceRange *ranges)
{
ASSERT(valid());
ASSERT(rangeCount == 1);
vkCmdClearDepthStencilImage(mHandle, image.getHandle(), imageLayout, &depthStencil, 1, ranges);
}
ANGLE_INLINE void CommandBuffer::clearAttachments(uint32_t attachmentCount,
const VkClearAttachment *attachments,
uint32_t rectCount,
const VkClearRect *rects)
{
ASSERT(valid());
vkCmdClearAttachments(mHandle, attachmentCount, attachments, rectCount, rects);
}
ANGLE_INLINE void CommandBuffer::copyImage(const Image &srcImage,
VkImageLayout srcImageLayout,
const Image &dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageCopy *regions)
{
ASSERT(valid() && srcImage.valid() && dstImage.valid());
ASSERT(regionCount == 1);
vkCmdCopyImage(mHandle, srcImage.getHandle(), srcImageLayout, dstImage.getHandle(),
dstImageLayout, 1, regions);
}
ANGLE_INLINE void CommandBuffer::beginRenderPass(const VkRenderPassBeginInfo &beginInfo,
VkSubpassContents subpassContents)
{
ASSERT(valid());
vkCmdBeginRenderPass(mHandle, &beginInfo, subpassContents);
}
ANGLE_INLINE void CommandBuffer::endRenderPass()
{
ASSERT(mHandle != VK_NULL_HANDLE);
vkCmdEndRenderPass(mHandle);
}
ANGLE_INLINE void CommandBuffer::bindIndexBuffer(const Buffer &buffer,
VkDeviceSize offset,
VkIndexType indexType)
{
ASSERT(valid());
vkCmdBindIndexBuffer(mHandle, buffer.getHandle(), offset, indexType);
}
ANGLE_INLINE void CommandBuffer::bindDescriptorSets(const PipelineLayout &layout,
VkPipelineBindPoint pipelineBindPoint,
uint32_t firstSet,
uint32_t descriptorSetCount,
const VkDescriptorSet *descriptorSets,
uint32_t dynamicOffsetCount,
const uint32_t *dynamicOffsets)
{
ASSERT(valid() && layout.valid());
vkCmdBindDescriptorSets(mHandle, pipelineBindPoint, layout.getHandle(), firstSet,
descriptorSetCount, descriptorSets, dynamicOffsetCount, dynamicOffsets);
}
ANGLE_INLINE void CommandBuffer::executeCommands(uint32_t commandBufferCount,
const CommandBuffer *commandBuffers)
{
ASSERT(valid());
vkCmdExecuteCommands(mHandle, commandBufferCount, commandBuffers[0].ptr());
}
ANGLE_INLINE void CommandBuffer::getMemoryUsageStats(size_t *usedMemoryOut,
size_t *allocatedMemoryOut) const
{
// No data available.
*usedMemoryOut = 0;
*allocatedMemoryOut = 1;
}
ANGLE_INLINE void CommandBuffer::fillBuffer(const Buffer &dstBuffer,
VkDeviceSize dstOffset,
VkDeviceSize size,
uint32_t data)
{
ASSERT(valid());
vkCmdFillBuffer(mHandle, dstBuffer.getHandle(), dstOffset, size, data);
}
ANGLE_INLINE void CommandBuffer::pushConstants(const PipelineLayout &layout,
VkShaderStageFlags flag,
uint32_t offset,
uint32_t size,
const void *data)
{
ASSERT(valid() && layout.valid());
ASSERT(offset == 0);
vkCmdPushConstants(mHandle, layout.getHandle(), flag, 0, size, data);
}
ANGLE_INLINE void CommandBuffer::setEvent(VkEvent event, VkPipelineStageFlags stageMask)
{
ASSERT(valid() && event != VK_NULL_HANDLE);
vkCmdSetEvent(mHandle, event, stageMask);
}
ANGLE_INLINE void CommandBuffer::resetEvent(VkEvent event, VkPipelineStageFlags stageMask)
{
ASSERT(valid() && event != VK_NULL_HANDLE);
vkCmdResetEvent(mHandle, event, stageMask);
}
ANGLE_INLINE void CommandBuffer::waitEvents(uint32_t eventCount,
const VkEvent *events,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
uint32_t memoryBarrierCount,
const VkMemoryBarrier *memoryBarriers,
uint32_t bufferMemoryBarrierCount,
const VkBufferMemoryBarrier *bufferMemoryBarriers,
uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier *imageMemoryBarriers)
{
ASSERT(valid());
vkCmdWaitEvents(mHandle, eventCount, events, srcStageMask, dstStageMask, memoryBarrierCount,
memoryBarriers, bufferMemoryBarrierCount, bufferMemoryBarriers,
imageMemoryBarrierCount, imageMemoryBarriers);
}
ANGLE_INLINE void CommandBuffer::resetQueryPool(VkQueryPool queryPool,
uint32_t firstQuery,
uint32_t queryCount)
{
ASSERT(valid());
vkCmdResetQueryPool(mHandle, queryPool, firstQuery, queryCount);
}
ANGLE_INLINE void CommandBuffer::resolveImage(const Image &srcImage,
VkImageLayout srcImageLayout,
const Image &dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageResolve *regions)
{
ASSERT(valid() && srcImage.valid() && dstImage.valid());
vkCmdResolveImage(mHandle, srcImage.getHandle(), srcImageLayout, dstImage.getHandle(),
dstImageLayout, regionCount, regions);
}
ANGLE_INLINE void CommandBuffer::beginQuery(VkQueryPool queryPool,
uint32_t query,
VkQueryControlFlags flags)
{
ASSERT(valid());
vkCmdBeginQuery(mHandle, queryPool, query, flags);
}
ANGLE_INLINE void CommandBuffer::endQuery(VkQueryPool queryPool, uint32_t query)
{
ASSERT(valid());
vkCmdEndQuery(mHandle, queryPool, query);
}
ANGLE_INLINE void CommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStage,
VkQueryPool queryPool,
uint32_t query)
{
ASSERT(valid());
vkCmdWriteTimestamp(mHandle, pipelineStage, queryPool, query);
}
ANGLE_INLINE void CommandBuffer::draw(uint32_t vertexCount,
uint32_t instanceCount,
uint32_t firstVertex,
uint32_t firstInstance)
{
ASSERT(valid());
vkCmdDraw(mHandle, vertexCount, instanceCount, firstVertex, firstInstance);
}
ANGLE_INLINE void CommandBuffer::draw(uint32_t vertexCount, uint32_t firstVertex)
{
ASSERT(valid());
vkCmdDraw(mHandle, vertexCount, 1, firstVertex, 0);
}
ANGLE_INLINE void CommandBuffer::drawInstanced(uint32_t vertexCount,
uint32_t instanceCount,
uint32_t firstVertex)
{
ASSERT(valid());
vkCmdDraw(mHandle, vertexCount, instanceCount, firstVertex, 0);
}
ANGLE_INLINE void CommandBuffer::drawInstancedBaseInstance(uint32_t vertexCount,
uint32_t instanceCount,
uint32_t firstVertex,
uint32_t firstInstance)
{
ASSERT(valid());
vkCmdDraw(mHandle, vertexCount, instanceCount, firstVertex, firstInstance);
}
ANGLE_INLINE void CommandBuffer::drawIndexed(uint32_t indexCount,
uint32_t instanceCount,
uint32_t firstIndex,
int32_t vertexOffset,
uint32_t firstInstance)
{
ASSERT(valid());
vkCmdDrawIndexed(mHandle, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
}
ANGLE_INLINE void CommandBuffer::drawIndexed(uint32_t indexCount)
{
ASSERT(valid());
vkCmdDrawIndexed(mHandle, indexCount, 1, 0, 0, 0);
}
ANGLE_INLINE void CommandBuffer::drawIndexedInstanced(uint32_t indexCount, uint32_t instanceCount)
{
ASSERT(valid());
vkCmdDrawIndexed(mHandle, indexCount, instanceCount, 0, 0, 0);
}
ANGLE_INLINE void CommandBuffer::drawIndexedInstancedBaseVertexBaseInstance(uint32_t indexCount,
uint32_t instanceCount,
uint32_t firstIndex,
int32_t vertexOffset,
uint32_t firstInstance)
{
ASSERT(valid());
vkCmdDrawIndexed(mHandle, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
}
ANGLE_INLINE void CommandBuffer::drawIndexedIndirect(const Buffer &buffer,
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride)
{
ASSERT(valid());
vkCmdDrawIndexedIndirect(mHandle, buffer.getHandle(), offset, drawCount, stride);
}
ANGLE_INLINE void CommandBuffer::drawIndirect(const Buffer &buffer,
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride)
{
ASSERT(valid());
vkCmdDrawIndirect(mHandle, buffer.getHandle(), offset, drawCount, stride);
}
ANGLE_INLINE void CommandBuffer::dispatch(uint32_t groupCountX,
uint32_t groupCountY,
uint32_t groupCountZ)
{
ASSERT(valid());
vkCmdDispatch(mHandle, groupCountX, groupCountY, groupCountZ);
}
ANGLE_INLINE void CommandBuffer::dispatchIndirect(const Buffer &buffer, VkDeviceSize offset)
{
ASSERT(valid());
vkCmdDispatchIndirect(mHandle, buffer.getHandle(), offset);
}
ANGLE_INLINE void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint,
const Pipeline &pipeline)
{
ASSERT(valid() && pipeline.valid());
vkCmdBindPipeline(mHandle, pipelineBindPoint, pipeline.getHandle());
}
ANGLE_INLINE void CommandBuffer::bindGraphicsPipeline(const Pipeline &pipeline)
{
ASSERT(valid() && pipeline.valid());
vkCmdBindPipeline(mHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getHandle());
}
ANGLE_INLINE void CommandBuffer::bindComputePipeline(const Pipeline &pipeline)
{
ASSERT(valid() && pipeline.valid());
vkCmdBindPipeline(mHandle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.getHandle());
}
ANGLE_INLINE void CommandBuffer::bindVertexBuffers(uint32_t firstBinding,
uint32_t bindingCount,
const VkBuffer *buffers,
const VkDeviceSize *offsets)
{
ASSERT(valid());
vkCmdBindVertexBuffers(mHandle, firstBinding, bindingCount, buffers, offsets);
}
} // namespace priv
// Image implementation.
ANGLE_INLINE void Image::setHandle(VkImage handle)
{
mHandle = handle;
}
ANGLE_INLINE void Image::reset()
{
mHandle = VK_NULL_HANDLE;
}
ANGLE_INLINE void Image::destroy(VkDevice device)
{
if (valid())
{
vkDestroyImage(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult Image::init(VkDevice device, const VkImageCreateInfo &createInfo)
{
ASSERT(!valid());
return vkCreateImage(device, &createInfo, nullptr, &mHandle);
}
ANGLE_INLINE void Image::getMemoryRequirements(VkDevice device,
VkMemoryRequirements *requirementsOut) const
{
ASSERT(valid());
vkGetImageMemoryRequirements(device, mHandle, requirementsOut);
}
ANGLE_INLINE VkResult Image::bindMemory(VkDevice device, const vk::DeviceMemory &deviceMemory)
{
ASSERT(valid() && deviceMemory.valid());
return vkBindImageMemory(device, mHandle, deviceMemory.getHandle(), 0);
}
ANGLE_INLINE void Image::getSubresourceLayout(VkDevice device,
VkImageAspectFlagBits aspectMask,
uint32_t mipLevel,
uint32_t arrayLayer,
VkSubresourceLayout *outSubresourceLayout) const
{
VkImageSubresource subresource = {};
subresource.aspectMask = aspectMask;
subresource.mipLevel = mipLevel;
subresource.arrayLayer = arrayLayer;
vkGetImageSubresourceLayout(device, getHandle(), &subresource, outSubresourceLayout);
}
// ImageView implementation.
ANGLE_INLINE void ImageView::destroy(VkDevice device)
{
if (valid())
{
vkDestroyImageView(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult ImageView::init(VkDevice device, const VkImageViewCreateInfo &createInfo)
{
return vkCreateImageView(device, &createInfo, nullptr, &mHandle);
}
// Semaphore implementation.
ANGLE_INLINE void Semaphore::destroy(VkDevice device)
{
if (valid())
{
vkDestroySemaphore(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult Semaphore::init(VkDevice device)
{
ASSERT(!valid());
VkSemaphoreCreateInfo semaphoreInfo = {};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
semaphoreInfo.flags = 0;
return vkCreateSemaphore(device, &semaphoreInfo, nullptr, &mHandle);
}
// Framebuffer implementation.
ANGLE_INLINE void Framebuffer::destroy(VkDevice device)
{
if (valid())
{
vkDestroyFramebuffer(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult Framebuffer::init(VkDevice device, const VkFramebufferCreateInfo &createInfo)
{
ASSERT(!valid());
return vkCreateFramebuffer(device, &createInfo, nullptr, &mHandle);
}
ANGLE_INLINE void Framebuffer::setHandle(VkFramebuffer handle)
{
mHandle = handle;
}
// DeviceMemory implementation.
ANGLE_INLINE void DeviceMemory::destroy(VkDevice device)
{
if (valid())
{
vkFreeMemory(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult DeviceMemory::allocate(VkDevice device, const VkMemoryAllocateInfo &allocInfo)
{
ASSERT(!valid());
return vkAllocateMemory(device, &allocInfo, nullptr, &mHandle);
}
ANGLE_INLINE VkResult DeviceMemory::map(VkDevice device,
VkDeviceSize offset,
VkDeviceSize size,
VkMemoryMapFlags flags,
uint8_t **mapPointer) const
{
ASSERT(valid());
return vkMapMemory(device, mHandle, offset, size, flags, reinterpret_cast<void **>(mapPointer));
}
ANGLE_INLINE void DeviceMemory::unmap(VkDevice device) const
{
ASSERT(valid());
vkUnmapMemory(device, mHandle);
}
// RenderPass implementation.
ANGLE_INLINE void RenderPass::destroy(VkDevice device)
{
if (valid())
{
vkDestroyRenderPass(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult RenderPass::init(VkDevice device, const VkRenderPassCreateInfo &createInfo)
{
ASSERT(!valid());
return vkCreateRenderPass(device, &createInfo, nullptr, &mHandle);
}
// Buffer implementation.
ANGLE_INLINE void Buffer::destroy(VkDevice device)
{
if (valid())
{
vkDestroyBuffer(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult Buffer::init(VkDevice device, const VkBufferCreateInfo &createInfo)
{
ASSERT(!valid());
return vkCreateBuffer(device, &createInfo, nullptr, &mHandle);
}
ANGLE_INLINE VkResult Buffer::bindMemory(VkDevice device, const DeviceMemory &deviceMemory)
{
ASSERT(valid() && deviceMemory.valid());
return vkBindBufferMemory(device, mHandle, deviceMemory.getHandle(), 0);
}
ANGLE_INLINE void Buffer::getMemoryRequirements(VkDevice device,
VkMemoryRequirements *memoryRequirementsOut)
{
ASSERT(valid());
vkGetBufferMemoryRequirements(device, mHandle, memoryRequirementsOut);
}
// BufferView implementation.
ANGLE_INLINE void BufferView::destroy(VkDevice device)
{
if (valid())
{
vkDestroyBufferView(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult BufferView::init(VkDevice device, const VkBufferViewCreateInfo &createInfo)
{
ASSERT(!valid());
return vkCreateBufferView(device, &createInfo, nullptr, &mHandle);
}
// ShaderModule implementation.
ANGLE_INLINE void ShaderModule::destroy(VkDevice device)
{
if (mHandle != VK_NULL_HANDLE)
{
vkDestroyShaderModule(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult ShaderModule::init(VkDevice device,
const VkShaderModuleCreateInfo &createInfo)
{
ASSERT(!valid());
return vkCreateShaderModule(device, &createInfo, nullptr, &mHandle);
}
// PipelineLayout implementation.
ANGLE_INLINE void PipelineLayout::destroy(VkDevice device)
{
if (valid())
{
vkDestroyPipelineLayout(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult PipelineLayout::init(VkDevice device,
const VkPipelineLayoutCreateInfo &createInfo)
{
ASSERT(!valid());
return vkCreatePipelineLayout(device, &createInfo, nullptr, &mHandle);
}
// PipelineCache implementation.
ANGLE_INLINE void PipelineCache::destroy(VkDevice device)
{
if (valid())
{
vkDestroyPipelineCache(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult PipelineCache::init(VkDevice device,
const VkPipelineCacheCreateInfo &createInfo)
{
ASSERT(!valid());
// Note: if we are concerned with memory usage of this cache, we should give it custom
// allocators. Also, failure of this function is of little importance.
return vkCreatePipelineCache(device, &createInfo, nullptr, &mHandle);
}
ANGLE_INLINE VkResult PipelineCache::merge(VkDevice device,
VkPipelineCache dstCache,
uint32_t srcCacheCount,
const VkPipelineCache *srcCaches)
{
ASSERT(valid());
return vkMergePipelineCaches(device, dstCache, srcCacheCount, srcCaches);
}
ANGLE_INLINE VkResult PipelineCache::getCacheData(VkDevice device,
size_t *cacheSize,
void *cacheData)
{
ASSERT(valid());
// Note: vkGetPipelineCacheData can return VK_INCOMPLETE if cacheSize is smaller than actual
// size. There are two usages of this function. One is with *cacheSize == 0 to query the size
// of the cache, and one is with an appropriate buffer to retrieve the cache contents.
// VK_INCOMPLETE in the first case is an expected output. In the second case, VK_INCOMPLETE is
// also acceptable and the resulting buffer will contain valid value by spec. Angle currently
// ensures *cacheSize to be either 0 or of enough size, therefore VK_INCOMPLETE is not expected.
return vkGetPipelineCacheData(device, mHandle, cacheSize, cacheData);
}
// Pipeline implementation.
ANGLE_INLINE void Pipeline::destroy(VkDevice device)
{
if (valid())
{
vkDestroyPipeline(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult Pipeline::initGraphics(VkDevice device,
const VkGraphicsPipelineCreateInfo &createInfo,
const PipelineCache &pipelineCacheVk)
{
ASSERT(!valid());
return vkCreateGraphicsPipelines(device, pipelineCacheVk.getHandle(), 1, &createInfo, nullptr,
&mHandle);
}
ANGLE_INLINE VkResult Pipeline::initCompute(VkDevice device,
const VkComputePipelineCreateInfo &createInfo,
const PipelineCache &pipelineCacheVk)
{
ASSERT(!valid());
return vkCreateComputePipelines(device, pipelineCacheVk.getHandle(), 1, &createInfo, nullptr,
&mHandle);
}
// DescriptorSetLayout implementation.
ANGLE_INLINE void DescriptorSetLayout::destroy(VkDevice device)
{
if (valid())
{
vkDestroyDescriptorSetLayout(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult DescriptorSetLayout::init(VkDevice device,
const VkDescriptorSetLayoutCreateInfo &createInfo)
{
ASSERT(!valid());
return vkCreateDescriptorSetLayout(device, &createInfo, nullptr, &mHandle);
}
// DescriptorPool implementation.
ANGLE_INLINE void DescriptorPool::destroy(VkDevice device)
{
if (valid())
{
vkDestroyDescriptorPool(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult DescriptorPool::init(VkDevice device,
const VkDescriptorPoolCreateInfo &createInfo)
{
ASSERT(!valid());
return vkCreateDescriptorPool(device, &createInfo, nullptr, &mHandle);
}
ANGLE_INLINE VkResult
DescriptorPool::allocateDescriptorSets(VkDevice device,
const VkDescriptorSetAllocateInfo &allocInfo,
VkDescriptorSet *descriptorSetsOut)
{
ASSERT(valid());
return vkAllocateDescriptorSets(device, &allocInfo, descriptorSetsOut);
}
ANGLE_INLINE VkResult DescriptorPool::freeDescriptorSets(VkDevice device,
uint32_t descriptorSetCount,
const VkDescriptorSet *descriptorSets)
{
ASSERT(valid());
ASSERT(descriptorSetCount > 0);
return vkFreeDescriptorSets(device, mHandle, descriptorSetCount, descriptorSets);
}
// Sampler implementation.
ANGLE_INLINE void Sampler::destroy(VkDevice device)
{
if (valid())
{
vkDestroySampler(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult Sampler::init(VkDevice device, const VkSamplerCreateInfo &createInfo)
{
ASSERT(!valid());
return vkCreateSampler(device, &createInfo, nullptr, &mHandle);
}
// Event implementation.
ANGLE_INLINE void Event::destroy(VkDevice device)
{
if (valid())
{
vkDestroyEvent(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult Event::init(VkDevice device, const VkEventCreateInfo &createInfo)
{
ASSERT(!valid());
return vkCreateEvent(device, &createInfo, nullptr, &mHandle);
}
ANGLE_INLINE VkResult Event::getStatus(VkDevice device) const
{
ASSERT(valid());
return vkGetEventStatus(device, mHandle);
}
ANGLE_INLINE VkResult Event::set(VkDevice device) const
{
ASSERT(valid());
return vkSetEvent(device, mHandle);
}
ANGLE_INLINE VkResult Event::reset(VkDevice device) const
{
ASSERT(valid());
return vkResetEvent(device, mHandle);
}
// Fence implementation.
ANGLE_INLINE void Fence::destroy(VkDevice device)
{
if (valid())
{
vkDestroyFence(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult Fence::init(VkDevice device, const VkFenceCreateInfo &createInfo)
{
ASSERT(!valid());
return vkCreateFence(device, &createInfo, nullptr, &mHandle);
}
ANGLE_INLINE VkResult Fence::reset(VkDevice device)
{
ASSERT(valid());
return vkResetFences(device, 1, &mHandle);
}
ANGLE_INLINE VkResult Fence::getStatus(VkDevice device) const
{
ASSERT(valid());
return vkGetFenceStatus(device, mHandle);
}
ANGLE_INLINE VkResult Fence::wait(VkDevice device, uint64_t timeout) const
{
ASSERT(valid());
return vkWaitForFences(device, 1, &mHandle, true, timeout);
}
// QueryPool implementation.
ANGLE_INLINE void QueryPool::destroy(VkDevice device)
{
if (valid())
{
vkDestroyQueryPool(device, mHandle, nullptr);
mHandle = VK_NULL_HANDLE;
}
}
ANGLE_INLINE VkResult QueryPool::init(VkDevice device, const VkQueryPoolCreateInfo &createInfo)
{
ASSERT(!valid());
return vkCreateQueryPool(device, &createInfo, nullptr, &mHandle);
}
ANGLE_INLINE VkResult QueryPool::getResults(VkDevice device,
uint32_t firstQuery,
uint32_t queryCount,
size_t dataSize,
void *data,
VkDeviceSize stride,
VkQueryResultFlags flags) const
{
ASSERT(valid());
return vkGetQueryPoolResults(device, mHandle, firstQuery, queryCount, dataSize, data, stride,
flags);
}
} // namespace vk
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_VK_WRAPPER_H_