feat(renderer/vk): dynamic rendering
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
light7734 2025-10-26 16:43:56 +03:30
parent 97ca429d38
commit 736c37d2f1
Signed by: light7734
GPG key ID: 8C30176798F1A6BA
11 changed files with 251 additions and 68 deletions

View file

@ -75,10 +75,17 @@ void Device::initialize_logical_device()
auto extensions = std::vector<const char *> { auto extensions = std::vector<const char *> {
VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME,
};
const auto dynamic_rendering_features = VkPhysicalDeviceDynamicRenderingFeatures {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES,
.dynamicRendering = true,
}; };
auto device_info = VkDeviceCreateInfo { auto device_info = VkDeviceCreateInfo {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = &dynamic_rendering_features,
.queueCreateInfoCount = static_cast<uint32_t>(queue_infos.size()), .queueCreateInfoCount = static_cast<uint32_t>(queue_infos.size()),
.pQueueCreateInfos = queue_infos.data(), .pQueueCreateInfos = queue_infos.data(),
.enabledExtensionCount = static_cast<uint32_t>(extensions.size()), .enabledExtensionCount = static_cast<uint32_t>(extensions.size()),

View file

@ -100,12 +100,16 @@ PFN_vkFreeMemory vk_free_memory {};
PFN_vkResetCommandBuffer vk_reset_command_buffer {}; PFN_vkResetCommandBuffer vk_reset_command_buffer {};
PFN_vkCmdBeginRendering vk_cmd_begin_rendering {};
PFN_vkCmdEndRendering vk_cmd_end_rendering {};
PFN_vkGetPhysicalDeviceSurfaceSupportKHR vk_get_physical_device_surface_support {}; PFN_vkGetPhysicalDeviceSurfaceSupportKHR vk_get_physical_device_surface_support {};
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vk_get_physical_device_surface_capabilities {}; PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vk_get_physical_device_surface_capabilities {};
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vk_get_physical_device_surface_formats {}; PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vk_get_physical_device_surface_formats {};
auto vk_create_xlib_surface_khr = PFN_vkCreateXlibSurfaceKHR {}; auto vk_create_xlib_surface_khr = PFN_vkCreateXlibSurfaceKHR {};
auto vk_destroy_surface_khr = PFN_vkDestroySurfaceKHR {}; auto vk_destroy_surface_khr = PFN_vkDestroySurfaceKHR {};
// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables) // NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
Instance::Instance() Instance::Instance()
@ -392,6 +396,9 @@ void Instance::load_device_functions_impl(VkDevice device)
load_fn(vk_free_memory, "vkFreeMemory"); load_fn(vk_free_memory, "vkFreeMemory");
load_fn(vk_get_buffer_memory_requirements, "vkGetBufferMemoryRequirements"); load_fn(vk_get_buffer_memory_requirements, "vkGetBufferMemoryRequirements");
load_fn(vk_reset_command_buffer, "vkResetCommandBuffer"); load_fn(vk_reset_command_buffer, "vkResetCommandBuffer");
load_fn(vk_cmd_begin_rendering, "vkCmdBeginRendering");
load_fn(vk_cmd_end_rendering, "vkCmdEndRendering");
} }
auto Instance::enumerate_gpus() const -> std::vector<VkPhysicalDevice> auto Instance::enumerate_gpus() const -> std::vector<VkPhysicalDevice>

View file

@ -49,6 +49,17 @@ public:
return m_images.size(); return m_images.size();
} }
[[nodiscard]] auto get_image_view(uint32_t idx) -> VkImageView
{
return m_image_views[idx];
}
[[nodiscard]] auto get_image(uint32_t idx) -> VkImage
{
return m_images[idx];
}
[[nodiscard]] auto create_framebuffers_for_pass(VkRenderPass pass) const [[nodiscard]] auto create_framebuffers_for_pass(VkRenderPass pass) const
-> std::vector<VkFramebuffer>; -> std::vector<VkFramebuffer>;

View file

@ -113,16 +113,16 @@ Pass::Pass(
.blendConstants = { 0.0f, 0.0, 0.0, 0.0 }, .blendConstants = { 0.0f, 0.0, 0.0, 0.0 },
}; };
auto attachment_description = VkAttachmentDescription { // auto attachment_description = VkAttachmentDescription {
.format = static_cast<Swapchain *>(swapchain)->get_format(), // .format =,
.samples = VK_SAMPLE_COUNT_1_BIT, // .samples = VK_SAMPLE_COUNT_1_BIT,
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, // .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE, // .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, // .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, // .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, // .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
}; // };
auto color_attachment_ref = VkAttachmentReference { auto color_attachment_ref = VkAttachmentReference {
.attachment = 0, .attachment = 0,
@ -144,21 +144,18 @@ Pass::Pass(
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
}; };
m_pass = m_device->create_pass( auto color_format = static_cast<Swapchain *>(swapchain)->get_format();
VkRenderPassCreateInfo { auto rendering_info = VkPipelineRenderingCreateInfoKHR {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
.attachmentCount = 1u, .colorAttachmentCount = 1u,
.pAttachments = &attachment_description, .pColorAttachmentFormats = &color_format,
.subpassCount = 1u,
.pSubpasses = &subpass_description, };
.dependencyCount = 1u,
.pDependencies = &pass_dependency,
}
);
m_pipeline = m_device->create_graphics_pipeline( m_pipeline = m_device->create_graphics_pipeline(
VkGraphicsPipelineCreateInfo { VkGraphicsPipelineCreateInfo {
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = &rendering_info,
.stageCount = static_cast<uint32_t>(shader_stages.size()), .stageCount = static_cast<uint32_t>(shader_stages.size()),
.pStages = shader_stages.data(), .pStages = shader_stages.data(),
.pVertexInputState = &vertex_input, .pVertexInputState = &vertex_input,
@ -170,14 +167,14 @@ Pass::Pass(
.pColorBlendState = &color_blend, .pColorBlendState = &color_blend,
.pDynamicState = &dynamic_state, .pDynamicState = &dynamic_state,
.layout = m_layout, .layout = m_layout,
.renderPass = m_pass, .renderPass = VK_NULL_HANDLE,
.subpass = 0u, .subpass = 0u,
.basePipelineHandle = VK_NULL_HANDLE, .basePipelineHandle = VK_NULL_HANDLE,
.basePipelineIndex = -1, .basePipelineIndex = -1,
} }
); );
m_framebuffers = static_cast<Swapchain *>(swapchain)->create_framebuffers_for_pass(m_pass); // m_framebuffers = static_cast<Swapchain *>(swapchain)->create_framebuffers_for_pass(m_pass);
m_device->destroy_shader_module(vertex_module); m_device->destroy_shader_module(vertex_module);
m_device->destroy_shader_module(fragment_module); m_device->destroy_shader_module(fragment_module);
@ -193,7 +190,7 @@ Pass::~Pass()
m_device->wait_idle(); m_device->wait_idle();
m_device->destroy_framebuffers(m_framebuffers); m_device->destroy_framebuffers(m_framebuffers);
m_device->destroy_pipeline(m_pipeline); m_device->destroy_pipeline(m_pipeline);
m_device->destroy_pass(m_pass); // m_device->destroy_pass(m_pass);
m_device->destroy_pipeline_layout(m_layout); m_device->destroy_pipeline_layout(m_layout);
} }
@ -206,7 +203,8 @@ void Pass::replace_swapchain(const ISwapchain &swapchain)
m_device->wait_idle(); m_device->wait_idle();
m_device->destroy_framebuffers(m_framebuffers); m_device->destroy_framebuffers(m_framebuffers);
m_framebuffers = static_cast<const Swapchain &>(swapchain).create_framebuffers_for_pass(m_pass); // m_framebuffers = static_cast<const Swapchain
// &>(swapchain).create_framebuffers_for_pass(m_pass);
} }
auto Pass::create_module(lt::assets::Blob blob) -> VkShaderModule auto Pass::create_module(lt::assets::Blob blob) -> VkShaderModule

View file

@ -29,11 +29,6 @@ public:
void replace_swapchain(const ISwapchain &swapchain); void replace_swapchain(const ISwapchain &swapchain);
[[nodiscard]] auto get_pass() -> VkRenderPass
{
return m_pass;
}
[[nodiscard]] auto get_pipeline() -> VkPipeline [[nodiscard]] auto get_pipeline() -> VkPipeline
{ {
return m_pipeline; return m_pipeline;
@ -54,8 +49,6 @@ private:
memory::NullOnMove<class Device *> m_device {}; memory::NullOnMove<class Device *> m_device {};
VkRenderPass m_pass = VK_NULL_HANDLE;
VkPipeline m_pipeline = VK_NULL_HANDLE; VkPipeline m_pipeline = VK_NULL_HANDLE;
VkPipelineLayout m_layout = VK_NULL_HANDLE; VkPipelineLayout m_layout = VK_NULL_HANDLE;

View file

@ -143,12 +143,79 @@ void Renderer::replace_swapchain(ISwapchain *swapchain)
void Renderer::record_cmd(VkCommandBuffer cmd, uint32_t image_idx) void Renderer::record_cmd(VkCommandBuffer cmd, uint32_t image_idx)
{ {
auto cmd_begin_info = VkCommandBufferBeginInfo { const auto cmd_begin_info = VkCommandBufferBeginInfo {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = {}, .flags = {},
.pInheritanceInfo = nullptr, .pInheritanceInfo = nullptr,
}; };
const auto begin_frame_barrier = VkImageMemoryBarrier {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = {},
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
.image = m_swapchain->get_image(image_idx),
.subresourceRange = VkImageSubresourceRange{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0u,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0u,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
};
const auto end_frame_barrier = VkImageMemoryBarrier {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
.dstAccessMask = {},
.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
.image = m_swapchain->get_image(image_idx),
.subresourceRange = VkImageSubresourceRange{
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0u,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0u,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
};
const auto scissor = VkRect2D {
.offset = { .x = 0u, .y = 0u },
.extent = m_resolution,
};
const auto viewport = VkViewport {
.x = 0.0f,
.y = 0.0f,
.width = static_cast<float>(m_resolution.width),
.height = static_cast<float>(m_resolution.height),
.minDepth = 0.0f,
.maxDepth = 1.0f,
};
const auto color_attachment_info = VkRenderingAttachmentInfoKHR {
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.imageView = m_swapchain->get_image_view(image_idx),
.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
.resolveMode = VK_RESOLVE_MODE_NONE,
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.clearValue = VkClearValue { .color = { 0.93, 0.93, 0.93, 1.0 } },
};
const auto rendering_info = VkRenderingInfoKHR {
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
.renderArea = scissor,
.layerCount = 1,
.colorAttachmentCount = 1,
.pColorAttachments = &color_attachment_info,
};
vkc(vk_begin_command_buffer(cmd, &cmd_begin_info)); vkc(vk_begin_command_buffer(cmd, &cmd_begin_info));
vk_cmd_push_constants( vk_cmd_push_constants(
cmd, cmd,
@ -158,46 +225,41 @@ void Renderer::record_cmd(VkCommandBuffer cmd, uint32_t image_idx)
sizeof(FrameConstants), sizeof(FrameConstants),
&m_frame_constants &m_frame_constants
); );
vk_cmd_pipeline_barrier(
auto clear_value = VkClearValue { cmd,
.color = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
0.93, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
0.93, 0,
0.93, 0,
1.0, nullptr,
}, 0,
}; nullptr,
1,
auto pass_begin_info = VkRenderPassBeginInfo { &begin_frame_barrier
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, );
.renderPass = m_pass->get_pass(), vk_cmd_begin_rendering(cmd, &rendering_info);
.framebuffer = m_pass->get_framebuffers()[image_idx],
.renderArea = { .offset = {}, .extent = m_resolution },
.clearValueCount = 1u,
.pClearValues = &clear_value
};
vk_cmd_begin_render_pass(cmd, &pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
vk_cmd_bind_pipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pass->get_pipeline()); vk_cmd_bind_pipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pass->get_pipeline());
auto viewport = VkViewport {
.x = 0.0f,
.y = 0.0f,
.width = static_cast<float>(m_resolution.width),
.height = static_cast<float>(m_resolution.height),
.minDepth = 0.0f,
.maxDepth = 1.0f,
};
vk_cmd_set_viewport(cmd, 0, 1, &viewport); vk_cmd_set_viewport(cmd, 0, 1, &viewport);
auto scissor = VkRect2D {
.offset = { .x = 0u, .y = 0u },
.extent = m_resolution,
};
vk_cmd_set_scissors(cmd, 0, 1, &scissor); vk_cmd_set_scissors(cmd, 0, 1, &scissor);
vk_cmd_draw(cmd, 3, 1, 0, 0); vk_cmd_draw(cmd, 3, 1, 0, 0);
vk_cmd_end_render_pass(cmd); vk_cmd_end_rendering(cmd);
vk_cmd_pipeline_barrier(
cmd,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
0,
0,
nullptr,
0,
nullptr,
1,
&end_frame_barrier
);
vkc(vk_end_command_buffer(cmd)); vkc(vk_end_command_buffer(cmd));
} }
void submit_sprite(const components::Sprite &sprite, const math::components::Transform &transform)
{
}
} // namespace lt::renderer::vk } // namespace lt::renderer::vk

View file

@ -3,8 +3,10 @@
#include <memory/reference.hpp> #include <memory/reference.hpp>
#include <ranges> #include <ranges>
#include <renderer/backend/vk/context/device.hpp> #include <renderer/backend/vk/context/device.hpp>
#include <renderer/backend/vk/data/buffer.hpp>
#include <renderer/backend/vk/renderer/pass.hpp> #include <renderer/backend/vk/renderer/pass.hpp>
#include <renderer/backend/vk/utils.hpp> #include <renderer/backend/vk/utils.hpp>
#include <renderer/frontend/data/buffer.hpp>
#include <renderer/frontend/renderer/pass.hpp> #include <renderer/frontend/renderer/pass.hpp>
#include <renderer/frontend/renderer/renderer.hpp> #include <renderer/frontend/renderer/renderer.hpp>
@ -34,6 +36,13 @@ public:
m_frame_constants = constants; m_frame_constants = constants;
} }
void submit_sprite(
const components::Sprite &sprite,
const math::components::Transform &transform
) override
{
}
private: private:
void record_cmd(VkCommandBuffer cmd, uint32_t image_idx); void record_cmd(VkCommandBuffer cmd, uint32_t image_idx);

View file

@ -88,6 +88,9 @@ extern PFN_vkUnmapMemory vk_unmap_memory;
extern PFN_vkFreeMemory vk_free_memory; extern PFN_vkFreeMemory vk_free_memory;
extern PFN_vkResetCommandBuffer vk_reset_command_buffer; extern PFN_vkResetCommandBuffer vk_reset_command_buffer;
extern PFN_vkCmdBeginRendering vk_cmd_begin_rendering;
extern PFN_vkCmdEndRendering vk_cmd_end_rendering;
// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables) // NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
} // namespace lt::renderer::vk } // namespace lt::renderer::vk

View file

@ -1,7 +1,9 @@
#pragma once #pragma once
#include <math/components/transform.hpp>
#include <memory/scope.hpp> #include <memory/scope.hpp>
#include <renderer/api.hpp> #include <renderer/api.hpp>
#include <renderer/components/sprite.hpp>
#include <renderer/data/frame_constants.hpp> #include <renderer/data/frame_constants.hpp>
namespace lt::renderer { namespace lt::renderer {
@ -44,6 +46,11 @@ public:
virtual void replace_swapchain(class ISwapchain *swapchain) = 0; virtual void replace_swapchain(class ISwapchain *swapchain) = 0;
virtual void set_frame_constants(FrameConstants constants) = 0; virtual void set_frame_constants(FrameConstants constants) = 0;
virtual void submit_sprite(
const components::Sprite &sprite,
const math::components::Transform &transform
) = 0;
}; };
} // namespace lt::renderer } // namespace lt::renderer

View file

@ -1,6 +1,8 @@
#include <camera/components.hpp> #include <camera/components.hpp>
#include <math/algebra.hpp> #include <math/algebra.hpp>
#include <math/components/transform.hpp>
#include <renderer/components/messenger.hpp> #include <renderer/components/messenger.hpp>
#include <renderer/components/sprite.hpp>
#include <renderer/frontend/context/device.hpp> #include <renderer/frontend/context/device.hpp>
#include <renderer/frontend/context/gpu.hpp> #include <renderer/frontend/context/gpu.hpp>
#include <renderer/frontend/context/instance.hpp> #include <renderer/frontend/context/instance.hpp>
@ -88,6 +90,13 @@ void System::tick(app::TickInfo tick)
} }
} }
// for each sprite, submit a new "model matrix" + "color" to go into the scene's SSBO
for (auto &[id, sprite, transform] :
m_registry->view<components::Sprite, math::components::Transform>())
{
m_renderer->submit_sprite(sprite, transform);
}
m_renderer->set_frame_constants({ .view_projection = perspective }); m_renderer->set_frame_constants({ .view_projection = perspective });
if (m_renderer->draw(m_frame_idx) != IRenderer::DrawResult::success) if (m_renderer->draw(m_frame_idx) != IRenderer::DrawResult::success)
{ {

View file

@ -0,0 +1,77 @@
#pragma once
#include <assets/shader.hpp>
#include <math/vec3.hpp>
#include <memory/reference.hpp>
namespace lt::renderer::components {
enum class VertexFormat : uint8_t
{
r32_g32_b32_sfloat,
r32_g32_sfloat,
};
enum class VertexInputRate : uint8_t
{
per_vertex,
per_instance,
};
struct VertexInputAttributeDescriptipn
{
uint32_t location;
uint32_t binding;
uint32_t offset;
VertexFormat format;
};
struct VertexInputBindingDescription
{
uint32_t binding;
uint32_t stride;
};
/** Requires a math::components::Transform component on the same entity to be functional. */
struct Sprite
{
struct Vertex
{
math::vec3 position;
math::vec3 color;
[[nodiscard]] constexpr static auto get_attributes()
-> std::array<VertexInputAttributeDescriptipn, 2>
{
return {
VertexInputAttributeDescriptipn {
.location = 0u,
.binding = 0u,
.offset = offsetof(Sprite::Vertex, position),
.format = VertexFormat::r32_g32_b32_sfloat,
},
VertexInputAttributeDescriptipn {
.location = 1u,
.binding = 0u,
.offset = offsetof(Sprite::Vertex, color),
.format = VertexFormat::r32_g32_b32_sfloat,
},
};
}
};
memory::Ref<assets::ShaderAsset> vertex_shader;
memory::Ref<assets::ShaderAsset> fragment_shader;
};
} // namespace lt::renderer::components