wip: convert from include style to module import style :D
Some checks reported errors
continuous-integration/drone/push Build was killed

This commit is contained in:
light7734 2025-11-09 17:16:57 +03:30
parent b4fe163f15
commit 1df42cf30d
Signed by: light7734
GPG key ID: 8C30176798F1A6BA
50 changed files with 1198 additions and 981 deletions

View file

@ -46,7 +46,7 @@ add_library_module(
vec2.cppm
vec3.cppm
vec4.cppm
components/transform.cppm
components.cppm
)
add_library_module(
@ -152,13 +152,14 @@ add_library_module(
INTERFACES
frontends.cppm
factory.cppm
backends/vk/library_wrapper.cppm
backends/vk/context/device.cppm
backends/vk/context/gpu.cppm
backends/vk/context/instance.cppm
backends/vk/context/surface.cppm
backends/vk/context/swapchain.cppm
backends/vk/data/buffer.cppm
vk/api_wrapper.cppm
vk/device.cppm
vk/gpu.cppm
vk/instance.cppm
vk/surface.cppm
vk/swapchain.cppm
vk/buffer.cppm
vk/pass.cppm
DEPENDENCIES
app
ecs

View file

@ -1,63 +0,0 @@
#pragma once
inline void bake_shader(
const std::filesystem::path &in_path,
const std::filesystem::path &out_path,
lt::assets::ShaderAsset::Type type
)
{
using lt::assets::ShaderAsset;
using enum lt::assets::ShaderAsset::Type;
auto glsl_path = in_path.string();
auto spv_path = std::format("{}.spv", glsl_path);
lt::log::trace(
"Compiling {} shader {} -> {}",
type == vertex ? "vertex" : "fragment",
glsl_path,
spv_path
);
// Don't bother linking to shaderc, just invoke the command with a system call.
// NOLINTNEXTLINE(concurrency-mt-unsafe)
system(
std::format(
"glslc --target-env=vulkan1.4 -std=450core -fshader-stage={} {} -o {}",
type == vertex ? "vert" : "frag",
glsl_path,
spv_path
)
.c_str()
);
auto stream = std::ifstream(spv_path, std::ios::binary);
lt::debug::ensure(
stream.is_open(),
"Failed to open compiled {} shader at: {}",
type == vertex ? "vert" : "frag",
spv_path
);
stream.seekg(0, std::ios::end);
const auto size = stream.tellg();
auto bytes = std::vector<std::byte>(size);
stream.seekg(0, std::ios::beg);
stream.read((char *)bytes.data(), size); // NOLINT
lt::log::debug("BYTES: {}", bytes.size());
stream.close();
std::filesystem::remove(spv_path);
ShaderAsset::pack(
out_path,
lt::assets::AssetMetadata {
.version = lt::assets::current_version,
.type = ShaderAsset::asset_type_identifier,
},
ShaderAsset::Metadata {
.type = type,
},
std::move(bytes)
);
}

View file

@ -1,3 +1,64 @@
#pragma once
#include <app/layer.hpp>
#include <imgui.h>
#include <math/vec2.hpp>
#include <memory/reference.hpp>
#include <mirror/panels/asset_browser.hpp>
#include <mirror/panels/properties.hpp>
#include <mirror/panels/scene_hierarchy.hpp>
#include <renderer/texture.hpp>
namespace lt {
class Scene;
class EditorLayer: public Layer
{
public:
EditorLayer(const std::string &name);
~EditorLayer() override;
EditorLayer(EditorLayer &&) = delete;
EditorLayer(const EditorLayer &) = delete;
auto operator=(EditorLayer &&) const -> EditorLayer & = delete;
auto operator=(const EditorLayer &) const -> EditorLayer & = delete;
void on_update(float delta_time) override;
void on_render() override;
void on_user_interface_update() override;
private:
std::string m_scene_dir;
math::vec2 m_direction;
float m_speed = 1000.0f;
memory::Ref<Scene> m_scene;
memory::Ref<SceneHierarchyPanel> m_sceneHierarchyPanel;
memory::Ref<PropertiesPanel> m_properties_panel;
memory::Ref<AssetBrowserPanel> m_content_browser_panel;
memory::Ref<Framebuffer> m_framebuffer;
Entity m_camera_entity;
ImVec2 m_available_content_region_prev;
};
} // namespace lt
#include <app/application.hpp>
#include <asset_manager/asset_manager.hpp>
#include <camera/component.hpp>

View file

@ -1,3 +1,51 @@
#pragma once
#include <filesystem>
#include <memory/reference.hpp>
#include <mirror/panels/panel.hpp>
#include <renderer/texture.hpp>
namespace lt {
class Scene;
class AssetBrowserPanel: public Panel
{
public:
AssetBrowserPanel(memory::Ref<Scene> active_scene);
void on_user_interface_update();
private:
enum class AssetType
{
none = 0,
scene,
directory,
text,
image,
};
std::filesystem::path m_current_directory;
const std::filesystem::path m_assets_path;
float m_file_size = 128.0f;
float m_file_padding = 8.0f;
memory::Ref<Scene> m_active_scene;
memory::Ref<Texture> m_directory_texture;
memory::Ref<Texture> m_scene_texture;
memory::Ref<Texture> m_image_texture;
memory::Ref<Texture> m_text_texture;
};
} // namespace lt
#include <asset_manager/asset_manager.hpp>
#include <ecs/registry.hpp>
#include <ecs/serializer.hpp>

View file

@ -1,3 +1,36 @@
#pragma once
#include <ecs/entity.hpp>
#include <math/vec3.hpp>
#include <mirror/panels/panel.hpp>
namespace lt {
class PropertiesPanel: public Panel
{
public:
PropertiesPanel() = default;
void on_user_interface_update();
void set_entity_context(const Entity &entity);
private:
void draw_vec3_control(
const std::string &label,
math::vec3 &values,
float reset_value = 0.0f,
float column_width = 100.0f
);
template<typename ComponentType, typename UIFunction>
void draw_component(const std::string &name, Entity entity, UIFunction function);
Entity m_entity_context;
};
} // namespace lt
#include <asset_manager/asset_manager.hpp>
#include <camera/component.hpp>
#include <ecs/components.hpp>

View file

@ -1,3 +1,42 @@
#pragma once
#include <ecs/entity.hpp>
#include <ecs/registry.hpp>
#include <memory/reference.hpp>
#include <mirror/panels/panel.hpp>
namespace lt {
class PropertiesPanel;
class SceneHierarchyPanel: public Panel
{
public:
SceneHierarchyPanel();
SceneHierarchyPanel(
memory::Ref<Scene> context,
memory::Ref<PropertiesPanel> properties_panel = nullptr
);
void on_user_interface_update();
void set_context(
memory::Ref<Scene> context,
memory::Ref<PropertiesPanel> properties_panel = nullptr
);
private:
void draw_node(Entity entity, const std::string &label);
memory::Ref<Scene> m_context;
memory::Ref<PropertiesPanel> m_properties_panel_context;
Entity m_selection_context;
};
} // namespace lt
#include <ecs/components.hpp>
#include <imgui.h>
#include <memory/reference.hpp>

View file

@ -1,59 +0,0 @@
#pragma once
#include <app/layer.hpp>
#include <imgui.h>
#include <math/vec2.hpp>
#include <memory/reference.hpp>
#include <mirror/panels/asset_browser.hpp>
#include <mirror/panels/properties.hpp>
#include <mirror/panels/scene_hierarchy.hpp>
#include <renderer/texture.hpp>
namespace lt {
class Scene;
class EditorLayer: public Layer
{
public:
EditorLayer(const std::string &name);
~EditorLayer() override;
EditorLayer(EditorLayer &&) = delete;
EditorLayer(const EditorLayer &) = delete;
auto operator=(EditorLayer &&) const -> EditorLayer & = delete;
auto operator=(const EditorLayer &) const -> EditorLayer & = delete;
void on_update(float delta_time) override;
void on_render() override;
void on_user_interface_update() override;
private:
std::string m_scene_dir;
math::vec2 m_direction;
float m_speed = 1000.0f;
memory::Ref<Scene> m_scene;
memory::Ref<SceneHierarchyPanel> m_sceneHierarchyPanel;
memory::Ref<PropertiesPanel> m_properties_panel;
memory::Ref<AssetBrowserPanel> m_content_browser_panel;
memory::Ref<Framebuffer> m_framebuffer;
Entity m_camera_entity;
ImVec2 m_available_content_region_prev;
};
} // namespace lt

View file

@ -1,48 +0,0 @@
#pragma once
#include <filesystem>
#include <memory/reference.hpp>
#include <mirror/panels/panel.hpp>
#include <renderer/texture.hpp>
namespace lt {
class Scene;
class AssetBrowserPanel: public Panel
{
public:
AssetBrowserPanel(memory::Ref<Scene> active_scene);
void on_user_interface_update();
private:
enum class AssetType
{
none = 0,
scene,
directory,
text,
image,
};
std::filesystem::path m_current_directory;
const std::filesystem::path m_assets_path;
float m_file_size = 128.0f;
float m_file_padding = 8.0f;
memory::Ref<Scene> m_active_scene;
memory::Ref<Texture> m_directory_texture;
memory::Ref<Texture> m_scene_texture;
memory::Ref<Texture> m_image_texture;
memory::Ref<Texture> m_text_texture;
};
} // namespace lt

View file

@ -1,33 +0,0 @@
#pragma once
#include <ecs/entity.hpp>
#include <math/vec3.hpp>
#include <mirror/panels/panel.hpp>
namespace lt {
class PropertiesPanel: public Panel
{
public:
PropertiesPanel() = default;
void on_user_interface_update();
void set_entity_context(const Entity &entity);
private:
void draw_vec3_control(
const std::string &label,
math::vec3 &values,
float reset_value = 0.0f,
float column_width = 100.0f
);
template<typename ComponentType, typename UIFunction>
void draw_component(const std::string &name, Entity entity, UIFunction function);
Entity m_entity_context;
};
} // namespace lt

View file

@ -1,39 +0,0 @@
#pragma once
#include <ecs/entity.hpp>
#include <ecs/registry.hpp>
#include <memory/reference.hpp>
#include <mirror/panels/panel.hpp>
namespace lt {
class PropertiesPanel;
class SceneHierarchyPanel: public Panel
{
public:
SceneHierarchyPanel();
SceneHierarchyPanel(
memory::Ref<Scene> context,
memory::Ref<PropertiesPanel> properties_panel = nullptr
);
void on_user_interface_update();
void set_context(
memory::Ref<Scene> context,
memory::Ref<PropertiesPanel> properties_panel = nullptr
);
private:
void draw_node(Entity entity, const std::string &label);
memory::Ref<Scene> m_context;
memory::Ref<PropertiesPanel> m_properties_panel_context;
Entity m_selection_context;
};
} // namespace lt

View file

@ -1,296 +0,0 @@
#include <renderer/backend/vk/context/device.hpp>
#include <renderer/backend/vk/context/swapchain.hpp>
#include <renderer/backend/vk/renderer/pass.hpp>
#include <renderer/data/frame_constants.hpp>
namespace lt::renderer::vk {
Pass::Pass(
IDevice *device,
ISwapchain *swapchain,
const lt::assets::ShaderAsset &vertex_shader,
const lt::assets::ShaderAsset &fragment_shader
)
: m_device(static_cast<Device *>(device))
{
auto binding = VkDescriptorSetLayoutBinding {
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.descriptorCount = 1'000,
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
};
const auto descriptor_binding_flags = VkDescriptorBindingFlagsEXT {
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT
| VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT
| VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT
| VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT,
};
constexpr auto descriptor_count = uint32_t { 1'000 };
auto descriptor_binding_flags_info = VkDescriptorSetLayoutBindingFlagsCreateInfoEXT {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT,
.bindingCount = 1,
.pBindingFlags = &descriptor_binding_flags,
};
m_vertices_descriptor_set_layout = m_device->create_descriptor_set_layout(
{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.pNext = &descriptor_binding_flags_info,
.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT,
.bindingCount = 1u,
.pBindings = &binding,
}
);
auto pool_size = VkDescriptorPoolSize {
.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.descriptorCount = descriptor_count,
};
m_descriptor_pool = m_device->create_desscriptor_pool(
{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.poolSizeCount = 1u,
.pPoolSizes = &pool_size,
}
);
auto descriptor_set_variable_descriptor_count_info
= VkDescriptorSetVariableDescriptorCountAllocateInfo {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO,
.descriptorSetCount = 1u,
.pDescriptorCounts = &descriptor_count,
};
m_vertices_descriptor_set = m_device->allocate_descriptor_set(
VkDescriptorSetAllocateInfo {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.pNext = &descriptor_set_variable_descriptor_count_info,
.descriptorPool = m_descriptor_pool,
.descriptorSetCount = 1u,
.pSetLayouts = &m_vertices_descriptor_set_layout,
}
);
m_layout = m_device->create_pipeline_layout(
std::vector<VkDescriptorSetLayout> {
m_vertices_descriptor_set_layout,
},
std::vector<VkPushConstantRange> {
VkPushConstantRange {
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
.offset = 0u,
.size = sizeof(FrameConstants),
},
}
);
auto *vertex_module = create_module(
vertex_shader.unpack(lt::assets::ShaderAsset::BlobTag::code)
);
auto *fragment_module = create_module(
fragment_shader.unpack(lt::assets::ShaderAsset::BlobTag::code)
);
auto shader_stages = std::array<VkPipelineShaderStageCreateInfo, 2> {
VkPipelineShaderStageCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_VERTEX_BIT,
.module = vertex_module,
.pName = "main",
},
VkPipelineShaderStageCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
.module = fragment_module,
.pName = "main",
},
};
auto dynamic_states = std::array<VkDynamicState, 2> {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR,
};
auto dynamic_state = VkPipelineDynamicStateCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.dynamicStateCount = static_cast<uint32_t>(dynamic_states.size()),
.pDynamicStates = dynamic_states.data(),
};
auto vertex_input = VkPipelineVertexInputStateCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
};
auto input_assembly = VkPipelineInputAssemblyStateCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
.primitiveRestartEnable = VK_FALSE,
};
auto viewport_state = VkPipelineViewportStateCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.viewportCount = 1u,
.scissorCount = 1u,
};
auto rasterization = VkPipelineRasterizationStateCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.depthClampEnable = VK_FALSE,
.rasterizerDiscardEnable = VK_FALSE,
.polygonMode = VK_POLYGON_MODE_FILL,
.cullMode = VK_CULL_MODE_NONE,
.frontFace = VK_FRONT_FACE_CLOCKWISE,
.lineWidth = 1.0,
};
auto multisampling = VkPipelineMultisampleStateCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
.sampleShadingEnable = VK_FALSE,
.minSampleShading = 1.0,
.pSampleMask = nullptr,
.alphaToCoverageEnable = VK_FALSE,
.alphaToOneEnable = VK_FALSE,
};
auto color_blend_attachment = VkPipelineColorBlendAttachmentState {
.blendEnable = VK_FALSE,
.srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO,
.colorBlendOp = VK_BLEND_OP_ADD,
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
.alphaBlendOp = VK_BLEND_OP_ADD,
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
};
auto color_blend = VkPipelineColorBlendStateCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
.logicOpEnable = VK_FALSE,
.logicOp = VK_LOGIC_OP_COPY,
.attachmentCount = 1,
.pAttachments = &color_blend_attachment,
.blendConstants = { 0.0f, 0.0, 0.0, 0.0 },
};
// auto attachment_description = VkAttachmentDescription {
// .format =,
// .samples = VK_SAMPLE_COUNT_1_BIT,
// .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
// .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
// .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
// .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
// .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
// .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
// };
auto color_attachment_ref = VkAttachmentReference {
.attachment = 0,
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
};
auto subpass_description = VkSubpassDescription {
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.colorAttachmentCount = 1u,
.pColorAttachments = &color_attachment_ref,
};
auto pass_dependency = VkSubpassDependency {
.srcSubpass = VK_SUBPASS_EXTERNAL,
.dstSubpass = 0u,
.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
.srcAccessMask = 0u,
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
};
auto color_format = static_cast<Swapchain *>(swapchain)->get_format();
auto rendering_info = VkPipelineRenderingCreateInfoKHR {
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
.colorAttachmentCount = 1u,
.pColorAttachmentFormats = &color_format,
};
m_pipeline = m_device->create_graphics_pipeline(
VkGraphicsPipelineCreateInfo {
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = &rendering_info,
.stageCount = static_cast<uint32_t>(shader_stages.size()),
.pStages = shader_stages.data(),
.pVertexInputState = &vertex_input,
.pInputAssemblyState = &input_assembly,
.pViewportState = &viewport_state,
.pRasterizationState = &rasterization,
.pMultisampleState = &multisampling,
.pDepthStencilState = nullptr,
.pColorBlendState = &color_blend,
.pDynamicState = &dynamic_state,
.layout = m_layout,
.renderPass = VK_NULL_HANDLE,
.subpass = 0u,
.basePipelineHandle = VK_NULL_HANDLE,
.basePipelineIndex = -1,
}
);
// m_framebuffers = static_cast<Swapchain *>(swapchain)->create_framebuffers_for_pass(m_pass);
m_device->destroy_shader_module(vertex_module);
m_device->destroy_shader_module(fragment_module);
}
Pass::~Pass()
{
if (!m_device)
{
return;
}
m_device->wait_idle();
m_device->destroy_descriptor_set_layout(m_vertices_descriptor_set_layout);
m_device->free_descriptor_set(m_descriptor_pool, m_vertices_descriptor_set);
m_device->destroy_descriptor_pool(m_descriptor_pool);
m_device->destroy_framebuffers(m_framebuffers);
m_device->destroy_pipeline(m_pipeline);
// m_device->destroy_pass(m_pass);
m_device->destroy_pipeline_layout(m_layout);
}
void Pass::replace_swapchain(const ISwapchain &swapchain)
{
if (!m_device)
{
return;
}
m_device->wait_idle();
m_device->destroy_framebuffers(m_framebuffers);
// m_framebuffers = static_cast<const Swapchain
// &>(swapchain).create_framebuffers_for_pass(m_pass);
}
auto Pass::create_module(lt::assets::Blob blob) -> VkShaderModule
{
return m_device->create_shader_module(
VkShaderModuleCreateInfo {
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
.codeSize = blob.size(),
.pCode = reinterpret_cast<const uint32_t *>(blob.data()) // NOLINT
}
);
}
} // namespace lt::renderer::vk

View file

@ -1,65 +0,0 @@
#pragma once
#include <assets/shader.hpp>
#include <memory/pointer_types/null_on_move.hpp>
#include <renderer/backend/vk/utils.hpp>
#include <renderer/frontend/renderer/pass.hpp>
namespace lt::renderer::vk {
class Pass: public IPass
{
public:
Pass(
class IDevice *device,
class ISwapchain *swapchain,
const lt::assets::ShaderAsset &vertex_shader,
const lt::assets::ShaderAsset &fragment_shader
);
~Pass() override;
Pass(Pass &&) = default;
Pass(const Pass &) = delete;
auto operator=(Pass &&) -> Pass & = default;
auto operator=(const Pass &) -> Pass & = delete;
void replace_swapchain(const ISwapchain &swapchain);
[[nodiscard]] auto get_pipeline() -> VkPipeline
{
return m_pipeline;
}
[[nodiscard]] auto get_layout() -> VkPipelineLayout
{
return m_layout;
}
[[nodiscard]] auto get_framebuffers() -> std::vector<VkFramebuffer> &
{
return m_framebuffers;
}
private:
auto create_module(lt::assets::Blob blob) -> VkShaderModule;
memory::NullOnMove<class Device *> m_device {};
VkPipeline m_pipeline = VK_NULL_HANDLE;
VkPipelineLayout m_layout = VK_NULL_HANDLE;
std::vector<VkFramebuffer> m_framebuffers;
VkDescriptorPool m_descriptor_pool = VK_NULL_HANDLE;
VkDescriptorSetLayout m_vertices_descriptor_set_layout;
VkDescriptorSet m_vertices_descriptor_set = VK_NULL_HANDLE;
};
} // namespace lt::renderer::vk

View file

@ -1,94 +0,0 @@
#pragma once
#include <memory/reference.hpp>
#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 {
class Renderer: public IRenderer
{
public:
Renderer(
class IGpu *gpu,
class IDevice *device,
class ISwapchain *swapchain,
uint32_t max_frames_in_flight
);
~Renderer() override;
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;
void replace_swapchain(ISwapchain *swapchain) override;
void set_frame_constants(FrameConstants constants) override
{
m_frame_constants = constants;
}
void submit_sprite(
const components::Sprite &sprite,
const math::components::Transform &transform
) override;
private:
void record_cmd(VkCommandBuffer cmd, uint32_t image_idx);
void map_buffers(uint32_t frame_idx);
void flush_buffers(VkCommandBuffer cmd);
memory::NullOnMove<class Device *> m_device {};
class Swapchain *m_swapchain {};
memory::Ref<class Pass> m_pass;
VkCommandPool m_pool = VK_NULL_HANDLE;
VkCommandPool m_transient_pool = VK_NULL_HANDLE;
std::vector<VkCommandBuffer> m_cmds;
std::vector<VkFence> m_frame_fences;
std::vector<VkSemaphore> m_aquire_image_semaphores;
std::vector<VkSemaphore> m_submit_semaphores;
VkExtent2D m_resolution;
uint32_t m_max_frames_in_flight {};
FrameConstants m_frame_constants;
Buffer m_vertex_buffer;
Buffer m_staging_buffer;
size_t m_staging_offset;
std::span<std::byte> m_staging_map;
std::span<components::Sprite::Vertex> m_sprite_vertex_map;
size_t m_current_sprite_idx;
};
} // namespace lt::renderer::vk

View file

@ -1,8 +0,0 @@
#pragma once
#include <renderer/backend/vk/vulkan.hpp>
namespace lt::renderer::vk {
} // namespace lt::renderer::vk

View file

@ -1,6 +1,8 @@
export module renderer.factory;
import renderer.frontend;
import assets.shader;
import renderer.backend.vk.device;
import renderer.vk.pass;
import renderer.backend.vk.instance;
import renderer.backend.vk.swapchain;
import renderer.backend.vk.buffer;
@ -26,6 +28,13 @@ export namespace lt::renderer {
[[nodiscard]] auto create_swapchain(Api target_api, ISurface *surface, IGpu *gpu, IDevice *device)
-> memory::Scope<ISwapchain>;
[[nodiscard]] auto create_pass(
lt::renderer::Api target_api,
IDevice *device,
const lt::assets::ShaderAsset &vertex_shader,
const lt::assets::ShaderAsset &fragment_shader
) -> memory::Scope<IPass>;
} // namespace lt::renderer
module :private;
@ -117,3 +126,80 @@ using namespace lt::renderer;
case Api::direct_x: throw std::runtime_error { "Invalid API" };
}
}
[[nodiscard]] auto create_pass(
lt::renderer::Api target_api,
IDevice *device,
const lt::assets::ShaderAsset &vertex_shader,
const lt::assets::ShaderAsset &fragment_shader
) -> memory::Scope<IPass>
{
debug::ensure(device, "Failed to create renderer::IPass: null device");
switch (target_api)
{
case Api::vulkan:
return memory::create_scope<vkb::Pass>(device, vertex_shader, fragment_shader);
case Api::none:
case Api::metal:
case Api::direct_x: throw std::runtime_error { "Invalid API" };
}
}
// [[nodiscard]] /* static */ auto IRenderer::create(
// Api target_api,
// IGpu *gpu,
// IDevice *device,
// ISwapchain *swapchain,
// uint32_t max_frames_in_flight
// ) -> memory::Scope<IRenderer>
// {
// ensure(gpu, "Failed to create renderer::IRenderer: null gpu");
// ensure(device, "Failed to create renderer::IRenderer: null device");
// ensure(swapchain, "Failed to create renderer::IRenderer: null swapchain");
// ensure(
// std::clamp(max_frames_in_flight, frames_in_flight_lower_limit, frames_in_flight_upper_limit)
// == max_frames_in_flight,
// "Failed to initialize renderer::System: max_frames_in_flight ({}) not within bounds ({} -> "
// "{}) ",
// max_frames_in_flight,
// frames_in_flight_lower_limit,
// 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(
// Api target_api,
// IInstance *instance,
// CreateInfo info
// ) -> memory::Scope<IDebugger>
// {
// debug::ensure(
// info.severities != MessageSeverity::none,
// "Failed to create vk::Messenger: severities == none"
// );
//
// 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,102 +0,0 @@
export module renderer.frontend;
import debug.assertions;
import memory.scope;
import bitwise;
import std;
namespace lt::renderer {
export class IMessenger
{
public:
enum class MessageSeverity : std::uint8_t
{
none = 0u,
verbose = bitwise::bit(0u),
info = bitwise::bit(1u),
warning = bitwise::bit(2u),
error = bitwise::bit(3u),
all = verbose | info | warning | error,
};
enum class MessageType : std::uint8_t
{
none = 0u,
general = bitwise::bit(0u),
validation = bitwise::bit(1u),
performance = bitwise::bit(2u),
all = general | validation | performance,
};
struct MessageData
{
std::string message;
};
using Callback_T = std::function<void(
MessageSeverity message_severity,
MessageType message_type,
const MessageData &data,
std::any &user_data
)>;
struct CreateInfo
{
MessageSeverity severities;
MessageType types;
Callback_T callback;
std::any user_data;
};
[[nodiscard]] static auto create(Api target_api, class IInstance *instance, CreateInfo info)
-> memory::Scope<IMessenger>;
IMessenger() = default;
virtual ~IMessenger() = default;
IMessenger(IMessenger &&) = default;
IMessenger(const IMessenger &) = delete;
auto operator=(IMessenger &&) -> IMessenger & = default;
auto operator=(const IMessenger &) -> IMessenger & = delete;
};
} // namespace lt::renderer
module :private;
using namespace lt::renderer;
import renderer.backends.vk.messenger;
[[nodiscard]] /* static */ auto IMessenger::create(
Api target_api,
IInstance *instance,
CreateInfo info
) -> memory::Scope<IMessenger>
{
debug::ensure(
info.severities != MessageSeverity::none,
"Failed to create vk::Messenger: severities == none"
);
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,29 +0,0 @@
#include <assets/shader.hpp>
#include <renderer/backend/vk/renderer/pass.hpp>
#include <renderer/frontend/context/gpu.hpp>
#include <renderer/frontend/renderer/pass.hpp>
namespace lt::renderer {
[[nodiscard]] /* static */ auto IPass::create(
lt::renderer::Api target_api,
IDevice *device,
ISwapchain *swapchain,
const lt::assets::ShaderAsset &vertex_shader,
const lt::assets::ShaderAsset &fragment_shader
) -> memory::Scope<IPass>
{
ensure(device, "Failed to create renderer::IPass: null device");
ensure(swapchain, "Failed to create renderer::IPass: null swapchain");
switch (target_api)
{
case Api::vulkan:
return memory::create_scope<vk::Pass>(device, swapchain, vertex_shader, fragment_shader);
case Api::none:
case Api::metal:
case Api::direct_x: throw std::runtime_error { "Invalid API" };
}
}
} // namespace lt::renderer

View file

@ -1,39 +0,0 @@
#pragma once
#include <renderer/api.hpp>
#include <renderer/frontend/context/swapchain.hpp>
namespace lt::assets {
class ShaderAsset;
}
namespace lt::renderer {
class IPass
{
public:
[[nodiscard]] static auto create(
lt::renderer::Api target_api,
class IDevice *device,
class ISwapchain *swapchain,
const class lt::assets::ShaderAsset &vertex_shader,
const class lt::assets::ShaderAsset &fragment_shader
) -> memory::Scope<IPass>;
IPass() = default;
virtual ~IPass() = default;
IPass(IPass &&) = default;
IPass(const IPass &) = delete;
auto operator=(IPass &&) -> IPass & = default;
auto operator=(const IPass &) -> IPass & = delete;
void replace_swapchain(const ISwapchain &swapchain);
};
} // namespace lt::renderer

View file

@ -1,40 +0,0 @@
#include <memory/scope.hpp>
#include <renderer/api.hpp>
#include <renderer/backend/vk/renderer/renderer.hpp>
#include <renderer/frontend/renderer/renderer.hpp>
namespace lt::renderer {
[[nodiscard]] /* static */ auto IRenderer::create(
Api target_api,
IGpu *gpu,
IDevice *device,
ISwapchain *swapchain,
uint32_t max_frames_in_flight
) -> memory::Scope<IRenderer>
{
ensure(gpu, "Failed to create renderer::IRenderer: null gpu");
ensure(device, "Failed to create renderer::IRenderer: null device");
ensure(swapchain, "Failed to create renderer::IRenderer: null swapchain");
ensure(
std::clamp(max_frames_in_flight, frames_in_flight_lower_limit, frames_in_flight_upper_limit)
== max_frames_in_flight,
"Failed to initialize renderer::System: max_frames_in_flight ({}) not within bounds ({} -> "
"{}) ",
max_frames_in_flight,
frames_in_flight_lower_limit,
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" };
}
}
} // namespace lt::renderer

View file

@ -1,57 +0,0 @@
#pragma once
#include <math/components/transform.hpp>
#include <memory/scope.hpp>
#include <renderer/api.hpp>
#include <renderer/components/sprite.hpp>
#include <renderer/data/frame_constants.hpp>
namespace lt::renderer {
class IRenderer
{
public:
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;
};
} // namespace lt::renderer

View file

@ -1,5 +1,5 @@
export module renderer.frontend;
import assets.shader;
import ecs.entity;
import math.vec2;
import memory.scope;
@ -157,4 +157,138 @@ public:
private:
};
class IPass
{
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;
virtual ~IPass() = default;
IPass(IPass &&) = default;
IPass(const IPass &) = delete;
auto operator=(IPass &&) -> IPass & = default;
auto operator=(const IPass &) -> IPass & = delete;
};
// class IRenderer
// {
// public:
// 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;
// };
// class IDebugger
// {
// public:
// enum class MessageSeverity : std::uint8_t
// {
// none = 0u,
//
// verbose = bitwise::bit(0u),
// info = bitwise::bit(1u),
// warning = bitwise::bit(2u),
// error = bitwise::bit(3u),
//
// all = verbose | info | warning | error,
// };
//
// enum class MessageType : std::uint8_t
// {
// none = 0u,
// general = bitwise::bit(0u),
// validation = bitwise::bit(1u),
// performance = bitwise::bit(2u),
//
// all = general | validation | performance,
// };
//
// struct MessageData
// {
// std::string message;
// };
//
// using Callback_T = std::function<void(
// MessageSeverity message_severity,
// MessageType message_type,
// const MessageData &data,
// std::any &user_data
// )>;
//
// struct CreateInfo
// {
// MessageSeverity severities;
//
// MessageType types;
//
// Callback_T callback;
//
// std::any user_data;
// };
//
// [[nodiscard]] static auto create(Api target_api, class IInstance *instance, CreateInfo info)
// -> memory::Scope<IDebugger>;
//
// IDebugger() = default;
//
// virtual ~IDebugger() = default;
//
// IDebugger(IDebugger &&) = default;
//
// IDebugger(const IDebugger &) = delete;
//
// auto operator=(IDebugger &&) -> IDebugger & = default;
//
// auto operator=(const IDebugger &) -> IDebugger & = delete;
// };
} // namespace lt::renderer

View file

@ -184,6 +184,29 @@ enum T : VkFlags // NOLINT
};
}
namespace ColorComponentFlags {
enum T : VkFlags // NOLINT
{
r_bit = VK_COLOR_COMPONENT_R_BIT,
g_bit = VK_COLOR_COMPONENT_G_BIT,
b_bit = VK_COLOR_COMPONENT_B_BIT,
a_bit = VK_COLOR_COMPONENT_A_BIT,
};
};
namespace SampleCountFlags {
enum T : VkFlags // NOLINT
{
_1_bit = VK_SAMPLE_COUNT_1_BIT,
_2_bit = VK_SAMPLE_COUNT_2_BIT,
_4_bit = VK_SAMPLE_COUNT_4_BIT,
_8_bit = VK_SAMPLE_COUNT_8_BIT,
_16_bit = VK_SAMPLE_COUNT_16_BIT,
_32_bit = VK_SAMPLE_COUNT_32_BIT,
_64_bit = VK_SAMPLE_COUNT_64_BIT,
};
}
namespace CompositeAlpha {
enum T : VkFlags // NOLINT
{
@ -194,12 +217,152 @@ enum T : VkFlags // NOLINT
};
}
namespace CullModeFlags {
enum T : VkFlags // NOLINT
{
none = VK_CULL_MODE_NONE,
front_bit = VK_CULL_MODE_FRONT_BIT,
back_bit = VK_CULL_MODE_BACK_BIT,
front_and_back = VK_CULL_MODE_FRONT_AND_BACK,
};
}
namespace ShaderStageFlags {
enum T : VkFlags // NOLINT
{
vertex_bit = VK_SHADER_STAGE_VERTEX_BIT,
tessellation_control_bit = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
tessellation_evaluation_bit = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
geometry_bit = VK_SHADER_STAGE_GEOMETRY_BIT,
fragment_bit = VK_SHADER_STAGE_FRAGMENT_BIT,
compute_bit = VK_SHADER_STAGE_COMPUTE_BIT,
all_graphics = VK_SHADER_STAGE_ALL_GRAPHICS,
all = VK_SHADER_STAGE_ALL,
raygen_bit_khr = VK_SHADER_STAGE_RAYGEN_BIT_KHR,
any_hit_bit_khr = VK_SHADER_STAGE_ANY_HIT_BIT_KHR,
closest_hit_bit_khr = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
miss_bit_khr = VK_SHADER_STAGE_MISS_BIT_KHR,
intersection_bit_khr = VK_SHADER_STAGE_INTERSECTION_BIT_KHR,
callable_bit_khr = VK_SHADER_STAGE_CALLABLE_BIT_KHR,
task_bit_ext = VK_SHADER_STAGE_TASK_BIT_EXT,
mesh_bit_ext = VK_SHADER_STAGE_MESH_BIT_EXT,
};
}
enum class SharingMode : std::underlying_type_t<VkSharingMode>
{
exclusive = VK_SHARING_MODE_EXCLUSIVE,
concurrent = VK_SHARING_MODE_CONCURRENT,
};
enum class PolygonMode
{
fill = VK_POLYGON_MODE_FILL,
line = VK_POLYGON_MODE_LINE,
point = VK_POLYGON_MODE_POINT,
};
enum class FrontFace : std::underlying_type_t<VkFrontFace>
{
counter_clockwise = VK_FRONT_FACE_COUNTER_CLOCKWISE,
clockwise = VK_FRONT_FACE_CLOCKWISE,
};
enum class BlendFactor : std::underlying_type_t<VkBlendFactor>
{
zero = VK_BLEND_FACTOR_ZERO,
one = VK_BLEND_FACTOR_ONE,
src_color = VK_BLEND_FACTOR_SRC_COLOR,
one_minus_src_color = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
dst_color = VK_BLEND_FACTOR_DST_COLOR,
one_minus_dst_color = VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
src_alpha = VK_BLEND_FACTOR_SRC_ALPHA,
one_minus_src_alpha = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
dst_alpha = VK_BLEND_FACTOR_DST_ALPHA,
one_minus_dst_alpha = VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
constant_color = VK_BLEND_FACTOR_CONSTANT_COLOR,
one_minus_constant_color = VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
constant_alpha = VK_BLEND_FACTOR_CONSTANT_ALPHA,
one_minus_constant_alpha = VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA,
src_alpha_saturate = VK_BLEND_FACTOR_SRC_ALPHA_SATURATE,
src1_color = VK_BLEND_FACTOR_SRC1_COLOR,
one_minus_src1_color = VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR,
src1_alpha = VK_BLEND_FACTOR_SRC1_ALPHA,
one_minus_src1_alpha = VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA,
};
enum class PrimitiveTopology : std::underlying_type_t<VkPrimitiveTopology>
{
point_list = VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
line_list = VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
line_strip = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
triangle_list = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
triangle_strip = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
triangle_fan = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
line_list_with_adjacency = VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
line_strip_with_adjacency = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
triangle_list_with_adjacency = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
triangle_strip_with_adjacency = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
patch_list = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
};
enum class BlendOperation : std::underlying_type_t<VkBlendOp>
{
add = VK_BLEND_OP_ADD,
subtract = VK_BLEND_OP_SUBTRACT,
reverse_subtract = VK_BLEND_OP_REVERSE_SUBTRACT,
min = VK_BLEND_OP_MIN,
max = VK_BLEND_OP_MAX,
zero = VK_BLEND_OP_ZERO_EXT,
src = VK_BLEND_OP_SRC_EXT,
dst = VK_BLEND_OP_DST_EXT,
src_over = VK_BLEND_OP_SRC_OVER_EXT,
dst_over = VK_BLEND_OP_DST_OVER_EXT,
src_in = VK_BLEND_OP_SRC_IN_EXT,
dst_in = VK_BLEND_OP_DST_IN_EXT,
src_out = VK_BLEND_OP_SRC_OUT_EXT,
dst_out = VK_BLEND_OP_DST_OUT_EXT,
src_atop = VK_BLEND_OP_SRC_ATOP_EXT,
dst_atop = VK_BLEND_OP_DST_ATOP_EXT,
_xor = VK_BLEND_OP_XOR_EXT,
multiply = VK_BLEND_OP_MULTIPLY_EXT,
screen = VK_BLEND_OP_SCREEN_EXT,
overlay = VK_BLEND_OP_OVERLAY_EXT,
darken = VK_BLEND_OP_DARKEN_EXT,
lighten = VK_BLEND_OP_LIGHTEN_EXT,
colordodge = VK_BLEND_OP_COLORDODGE_EXT,
colorburn = VK_BLEND_OP_COLORBURN_EXT,
hardlight = VK_BLEND_OP_HARDLIGHT_EXT,
softlight = VK_BLEND_OP_SOFTLIGHT_EXT,
difference = VK_BLEND_OP_DIFFERENCE_EXT,
exclusion = VK_BLEND_OP_EXCLUSION_EXT,
invert = VK_BLEND_OP_INVERT_EXT,
invert_rgb = VK_BLEND_OP_INVERT_RGB_EXT,
lineardodge = VK_BLEND_OP_LINEARDODGE_EXT,
linearburn = VK_BLEND_OP_LINEARBURN_EXT,
vividlight = VK_BLEND_OP_VIVIDLIGHT_EXT,
linearlight = VK_BLEND_OP_LINEARLIGHT_EXT,
pinlight = VK_BLEND_OP_PINLIGHT_EXT,
hardmix = VK_BLEND_OP_HARDMIX_EXT,
hsl_hue = VK_BLEND_OP_HSL_HUE_EXT,
hsl_saturation = VK_BLEND_OP_HSL_SATURATION_EXT,
hsl_color = VK_BLEND_OP_HSL_COLOR_EXT,
hsl_luminosity = VK_BLEND_OP_HSL_LUMINOSITY_EXT,
plus = VK_BLEND_OP_PLUS_EXT,
plus_clamped = VK_BLEND_OP_PLUS_CLAMPED_EXT,
plus_clamped_alpha = VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT,
plus_darker = VK_BLEND_OP_PLUS_DARKER_EXT,
minus = VK_BLEND_OP_MINUS_EXT,
minus_clamped = VK_BLEND_OP_MINUS_CLAMPED_EXT,
contrast = VK_BLEND_OP_CONTRAST_EXT,
invert_ovg = VK_BLEND_OP_INVERT_OVG_EXT,
red = VK_BLEND_OP_RED_EXT,
green = VK_BLEND_OP_GREEN_EXT,
blue = VK_BLEND_OP_BLUE_EXT,
};
enum class ColorSpace : std::underlying_type_t<VkColorSpaceKHR>
{
srgb_nonlinear = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
@ -1036,6 +1199,7 @@ public:
friend class Swapchain;
friend class Image;
friend class ImageView;
friend class Pipeline;
struct CreateInfo
{
@ -1627,6 +1791,212 @@ private:
VkDeviceMemory m_memory {};
};
class ShaderModule
{
public:
friend class Pipeline;
struct CreateInfo
{
std::vector<std::byte> code;
};
ShaderModule() = default;
ShaderModule(Device &device, CreateInfo info);
~ShaderModule();
ShaderModule(ShaderModule &&) = default;
ShaderModule(const ShaderModule &) = delete;
auto operator=(ShaderModule &&) -> ShaderModule & = default;
auto operator=(const Memory &) -> Memory & = delete;
private:
[[nodiscard]] auto get_vk_handle()
{
return m_shader_module;
}
memory::NullOnMove<VkDevice> m_device {};
VkShaderModule m_shader_module {};
};
class Pipeline
{
public:
static constexpr auto object_type = VK_OBJECT_TYPE_PIPELINE;
struct InputAssemblyState
{
PrimitiveTopology topology;
bool primitive_restart_enabled;
};
struct ViewportState
{
std::uint32_t viewport_count;
std::uint32_t scissor_count;
};
struct RasterizationState
{
bool depth_clamp_enabled;
bool discard_enabled;
PolygonMode polygon_mode;
CullModeFlags::T cull_mode;
FrontFace front_face;
bool depth_bias_enabled;
float depth_bias_constant_factor;
float depth_bias_clamp;
float depth_bias_slope_factor;
float line_width;
};
struct MultisamplingState
{
SampleCountFlags::T rasterizer_samples;
bool sample_shading_enabled;
float min_sample_shading;
bool alpha_to_coverage_enabled;
bool alpha_to_one_enabled;
};
struct AttachmentState
{
struct Color
{
vk::Format format;
bool blend_enabled;
BlendFactor src_color;
BlendFactor dst_color;
BlendFactor src_alpha;
BlendFactor dst_alpha;
BlendOperation color_op;
BlendOperation alpha_op;
ColorComponentFlags::T color_write_mask;
};
std::vector<Color> color_attachments;
std::optional<vk::Format> depth_attachment;
std::optional<vk::Format> stencil_attachment;
};
struct CreateInfo
{
std::vector<std::pair<ShaderModule, ShaderStageFlags::T>> shaders;
InputAssemblyState input_assembly_state;
ViewportState viewport_state;
RasterizationState rasterization_state;
MultisamplingState multisampling_state;
AttachmentState attachment_state;
std::string_view debug_name;
};
Pipeline() = default;
Pipeline(Device &device, class PipelineLayout &layout, CreateInfo info);
Pipeline(Pipeline &&) = default;
Pipeline(const Pipeline &) = delete;
auto operator=(Pipeline &&) -> Pipeline & = default;
auto operator=(const Pipeline &) -> Pipeline & = delete;
~Pipeline();
private:
memory::NullOnMove<VkDevice> m_device {};
VkPipeline m_pipeline {};
};
class PipelineLayout
{
public:
friend class Pipeline;
static constexpr auto object_type = VK_OBJECT_TYPE_PIPELINE_LAYOUT;
struct CreateInfo
{
};
PipelineLayout() = default;
PipelineLayout(Device &device, CreateInfo info);
PipelineLayout(PipelineLayout &&) = default;
PipelineLayout(const PipelineLayout &) = delete;
auto operator=(PipelineLayout &&) -> PipelineLayout & = default;
auto operator=(const PipelineLayout &) -> PipelineLayout & = delete;
~PipelineLayout();
private:
[[nodiscard]] auto get_vk_handle() -> VkPipelineLayout
{
return m_layout;
}
memory::NullOnMove<VkDevice> m_device {};
VkPipelineLayout m_layout {};
};
class DescriptorPool
{
};
class DescriptorSetLayout
{
};
class DescriptorSet
{
};
} // namespace lt::renderer::vk
@ -3151,6 +3521,143 @@ void Memory::unmap()
api::unmap_memory(m_device, m_memory);
}
Pipeline::Pipeline(Device &device, PipelineLayout &layout, CreateInfo info)
: m_device(device.m_device.get())
, m_pipeline()
{
auto shader_stages = std::vector<VkPipelineShaderStageCreateInfo> {};
for (auto &[shader, stage] : info.shaders)
{
shader_stages.emplace_back(
VkPipelineShaderStageCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = static_cast<VkShaderStageFlagBits>(stage),
.module = shader.get_vk_handle(),
.pName = "main",
}
);
}
auto dynamic_states = std::array<VkDynamicState, 2> {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR,
};
auto dynamic_state = VkPipelineDynamicStateCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.dynamicStateCount = static_cast<uint32_t>(dynamic_states.size()),
.pDynamicStates = dynamic_states.data(),
};
auto vertex_input = VkPipelineVertexInputStateCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
};
auto input_assembly = VkPipelineInputAssemblyStateCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.topology = static_cast<VkPrimitiveTopology>(info.input_assembly_state.topology),
.primitiveRestartEnable = info.input_assembly_state.primitive_restart_enabled,
};
auto viewport_state = VkPipelineViewportStateCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.viewportCount = info.viewport_state.viewport_count,
.scissorCount = info.viewport_state.scissor_count,
};
auto rasterization = VkPipelineRasterizationStateCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.depthClampEnable = VK_FALSE,
.rasterizerDiscardEnable = VK_FALSE,
.polygonMode = VK_POLYGON_MODE_FILL,
.cullMode = VK_CULL_MODE_NONE,
.frontFace = VK_FRONT_FACE_CLOCKWISE,
.lineWidth = 1.0,
};
auto multisampling = VkPipelineMultisampleStateCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
.sampleShadingEnable = VK_FALSE,
.minSampleShading = 1.0,
.pSampleMask = nullptr,
.alphaToCoverageEnable = VK_FALSE,
.alphaToOneEnable = VK_FALSE,
};
auto color_blend_attachment = VkPipelineColorBlendAttachmentState {
.blendEnable = VK_FALSE,
.srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO,
.colorBlendOp = VK_BLEND_OP_ADD,
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
.alphaBlendOp = VK_BLEND_OP_ADD,
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
};
auto color_blend = VkPipelineColorBlendStateCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
.logicOpEnable = VK_FALSE,
.logicOp = VK_LOGIC_OP_COPY,
.attachmentCount = 1,
.pAttachments = &color_blend_attachment,
.blendConstants = { 0.0f, 0.0, 0.0, 0.0 },
};
auto color_attachment_formats = std::vector<vk::Format> {};
for (auto &color_attachment : info.attachment_state.color_attachments)
{
}
auto rendering_info = VkPipelineRenderingCreateInfoKHR {
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
.colorAttachmentCount = static_cast<uint32_t>(color_attachment_formats.size()),
.pColorAttachmentFormats = std::bit_cast<VkFormat *>(color_attachment_formats.data()),
.depthAttachmentFormat = info.attachment_state.depth_attachment ?
static_cast<VkFormat>(
*info.attachment_state.depth_attachment
) :
VK_FORMAT_UNDEFINED,
.stencilAttachmentFormat = info.attachment_state.stencil_attachment ?
static_cast<VkFormat>(
*info.attachment_state.stencil_attachment
) :
VK_FORMAT_UNDEFINED,
};
auto vk_info = VkGraphicsPipelineCreateInfo {
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = &rendering_info,
.stageCount = static_cast<uint32_t>(shader_stages.size()),
.pStages = shader_stages.data(),
.pVertexInputState = &vertex_input,
.pInputAssemblyState = &input_assembly,
.pViewportState = &viewport_state,
.pRasterizationState = &rasterization,
.pMultisampleState = &multisampling,
.pDepthStencilState = nullptr,
.pColorBlendState = &color_blend,
.pDynamicState = &dynamic_state,
.layout = layout.get_vk_handle(),
.renderPass = nullptr,
.subpass = {},
.basePipelineHandle = nullptr,
.basePipelineIndex = -1,
};
vkc(api::create_graphics_pipelines(m_device, nullptr, 1u, &vk_info, nullptr, &m_pipeline));
}
Pipeline::~Pipeline()
{
}
[[nodiscard]]
auto enumerate_instance_extension_properties() -> std::vector<VkExtensionProperties>
{

View file

@ -0,0 +1,183 @@
export module renderer.vk.pass;
import renderer.backend.vk.library_wrapper;
import renderer.backend.vk.device;
import renderer.backend.vk.swapchain;
import assets.shader;
import assets.metadata;
import memory.null_on_move;
import renderer.frontend;
import std;
namespace lt::renderer::vkb {
export class Pass: public IPass
{
public:
Pass(
class IDevice *device,
const lt::assets::ShaderAsset &vertex_shader,
const lt::assets::ShaderAsset &fragment_shader
);
[[nodiscard]] auto get_pipeline() -> vk::Pipeline &
{
return m_pipeline;
}
[[nodiscard]] auto get_layout() -> vk::PipelineLayout &
{
return m_layout;
}
private:
Device *m_device {};
vk::PipelineLayout m_layout;
vk::Pipeline m_pipeline;
vk::DescriptorPool m_descriptor_pool;
vk::DescriptorSetLayout m_vertices_descriptor_set_layout;
vk::DescriptorSet m_vertices_descriptor_set;
};
} // namespace lt::renderer::vkb
module :private;
using namespace ::lt::renderer::vkb;
using namespace ::lt::renderer;
Pass::Pass(
IDevice *device,
const lt::assets::ShaderAsset &vertex_shader,
const lt::assets::ShaderAsset &fragment_shader
)
: m_device(static_cast<Device *>(device))
{
// auto binding = VkDescriptorSetLayoutBinding {
// .binding = 0,
// .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
// .descriptorCount = 1'000,
// .stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
// };
//
// const auto descriptor_binding_flags = VkDescriptorBindingFlagsEXT {
// VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT
// | VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT
// | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT
// | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT,
// };
//
// constexpr auto descriptor_count = uint32_t { 1'000 };
//
// auto descriptor_binding_flags_info = VkDescriptorSetLayoutBindingFlagsCreateInfoEXT {
// .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT,
// .bindingCount = 1,
// .pBindingFlags = &descriptor_binding_flags,
// };
//
//
// m_vertices_descriptor_set_layout = m_device->create_descriptor_set_layout(
// {
// .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
// .pNext = &descriptor_binding_flags_info,
// .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT,
// .bindingCount = 1u,
// .pBindings = &binding,
//
// }
// );
//
// auto pool_size = VkDescriptorPoolSize {
// .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
// .descriptorCount = descriptor_count,
// };
//
// m_descriptor_pool = m_device->create_desscriptor_pool(
// {
// .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
// .poolSizeCount = 1u,
// .pPoolSizes = &pool_size,
// }
// );
//
// auto descriptor_set_variable_descriptor_count_info
// = VkDescriptorSetVariableDescriptorCountAllocateInfo {
// .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO,
// .descriptorSetCount = 1u,
// .pDescriptorCounts = &descriptor_count,
// };
//
// m_vertices_descriptor_set = m_device->allocate_descriptor_set(
// VkDescriptorSetAllocateInfo {
// .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
// .pNext = &descriptor_set_variable_descriptor_count_info,
// .descriptorPool = m_descriptor_pool,
// .descriptorSetCount = 1u,
// .pSetLayouts = &m_vertices_descriptor_set_layout,
// }
// );
m_layout = vk::PipelineLayout(
m_device->vk(),
vk::PipelineLayout::CreateInfo {
// std::vector<VkDescriptorSetLayout> {
// m_vertices_descriptor_set_layout,
// },
//
// std::vector<VkPushConstantRange> {
// VkPushConstantRange {
// .stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
// .offset = 0u,
// .size = sizeof(FrameConstants),
// },
// },
}
);
auto shaders = std::vector<std::pair<vk::ShaderModule, vk::ShaderStageFlags::T>> {};
shaders.emplace_back(
vk::ShaderModule(
m_device->vk(),
vk::ShaderModule::CreateInfo {
.code = vertex_shader.unpack(lt::assets::ShaderAsset::BlobTag::code),
}
),
vk::ShaderStageFlags::vertex_bit
);
shaders.emplace_back(
vk::ShaderModule(
m_device->vk(),
vk::ShaderModule::CreateInfo {
.code = fragment_shader.unpack(lt::assets::ShaderAsset::BlobTag::code),
}
),
vk::ShaderStageFlags::fragment_bit
);
m_pipeline = vk::Pipeline(
m_device->vk(),
m_layout,
vk::Pipeline::CreateInfo {
.shaders = std::move(shaders),
.input_assembly_state = {
.topology = vk::PrimitiveTopology::triangle_list,
.primitive_restart_enabled = true,
},
.viewport_state = {
.viewport_count = 1u,
.scissor_count = 1u,
},
.rasterization_state = vk::Pipeline::RasterizationState {},
.multisampling_state = vk::Pipeline::MultisamplingState {},
.attachment_state = vk::
Pipeline::AttachmentState {},
.debug_name = "abcdefgh"
}
);
}

View file

@ -1,3 +1,100 @@
#pragma once
#include <memory/reference.hpp>
#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 {
class Renderer: public IRenderer
{
public:
Renderer(
class IGpu *gpu,
class IDevice *device,
class ISwapchain *swapchain,
uint32_t max_frames_in_flight
);
~Renderer() override;
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;
void replace_swapchain(ISwapchain *swapchain) override;
void set_frame_constants(FrameConstants constants) override
{
m_frame_constants = constants;
}
void submit_sprite(
const components::Sprite &sprite,
const math::components::Transform &transform
) override;
private:
void record_cmd(VkCommandBuffer cmd, uint32_t image_idx);
void map_buffers(uint32_t frame_idx);
void flush_buffers(VkCommandBuffer cmd);
memory::NullOnMove<class Device *> m_device {};
class Swapchain *m_swapchain {};
memory::Ref<class Pass> m_pass;
VkCommandPool m_pool = VK_NULL_HANDLE;
VkCommandPool m_transient_pool = VK_NULL_HANDLE;
std::vector<VkCommandBuffer> m_cmds;
std::vector<VkFence> m_frame_fences;
std::vector<VkSemaphore> m_aquire_image_semaphores;
std::vector<VkSemaphore> m_submit_semaphores;
VkExtent2D m_resolution;
uint32_t m_max_frames_in_flight {};
FrameConstants m_frame_constants;
Buffer m_vertex_buffer;
Buffer m_staging_buffer;
size_t m_staging_offset;
std::span<std::byte> m_staging_map;
std::span<components::Sprite::Vertex> m_sprite_vertex_map;
size_t m_current_sprite_idx;
};
} // namespace lt::renderer::vk
module :private;
#include <memory/reference.hpp>
#include <renderer/backend/vk/context/swapchain.hpp>
#include <renderer/backend/vk/renderer/renderer.hpp>