wip: convert from include style to module import style :D
Some checks reported errors
continuous-integration/drone/push Build was killed
Some checks reported errors
continuous-integration/drone/push Build was killed
This commit is contained in:
parent
b4fe163f15
commit
1df42cf30d
50 changed files with 1198 additions and 981 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
);
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <renderer/backend/vk/vulkan.hpp>
|
||||
|
||||
namespace lt::renderer::vk {
|
||||
|
||||
|
||||
} // namespace lt::renderer::vk
|
||||
|
|
@ -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" };
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -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" };
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
{
|
||||
183
modules/renderer/vk/pass.cppm
Normal file
183
modules/renderer/vk/pass.cppm
Normal 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"
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
@ -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>
|
||||
Loading…
Add table
Reference in a new issue