wip: convert from include style to module import style :D

This commit is contained in:
light7734 2025-11-12 16:07:51 +03:30
parent 2f60b837c9
commit 018d19335d
Signed by: light7734
GPG key ID: 8C30176798F1A6BA
9 changed files with 1105 additions and 855 deletions

View file

@ -4,21 +4,23 @@ import math.vec3;
import memory.reference; import memory.reference;
import std; import std;
namespace lt::renderer::components { export namespace lt::renderer::components {
export enum class VertexFormat: std::uint8_t { enum class VertexFormat : std::uint8_t
{
r32_g32_b32_sfloat, r32_g32_b32_sfloat,
r32_g32_sfloat, r32_g32_sfloat,
}; };
export enum class VertexInputRate: std::uint8_t { enum class VertexInputRate : std::uint8_t
{
per_vertex, per_vertex,
per_instance, per_instance,
}; };
export struct VertexInputAttributeDescriptipn struct VertexInputAttributeDescriptipn
{ {
std::uint32_t location; std::uint32_t location;
@ -29,7 +31,7 @@ export struct VertexInputAttributeDescriptipn
VertexFormat format; VertexFormat format;
}; };
export struct VertexInputBindingDescription struct VertexInputBindingDescription
{ {
std::uint32_t binding; std::uint32_t binding;
@ -37,7 +39,7 @@ export struct VertexInputBindingDescription
}; };
/** Requires a math::components::Transform component on the same entity to be functional. */ /** Requires a math::components::Transform component on the same entity to be functional. */
export struct Sprite struct Sprite
{ {
struct Vertex struct Vertex
{ {
@ -52,7 +54,7 @@ export struct Sprite
VertexInputAttributeDescriptipn { VertexInputAttributeDescriptipn {
.location = 0u, .location = 0u,
.binding = 0u, .binding = 0u,
.offset = offsetof(Sprite::Vertex, position), .offset = 0u,
.format = VertexFormat::r32_g32_b32_sfloat, .format = VertexFormat::r32_g32_b32_sfloat,
}, },
@ -60,7 +62,7 @@ export struct Sprite
VertexInputAttributeDescriptipn { VertexInputAttributeDescriptipn {
.location = 1u, .location = 1u,
.binding = 0u, .binding = 0u,
.offset = offsetof(Sprite::Vertex, color), .offset = sizeof(math::vec3),
.format = VertexFormat::r32_g32_b32_sfloat, .format = VertexFormat::r32_g32_b32_sfloat,
}, },
}; };

View file

@ -5,9 +5,11 @@ import renderer.backend.vk.device;
import renderer.vk.pass; import renderer.vk.pass;
import renderer.backend.vk.instance; import renderer.backend.vk.instance;
import renderer.backend.vk.swapchain; import renderer.backend.vk.swapchain;
import renderer.vk.renderer;
import renderer.backend.vk.buffer; import renderer.backend.vk.buffer;
import renderer.backend.vk.gpu; import renderer.backend.vk.gpu;
import renderer.backend.vk.surface; import renderer.backend.vk.surface;
import renderer.vk.renderer;
import memory.scope; import memory.scope;
import debug.assertions; import debug.assertions;
import ecs.entity; import ecs.entity;
@ -35,6 +37,14 @@ export namespace lt::renderer {
const lt::assets::ShaderAsset &fragment_shader const lt::assets::ShaderAsset &fragment_shader
) -> memory::Scope<IPass>; ) -> memory::Scope<IPass>;
[[nodiscard]] auto create_renderer(
Api target_api,
IGpu *gpu,
IDevice *device,
ISwapchain *swapchain,
std::uint32_t max_frames_in_flight
) -> memory::Scope<IRenderer>
} // namespace lt::renderer } // namespace lt::renderer
module :private; module :private;
@ -147,59 +157,62 @@ using namespace lt::renderer;
} }
} }
// [[nodiscard]] /* static */ auto IRenderer::create( [[nodiscard]] auto create_renderer(
// Api target_api, Api target_api,
// IGpu *gpu, IGpu *gpu,
// IDevice *device, IDevice *device,
// ISwapchain *swapchain, ISwapchain *swapchain,
// uint32_t max_frames_in_flight std::uint32_t max_frames_in_flight
// ) -> memory::Scope<IRenderer> ) -> memory::Scope<IRenderer>
// { {
// ensure(gpu, "Failed to create renderer::IRenderer: null gpu"); debug::ensure(gpu, "Failed to create renderer::IRenderer: null gpu");
// ensure(device, "Failed to create renderer::IRenderer: null device"); debug::ensure(device, "Failed to create renderer::IRenderer: null device");
// ensure(swapchain, "Failed to create renderer::IRenderer: null swapchain"); debug::ensure(swapchain, "Failed to create renderer::IRenderer: null swapchain");
// ensure( debug::ensure(
// std::clamp(max_frames_in_flight, frames_in_flight_lower_limit, frames_in_flight_upper_limit) std::clamp(
// == max_frames_in_flight, max_frames_in_flight,
// "Failed to initialize renderer::System: max_frames_in_flight ({}) not within bounds ({} -> " IRenderer::frames_in_flight_lower_limit,
// "{}) ", IRenderer::frames_in_flight_upper_limit
// max_frames_in_flight, ) == max_frames_in_flight,
// frames_in_flight_lower_limit, "Failed to initialize renderer::System: max_frames_in_flight ({}) not within bounds ({} -> "
// frames_in_flight_upper_limit "{}) ",
// ); max_frames_in_flight,
// IRenderer::frames_in_flight_lower_limit,
// IRenderer::frames_in_flight_upper_limit
// switch (target_api) );
// {
// case Api::vulkan:
// return memory::create_scope<vk::Renderer>(gpu, device, swapchain, max_frames_in_flight);
// case Api::none:
// case Api::metal:
// case Api::direct_x: throw std::runtime_error { "Invalid API" };
// }
// }
// [[nodiscard]] /* static */ auto IDebugger::create( switch (target_api)
// Api target_api, {
// IInstance *instance, case Api::vulkan:
// CreateInfo info return memory::create_scope<vkb::Renderer>(gpu, device, swapchain, max_frames_in_flight);
// ) -> memory::Scope<IDebugger> case Api::none:
// { case Api::metal:
// debug::ensure( case Api::direct_x: throw std::runtime_error { "Invalid API" };
// info.severities != MessageSeverity::none, }
// "Failed to create vk::Messenger: severities == none" }
// );
//
// debug::ensure(info.types != MessageType::none, "Failed to create vk::Messenger: types == none"); [[nodiscard]] /* static */ auto IDebugger::create(
// Api target_api,
// debug::ensure(info.callback, "Failed to create vk::Messenger: null callback"); IInstance *instance,
// CreateInfo info
// switch (target_api) ) -> memory::Scope<IDebugger>
// { {
// case Api::vulkan: return memory::create_scope<vk::Messenger>(instance, std::move(info)); debug::ensure(
// case Api::none: info.severities != MessageSeverity::none,
// case Api::metal: "Failed to create vk::Messenger: severities == none"
// case Api::direct_x: throw std::runtime_error { "Invalid API" }; );
// }
// } debug::ensure(info.types != MessageType::none, "Failed to create vk::Messenger: types == none");
debug::ensure(info.callback, "Failed to create vk::Messenger: null callback");
switch (target_api)
{
case Api::vulkan: return memory::create_scope<vk::Messenger>(instance, std::move(info));
case Api::none:
case Api::metal:
case Api::direct_x: throw std::runtime_error { "Invalid API" };
}
}

View file

@ -1,4 +1,7 @@
export module renderer.frontend; export module renderer.frontend;
import renderer.data;
import renderer.components;
import math.components;
import assets.shader; import assets.shader;
import ecs.entity; import ecs.entity;
import math.vec2; import math.vec2;
@ -129,13 +132,6 @@ public:
std::size_t size; std::size_t size;
}; };
[[nodiscard]] static auto create(
Api target_api,
class IDevice *device,
class IGpu *gpu,
const CreateInfo &info
) -> memory::Scope<IBuffer>;
IBuffer() = default; IBuffer() = default;
virtual ~IBuffer() = default; virtual ~IBuffer() = default;
@ -160,13 +156,6 @@ private:
class IPass class IPass
{ {
public: public:
[[nodiscard]] static auto create(
lt::renderer::Api target_api,
class IDevice *device,
const class lt::assets::ShaderAsset &vertex_shader,
const class lt::assets::ShaderAsset &fragment_shader
) -> memory::Scope<IPass>;
IPass() = default; IPass() = default;
virtual ~IPass() = default; virtual ~IPass() = default;
@ -180,52 +169,43 @@ public:
auto operator=(const IPass &) -> IPass & = delete; auto operator=(const IPass &) -> IPass & = delete;
}; };
// class IRenderer class IRenderer
// { {
// public: public:
// static constexpr auto frames_in_flight_upper_limit = 5u; static constexpr auto frames_in_flight_upper_limit = 5u;
//
// static constexpr auto frames_in_flight_lower_limit = 1u;
//
// enum class Result : uint8_t
// {
// success = 0,
// invalid_swapchain,
// error,
// };
//
// [[nodiscard]] static auto create(
// Api target_api,
// class IGpu *gpu,
// class IDevice *device,
// class ISwapchain *swapchain,
// uint32_t max_frames_in_flight
// ) -> memory::Scope<IRenderer>;
//
// IRenderer() = default;
//
// virtual ~IRenderer() = default;
//
// IRenderer(IRenderer &&) = default;
//
// IRenderer(const IRenderer &) = delete;
//
// auto operator=(IRenderer &&) -> IRenderer & = default;
//
// auto operator=(const IRenderer &) -> IRenderer & = delete;
//
// virtual auto frame(uint32_t frame_idx, std::function<void()> submit_scene) -> Result = 0;
//
// virtual void replace_swapchain(class ISwapchain *swapchain) = 0;
//
// virtual void set_frame_constants(FrameConstants constants) = 0;
//
// virtual void submit_sprite(
// const components::Sprite &sprite,
// const math::components::Transform &transform
// ) = 0;
// };
static constexpr auto frames_in_flight_lower_limit = 1u;
enum class Result : std::uint8_t
{
success = 0,
invalid_swapchain,
error,
};
IRenderer() = default;
virtual ~IRenderer() = default;
IRenderer(IRenderer &&) = default;
IRenderer(const IRenderer &) = delete;
auto operator=(IRenderer &&) -> IRenderer & = default;
auto operator=(const IRenderer &) -> IRenderer & = delete;
virtual auto frame(std::uint32_t frame_idx, std::function<void()> submit_scene) -> Result = 0;
virtual void replace_swapchain(class ISwapchain *swapchain) = 0;
virtual void set_frame_constants(FrameConstants constants) = 0;
virtual void submit_sprite(
const components::Sprite &sprite,
const math::components::Transform &transform
) = 0;
};
// class IDebugger // class IDebugger
// { // {

File diff suppressed because it is too large Load diff

View file

@ -21,6 +21,11 @@ public:
return m_size; return m_size;
} }
[[nodiscard]] auto vk() -> vk::Buffer &
{
return m_buffer;
}
private: private:
[[nodiscard]] auto determine_allocation_info(Usage usage) const -> vk::Memory::AllocateInfo; [[nodiscard]] auto determine_allocation_info(Usage usage) const -> vk::Memory::AllocateInfo;

View file

@ -27,6 +27,16 @@ public:
return { m_graphics_queue_family_index, m_present_queue_family_index }; return { m_graphics_queue_family_index, m_present_queue_family_index };
} }
[[nodiscard]] auto graphics_queue() -> vk::Queue &
{
return m_graphics_queue;
}
[[nodiscard]] auto present_queue() -> vk::Queue &
{
return m_present_queue;
}
private: private:
void initialize_physical_device(); void initialize_physical_device();

View file

@ -1,5 +1,4 @@
export module renderer.vk.pass; export module renderer.vk.pass;
import renderer.data; import renderer.data;
import renderer.backend.vk.library_wrapper; import renderer.backend.vk.library_wrapper;
import renderer.backend.vk.device; import renderer.backend.vk.device;

View file

@ -1,84 +0,0 @@
#include <memory/pointer_types/null_on_move.hpp>
#include <renderer/backend/vk/context/device.hpp>
#include <renderer/backend/vk/context/instance.hpp>
#include <renderer/backend/vk/vulkan.hpp>
export namespace lt::renderer::vk::raii {
class DebugMessenger
{
public:
DebugMessenger(Instance *instance, VkDebugUtilsMessengerCreateInfoEXT info)
: m_instance(instance)
, m_object(m_instance->create_messenger(info))
{
}
~DebugMessenger()
{
if (m_instance)
{
m_instance->destroy_messenger(m_object);
}
}
DebugMessenger(DebugMessenger &&) = default;
DebugMessenger(const DebugMessenger &) = delete;
auto operator=(DebugMessenger &&) -> DebugMessenger & = default;
auto operator=(const DebugMessenger &) -> DebugMessenger & = delete;
private:
memory::NullOnMove<Instance *> m_instance {};
VkDebugUtilsMessengerEXT m_object;
};
class Memory
{
public:
Memory(Device *device, VkBuffer buffer, VkMemoryAllocateInfo info)
: m_device(device)
, m_object(m_device->allocate_memory(info))
{
m_device->bind_memory(buffer, m_object);
}
~Memory()
{
if (m_device)
{
m_device->free_memory(m_object);
}
}
Memory(Memory &&) = default;
Memory(const Memory &) = delete;
auto operator=(Memory &&) -> Memory & = default;
auto operator=(const Memory &) -> Memory & = delete;
[[nodiscard]] auto operator*() const -> VkDeviceMemory
{
return m_object;
}
[[nodiscard]] operator VkDeviceMemory() const
{
return m_object;
}
private:
memory::NullOnMove<Device *> m_device {};
VkDeviceMemory m_object = VK_NULL_HANDLE;
};
} // namespace lt::renderer::vk::raii

View file

@ -1,38 +1,33 @@
#pragma once export module renderer.vk.renderer;
import assets.shader;
import debug.assertions;
import renderer.backend.vk.library_wrapper;
import memory.reference;
import memory.null_on_move;
import renderer.backend.vk.device;
import math.vec2;
import math.components;
import renderer.backend.vk.swapchain;
import renderer.components;
import renderer.backend.vk.buffer;
import renderer.vk.pass;
import renderer.data;
import renderer.frontend;
import std;
#include <memory/reference.hpp> namespace lt::renderer::vkb {
#include <ranges>
#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/utils.hpp>
#include <renderer/frontend/data/buffer.hpp>
#include <renderer/frontend/renderer/pass.hpp>
#include <renderer/frontend/renderer/renderer.hpp>
namespace lt::renderer::vk { export class Renderer: public IRenderer
class Renderer: public IRenderer
{ {
public: public:
Renderer( Renderer(
class IGpu *gpu, class IGpu *gpu,
class IDevice *device, class IDevice *device,
class ISwapchain *swapchain, class ISwapchain *swapchain,
uint32_t max_frames_in_flight std::uint32_t max_frames_in_flight
); );
~Renderer() override; [[nodiscard]] auto frame(std::uint32_t frame_idx, std::function<void()> submit_scene)
Renderer(Renderer &&) = default;
Renderer(const Renderer &) = delete;
auto operator=(Renderer &&) -> Renderer & = default;
auto operator=(const Renderer &) -> Renderer & = delete;
[[nodiscard]] auto frame(uint32_t frame_idx, std::function<void()> submit_scene)
-> Result override; -> Result override;
void replace_swapchain(ISwapchain *swapchain) override; void replace_swapchain(ISwapchain *swapchain) override;
@ -48,33 +43,29 @@ public:
) override; ) override;
private: private:
void record_cmd(VkCommandBuffer cmd, uint32_t image_idx); void record_cmd(vk::CommandBuffer &cmd, std::uint32_t image_idx);
void map_buffers(uint32_t frame_idx); void map_buffers(std::uint32_t frame_idx);
void flush_buffers(VkCommandBuffer cmd); std::uint32_t m_max_frames_in_flight {};
memory::NullOnMove<class Device *> m_device {}; memory::NullOnMove<Device *> m_device {};
class Swapchain *m_swapchain {}; Swapchain *m_swapchain {};
memory::Ref<class Pass> m_pass; memory::Ref<Pass> m_pass;
VkCommandPool m_pool = VK_NULL_HANDLE; vk::CommandPool m_pool;
VkCommandPool m_transient_pool = VK_NULL_HANDLE; std::vector<vk::CommandBuffer> m_cmds;
std::vector<VkCommandBuffer> m_cmds; std::vector<vk::Fence> m_frame_fences;
std::vector<VkFence> m_frame_fences; std::vector<vk::Semaphore> m_acquire_image_semaphores;
std::vector<VkSemaphore> m_aquire_image_semaphores; std::vector<vk::Semaphore> m_submit_semaphores;
std::vector<VkSemaphore> m_submit_semaphores; math::uvec2 m_resolution;
VkExtent2D m_resolution;
uint32_t m_max_frames_in_flight {};
FrameConstants m_frame_constants; FrameConstants m_frame_constants;
@ -82,26 +73,27 @@ private:
Buffer m_staging_buffer; Buffer m_staging_buffer;
size_t m_staging_offset; std::size_t m_staging_offset;
std::span<std::byte> m_staging_map; std::span<std::byte> m_staging_map;
std::span<components::Sprite::Vertex> m_sprite_vertex_map; std::span<components::Sprite::Vertex> m_sprite_vertex_map;
size_t m_current_sprite_idx; std::size_t m_current_sprite_idx;
}; };
} // namespace lt::renderer::vk } // namespace lt::renderer::vkb
module :private; module :private;
using namespace lt::renderer;
using namespace lt::renderer::vkb;
#include <memory/reference.hpp> Renderer::Renderer(
#include <renderer/backend/vk/context/swapchain.hpp> IGpu *gpu,
#include <renderer/backend/vk/renderer/renderer.hpp> IDevice *device,
ISwapchain *swapchain,
namespace lt::renderer::vk { std::uint32_t max_frames_in_flight
)
Renderer::Renderer(IGpu *gpu, IDevice *device, ISwapchain *swapchain, uint32_t max_frames_in_flight)
: m_device(static_cast<Device *>(device)) : m_device(static_cast<Device *>(device))
, m_swapchain(static_cast<Swapchain *>(swapchain)) , m_swapchain(static_cast<Swapchain *>(swapchain))
, m_resolution(m_swapchain->get_resolution()) , m_resolution(m_swapchain->get_resolution())
@ -110,7 +102,7 @@ Renderer::Renderer(IGpu *gpu, IDevice *device, ISwapchain *swapchain, uint32_t m
, m_vertex_buffer( , m_vertex_buffer(
device, device,
gpu, gpu,
IBuffer::CreateInfo { {
.usage = IBuffer::Usage::vertex, .usage = IBuffer::Usage::vertex,
.size = 1'000'000, .size = 1'000'000,
.debug_name = "vertex buffer", .debug_name = "vertex buffer",
@ -119,91 +111,46 @@ Renderer::Renderer(IGpu *gpu, IDevice *device, ISwapchain *swapchain, uint32_t m
, m_staging_buffer( , m_staging_buffer(
device, device,
gpu, gpu,
IBuffer::CreateInfo { {
.usage = IBuffer::Usage::staging, .usage = IBuffer::Usage::staging,
.size = 1'000'000, .size = 1'000'000,
.debug_name = "staging buffer", .debug_name = "staging buffer",
} }
) )
{ , m_pass(
ensure(m_device, "Failed to initialize renderer: null device"); memory::create_ref<Pass>(
ensure(m_swapchain, "Failed to initialize renderer: null swapchain");
// TODO(Light): HARDCODED PASS!!!
m_pass = memory::create_ref<vk::Pass>(
m_device, m_device,
m_swapchain,
assets::ShaderAsset { "./data/test_assets/sprite.vert.asset" }, assets::ShaderAsset { "./data/test_assets/sprite.vert.asset" },
assets::ShaderAsset { "./data/test_assets/triangle.frag.asset" } assets::ShaderAsset { "./data/test_assets/triangle.frag.asset" }
); )
)
m_pool = m_device->create_command_pool( , m_pool(
VkCommandPoolCreateInfo { m_device->vk(),
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
.queueFamilyIndex = m_device->get_family_indices()[0],
}
);
m_transient_pool = m_device->create_command_pool(
VkCommandPoolCreateInfo {
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
.queueFamilyIndex = m_device->get_family_indices()[0],
}
);
m_cmds.resize(m_max_frames_in_flight);
m_cmds = m_device->allocate_command_buffers(
VkCommandBufferAllocateInfo {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.commandPool = m_pool,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandBufferCount = static_cast<uint32_t>(m_cmds.size()),
}
);
m_aquire_image_semaphores = m_device->create_semaphores(m_max_frames_in_flight);
m_frame_fences = m_device->create_fences(
VkFenceCreateInfo {
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
.flags = VK_FENCE_CREATE_SIGNALED_BIT,
},
m_max_frames_in_flight
);
for (auto idx = 0u;
auto [semaphore, fence] : std::views::zip(m_aquire_image_semaphores, m_frame_fences))
{ {
m_device->name(semaphore, "acquire image semaphore {}", idx); .flags = vk::CommandPool::CreateInfo::FlagBits::reset_command_buffer,
m_device->name(fence, "frame fence {}", idx); }
)
, m_cmds(m_pool.allocate(m_max_frames_in_flight, vk::CommandPool::BufferLevel::primary))
, m_acquire_image_semaphores(m_max_frames_in_flight)
, m_frame_fences(m_max_frames_in_flight)
, m_submit_semaphores(m_swapchain->get_image_count())
{
for (auto [semaphore, fence] : std::views::zip(m_acquire_image_semaphores, m_frame_fences))
{
semaphore = vk::Semaphore(m_device->vk());
fence = vk::Fence(m_device->vk(), { .signaled = true });
} }
m_submit_semaphores = m_device->create_semaphores(m_swapchain->get_image_count()); for (auto &semaphore : m_submit_semaphores)
for (auto idx = 0u; auto &semaphore : m_submit_semaphores)
{ {
m_device->name(semaphore, "submit semaphore {}", idx); semaphore = vk::Semaphore(m_device->vk());
} }
}; };
Renderer::~Renderer() [[nodiscard]] auto Renderer::frame(std::uint32_t frame_idx, std::function<void()> submit_scene)
-> Result
{ {
if (!m_device) debug::ensure(
{
return;
}
m_device->wait_idle();
m_device->destroy_semaphores(m_aquire_image_semaphores);
m_device->destroy_semaphores(m_submit_semaphores);
m_device->destroy_fences(m_frame_fences);
m_device->destroy_command_pool(m_pool);
m_device->destroy_command_pool(m_transient_pool);
}
[[nodiscard]] auto Renderer::frame(uint32_t frame_idx, std::function<void()> submit_scene) -> Result
{
ensure(
frame_idx < m_max_frames_in_flight, frame_idx < m_max_frames_in_flight,
"Failed to draw: frame_idx >= max_frames_in_flight ({} >= {})", "Failed to draw: frame_idx >= max_frames_in_flight ({} >= {})",
frame_idx, frame_idx,
@ -211,50 +158,33 @@ Renderer::~Renderer()
); );
auto &frame_fence = m_frame_fences[frame_idx]; auto &frame_fence = m_frame_fences[frame_idx];
auto &aquire_semaphore = m_aquire_image_semaphores[frame_idx]; auto &acquire_semaphore = m_acquire_image_semaphores[frame_idx];
auto &cmd = m_cmds[frame_idx]; auto &cmd = m_cmds[frame_idx];
m_device->wait_for_fence(frame_fence); frame_fence.wait();
const auto image_idx = m_swapchain->vk().acquire_image(acquire_semaphore);
auto image_idx = m_device->acquire_image(m_swapchain->vk(), aquire_semaphore); frame_fence.reset();
if (!image_idx.has_value())
{
return Result::invalid_swapchain;
}
m_device->reset_fence(frame_fence);
map_buffers(frame_idx); map_buffers(frame_idx);
submit_scene(); submit_scene();
record_cmd(cmd, *image_idx); record_cmd(cmd, image_idx);
auto wait_stage = VkPipelineStageFlags { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; auto &submit_semaphore = m_submit_semaphores[image_idx];
auto &submit_semaphore = m_submit_semaphores[*image_idx]; m_device->graphics_queue().submit(
m_device->submit( vk::Queue::SubmitInfo {
VkSubmitInfo { .command_buffer = &cmd,
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .wait_stages = vk::PipelineStageFlags::color_attachment_output_bit,
.waitSemaphoreCount = 1u, .wait_semaphore = &acquire_semaphore,
.pWaitSemaphores = &aquire_semaphore, .signal_semaphore = &submit_semaphore,
.pWaitDstStageMask = &wait_stage, .signal_fence = &frame_fence,
.commandBufferCount = 1u, }
.pCommandBuffers = &cmd,
.signalSemaphoreCount = 1u,
.pSignalSemaphores = &submit_semaphore,
},
frame_fence
); );
// TODO(Light): handle result m_device->present_queue().present(
auto result = VkResult {}; vk::Queue::PresentInfo {
m_device->present( .wait_semaphore = &submit_semaphore,
VkPresentInfoKHR { .swapchain = &m_swapchain->vk(),
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, .image_idx = image_idx,
.waitSemaphoreCount = 1u,
.pWaitSemaphores = &submit_semaphore,
.swapchainCount = 1u,
.pSwapchains = m_swapchain->vk_ptr(),
.pImageIndices = &image_idx.value(),
.pResults = &result,
} }
); );
@ -263,13 +193,12 @@ Renderer::~Renderer()
void Renderer::replace_swapchain(ISwapchain *swapchain) void Renderer::replace_swapchain(ISwapchain *swapchain)
{ {
m_device->wait_idle(); m_device->vk().wait_idle();
m_swapchain = static_cast<Swapchain *>(swapchain); m_swapchain = static_cast<Swapchain *>(swapchain);
m_resolution = m_swapchain->get_resolution(); m_resolution = m_swapchain->get_resolution();
m_pass->replace_swapchain(*swapchain);
} }
void Renderer::map_buffers(uint32_t frame_idx) void Renderer::map_buffers(std::uint32_t frame_idx)
{ {
using components::Sprite; using components::Sprite;
@ -286,140 +215,188 @@ void Renderer::map_buffers(uint32_t frame_idx)
); );
} }
void Renderer::flush_buffers(VkCommandBuffer cmd) void Renderer::record_cmd(vk::CommandBuffer &cmd, std::uint32_t image_idx)
{ {
// const auto cmd_begin_info = VkCommandBufferBeginInfo {
// .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
// .flags = {},
// .pInheritanceInfo = nullptr,
// };
// vk_reset_command_buffer(cmd, {});
// vkc(vk_begin_command_buffer(cmd, &cmd_begin_info));
// 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),
// .range = vk::Image::full_color_range,
// .subresourceRange = VkImageSubresourceRange{
// .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
// .baseMipLevel = 0u,
// .levelCount = VK_REMAINING_MIP_LEVELS,
// .baseArrayLayer = 0u,
// .layerCount = VK_REMAINING_ARRAY_LAYERS,
// },
// };
//
//
// vk_cmd_pipeline_barrier(
// cmd,
// VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
// VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
// 0,
// 0,
// nullptr,
// 0,
// nullptr,
// 1,
// &begin_frame_barrier
// );
//
// 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,
// },
// };
// 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
// );
// 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,
//
// };
m_staging_map = {}; m_staging_map = {};
m_sprite_vertex_map = {}; m_sprite_vertex_map = {};
cmd.begin({});
m_staging_buffer.unmap(); m_staging_buffer.unmap();
const auto buffer_copy_info = VkBufferCopy { cmd.copy(
.srcOffset = m_staging_offset,
.dstOffset = m_staging_offset,
.size = m_current_sprite_idx * sizeof(components::Sprite::Vertex),
};
vk_cmd_copy_buffer(cmd, m_staging_buffer.vk(), m_vertex_buffer.vk(), 1u, &buffer_copy_info);
}
void Renderer::record_cmd(VkCommandBuffer cmd, uint32_t image_idx)
{ {
const auto cmd_begin_info = VkCommandBufferBeginInfo { .src_buffer = &m_staging_buffer.vk(),
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .dst_buffer = &m_vertex_buffer.vk(),
.flags = {}, .src_offset = m_staging_offset,
.pInheritanceInfo = nullptr, .dst_offset = m_staging_offset,
}; .size = m_current_sprite_idx * sizeof(components::Sprite::Vertex),
}
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,
};
vk_reset_command_buffer(cmd, {});
vkc(vk_begin_command_buffer(cmd, &cmd_begin_info));
flush_buffers(cmd);
vk_cmd_push_constants(
cmd,
m_pass->get_layout(),
VK_SHADER_STAGE_VERTEX_BIT,
0u,
sizeof(FrameConstants),
&m_frame_constants
); );
vk_cmd_pipeline_barrier( cmd.push_constants(
cmd, {
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, .layout = &m_pass->get_layout(),
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, .shader_stages = vk::ShaderStageFlags::vertex_bit,
0, .offset = 0u,
0, .size = sizeof(FrameConstants),
nullptr, .data = &m_frame_constants,
0, }
nullptr,
1,
&begin_frame_barrier
); );
vk_cmd_begin_rendering(cmd, &rendering_info);
vk_cmd_bind_pipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pass->get_pipeline()); using AccessFlagBits = vk::CommandBuffer::ImageBarrierInfo::AccessFlagBits;
vk_cmd_set_viewport(cmd, 0, 1, &viewport); cmd.image_barrier(
vk_cmd_set_scissors(cmd, 0, 1, &scissor); {
vk_cmd_draw(cmd, m_current_sprite_idx, 1, 0, 0); .image = &m_swapchain->get_image(image_idx),
vk_cmd_end_rendering(cmd); .range = vk::Image::full_color_range,
vk_cmd_pipeline_barrier( .src_stages = vk::PipelineStageFlags::color_attachment_output_bit,
cmd, .dst_stages = vk::PipelineStageFlags::color_attachment_output_bit,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, .src_accesses = AccessFlagBits::none,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, .dst_accesses = AccessFlagBits::color_attachment_write,
0, .src_layout = vk::Image::Layout::undefined,
0, .dst_layout = vk::Image::Layout::color_attachment_optimal,
nullptr, }
0,
nullptr,
1,
&end_frame_barrier
); );
vkc(vk_end_command_buffer(cmd));
using Attachment = vk::CommandBuffer::RenderingInfo::AttachmentInfo;
cmd.begin_rendering(
{
.area_offset = {0u, 0u,},
.area_extent = m_resolution,
.color_attachments = std::vector<Attachment> {
Attachment{
.view= &m_swapchain->get_image_view(image_idx),
.layout = vk::Image::Layout::color_attachment_optimal,
.load_operation = Attachment::LoadOperation::load,
.store_operation = Attachment::StoreOperation::store,
.color_clear_values = {.5f, .5f, .5f, 1.f}
}
}
}
);
cmd.bind_pipeline(m_pass->get_pipeline(), vk::Pipeline::BindPoint::graphics);
// cmd.set_viewport();
// cmd.set_scissors();
cmd.draw(
{
.vertex_count = static_cast<std::uint32_t>(m_current_sprite_idx),
.instance_count = 1u,
.first_vertex = 0u,
.first_instance = 0u,
}
);
cmd.end_rendering();
cmd.image_barrier(
{
.image = &m_swapchain->get_image(image_idx),
.src_stages = vk::PipelineStageFlags::color_attachment_output_bit,
.dst_stages = vk::PipelineStageFlags::bottom_of_pipe_bit,
.src_accesses = AccessFlagBits::color_attachment_read
| AccessFlagBits::color_attachment_write,
.dst_accesses = {},
.src_layout = vk::Image::Layout::color_attachment_optimal,
.dst_layout = vk::Image::Layout::present_src,
}
);
cmd.end();
} }
void Renderer::submit_sprite( void Renderer::submit_sprite(
@ -462,5 +439,3 @@ void Renderer::submit_sprite(
.color = sprite.color, .color = sprite.color,
}; };
} }
} // namespace lt::renderer::vk