mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2025-10-30 07:01:10 +00:00
is it done?
This commit is contained in:
parent
ad0fd6eb77
commit
a7df89824c
11 changed files with 253 additions and 47 deletions
|
|
@ -1,10 +1,12 @@
|
||||||
#ifndef APPLICATION_HPP
|
#ifndef APPLICATION_HPP
|
||||||
#define APPLICATION_HPP
|
#define APPLICATION_HPP
|
||||||
|
|
||||||
|
#include "mini/commandbuffer.hpp"
|
||||||
#include "mini/commandpool.hpp"
|
#include "mini/commandpool.hpp"
|
||||||
#include "mini/image.hpp"
|
#include "mini/image.hpp"
|
||||||
#include "mini/semaphore.hpp"
|
#include "mini/semaphore.hpp"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <optional>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -148,14 +150,18 @@ private:
|
||||||
|
|
||||||
// (owned resources)
|
// (owned resources)
|
||||||
Mini::CommandPool cmdPool;
|
Mini::CommandPool cmdPool;
|
||||||
std::array<Mini::Semaphore, 8> copySemaphores; // copy current swap to frame
|
std::array<Mini::CommandBuffer, 8> cmdBufs1;
|
||||||
|
std::array<Mini::CommandBuffer, 8> cmdBufs2;
|
||||||
|
std::array<Mini::Semaphore, 8> copySemaphores1; // copy current swap to frame
|
||||||
|
std::array<Mini::Semaphore, 8> copySemaphores2; // (for present)
|
||||||
std::array<Mini::Semaphore, 8> acquireSemaphores; // acquire new swapchain image
|
std::array<Mini::Semaphore, 8> acquireSemaphores; // acquire new swapchain image
|
||||||
std::array<Mini::Semaphore, 8> renderSemaphores; // fg is done
|
std::array<Mini::Semaphore, 8> renderSemaphores; // fg is done
|
||||||
std::array<Mini::Semaphore, 8> presentSemaphores; // copy is done, ready to present
|
std::array<Mini::Semaphore, 8> presentSemaphores; // copy is done, ready to present
|
||||||
|
|
||||||
Mini::Image frame_0, frame_1;
|
Mini::Image frame_0, frame_1, out_img;
|
||||||
std::shared_ptr<int32_t> lsfgId;
|
std::shared_ptr<int32_t> lsfgId;
|
||||||
uint64_t frameIdx{0};
|
uint64_t frameIdx{0};
|
||||||
|
std::optional<uint32_t> deferredIdx; // index of the frame to present next
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // APPLICATION_HPP
|
#endif // APPLICATION_HPP
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,8 @@ namespace Mini {
|
||||||
/// @throws LSFG::vulkan_error if submission fails.
|
/// @throws LSFG::vulkan_error if submission fails.
|
||||||
///
|
///
|
||||||
void submit(VkQueue queue,
|
void submit(VkQueue queue,
|
||||||
const std::vector<Semaphore>& waitSemaphores = {},
|
const std::vector<VkSemaphore>& waitSemaphores = {},
|
||||||
const std::vector<Semaphore>& signalSemaphores = {});
|
const std::vector<VkSemaphore>& signalSemaphores = {});
|
||||||
|
|
||||||
/// Get the state of the command buffer.
|
/// Get the state of the command buffer.
|
||||||
[[nodiscard]] CommandBufferState getState() const { return *this->state; }
|
[[nodiscard]] CommandBufferState getState() const { return *this->state; }
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
#ifndef CONTEXT_HPP
|
#ifndef CONTEXT_HPP
|
||||||
#define CONTEXT_HPP
|
#define CONTEXT_HPP
|
||||||
|
|
||||||
|
#include "core/commandbuffer.hpp"
|
||||||
#include "core/commandpool.hpp"
|
#include "core/commandpool.hpp"
|
||||||
#include "core/descriptorpool.hpp"
|
#include "core/descriptorpool.hpp"
|
||||||
#include "core/image.hpp"
|
#include "core/image.hpp"
|
||||||
|
#include "core/semaphore.hpp"
|
||||||
#include "shaderchains/alpha.hpp"
|
#include "shaderchains/alpha.hpp"
|
||||||
#include "shaderchains/beta.hpp"
|
#include "shaderchains/beta.hpp"
|
||||||
#include "shaderchains/delta.hpp"
|
#include "shaderchains/delta.hpp"
|
||||||
|
|
@ -30,10 +32,11 @@ namespace LSFG {
|
||||||
/// @param height Height of the input images.
|
/// @param height Height of the input images.
|
||||||
/// @param in0 File descriptor for the first input image.
|
/// @param in0 File descriptor for the first input image.
|
||||||
/// @param in1 File descriptor for the second input image.
|
/// @param in1 File descriptor for the second input image.
|
||||||
|
/// @param out File descriptor for the output image.
|
||||||
///
|
///
|
||||||
/// @throws LSFG::vulkan_error if the generator fails to initialize.
|
/// @throws LSFG::vulkan_error if the generator fails to initialize.
|
||||||
///
|
///
|
||||||
Context(const Core::Device& device, uint32_t width, uint32_t height, int in0, int in1);
|
Context(const Core::Device& device, uint32_t width, uint32_t height, int in0, int in1, int out);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Schedule the next generation.
|
/// Schedule the next generation.
|
||||||
|
|
@ -57,6 +60,9 @@ namespace LSFG {
|
||||||
Core::CommandPool cmdPool;
|
Core::CommandPool cmdPool;
|
||||||
|
|
||||||
Core::Image inImg_0, inImg_1; // inImg_0 is next (inImg_1 prev) when fc % 2 == 0
|
Core::Image inImg_0, inImg_1; // inImg_0 is next (inImg_1 prev) when fc % 2 == 0
|
||||||
|
std::array<Core::Semaphore, 8> inSemaphores;
|
||||||
|
std::array<Core::Semaphore, 8> outSemaphores;
|
||||||
|
std::array<Core::CommandBuffer, 8> cmdBuffers;
|
||||||
uint64_t fc{0};
|
uint64_t fc{0};
|
||||||
|
|
||||||
Shaderchains::Downsample downsampleChain;
|
Shaderchains::Downsample downsampleChain;
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ namespace LSFG::Shaderchains {
|
||||||
/// @param inImg3 The first related input texture
|
/// @param inImg3 The first related input texture
|
||||||
/// @param inImg4 The second related input texture
|
/// @param inImg4 The second related input texture
|
||||||
/// @param inImg5 The third related input texture
|
/// @param inImg5 The third related input texture
|
||||||
|
/// @param outFd File descriptor for the output image.
|
||||||
///
|
///
|
||||||
/// @throws LSFG::vulkan_error if resource creation fails.
|
/// @throws LSFG::vulkan_error if resource creation fails.
|
||||||
///
|
///
|
||||||
|
|
@ -42,7 +43,8 @@ namespace LSFG::Shaderchains {
|
||||||
Core::Image inImg2,
|
Core::Image inImg2,
|
||||||
Core::Image inImg3,
|
Core::Image inImg3,
|
||||||
Core::Image inImg4,
|
Core::Image inImg4,
|
||||||
Core::Image inImg5);
|
Core::Image inImg5,
|
||||||
|
int outFd);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Dispatch the shaderchain.
|
/// Dispatch the shaderchain.
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,12 @@ namespace LSFG {
|
||||||
/// @param height Height of the input images.
|
/// @param height Height of the input images.
|
||||||
/// @param in0 File descriptor for the first input image.
|
/// @param in0 File descriptor for the first input image.
|
||||||
/// @param in1 File descriptor for the second input image.
|
/// @param in1 File descriptor for the second input image.
|
||||||
|
/// @param out File descriptor for the output image.
|
||||||
/// @return A unique identifier for the created context.
|
/// @return A unique identifier for the created context.
|
||||||
///
|
///
|
||||||
/// @throws LSFG::vulkan_error if the context cannot be created.
|
/// @throws LSFG::vulkan_error if the context cannot be created.
|
||||||
///
|
///
|
||||||
int32_t createContext(uint32_t width, uint32_t height, int in0, int in1);
|
int32_t createContext(uint32_t width, uint32_t height, int in0, int in1, int out);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Present a context.
|
/// Present a context.
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
using namespace LSFG;
|
using namespace LSFG;
|
||||||
|
|
||||||
Context::Context(const Core::Device& device, uint32_t width, uint32_t height, int in0, int in1) {
|
Context::Context(const Core::Device& device, uint32_t width, uint32_t height, int in0, int in1, int out) {
|
||||||
// import images
|
// import images
|
||||||
this->inImg_0 = Core::Image(device, { width, height },
|
this->inImg_0 = Core::Image(device, { width, height },
|
||||||
VK_FORMAT_R8G8B8A8_UNORM,
|
VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
|
@ -90,15 +90,19 @@ Context::Context(const Core::Device& device, uint32_t width, uint32_t height, in
|
||||||
this->inImg_0,
|
this->inImg_0,
|
||||||
this->zetaChains.at(2).getOutImage(),
|
this->zetaChains.at(2).getOutImage(),
|
||||||
this->epsilonChains.at(2).getOutImage(),
|
this->epsilonChains.at(2).getOutImage(),
|
||||||
this->deltaChains.at(2).getOutImage()
|
this->deltaChains.at(2).getOutImage(),
|
||||||
|
out
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::present(const Core::Device& device, int inSem, int outSem) {
|
void Context::present(const Core::Device& device, int inSem, int outSem) {
|
||||||
const Core::Semaphore inSemaphore(device, inSem);
|
auto& inSemaphore = this->inSemaphores.at(this->fc % 8);
|
||||||
const Core::Semaphore outSemaphore(device, outSem);
|
inSemaphore = Core::Semaphore(device, inSem);
|
||||||
|
auto& outSemaphore = this->outSemaphores.at(this->fc % 8);
|
||||||
|
outSemaphore = Core::Semaphore(device, outSem);
|
||||||
|
|
||||||
Core::CommandBuffer cmdBuffer(device, this->cmdPool);
|
auto& cmdBuffer = this->cmdBuffers.at(this->fc % 8);
|
||||||
|
cmdBuffer = Core::CommandBuffer(device, this->cmdPool);
|
||||||
cmdBuffer.begin();
|
cmdBuffer.begin();
|
||||||
|
|
||||||
this->downsampleChain.Dispatch(cmdBuffer, fc);
|
this->downsampleChain.Dispatch(cmdBuffer, fc);
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,12 @@ void LSFG::initialize() {
|
||||||
std::srand(static_cast<uint32_t>(std::time(nullptr)));
|
std::srand(static_cast<uint32_t>(std::time(nullptr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t LSFG::createContext(uint32_t width, uint32_t height, int in0, int in1) {
|
int32_t LSFG::createContext(uint32_t width, uint32_t height, int in0, int in1, int out) {
|
||||||
if (!instance.has_value() || !device.has_value())
|
if (!instance.has_value() || !device.has_value())
|
||||||
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized");
|
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized");
|
||||||
|
|
||||||
auto id = std::rand();
|
auto id = std::rand();
|
||||||
contexts.emplace(id, Context(*device, width, height, in0, in1));
|
contexts.emplace(id, Context(*device, width, height, in0, in1, out));
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,6 @@ void Magic::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
this->pipeline.bind(buf);
|
this->pipeline.bind(buf);
|
||||||
this->descriptorSets.at(fc).bind(buf, this->pipeline);
|
this->descriptorSets.at(fc % 3).bind(buf, this->pipeline);
|
||||||
buf.dispatch(threadsX, threadsY, 1);
|
buf.dispatch(threadsX, threadsY, 1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@ Merge::Merge(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||||
Core::Image inImg2,
|
Core::Image inImg2,
|
||||||
Core::Image inImg3,
|
Core::Image inImg3,
|
||||||
Core::Image inImg4,
|
Core::Image inImg4,
|
||||||
Core::Image inImg5)
|
Core::Image inImg5,
|
||||||
|
int outFd)
|
||||||
: inImg1(std::move(inImg1)),
|
: inImg1(std::move(inImg1)),
|
||||||
inImg2(std::move(inImg2)),
|
inImg2(std::move(inImg2)),
|
||||||
inImg3(std::move(inImg3)),
|
inImg3(std::move(inImg3)),
|
||||||
|
|
@ -30,7 +31,8 @@ Merge::Merge(const Core::Device& device, const Core::DescriptorPool& pool,
|
||||||
extent,
|
extent,
|
||||||
VK_FORMAT_R8G8B8A8_UNORM,
|
VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||||
VK_IMAGE_ASPECT_COLOR_BIT);
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
outFd);
|
||||||
|
|
||||||
for (size_t fc = 0; fc < 2; fc++) {
|
for (size_t fc = 0; fc < 2; fc++) {
|
||||||
this->descriptorSets.at(fc).update(device)
|
this->descriptorSets.at(fc).update(device)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
#include "application.hpp"
|
#include "application.hpp"
|
||||||
|
#include "mini/commandbuffer.hpp"
|
||||||
#include "mini/commandpool.hpp"
|
#include "mini/commandpool.hpp"
|
||||||
#include "mini/image.hpp"
|
#include "mini/image.hpp"
|
||||||
#include "mini/semaphore.hpp"
|
#include "mini/semaphore.hpp"
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
#include <iostream>
|
||||||
#include <lsfg.hpp>
|
#include <lsfg.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
@ -44,7 +47,15 @@ SwapchainContext::SwapchainContext(const Application& app, VkSwapchainKHR swapch
|
||||||
VK_IMAGE_ASPECT_COLOR_BIT, &frame1fd
|
VK_IMAGE_ASPECT_COLOR_BIT, &frame1fd
|
||||||
);
|
);
|
||||||
|
|
||||||
auto id = LSFG::createContext(extent.width, extent.height, frame0fd, frame1fd);
|
int outfd{};
|
||||||
|
this->out_img = Mini::Image(
|
||||||
|
app.getDevice(), app.getPhysicalDevice(),
|
||||||
|
extent, VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
||||||
|
VK_IMAGE_ASPECT_COLOR_BIT, &outfd
|
||||||
|
);
|
||||||
|
|
||||||
|
auto id = LSFG::createContext(extent.width, extent.height, frame0fd, frame1fd, outfd);
|
||||||
this->lsfgId = std::shared_ptr<int32_t>(
|
this->lsfgId = std::shared_ptr<int32_t>(
|
||||||
new int32_t(id),
|
new int32_t(id),
|
||||||
[](const int32_t* id) {
|
[](const int32_t* id) {
|
||||||
|
|
@ -64,39 +75,222 @@ void Application::presentSwapchain(VkSwapchainKHR handle, VkQueue queue,
|
||||||
|
|
||||||
void SwapchainContext::present(const Application& app, VkQueue queue,
|
void SwapchainContext::present(const Application& app, VkQueue queue,
|
||||||
const std::vector<VkSemaphore>& semaphores, uint32_t idx) {
|
const std::vector<VkSemaphore>& semaphores, uint32_t idx) {
|
||||||
|
|
||||||
|
// present deferred frame if any
|
||||||
|
if (this->deferredIdx.has_value()) {
|
||||||
|
VkSemaphore deferredSemaphore = this->copySemaphores2.at((this->frameIdx - 1) % 8).handle();
|
||||||
|
const uint32_t deferredIdx = this->deferredIdx.value();
|
||||||
|
const VkPresentInfoKHR presentInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||||
|
.waitSemaphoreCount = 1,
|
||||||
|
.pWaitSemaphores = &deferredSemaphore,
|
||||||
|
.swapchainCount = 1,
|
||||||
|
.pSwapchains = &this->swapchain,
|
||||||
|
.pImageIndices = &deferredIdx,
|
||||||
|
};
|
||||||
|
auto res = vkQueuePresentKHR(queue, &presentInfo);
|
||||||
|
if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR)
|
||||||
|
throw LSFG::vulkan_error(res, "Failed to present deferred swapchain image");
|
||||||
|
}
|
||||||
|
this->deferredIdx.emplace(idx);
|
||||||
|
|
||||||
// create semaphores
|
// create semaphores
|
||||||
int copySem{};
|
int copySem{};
|
||||||
int presentSem{};
|
Mini::Semaphore& copySemaphore1 = this->copySemaphores1.at(this->frameIdx % 8);
|
||||||
Mini::Semaphore& copySemaphore = this->copySemaphores.at(this->frameIdx % 8);
|
copySemaphore1 = Mini::Semaphore(app.getDevice(), ©Sem);
|
||||||
copySemaphore = Mini::Semaphore(app.getDevice(), ©Sem);
|
Mini::Semaphore& copySemaphore2 = this->copySemaphores2.at(this->frameIdx % 8);
|
||||||
|
copySemaphore2 = Mini::Semaphore(app.getDevice());
|
||||||
Mini::Semaphore& acquireSemaphore = this->acquireSemaphores.at(this->frameIdx % 8);
|
Mini::Semaphore& acquireSemaphore = this->acquireSemaphores.at(this->frameIdx % 8);
|
||||||
acquireSemaphore = Mini::Semaphore(app.getDevice());
|
acquireSemaphore = Mini::Semaphore(app.getDevice());
|
||||||
|
int renderSem{};
|
||||||
Mini::Semaphore& renderSemaphore = this->renderSemaphores.at(this->frameIdx % 8);
|
Mini::Semaphore& renderSemaphore = this->renderSemaphores.at(this->frameIdx % 8);
|
||||||
renderSemaphore = Mini::Semaphore(app.getDevice());
|
renderSemaphore = Mini::Semaphore(app.getDevice(), &renderSem);
|
||||||
Mini::Semaphore& presentSemaphore = this->presentSemaphores.at(this->frameIdx % 8);
|
Mini::Semaphore& presentSemaphore = this->presentSemaphores.at(this->frameIdx % 8);
|
||||||
presentSemaphore = Mini::Semaphore(app.getDevice(), &presentSem);
|
presentSemaphore = Mini::Semaphore(app.getDevice());
|
||||||
|
|
||||||
// ...
|
// copy swapchain image to next frame image
|
||||||
|
auto& cmdBuf1 = this->cmdBufs1.at(this->frameIdx % 8);
|
||||||
|
cmdBuf1 = Mini::CommandBuffer(app.getDevice(), this->cmdPool);
|
||||||
|
cmdBuf1.begin();
|
||||||
|
|
||||||
|
auto& srcImage1 = this->images.at(idx);
|
||||||
|
auto& dstImage1 = (this->frameIdx % 2 == 0) ? this->frame_0 : this->frame_1;
|
||||||
|
|
||||||
|
const VkImageMemoryBarrier srcBarrier{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
|
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
|
||||||
|
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
.image = srcImage1,
|
||||||
|
.subresourceRange = {
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.levelCount = 1,
|
||||||
|
.layerCount = 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const VkImageMemoryBarrier dstBarrier{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
|
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
.image = dstImage1.handle(),
|
||||||
|
.subresourceRange = {
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.levelCount = 1,
|
||||||
|
.layerCount = 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const std::vector<VkImageMemoryBarrier> barriers = { srcBarrier, dstBarrier };
|
||||||
|
vkCmdPipelineBarrier(cmdBuf1.handle(),
|
||||||
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
0, 0, nullptr, 0, nullptr, 2, barriers.data());
|
||||||
|
|
||||||
|
const VkImageCopy imageCopy{
|
||||||
|
.srcSubresource = {
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.layerCount = 1
|
||||||
|
},
|
||||||
|
.dstSubresource = {
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.layerCount = 1
|
||||||
|
},
|
||||||
|
.extent = {
|
||||||
|
.width = this->extent.width,
|
||||||
|
.height = this->extent.height,
|
||||||
|
.depth = 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
vkCmdCopyImage(cmdBuf1.handle(),
|
||||||
|
srcImage1, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
dstImage1.handle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
1, &imageCopy);
|
||||||
|
|
||||||
|
const VkImageMemoryBarrier presentBarrier{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
||||||
|
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||||
|
.image = dstImage1.handle(),
|
||||||
|
.subresourceRange = {
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.levelCount = 1,
|
||||||
|
.layerCount = 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
vkCmdPipelineBarrier(cmdBuf1.handle(),
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||||
|
0, 0, nullptr, 0, nullptr, 1, &presentBarrier);
|
||||||
|
|
||||||
|
cmdBuf1.end();
|
||||||
|
cmdBuf1.submit(app.getGraphicsQueue(),
|
||||||
|
semaphores, { copySemaphore1.handle(), copySemaphore2.handle() });
|
||||||
|
|
||||||
// render the intermediary frame
|
// render the intermediary frame
|
||||||
// FIXME: i forgot the flippin output
|
try {
|
||||||
// FIXME: semaphores are being destroyed in the context
|
LSFG::presentContext(*this->lsfgId, copySem, renderSem);
|
||||||
LSFG::presentContext(*this->lsfgId, copySem, presentSem);
|
} catch(std::exception& e) {
|
||||||
|
std::cerr << "LSFG error: " << e.what() << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
// ...
|
// acquire the next swapchain image
|
||||||
|
uint32_t newIdx{};
|
||||||
|
auto res = vkAcquireNextImageKHR(app.getDevice(), this->swapchain, UINT64_MAX,
|
||||||
|
acquireSemaphore.handle(), VK_NULL_HANDLE, &newIdx);
|
||||||
|
if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR)
|
||||||
|
throw LSFG::vulkan_error(res, "Failed to acquire next swapchain image");
|
||||||
|
|
||||||
// ...
|
// copy the output image to the swapchain image
|
||||||
|
auto& cmdBuf2 = this->cmdBufs2.at((this->frameIdx + 1) % 8);
|
||||||
|
cmdBuf2 = Mini::CommandBuffer(app.getDevice(), this->cmdPool);
|
||||||
|
cmdBuf2.begin();
|
||||||
|
|
||||||
|
auto& srcImage2 = this->out_img;
|
||||||
|
auto& dstImage2 = this->images.at(newIdx);
|
||||||
|
|
||||||
|
const VkImageMemoryBarrier srcBarrier2{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
|
.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
|
||||||
|
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
.image = srcImage2.handle(),
|
||||||
|
.subresourceRange = {
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.levelCount = 1,
|
||||||
|
.layerCount = 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const VkImageMemoryBarrier dstBarrier2{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
||||||
|
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
.image = dstImage2,
|
||||||
|
.subresourceRange = {
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.levelCount = 1,
|
||||||
|
.layerCount = 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const std::vector<VkImageMemoryBarrier> barriers2 = { srcBarrier2, dstBarrier2 };
|
||||||
|
vkCmdPipelineBarrier(cmdBuf2.handle(),
|
||||||
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
0, 0, nullptr, 0, nullptr, 2, barriers2.data());
|
||||||
|
|
||||||
|
const VkImageCopy imageCopy2{
|
||||||
|
.srcSubresource = {
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.layerCount = 1
|
||||||
|
},
|
||||||
|
.dstSubresource = {
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.layerCount = 1
|
||||||
|
},
|
||||||
|
.extent = {
|
||||||
|
.width = this->extent.width,
|
||||||
|
.height = this->extent.height,
|
||||||
|
.depth = 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
vkCmdCopyImage(cmdBuf2.handle(),
|
||||||
|
srcImage2.handle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
dstImage2, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
1, &imageCopy2);
|
||||||
|
|
||||||
|
const VkImageMemoryBarrier presentBarrier2{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
||||||
|
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||||
|
.image = dstImage2,
|
||||||
|
.subresourceRange = {
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.levelCount = 1,
|
||||||
|
.layerCount = 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
vkCmdPipelineBarrier(cmdBuf2.handle(),
|
||||||
|
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||||
|
0, 0, nullptr, 0, nullptr, 1, &presentBarrier2);
|
||||||
|
|
||||||
|
cmdBuf2.end();
|
||||||
|
cmdBuf2.submit(app.getGraphicsQueue(),
|
||||||
|
{ acquireSemaphore.handle(), renderSemaphore.handle() },
|
||||||
|
{ presentSemaphore.handle() });
|
||||||
|
|
||||||
|
// present the swapchain image
|
||||||
|
VkSemaphore presentSemaphoreHandle = presentSemaphore.handle();
|
||||||
const VkPresentInfoKHR presentInfo = {
|
const VkPresentInfoKHR presentInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||||
.waitSemaphoreCount = static_cast<uint32_t>(semaphores.size()),
|
.waitSemaphoreCount = 1,
|
||||||
.pWaitSemaphores = semaphores.data(),
|
.pWaitSemaphores = &presentSemaphoreHandle,
|
||||||
.swapchainCount = 1,
|
.swapchainCount = 1,
|
||||||
.pSwapchains = &this->swapchain,
|
.pSwapchains = &this->swapchain,
|
||||||
.pImageIndices = &idx
|
.pImageIndices = &newIdx,
|
||||||
};
|
};
|
||||||
auto res = vkQueuePresentKHR(queue, &presentInfo);
|
res = vkQueuePresentKHR(queue, &presentInfo);
|
||||||
if (res != VK_SUCCESS) // FIXME: somehow return VK_SUBOPTIMAL_KHR
|
if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR) // FIXME: somehow return VK_SUBOPTIMAL_KHR
|
||||||
throw LSFG::vulkan_error(res, "Failed to present swapchain");
|
throw LSFG::vulkan_error(res, "Failed to present swapchain");
|
||||||
|
|
||||||
this->frameIdx++;
|
this->frameIdx++;
|
||||||
|
|
|
||||||
|
|
@ -53,32 +53,23 @@ void CommandBuffer::end() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBuffer::submit(VkQueue queue,
|
void CommandBuffer::submit(VkQueue queue,
|
||||||
const std::vector<Semaphore>& waitSemaphores,
|
const std::vector<VkSemaphore>& waitSemaphores,
|
||||||
const std::vector<Semaphore>& signalSemaphores) {
|
const std::vector<VkSemaphore>& signalSemaphores) {
|
||||||
if (*this->state != CommandBufferState::Full)
|
if (*this->state != CommandBufferState::Full)
|
||||||
throw std::logic_error("Command buffer is not in Full state");
|
throw std::logic_error("Command buffer is not in Full state");
|
||||||
|
|
||||||
const std::vector<VkPipelineStageFlags> waitStages(waitSemaphores.size(),
|
const std::vector<VkPipelineStageFlags> waitStages(waitSemaphores.size(),
|
||||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
||||||
|
|
||||||
std::vector<VkSemaphore> waitSemaphoresHandles;
|
|
||||||
waitSemaphoresHandles.reserve(waitSemaphores.size());
|
|
||||||
for (const auto& semaphore : waitSemaphores)
|
|
||||||
waitSemaphoresHandles.push_back(semaphore.handle());
|
|
||||||
std::vector<VkSemaphore> signalSemaphoresHandles;
|
|
||||||
signalSemaphoresHandles.reserve(signalSemaphores.size());
|
|
||||||
for (const auto& semaphore : signalSemaphores)
|
|
||||||
signalSemaphoresHandles.push_back(semaphore.handle());
|
|
||||||
|
|
||||||
const VkSubmitInfo submitInfo{
|
const VkSubmitInfo submitInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||||
.waitSemaphoreCount = static_cast<uint32_t>(waitSemaphores.size()),
|
.waitSemaphoreCount = static_cast<uint32_t>(waitSemaphores.size()),
|
||||||
.pWaitSemaphores = waitSemaphoresHandles.data(),
|
.pWaitSemaphores = waitSemaphores.data(),
|
||||||
.pWaitDstStageMask = waitStages.data(),
|
.pWaitDstStageMask = waitStages.data(),
|
||||||
.commandBufferCount = 1,
|
.commandBufferCount = 1,
|
||||||
.pCommandBuffers = &(*this->commandBuffer),
|
.pCommandBuffers = &(*this->commandBuffer),
|
||||||
.signalSemaphoreCount = static_cast<uint32_t>(signalSemaphores.size()),
|
.signalSemaphoreCount = static_cast<uint32_t>(signalSemaphores.size()),
|
||||||
.pSignalSemaphores = signalSemaphoresHandles.data()
|
.pSignalSemaphores = signalSemaphores.data()
|
||||||
};
|
};
|
||||||
auto res = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
|
auto res = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||||
if (res != VK_SUCCESS)
|
if (res != VK_SUCCESS)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue