[&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);
});
}
}
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<const VkRenderPassBeginInfo *>(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();
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 &)
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<const PipelineState *>(this);
- const VulkanFunctions &vk = device.get_functions();
if(!last)
{
}
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<VkIndexType>(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())
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());
}
}
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);
}
}
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
- vk.CmdSetViewport(command_buffer, 0, 1, &viewport);
+ vkCmd.SetViewport(0, 1, &viewport);
}
if(unapplied&PipelineState::SCISSOR)
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);
}
}
namespace GL {
class Device;
+class VulkanCommandRecorder;
class VulkanPipelineState: public NonCopyable
{
VkDescriptorSetLayout get_descriptor_set_layout(unsigned) const;
unsigned fill_descriptor_writes(unsigned, unsigned, std::vector<char> &) const;
- void apply(VkCommandBuffer, const VulkanPipelineState *, unsigned, bool) const;
+ void apply(const VulkanCommandRecorder &, const VulkanPipelineState *, unsigned, bool) const;
};
using PipelineStateBackend = VulkanPipelineState;
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;
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(); )
namespace Msp {
namespace GL {
+class VulkanCommandRecorder;
+
class Synchronizer
{
private:
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);
[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));
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);
[&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));
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);
});
}
[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));
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);
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<const Texture *>(this);
- const VulkanFunctions &vk = device.get_functions();
VkImageBlit region = { };
region.srcSubresource.aspectMask = get_vulkan_aspect(get_components(self.storage_fmt));
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);
});
}
[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));
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);
return *j;
}
-void TransferQueue::dispatch_transfers(VkCommandBuffer command_buffer)
+void TransferQueue::dispatch_transfers(const VulkanCommandRecorder &vkCmd)
{
if(transfers.empty())
return;
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;
}
class Buffer;
class Device;
+class VulkanCommandRecorder;
class TransferQueue
{
std::size_t size = 0;
void *staging_address = 0;
std::function<void()> synchronize;
- std::function<void(VkCommandBuffer, VkBuffer, std::size_t)> transfer;
+ std::function<void(const VulkanCommandRecorder &, VkBuffer, std::size_t)> transfer;
};
Device &device;
PendingTransfer &insert_transfer(PendingTransfer &&);
public:
- void dispatch_transfers(VkCommandBuffer);
+ void dispatch_transfers(const VulkanCommandRecorder &);
};
template<typename S, typename T>
{ 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