Successfully cleared the screen. created synchronization objects for rendering and presentation
This commit is contained in:
parent
c393e0cdb1
commit
4365cc45d1
@ -4,7 +4,6 @@ set(CMAKE_CXX_STANDARD 20)
|
|||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "-DDEBUG")
|
set(CMAKE_CXX_FLAGS "-DDEBUG")
|
||||||
set(CMAKE_CXX_FLAGS "-fsanitize=address -g -DDEBUG -D_DEBUG")
|
|
||||||
|
|
||||||
project(Pleascach)
|
project(Pleascach)
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
#include <Renderer/Pipeline.hpp>
|
#include <Renderer/Pipeline.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
#include <util/log.hpp>
|
||||||
|
|
||||||
CommandBuffer::CommandBuffer(vk::Device dev, u32 queue_family) {
|
CommandBuffer::CommandBuffer(vk::Device dev, u32 queue_family) {
|
||||||
/* (For now) allow command buffers to be individually recycled */
|
/* (For now) allow command buffers to be individually recycled */
|
||||||
auto pool_info = vk::CommandPoolCreateInfo {
|
auto pool_info = vk::CommandPoolCreateInfo {
|
||||||
@ -18,7 +20,6 @@ CommandBuffer::CommandBuffer(vk::Device dev, u32 queue_family) {
|
|||||||
.level = vk::CommandBufferLevel::ePrimary,
|
.level = vk::CommandBufferLevel::ePrimary,
|
||||||
.commandBufferCount = 1,
|
.commandBufferCount = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
command_buffer = dev.allocateCommandBuffers(alloc_info)[0];
|
command_buffer = dev.allocateCommandBuffers(alloc_info)[0];
|
||||||
}
|
}
|
||||||
@ -26,7 +27,6 @@ CommandBuffer::CommandBuffer(vk::Device dev, u32 queue_family) {
|
|||||||
void CommandBuffer::begin() {
|
void CommandBuffer::begin() {
|
||||||
auto begin_info = vk::CommandBufferBeginInfo{
|
auto begin_info = vk::CommandBufferBeginInfo{
|
||||||
.flags = static_cast<vk::CommandBufferUsageFlags>(0),
|
.flags = static_cast<vk::CommandBufferUsageFlags>(0),
|
||||||
.pInheritanceInfo = nullptr,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
command_buffer.begin(begin_info);
|
command_buffer.begin(begin_info);
|
||||||
@ -50,8 +50,10 @@ void CommandBuffer::end() {
|
|||||||
|
|
||||||
void CommandBuffer::recycle() {
|
void CommandBuffer::recycle() {
|
||||||
command_buffer.reset();
|
command_buffer.reset();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBuffer::cleanup(vk::Device dev) {
|
void CommandBuffer::cleanup(vk::Device dev) {
|
||||||
|
dev.freeCommandBuffers(command_pool, command_buffer);
|
||||||
dev.destroyCommandPool(command_pool);
|
dev.destroyCommandPool(command_pool);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,4 +29,8 @@ struct CommandBuffer {
|
|||||||
|
|
||||||
vk::CommandBuffer command_buffer;
|
vk::CommandBuffer command_buffer;
|
||||||
vk::CommandPool command_pool;
|
vk::CommandPool command_pool;
|
||||||
|
|
||||||
|
operator vk::CommandBuffer* () {
|
||||||
|
return &command_buffer;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -145,8 +145,6 @@ Renderer::Renderer(Window& win) : win(win) {
|
|||||||
Log::error("Failed to get surface from window\n");
|
Log::error("Failed to get surface from window\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
swapchain = std::make_unique<Swapchain>(dev, surface, win.getDimensions());
|
|
||||||
|
|
||||||
queue = dev.getQueue(queue_family, 0);
|
queue = dev.getQueue(queue_family, 0);
|
||||||
|
|
||||||
|
|
||||||
@ -185,7 +183,7 @@ Renderer::Renderer(Window& win) : win(win) {
|
|||||||
.memoryTypeIndex = mem::choose_heap(phys_dev, depth_mem_reqs, vk::MemoryPropertyFlagBits::eDeviceLocal),
|
.memoryTypeIndex = mem::choose_heap(phys_dev, depth_mem_reqs, vk::MemoryPropertyFlagBits::eDeviceLocal),
|
||||||
};
|
};
|
||||||
|
|
||||||
auto depth_alloc = dev.allocateMemory(depth_alloc_info);
|
depth_alloc = dev.allocateMemory(depth_alloc_info);
|
||||||
dev.bindImageMemory(depth_image, depth_alloc, 0);
|
dev.bindImageMemory(depth_image, depth_alloc, 0);
|
||||||
|
|
||||||
auto depth_view_info = vk::ImageViewCreateInfo {
|
auto depth_view_info = vk::ImageViewCreateInfo {
|
||||||
@ -208,29 +206,101 @@ Renderer::Renderer(Window& win) : win(win) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
depth_image_view = dev.createImageView(depth_view_info);
|
depth_image_view = dev.createImageView(depth_view_info);
|
||||||
|
|
||||||
|
render_fence = dev.createFence(vk::FenceCreateInfo { .flags = vk::FenceCreateFlagBits::eSignaled });
|
||||||
|
|
||||||
|
image_wait_semaphore = dev.createSemaphore(vk::SemaphoreCreateInfo{});
|
||||||
|
render_wait_semaphore = dev.createSemaphore(vk::SemaphoreCreateInfo{});
|
||||||
|
|
||||||
|
render_pass = std::make_unique<RenderPass>(dev);
|
||||||
|
swapchain = std::make_unique<Swapchain>(dev, surface, win.getDimensions(), *render_pass, depth_image_view);
|
||||||
|
|
||||||
|
command_buffer = std::make_unique<CommandBuffer>(dev, queue_family);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::draw() {
|
void Renderer::draw() {
|
||||||
|
Log::info("draw() called \n");
|
||||||
|
|
||||||
|
dev.waitForFences(render_fence, true, UINT64_MAX);
|
||||||
|
dev.resetFences(render_fence);
|
||||||
|
|
||||||
/* check if the swapchain is still good (no resize) */
|
/* check if the swapchain is still good (no resize) */
|
||||||
auto image_ret = dev.acquireNextImageKHR(*swapchain, UINT64_MAX);
|
auto image_ret = dev.acquireNextImageKHR(*swapchain, UINT64_MAX, image_wait_semaphore);
|
||||||
if (image_ret.result == vk::Result::eErrorOutOfDateKHR) {
|
if (image_ret.result == vk::Result::eErrorOutOfDateKHR) {
|
||||||
swapchain->recreate(win.getDimensions());
|
swapchain->recreate(win.getDimensions());
|
||||||
}
|
}
|
||||||
|
|
||||||
current_image_idx = image_ret.value;
|
current_image_idx = image_ret.value;
|
||||||
|
|
||||||
|
/* prepare command buffer for recording commands */
|
||||||
command_buffer->recycle();
|
command_buffer->recycle();
|
||||||
command_buffer->begin();
|
command_buffer->begin();
|
||||||
|
|
||||||
|
vk::ClearValue clear_values[] = {
|
||||||
|
vk::ClearColorValue(1.0f, 0.0f, 1.0f, 1.0f),
|
||||||
|
vk::ClearDepthStencilValue {.depth = 1.0f}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* use renderpass to transform images from unspecified layout to a presentable one while clearing */
|
||||||
|
auto render_pass_info = vk::RenderPassBeginInfo {
|
||||||
|
.renderPass = *render_pass,
|
||||||
|
.framebuffer = swapchain->framebuffers[current_image_idx],
|
||||||
|
.renderArea = {
|
||||||
|
.offset = { 0, 0 },
|
||||||
|
.extent = swapchain->extent,
|
||||||
|
},
|
||||||
|
.clearValueCount = std::size(clear_values),
|
||||||
|
.pClearValues = clear_values,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto viewport = vk::Viewport{
|
||||||
|
.x = 0.0f,
|
||||||
|
.y = 0.0f,
|
||||||
|
.width = static_cast<float>(swapchain->extent.width),
|
||||||
|
.height = static_cast<float>(swapchain->extent.height),
|
||||||
|
.minDepth = 0.0f,
|
||||||
|
.maxDepth = 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto scissor = vk::Rect2D{
|
||||||
|
.offset = {0, 0},
|
||||||
|
.extent = swapchain->extent,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* no secondary command buffers (yet), so contents are passed inline */
|
||||||
|
command_buffer->command_buffer.beginRenderPass(render_pass_info, vk::SubpassContents::eInline);
|
||||||
|
command_buffer->command_buffer.setViewport(0, viewport);
|
||||||
|
command_buffer->command_buffer.setScissor(0, scissor);
|
||||||
|
command_buffer->command_buffer.endRenderPass();
|
||||||
|
|
||||||
command_buffer->end();
|
command_buffer->end();
|
||||||
|
|
||||||
|
|
||||||
|
vk::PipelineStageFlags stage_flags = vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
||||||
|
|
||||||
|
/* submit our command buffer to the queue */
|
||||||
|
auto submit_info = vk::SubmitInfo{
|
||||||
|
.waitSemaphoreCount = 1,
|
||||||
|
.pWaitSemaphores = &image_wait_semaphore,
|
||||||
|
.pWaitDstStageMask = &stage_flags,
|
||||||
|
.commandBufferCount = 1,
|
||||||
|
.pCommandBuffers = &command_buffer->command_buffer,
|
||||||
|
.signalSemaphoreCount = 1,
|
||||||
|
.pSignalSemaphores = &render_wait_semaphore,
|
||||||
|
};
|
||||||
|
|
||||||
|
queue.submit(submit_info, render_fence);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::present() {
|
void Renderer::present() {
|
||||||
|
Log::info("present() called \n");
|
||||||
auto present_info = vk::PresentInfoKHR{
|
auto present_info = vk::PresentInfoKHR{
|
||||||
|
.waitSemaphoreCount = 1,
|
||||||
|
.pWaitSemaphores = &render_wait_semaphore,
|
||||||
.swapchainCount = 1,
|
.swapchainCount = 1,
|
||||||
.pSwapchains = &swapchain->operator vk::SwapchainKHR &(),
|
.pSwapchains = &swapchain->operator vk::SwapchainKHR & (),
|
||||||
.pImageIndices = ¤t_image_idx,
|
.pImageIndices = ¤t_image_idx,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -239,6 +309,7 @@ void Renderer::present() {
|
|||||||
break;
|
break;
|
||||||
case vk::Result::eSuboptimalKHR:
|
case vk::Result::eSuboptimalKHR:
|
||||||
case vk::Result::eErrorOutOfDateKHR:
|
case vk::Result::eErrorOutOfDateKHR:
|
||||||
|
Log::info("Recreating swapchain");
|
||||||
swapchain->recreate(win.getDimensions());
|
swapchain->recreate(win.getDimensions());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -250,9 +321,13 @@ void Renderer::present() {
|
|||||||
Renderer::~Renderer() {
|
Renderer::~Renderer() {
|
||||||
dev.destroyImage(depth_image);
|
dev.destroyImage(depth_image);
|
||||||
dev.destroyImageView(depth_image_view);
|
dev.destroyImageView(depth_image_view);
|
||||||
|
dev.freeMemory(depth_alloc);
|
||||||
|
|
||||||
|
|
||||||
swapchain.reset();
|
swapchain.reset();
|
||||||
dev.waitIdle();
|
dev.waitIdle();
|
||||||
|
command_buffer->cleanup(dev);
|
||||||
|
render_pass->cleanup(dev);
|
||||||
dev.destroy();
|
dev.destroy();
|
||||||
instance.destroySurfaceKHR(surface);
|
instance.destroySurfaceKHR(surface);
|
||||||
instance.destroy();
|
instance.destroy();
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <Renderer/Swapchain.hpp>
|
#include <Renderer/Swapchain.hpp>
|
||||||
#include <Renderer/CommandBuffer.hpp>
|
#include <Renderer/CommandBuffer.hpp>
|
||||||
|
#include <Renderer/RenderPass.hpp>
|
||||||
|
|
||||||
struct Window;
|
struct Window;
|
||||||
|
|
||||||
@ -23,6 +24,8 @@ struct Renderer {
|
|||||||
vk::Instance instance;
|
vk::Instance instance;
|
||||||
vk::Device dev;
|
vk::Device dev;
|
||||||
|
|
||||||
|
vk::Fence render_fence;
|
||||||
|
vk::Semaphore image_wait_semaphore, render_wait_semaphore;
|
||||||
vk::SurfaceKHR surface;
|
vk::SurfaceKHR surface;
|
||||||
std::unique_ptr<Swapchain> swapchain;
|
std::unique_ptr<Swapchain> swapchain;
|
||||||
|
|
||||||
@ -30,8 +33,11 @@ struct Renderer {
|
|||||||
vk::Queue queue;
|
vk::Queue queue;
|
||||||
|
|
||||||
std::unique_ptr<CommandBuffer> command_buffer;
|
std::unique_ptr<CommandBuffer> command_buffer;
|
||||||
|
std::unique_ptr<RenderPass> render_pass;
|
||||||
|
|
||||||
uint32_t current_image_idx;
|
uint32_t current_image_idx;
|
||||||
|
|
||||||
vk::Image depth_image;
|
vk::Image depth_image;
|
||||||
vk::ImageView depth_image_view;
|
vk::ImageView depth_image_view;
|
||||||
|
vk::DeviceMemory depth_alloc;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
#include <Renderer/Swapchain.hpp>
|
#include <Renderer/Swapchain.hpp>
|
||||||
|
|
||||||
Swapchain::Swapchain(vk::Device& dev, const vk::SurfaceKHR& surface, const vk::Extent2D& extent) : dev(dev), surface(surface) {
|
Swapchain::Swapchain(vk::Device& dev, const vk::SurfaceKHR& surface, const vk::Extent2D& extent, RenderPass render_pass, vk::ImageView depth_image_view)
|
||||||
|
: dev(dev), surface(surface), render_pass(render_pass), depth_image_view(depth_image_view) {
|
||||||
create(extent);
|
create(extent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Swapchain::create(const vk::Extent2D& extent, vk::SwapchainKHR old_swapchain) {
|
void Swapchain::create(const vk::Extent2D& extent, vk::SwapchainKHR old_swapchain) {
|
||||||
|
this->extent = extent;
|
||||||
|
|
||||||
auto format = vk::Format::eB8G8R8A8Unorm;
|
auto format = vk::Format::eB8G8R8A8Unorm;
|
||||||
|
|
||||||
@ -33,8 +35,9 @@ void Swapchain::create(const vk::Extent2D& extent, vk::SwapchainKHR old_swapchai
|
|||||||
|
|
||||||
images = dev.getSwapchainImagesKHR(swapchain);
|
images = dev.getSwapchainImagesKHR(swapchain);
|
||||||
views.resize(images.size());
|
views.resize(images.size());
|
||||||
for(size_t i = 0; i < views.size(); i++) {
|
framebuffers.resize(images.size());
|
||||||
auto color_image_info = vk::ImageViewCreateInfo {
|
for (size_t i = 0; i < views.size(); i++) {
|
||||||
|
auto color_image_info = vk::ImageViewCreateInfo{
|
||||||
.image = images[i],
|
.image = images[i],
|
||||||
.viewType = vk::ImageViewType::e2D,
|
.viewType = vk::ImageViewType::e2D,
|
||||||
.format = format,
|
.format = format,
|
||||||
@ -52,8 +55,19 @@ void Swapchain::create(const vk::Extent2D& extent, vk::SwapchainKHR old_swapchai
|
|||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
views[i] = dev.createImageView(color_image_info);
|
views[i] = dev.createImageView(color_image_info);
|
||||||
|
|
||||||
|
vk::ImageView attachments[] = { views[i], depth_image_view };
|
||||||
|
auto framebuffer_info = vk::FramebufferCreateInfo {
|
||||||
|
.renderPass = render_pass,
|
||||||
|
.attachmentCount = static_cast<uint32_t>(std::size(attachments)),
|
||||||
|
.pAttachments = attachments,
|
||||||
|
.width = extent.width,
|
||||||
|
.height = extent.height,
|
||||||
|
.layers = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
framebuffers[i] = dev.createFramebuffer(framebuffer_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,10 +75,12 @@ void Swapchain::create(const vk::Extent2D& extent, vk::SwapchainKHR old_swapchai
|
|||||||
void Swapchain::recreate(const vk::Extent2D& extent) {
|
void Swapchain::recreate(const vk::Extent2D& extent) {
|
||||||
dev.waitIdle();
|
dev.waitIdle();
|
||||||
cleanup();
|
cleanup();
|
||||||
create(extent);
|
create(extent, swapchain);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Swapchain::cleanup() {
|
void Swapchain::cleanup() {
|
||||||
|
for(auto& fb : framebuffers)
|
||||||
|
dev.destroyFramebuffer(fb);
|
||||||
dev.destroySwapchainKHR(swapchain);
|
dev.destroySwapchainKHR(swapchain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,8 +3,12 @@
|
|||||||
#define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS
|
#define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
#include <Renderer/RenderPass.hpp>
|
||||||
|
|
||||||
|
|
||||||
struct Swapchain {
|
struct Swapchain {
|
||||||
Swapchain(vk::Device& dev, const vk::SurfaceKHR& surface, const vk::Extent2D& extent);
|
Swapchain(vk::Device& dev, const vk::SurfaceKHR& surface, const vk::Extent2D& extent, RenderPass render_pass, vk::ImageView depth_image_view);
|
||||||
vk::SwapchainKHR swapchain;
|
vk::SwapchainKHR swapchain;
|
||||||
inline operator vk::SwapchainKHR& () {
|
inline operator vk::SwapchainKHR& () {
|
||||||
return swapchain;
|
return swapchain;
|
||||||
@ -14,6 +18,12 @@ struct Swapchain {
|
|||||||
vk::SurfaceKHR surface;
|
vk::SurfaceKHR surface;
|
||||||
std::vector<vk::Image> images;
|
std::vector<vk::Image> images;
|
||||||
std::vector<vk::ImageView> views;
|
std::vector<vk::ImageView> views;
|
||||||
|
std::vector<vk::Framebuffer> framebuffers;
|
||||||
|
|
||||||
|
RenderPass render_pass;
|
||||||
|
vk::ImageView depth_image_view;
|
||||||
|
|
||||||
|
vk::Extent2D extent;
|
||||||
|
|
||||||
void create(const vk::Extent2D& extent, vk::SwapchainKHR old_swapchain = nullptr);
|
void create(const vk::Extent2D& extent, vk::SwapchainKHR old_swapchain = nullptr);
|
||||||
void recreate(const vk::Extent2D& extent);
|
void recreate(const vk::Extent2D& extent);
|
||||||
|
|||||||
@ -3,13 +3,11 @@
|
|||||||
#include <Renderer/Renderer.hpp>
|
#include <Renderer/Renderer.hpp>
|
||||||
|
|
||||||
#include <util/log.hpp>
|
#include <util/log.hpp>
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main() {
|
int main(int argc, char* argv[]) {
|
||||||
try {
|
try {
|
||||||
Window win("Test", 256, 512);
|
Window win(argv[0], 256, 512);
|
||||||
auto in = win.getInput();
|
auto in = win.getInput();
|
||||||
Renderer ren(win);
|
Renderer ren(win);
|
||||||
|
|
||||||
@ -23,7 +21,6 @@ int main() {
|
|||||||
switch (event.tag) {
|
switch (event.tag) {
|
||||||
case InputEvent::Tag::RESIZE:
|
case InputEvent::Tag::RESIZE:
|
||||||
Log::info("Event Processed: Resized to %dx%d\n", event.resize.width, event.resize.height);
|
Log::info("Event Processed: Resized to %dx%d\n", event.resize.width, event.resize.height);
|
||||||
win.setDimensions(event.resize.width, event.resize.width);
|
|
||||||
/* no need to have a resize() function in the renderer, b/c swapchain images will be
|
/* no need to have a resize() function in the renderer, b/c swapchain images will be
|
||||||
* automatically marked out-of-date, and recreation will be triggered in our code
|
* automatically marked out-of-date, and recreation will be triggered in our code
|
||||||
*/
|
*/
|
||||||
@ -36,6 +33,9 @@ int main() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ren.draw();
|
||||||
|
ren.present();
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (const std::string& e) {
|
} catch (const std::string& e) {
|
||||||
|
|||||||
81
renderer/RenderPass.cpp
Normal file
81
renderer/RenderPass.cpp
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#include <Renderer/RenderPass.hpp>
|
||||||
|
|
||||||
|
RenderPass::RenderPass(vk::Device dev, vk::Format image_format, vk::Format depth_format) {
|
||||||
|
/* transform color image from UNDEFINED format to presentable one for rendering */
|
||||||
|
auto color_attach_desc = vk::AttachmentDescription {
|
||||||
|
.format = image_format,
|
||||||
|
.samples = vk::SampleCountFlagBits::e1,
|
||||||
|
/* since its set to clear, it clears the initial image to the specified
|
||||||
|
clear color instead of loading the data */
|
||||||
|
.loadOp = vk::AttachmentLoadOp::eClear,
|
||||||
|
/* we care about the data after the end of the renderpass, so store */
|
||||||
|
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||||
|
/* for the depth stencil buffer, we care about neither */
|
||||||
|
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
|
||||||
|
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
||||||
|
.initialLayout = vk::ImageLayout::eUndefined,
|
||||||
|
.finalLayout = vk::ImageLayout::ePresentSrcKHR,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto color_attach_ref = vk::AttachmentReference { .attachment = 0, .layout = vk::ImageLayout::eColorAttachmentOptimal };
|
||||||
|
|
||||||
|
auto depth_attach_desc = vk::AttachmentDescription{
|
||||||
|
.format = depth_format,
|
||||||
|
.samples = vk::SampleCountFlagBits::e1,
|
||||||
|
.loadOp = vk::AttachmentLoadOp::eClear,
|
||||||
|
.storeOp = vk::AttachmentStoreOp::eDontCare,
|
||||||
|
.stencilLoadOp = vk::AttachmentLoadOp::eClear,
|
||||||
|
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
||||||
|
.initialLayout = vk::ImageLayout::eUndefined,
|
||||||
|
.finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto depth_attach_ref = vk::AttachmentReference{ .attachment = 1, .layout = vk::ImageLayout::eDepthStencilAttachmentOptimal };
|
||||||
|
|
||||||
|
/* only one subpass for now, uses both attachments */
|
||||||
|
auto subpass_desc = vk::SubpassDescription {
|
||||||
|
.pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
|
||||||
|
.colorAttachmentCount = 1,
|
||||||
|
.pColorAttachments = &color_attach_ref,
|
||||||
|
.pDepthStencilAttachment = &depth_attach_ref,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* designates producer and consumer of the image to position subpass */
|
||||||
|
auto color_dep = vk::SubpassDependency{
|
||||||
|
.srcSubpass = vk::SubpassExternal,
|
||||||
|
.dstSubpass = 0,
|
||||||
|
.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput,
|
||||||
|
.srcAccessMask = vk::AccessFlagBits::eNone,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto depth_dep = vk::SubpassDependency {
|
||||||
|
.srcSubpass = vk::SubpassExternal,
|
||||||
|
.dstSubpass = 0,
|
||||||
|
.srcStageMask = vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests,
|
||||||
|
.srcAccessMask = vk::AccessFlagBits::eNone,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentWrite,
|
||||||
|
};
|
||||||
|
|
||||||
|
vk::AttachmentDescription descs[] = { color_attach_desc, depth_attach_desc };
|
||||||
|
vk::SubpassDependency deps[] = { color_dep, depth_dep};
|
||||||
|
vk::SubpassDescription subpasses[] = {subpass_desc};
|
||||||
|
|
||||||
|
auto pass_info = vk::RenderPassCreateInfo {
|
||||||
|
.attachmentCount = static_cast<uint32_t>(std::size(descs)),
|
||||||
|
.pAttachments = descs,
|
||||||
|
.subpassCount = static_cast<uint32_t>(std::size(subpasses)),
|
||||||
|
.pSubpasses = subpasses,
|
||||||
|
.dependencyCount = static_cast<uint32_t>(std::size(deps)),
|
||||||
|
.pDependencies = deps,
|
||||||
|
};
|
||||||
|
|
||||||
|
render_pass = dev.createRenderPass(pass_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderPass::cleanup(vk::Device dev) {
|
||||||
|
dev.destroyRenderPass(render_pass);
|
||||||
|
}
|
||||||
16
renderer/RenderPass.hpp
Normal file
16
renderer/RenderPass.hpp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS
|
||||||
|
#include <vulkan/vulkan.hpp>
|
||||||
|
|
||||||
|
struct RenderPass {
|
||||||
|
vk::RenderPass render_pass;
|
||||||
|
|
||||||
|
RenderPass(vk::Device dev, vk::Format image_format = vk::Format::eB8G8R8A8Unorm, vk::Format depth_format = vk::Format::eD16Unorm);
|
||||||
|
|
||||||
|
void cleanup(vk::Device dev);
|
||||||
|
|
||||||
|
operator vk::RenderPass&() {
|
||||||
|
return render_pass;
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user