refactor(cleanup): reuse command buffers and semaphores

This commit is contained in:
PancakeTAS 2025-12-20 23:27:40 +01:00
parent 55c5c903af
commit 0e65c9881f
7 changed files with 40 additions and 30 deletions

View file

@ -98,7 +98,7 @@ namespace lsfgvk {
size_t idx{1};
size_t fidx{0}; // real frame index
std::vector<vk::CommandBuffer> cmdbufs; // TODO: ponder reuse
std::vector<vk::CommandBuffer> cmdbufs;
vk::Fence cmdbufFence;
ls::Ctx ctx;
@ -510,7 +510,9 @@ ContextImpl::ContextImpl(const InstanceImpl& instance,
}
const vk::CommandBuffer cmdbuf{ctx.vk};
cmdbuf.begin(ctx.vk);
cmdbuf.insertBarriers(ctx.vk, barriers);
cmdbuf.end(ctx.vk);
cmdbuf.submit(ctx.vk); // wait for completion
}
@ -545,8 +547,8 @@ void Context::scheduleFrames() {
this->cmdbufFence.reset(this->ctx.vk);
// schedule pre-pass
vk::CommandBuffer& cmdbuf = this->cmdbufs.at(0);
cmdbuf = vk::CommandBuffer(this->ctx.vk);
const auto& cmdbuf = this->cmdbufs.at(0);
cmdbuf.begin(ctx.vk);
this->mipmaps.render(ctx.vk, cmdbuf, this->fidx);
for (size_t i = 0; i < 7; ++i) {
@ -556,6 +558,7 @@ void Context::scheduleFrames() {
this->beta0.render(ctx.vk, cmdbuf, this->fidx);
this->beta1.render(ctx.vk, cmdbuf);
cmdbuf.end(ctx.vk);
cmdbuf.submit(this->ctx.vk,
{}, this->syncSemaphore.handle(), this->idx,
{}, this->prepassSemaphore.handle(), this->idx
@ -565,8 +568,8 @@ void Context::scheduleFrames() {
// schedule main passes
for (size_t i = 0; i < this->destImages.size(); i++) {
vk::CommandBuffer& cmdbuf = this->cmdbufs.at(i + 1);
cmdbuf = vk::CommandBuffer(this->ctx.vk);
const auto& cmdbuf = this->cmdbufs.at(i + 1);
cmdbuf.begin(ctx.vk);
const auto& pass = this->passes.at(i);
for (size_t j = 0; j < 7; j++) {
@ -579,6 +582,7 @@ void Context::scheduleFrames() {
}
pass.generate->render(ctx.vk, cmdbuf, this->fidx);
cmdbuf.end(ctx.vk);
cmdbuf.submit(this->ctx.vk,
{}, this->prepassSemaphore.handle(), this->idx - 1,
{}, this->syncSemaphore.handle(), this->idx + i,

View file

@ -25,6 +25,11 @@ namespace vk {
/// @throws ls::vulkan_error on failure
CommandBuffer(const vk::Vulkan& vk);
/// begin recording commands
/// @param vk the vulkan instance
/// @throws ls::vulkan_error on failure
void begin(const vk::Vulkan& vk) const;
/// blit an image
/// @param vk the vulkan instance
/// @param preBarriers image memory barriers to apply before blit
@ -63,6 +68,11 @@ namespace vk {
void copyBufferToImage(const vk::Vulkan& vk,
const vk::Buffer& buffer, const vk::Image& image) const;
/// end recording commands
/// @param vk the vulkan instance
/// @throws ls::vulkan_error on failure
void end(const vk::Vulkan& vk) const;
/// submit the command buffer
/// @param vk the vulkan instance
/// @param waitSemaphores the semaphores to wait on

View file

@ -51,8 +51,9 @@ namespace {
}
CommandBuffer::CommandBuffer(const vk::Vulkan& vk)
: commandBuffer(createCommandBuffer(vk)) {
: commandBuffer(createCommandBuffer(vk)) {}
void CommandBuffer::begin(const vk::Vulkan& vk) const {
const VkCommandBufferBeginInfo beginInfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
@ -62,7 +63,6 @@ CommandBuffer::CommandBuffer(const vk::Vulkan& vk)
throw ls::vulkan_error(res, "vkBeginCommandBuffer() failed");
}
void CommandBuffer::insertBarriers(const vk::Vulkan& vk,
const std::vector<vk::Barrier>& barriers) const {
vk.df().CmdPipelineBarrier(*this->commandBuffer,
@ -189,16 +189,18 @@ void CommandBuffer::copyBufferToImage(const vk::Vulkan& vk,
);
}
void CommandBuffer::end(const vk::Vulkan& vk) const {
auto res = vk.df().EndCommandBuffer(*this->commandBuffer);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkEndCommandBuffer() failed");
}
void CommandBuffer::submit(const vk::Vulkan& vk,
std::vector<VkSemaphore> waitSemaphores,
VkSemaphore waitTimelineSemaphore, uint64_t waitValue,
std::vector<VkSemaphore> signalSemaphores,
VkSemaphore signalTimelineSemaphore, uint64_t signalValue,
VkFence fence) const {
auto res = vk.df().EndCommandBuffer(*this->commandBuffer);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkEndCommandBuffer() failed");
// create arrays of semaphores and values
if (waitTimelineSemaphore)
waitSemaphores.push_back(waitTimelineSemaphore);
@ -233,23 +235,20 @@ void CommandBuffer::submit(const vk::Vulkan& vk,
.signalSemaphoreCount = static_cast<uint32_t>(signalSemaphores.size()),
.pSignalSemaphores = signalSemaphores.data()
};
res = vk.df().QueueSubmit(vk.queue(), 1, &submitInfo, fence);
auto res = vk.df().QueueSubmit(vk.queue(), 1, &submitInfo, fence);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkQueueSubmit() failed");
}
void CommandBuffer::submit(const vk::Vulkan& vk) const {
auto res = vk.df().EndCommandBuffer(*this->commandBuffer);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkEndCommandBuffer() failed");
void CommandBuffer::submit(const vk::Vulkan& vk) const {
const VkSubmitInfo submitInfo{
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.commandBufferCount = 1,
.pCommandBuffers = &*this->commandBuffer
};
const vk::Fence fence{vk};
res = vk.df().QueueSubmit(vk.queue(), 1, &submitInfo, fence.handle());
auto res = vk.df().QueueSubmit(vk.queue(), 1, &submitInfo, fence.handle());
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkQueueSubmit() failed");

View file

@ -223,6 +223,7 @@ namespace {
const VkCommandPoolCreateInfo cmdpoolInfo{
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
.queueFamilyIndex = cfi
};
auto res = fd.CreateCommandPool(device, &cmdpoolInfo, nullptr, &handle);

View file

@ -60,7 +60,9 @@ namespace {
VK_BUFFER_USAGE_TRANSFER_SRC_BIT};
const vk::CommandBuffer cmdbuf{vk};
cmdbuf.begin(vk);
cmdbuf.copyBufferToImage(vk, stagingbuf, image);
cmdbuf.end(vk);
const vk::TimelineSemaphore sema{vk, 0};
cmdbuf.submit(vk);

View file

@ -152,7 +152,8 @@ VkResult Swapchain::present(const vk::Vulkan& vk,
this->renderFence->reset(vk);
// copy swapchain image into backend source image
auto& cmdbuf = this->renderCommandBuffer.emplace(vk);
const auto& cmdbuf = *this->renderCommandBuffer;
cmdbuf.begin(vk);
cmdbuf.blitImage(vk,
{
@ -181,24 +182,16 @@ VkResult Swapchain::present(const vk::Vulkan& vk,
}
);
cmdbuf.end(vk);
cmdbuf.submit(vk,
semaphores, nullptr, 0,
{}, this->syncSemaphore->handle(), this->idx++
);
for (size_t i = 0; i < this->destinationImages.size(); i++) {
auto& postCopySemaphores = this->postCopySemaphores.at(this->idx % this->postCopySemaphores.size());
auto& destinationImage = this->destinationImages.at(i);
auto& pass = this->passes.at(i);
pass = RenderPass {
.commandBuffer = vk::CommandBuffer(vk),
.acquireSemaphore = vk::Semaphore(vk)
};
auto& postCopySemaphores = this->postCopySemaphores.at(this->idx % this->postCopySemaphores.size());
postCopySemaphores = {
vk::Semaphore(vk),
vk::Semaphore(vk)
};
// acquire swapchain image
uint32_t aqImageIdx{};
@ -214,6 +207,7 @@ VkResult Swapchain::present(const vk::Vulkan& vk,
// copy backend destination image into swapchain image
auto& cmdbuf = pass.commandBuffer;
cmdbuf.begin(vk);
cmdbuf.blitImage(vk,
{
@ -253,6 +247,7 @@ VkResult Swapchain::present(const vk::Vulkan& vk,
postCopySemaphores.second.handle()
};
cmdbuf.end(vk);
cmdbuf.submit(vk,
waitSemaphores, this->syncSemaphore->handle(), this->idx,
signalSemaphores, nullptr, 0,

View file

@ -11,7 +11,6 @@
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <cstdint>
#include <optional>
#include <utility>
#include <vector>
@ -62,7 +61,7 @@ namespace lsfgvk::layer {
std::vector<vk::Image> destinationImages;
ls::lazy<vk::TimelineSemaphore> syncSemaphore;
std::optional<vk::CommandBuffer> renderCommandBuffer;
ls::lazy<vk::CommandBuffer> renderCommandBuffer;
ls::lazy<vk::Fence> renderFence;
struct RenderPass {
vk::CommandBuffer commandBuffer;