From: Mikko Rasa Date: Sat, 19 Mar 2022 08:51:40 +0000 (+0200) Subject: Add a wrapper class for recording Vulkan commands X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=d05d9963e185566f03ea348999655037617e4ba9 Add a wrapper class for recording Vulkan commands This makes the command syntax shorter by storing the command buffer handle in the wrapper. --- diff --git a/source/backends/vulkan/buffer_backend.cpp b/source/backends/vulkan/buffer_backend.cpp index c3dcb8e1..bde76bea 100644 --- a/source/backends/vulkan/buffer_backend.cpp +++ b/source/backends/vulkan/buffer_backend.cpp @@ -121,14 +121,12 @@ void Buffer::AsyncTransfer::allocate() [&buf, off, sz](){ buf.device.get_synchronizer().write_buffer(buf.handle, off, sz); }, - [&buf, off, sz](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){ - const VulkanFunctions &vk = buf.device.get_functions(); - + [&buf, off, sz](const VulkanCommandRecorder &vkCmd, VkBuffer staging_buf, size_t src_off){ VkBufferCopy region = { }; region.srcOffset = src_off; region.dstOffset = off; region.size = sz; - vk.CmdCopyBuffer(cmd_buf, staging_buf, buf.handle, 1, ®ion); + vkCmd.CopyBuffer(staging_buf, buf.handle, 1, ®ion); }); } } diff --git a/source/backends/vulkan/commands_backend.cpp b/source/backends/vulkan/commands_backend.cpp index 13acd8a3..2698d431 100644 --- a/source/backends/vulkan/commands_backend.cpp +++ b/source/backends/vulkan/commands_backend.cpp @@ -149,21 +149,22 @@ void VulkanCommands::begin_render_pass(bool clear, const ClearValue *clear_value void VulkanCommands::end_render_pass() { const VulkanFunctions &vk = device.get_functions(); + VulkanCommandRecorder vkCmd(vk, pass_buffer); vk.EndCommandBuffer(pass_buffer); - device.get_transfer_queue().dispatch_transfers(primary_buffer); + device.get_transfer_queue().dispatch_transfers(vkCmd); Synchronizer &sync = device.get_synchronizer(); sync.reset(); if(!fb_is_swapchain) framebuffer->prepare_image_layouts(discard_fb_contents); - sync.barrier(primary_buffer); + sync.barrier(vkCmd); const VkRenderPassBeginInfo &begin_info = *reinterpret_cast(pass_begin_info.data()); - vk.CmdBeginRenderPass(primary_buffer, begin_info, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); - vk.CmdExecuteCommands(primary_buffer, 1, &pass_buffer); - vk.CmdEndRenderPass(primary_buffer); + vkCmd.BeginRenderPass(begin_info, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); + vkCmd.ExecuteCommands(1, &pass_buffer); + vkCmd.EndRenderPass(); framebuffer = 0; viewport = Rect::max(); @@ -253,15 +254,16 @@ void VulkanCommands::draw_instanced(const Batch &batch, unsigned count) throw invalid_operation("VulkanCommands::draw_instanced"); const VulkanFunctions &vk = device.get_functions(); + VulkanCommandRecorder vkCmd(vk, pass_buffer); if(!framebuffer) begin_render_pass(false, 0); pipeline_state->refresh(); - pipeline_state->apply(pass_buffer, last_pipeline, frame_index, fb_is_swapchain); + pipeline_state->apply(vkCmd, last_pipeline, frame_index, fb_is_swapchain); last_pipeline = pipeline_state; unsigned first_index = batch.get_offset()/batch.get_index_size(); - vk.CmdDrawIndexed(pass_buffer, batch.size(), count, first_index, 0, 0); + vkCmd.DrawIndexed(batch.size(), count, first_index, 0, 0); } void VulkanCommands::resolve_multisample(Framebuffer &) diff --git a/source/backends/vulkan/pipelinestate_backend.cpp b/source/backends/vulkan/pipelinestate_backend.cpp index d14bc00c..7deae24c 100644 --- a/source/backends/vulkan/pipelinestate_backend.cpp +++ b/source/backends/vulkan/pipelinestate_backend.cpp @@ -386,10 +386,9 @@ unsigned VulkanPipelineState::fill_descriptor_writes(unsigned index, unsigned fr return n_writes; } -void VulkanPipelineState::apply(VkCommandBuffer command_buffer, const VulkanPipelineState *last, unsigned frame, bool negative_viewport) const +void VulkanPipelineState::apply(const VulkanCommandRecorder &vkCmd, const VulkanPipelineState *last, unsigned frame, bool negative_viewport) const { const PipelineState &self = *static_cast(this); - const VulkanFunctions &vk = device.get_functions(); if(!last) { @@ -424,14 +423,14 @@ void VulkanPipelineState::apply(VkCommandBuffer command_buffer, const VulkanPipe } if(unapplied&PipelineState::SHPROG) - vk.CmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, handle); + vkCmd.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, handle); if(unapplied&PipelineState::VERTEX_SETUP) if(const VertexSetup *vs = self.vertex_setup) { - vk.CmdBindVertexBuffers(command_buffer, 0, vs->n_bindings, vs->buffers, vs->offsets); + vkCmd.BindVertexBuffers(0, vs->n_bindings, vs->buffers, vs->offsets); VkIndexType index_type = static_cast(get_vulkan_index_type(vs->get_index_type())); - vk.CmdBindIndexBuffer(command_buffer, vs->get_index_buffer()->handle, 0, index_type); + vkCmd.BindIndexBuffer(vs->get_index_buffer()->handle, 0, index_type); } if(!self.uniform_blocks.empty()) @@ -440,7 +439,7 @@ void VulkanPipelineState::apply(VkCommandBuffer command_buffer, const VulkanPipe if(first_block.used && first_block.binding==ReflectData::PUSH_CONSTANT) { const UniformBlock &pc_block = *first_block.block; - vk.CmdPushConstants(command_buffer, self.shprog->layout_handle, self.shprog->stage_flags, + vkCmd.PushConstants(self.shprog->layout_handle, self.shprog->stage_flags, pc_block.get_offset(), pc_block.get_data_size(), pc_block.get_data_pointer()); } } @@ -453,7 +452,7 @@ void VulkanPipelineState::apply(VkCommandBuffer command_buffer, const VulkanPipe descriptor_set_handles.push_back(device.get_descriptor_pool().get_descriptor_set( self.descriptor_set_slots[i], self, i, frame)); - vk.CmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, self.shprog->layout_handle, + vkCmd.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, self.shprog->layout_handle, first_changed_desc_set, descriptor_set_handles.size(), descriptor_set_handles.data(), 0, 0); } @@ -476,7 +475,7 @@ void VulkanPipelineState::apply(VkCommandBuffer command_buffer, const VulkanPipe } viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; - vk.CmdSetViewport(command_buffer, 0, 1, &viewport); + vkCmd.SetViewport(0, 1, &viewport); } if(unapplied&PipelineState::SCISSOR) @@ -487,7 +486,7 @@ void VulkanPipelineState::apply(VkCommandBuffer command_buffer, const VulkanPipe scissor.offset.y = scissor_rect.bottom; scissor.extent.width = scissor_rect.width; scissor.extent.height = scissor_rect.height; - vk.CmdSetScissor(command_buffer, 0, 1, &scissor); + vkCmd.SetScissor(0, 1, &scissor); } } diff --git a/source/backends/vulkan/pipelinestate_backend.h b/source/backends/vulkan/pipelinestate_backend.h index d033fbb8..892d8b3a 100644 --- a/source/backends/vulkan/pipelinestate_backend.h +++ b/source/backends/vulkan/pipelinestate_backend.h @@ -8,6 +8,7 @@ namespace Msp { namespace GL { class Device; +class VulkanCommandRecorder; class VulkanPipelineState: public NonCopyable { @@ -38,7 +39,7 @@ protected: VkDescriptorSetLayout get_descriptor_set_layout(unsigned) const; unsigned fill_descriptor_writes(unsigned, unsigned, std::vector &) const; - void apply(VkCommandBuffer, const VulkanPipelineState *, unsigned, bool) const; + void apply(const VulkanCommandRecorder &, const VulkanPipelineState *, unsigned, bool) const; }; using PipelineStateBackend = VulkanPipelineState; diff --git a/source/backends/vulkan/synchronizer.cpp b/source/backends/vulkan/synchronizer.cpp index 9995f248..28488fd0 100644 --- a/source/backends/vulkan/synchronizer.cpp +++ b/source/backends/vulkan/synchronizer.cpp @@ -121,10 +121,8 @@ void Synchronizer::reset() i.pending_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } -void Synchronizer::barrier(VkCommandBuffer command_buffer) +void Synchronizer::barrier(const VulkanCommandRecorder &vkCmd) { - const VulkanFunctions &vk = device.get_functions(); - if(buffer_accesses.empty() && image_accesses.empty()) return; @@ -201,7 +199,7 @@ void Synchronizer::barrier(VkCommandBuffer command_buffer) if(!dst_stage) dst_stage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - vk.CmdPipelineBarrier(command_buffer, src_stage, dst_stage, 0, 0, 0, + vkCmd.PipelineBarrier(src_stage, dst_stage, 0, 0, 0, buffer_barriers.size(), buffer_barriers.data(), image_barriers.size(), image_barriers.data()); for(auto i=buffer_accesses.begin(); i!=buffer_accesses.end(); ) diff --git a/source/backends/vulkan/synchronizer.h b/source/backends/vulkan/synchronizer.h index 077274f8..32a4d979 100644 --- a/source/backends/vulkan/synchronizer.h +++ b/source/backends/vulkan/synchronizer.h @@ -8,6 +8,8 @@ namespace Msp { namespace GL { +class VulkanCommandRecorder; + class Synchronizer { private: @@ -40,7 +42,7 @@ public: void split_image_mipmap(VkImage, unsigned, unsigned); void change_image_layout(VkImage, unsigned, int, unsigned, bool); void reset(); - void barrier(VkCommandBuffer); + void barrier(const VulkanCommandRecorder &); private: bool is_write_layout(unsigned); diff --git a/source/backends/vulkan/texture1d_backend.cpp b/source/backends/vulkan/texture1d_backend.cpp index 539060da..59ef60d0 100644 --- a/source/backends/vulkan/texture1d_backend.cpp +++ b/source/backends/vulkan/texture1d_backend.cpp @@ -34,9 +34,7 @@ void VulkanTexture1D::sub_image(unsigned level, int x, unsigned wd, const void * [this, level, discard](){ change_layout(level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard); }, - [this, level, x, wd](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){ - const VulkanFunctions &vk = device.get_functions(); - + [this, level, x, wd](const VulkanCommandRecorder &vkCmd, VkBuffer staging_buf, size_t src_off){ VkBufferImageCopy region = { }; region.bufferOffset = src_off; region.imageSubresource.aspectMask = get_vulkan_aspect(get_components(storage_fmt)); @@ -45,7 +43,7 @@ void VulkanTexture1D::sub_image(unsigned level, int x, unsigned wd, const void * region.imageSubresource.layerCount = 1; region.imageOffset = { x, 0, 0 }; region.imageExtent = { wd, 1, 1 }; - vk.CmdCopyBufferToImage(cmd_buf, staging_buf, handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + vkCmd.CopyBufferToImage(staging_buf, handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); }); stage_pixels(staging, data, wd); diff --git a/source/backends/vulkan/texture2d_backend.cpp b/source/backends/vulkan/texture2d_backend.cpp index 1ab49b88..d1bb74f5 100644 --- a/source/backends/vulkan/texture2d_backend.cpp +++ b/source/backends/vulkan/texture2d_backend.cpp @@ -69,9 +69,7 @@ void *VulkanTexture2D::AsyncTransfer::allocate() [&tex, level, discard](){ tex.change_layout(level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard); }, - [&tex, level, x, y, wd, ht](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){ - const VulkanFunctions &vk = tex.device.get_functions(); - + [&tex, level, x, y, wd, ht](const VulkanCommandRecorder &vkCmd, VkBuffer staging_buf, size_t src_off){ VkBufferImageCopy region = { }; region.bufferOffset = src_off; region.imageSubresource.aspectMask = get_vulkan_aspect(get_components(tex.storage_fmt)); @@ -80,7 +78,7 @@ void *VulkanTexture2D::AsyncTransfer::allocate() region.imageSubresource.layerCount = 1; region.imageOffset = { x, y, 0 }; region.imageExtent = { wd, ht, 1 }; - vk.CmdCopyBufferToImage(cmd_buf, staging_buf, tex.handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + vkCmd.CopyBufferToImage(staging_buf, tex.handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); }); } diff --git a/source/backends/vulkan/texture3d_backend.cpp b/source/backends/vulkan/texture3d_backend.cpp index 67adb8d1..d2180556 100644 --- a/source/backends/vulkan/texture3d_backend.cpp +++ b/source/backends/vulkan/texture3d_backend.cpp @@ -40,9 +40,7 @@ void VulkanTexture3D::sub_image(unsigned level, int x, int y, int z, unsigned wd [this, level, discard](){ change_layout(level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard); }, - [this, level, x, y, z, wd, ht, dp](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){ - const VulkanFunctions &vk = device.get_functions(); - + [this, level, x, y, z, wd, ht, dp](const VulkanCommandRecorder &vkCmd, VkBuffer staging_buf, size_t src_off){ VkBufferImageCopy region = { }; region.bufferOffset = src_off; region.imageSubresource.aspectMask = get_vulkan_aspect(get_components(storage_fmt)); @@ -51,7 +49,7 @@ void VulkanTexture3D::sub_image(unsigned level, int x, int y, int z, unsigned wd region.imageSubresource.layerCount = (is_array() ? dp : 1); region.imageOffset = { x, y, (is_array() ? 0 : z) }; region.imageExtent = { wd, ht, (is_array() ? 1 : dp) }; - vk.CmdCopyBufferToImage(cmd_buf, staging_buf, handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + vkCmd.CopyBufferToImage(staging_buf, handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); }); stage_pixels(staging, data, wd*ht*dp); diff --git a/source/backends/vulkan/texture_backend.cpp b/source/backends/vulkan/texture_backend.cpp index bf269217..5b737498 100644 --- a/source/backends/vulkan/texture_backend.cpp +++ b/source/backends/vulkan/texture_backend.cpp @@ -146,9 +146,8 @@ void VulkanTexture::generate_mipmap() change_layout(i, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false); change_layout(i+1, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); }, - [this, i](VkCommandBuffer cmd_buf, VkBuffer, size_t){ + [this, i](const VulkanCommandRecorder &vkCmd, VkBuffer, size_t){ const Texture &self = *static_cast(this); - const VulkanFunctions &vk = device.get_functions(); VkImageBlit region = { }; region.srcSubresource.aspectMask = get_vulkan_aspect(get_components(self.storage_fmt)); @@ -160,7 +159,7 @@ void VulkanTexture::generate_mipmap() fill_mipmap_blit(i, ®ion); - vk.CmdBlitImage(cmd_buf, handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + vkCmd.BlitImage(handle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion, VK_FILTER_LINEAR); }); } diff --git a/source/backends/vulkan/texturecube_backend.cpp b/source/backends/vulkan/texturecube_backend.cpp index a92247d5..f0b941bf 100644 --- a/source/backends/vulkan/texturecube_backend.cpp +++ b/source/backends/vulkan/texturecube_backend.cpp @@ -37,9 +37,7 @@ void VulkanTextureCube::sub_image(unsigned face, unsigned level, int x, int y, u [this, level, discard](){ change_layout(level, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, discard); }, - [this, face, level, x, y, wd, ht](VkCommandBuffer cmd_buf, VkBuffer staging_buf, size_t src_off){ - const VulkanFunctions &vk = device.get_functions(); - + [this, face, level, x, y, wd, ht](const VulkanCommandRecorder &vkCmd, VkBuffer staging_buf, size_t src_off){ VkBufferImageCopy region = { }; region.bufferOffset = src_off; region.imageSubresource.aspectMask = get_vulkan_aspect(get_components(storage_fmt)); @@ -48,7 +46,7 @@ void VulkanTextureCube::sub_image(unsigned face, unsigned level, int x, int y, u region.imageSubresource.layerCount = 1; region.imageOffset = { x, y, 0 }; region.imageExtent = { wd, ht, 1 }; - vk.CmdCopyBufferToImage(cmd_buf, staging_buf, handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + vkCmd.CopyBufferToImage(staging_buf, handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); }); stage_pixels(staging, data, wd*ht); diff --git a/source/backends/vulkan/transferqueue.cpp b/source/backends/vulkan/transferqueue.cpp index f6f3c6f5..5419245b 100644 --- a/source/backends/vulkan/transferqueue.cpp +++ b/source/backends/vulkan/transferqueue.cpp @@ -78,7 +78,7 @@ TransferQueue::PendingTransfer &TransferQueue::insert_transfer(PendingTransfer & return *j; } -void TransferQueue::dispatch_transfers(VkCommandBuffer command_buffer) +void TransferQueue::dispatch_transfers(const VulkanCommandRecorder &vkCmd) { if(transfers.empty()) return; @@ -90,12 +90,12 @@ void TransferQueue::dispatch_transfers(VkCommandBuffer command_buffer) for(; (j!=transfers.end() && j->order==i->order); ++j) j->synchronize(); - device.get_synchronizer().barrier(command_buffer); + device.get_synchronizer().barrier(vkCmd); for(; i!=j; ++i) { VkBuffer buffer = (i->buffer_index>=0 ? buffers[i->buffer_index].buffer : 0); - i->transfer(command_buffer, buffer, i->offset); + i->transfer(vkCmd, buffer, i->offset); if(i->buffer_index>=0) buffers[i->buffer_index].last_frame = current_frame; } diff --git a/source/backends/vulkan/transferqueue.h b/source/backends/vulkan/transferqueue.h index e78137fc..536edbd8 100644 --- a/source/backends/vulkan/transferqueue.h +++ b/source/backends/vulkan/transferqueue.h @@ -10,6 +10,7 @@ namespace GL { class Buffer; class Device; +class VulkanCommandRecorder; class TransferQueue { @@ -39,7 +40,7 @@ private: std::size_t size = 0; void *staging_address = 0; std::function synchronize; - std::function transfer; + std::function transfer; }; Device &device; @@ -68,7 +69,7 @@ private: PendingTransfer &insert_transfer(PendingTransfer &&); public: - void dispatch_transfers(VkCommandBuffer); + void dispatch_transfers(const VulkanCommandRecorder &); }; template diff --git a/source/backends/vulkan/vulkan.h b/source/backends/vulkan/vulkan.h index c41813fa..d77e2cc4 100644 --- a/source/backends/vulkan/vulkan.h +++ b/source/backends/vulkan/vulkan.h @@ -417,6 +417,61 @@ public: { return { vkSetDebugUtilsObjectName(device, &rNameInfo), "vkSetDebugUtilsObjectName" }; } }; +class VulkanCommandRecorder +{ +private: + const VulkanFunctions &vk; + VkCommandBuffer commandBuffer; + +public: + VulkanCommandRecorder(const VulkanFunctions &v, VkCommandBuffer b): vk(v), commandBuffer(b) { } + + void ExecuteCommands(std::uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers) const + { vk.CmdExecuteCommands(commandBuffer, commandBufferCount, pCommandBuffers); } + + void PipelineBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) const + { vk.CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); } + + void BeginRenderPass(const VkRenderPassBeginInfo &rRenderPassBegin, VkSubpassContents contents) const + { vk.CmdBeginRenderPass(commandBuffer, rRenderPassBegin, contents); } + + void EndRenderPass() const + { vk.CmdEndRenderPass(commandBuffer); } + + void BindPipeline(VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) const + { vk.CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline); } + + void BindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, std::uint32_t firstSet, std::uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets, std::uint32_t dynamicOffsetCount, const std::uint32_t *pDynamicOffsets) const + { vk.CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets); } + + void PushConstants(VkPipelineLayout layout, VkShaderStageFlags stageFlags, std::uint32_t offset, std::uint32_t size, const void *pValues) const + { vk.CmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues); } + + void CopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, std::uint32_t regionCount, const VkBufferCopy *pRegions) const + { vk.CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions); } + + void CopyBufferToImage(VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, std::uint32_t regionCount, const VkBufferImageCopy *pRegions) const + { vk.CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions); } + + void BlitImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit *pRegions, VkFilter filter) const + { vk.CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter); } + + void BindIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) const + { vk.CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType); } + + void DrawIndexed(std::uint32_t indexCount, std::uint32_t instanceCount, std::uint32_t firstIndex, std::int32_t vertexOffset, std::uint32_t firstInstance) const + { vk.CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); } + + void BindVertexBuffers(std::uint32_t firstBinding, std::uint32_t bindingCount, const VkBuffer *pBuffers, const VkDeviceSize *pOffsets) const + { vk.CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets); } + + void SetViewport(std::uint32_t firstViewport, std::uint32_t viewportCount, const VkViewport *pViewports) const + { vk.CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports); } + + void SetScissor(std::uint32_t firstScissor, std::uint32_t scissorCount, const VkRect2D *pScissors) const + { vk.CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors); } +}; + } // namespace GL } // namespace Msp