mirror of
https://github.com/slendidev/lunar.git
synced 2025-12-08 10:29:52 +02:00
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +1,6 @@
|
||||
[submodule "thirdparty/imgui"]
|
||||
path = thirdparty/imgui
|
||||
url = https://github.com/ocornut/imgui.git
|
||||
[submodule "thirdparty/smath"]
|
||||
path = thirdparty/smath
|
||||
url = https://github.com/slendidev/smath.git
|
||||
|
||||
@@ -47,6 +47,8 @@ add_project_arguments(
|
||||
'-Wno-unsafe-buffer-usage',
|
||||
'-Wno-c23-extensions',
|
||||
'-Wno-old-style-cast',
|
||||
'-Wno-implicit-int-float-conversion',
|
||||
'-Wno-implicit-float-conversion',
|
||||
],
|
||||
language : 'cpp'
|
||||
)
|
||||
@@ -89,7 +91,11 @@ exe = executable('vr-compositor',
|
||||
'src/VulkanRenderer.cpp',
|
||||
'src/Application.cpp',
|
||||
],
|
||||
include_directories: [ vkbootstrap_inc, imgui_inc ],
|
||||
include_directories: [
|
||||
vkbootstrap_inc,
|
||||
imgui_inc,
|
||||
'thirdparty/smath/include'
|
||||
],
|
||||
link_with: imgui_lib,
|
||||
dependencies: [
|
||||
wayland_dep,
|
||||
|
||||
@@ -17,6 +17,8 @@ shader_sources = files(
|
||||
'gradient.comp',
|
||||
'triangle.frag',
|
||||
'triangle.vert',
|
||||
'triangle_mesh.frag',
|
||||
'triangle_mesh.vert',
|
||||
)
|
||||
|
||||
spirv_shaders = []
|
||||
|
||||
11
shaders/triangle_mesh.frag
Normal file
11
shaders/triangle_mesh.frag
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 450
|
||||
|
||||
layout (location = 0) in vec3 in_color;
|
||||
layout (location = 1) in vec3 in_uv;
|
||||
|
||||
layout (location = 0) out vec4 out_frag_color;
|
||||
|
||||
void main() {
|
||||
out_frag_color = vec4(in_color, 1.0f);
|
||||
}
|
||||
|
||||
32
shaders/triangle_mesh.vert
Normal file
32
shaders/triangle_mesh.vert
Normal file
@@ -0,0 +1,32 @@
|
||||
#version 450
|
||||
#extension GL_EXT_buffer_reference : require
|
||||
|
||||
layout (location = 0) out vec3 out_color;
|
||||
layout (location = 1) out vec3 out_uv;
|
||||
|
||||
struct Vertex {
|
||||
vec3 position;
|
||||
float uv_x;
|
||||
vec3 normal;
|
||||
float uv_y;
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
layout(buffer_reference, std430) readonly buffer VertexBuffer{
|
||||
Vertex vertices[];
|
||||
};
|
||||
|
||||
layout(push_constant) uniform constants {
|
||||
mat4 world_matrix;
|
||||
VertexBuffer vertex_buffer;
|
||||
} PushConstants;
|
||||
|
||||
void main() {
|
||||
Vertex v = PushConstants.vertex_buffer.vertices[gl_VertexIndex];
|
||||
|
||||
gl_Position = PushConstants.world_matrix * vec4(v.position, 1.0f);
|
||||
out_color = v.color.xyz;
|
||||
out_uv.x = v.uv_x;
|
||||
out_uv.y = v.uv_y;
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <vk_mem_alloc.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace Lunar {
|
||||
|
||||
struct AllocatedImage {
|
||||
VkImage image;
|
||||
VkImageView image_view;
|
||||
VmaAllocation allocation;
|
||||
VkExtent3D extent;
|
||||
VkFormat format;
|
||||
};
|
||||
|
||||
} // namespace Lunar
|
||||
@@ -33,6 +33,7 @@ VulkanRenderer::VulkanRenderer(SDL_Window *window, Logger &logger)
|
||||
sync_init();
|
||||
descriptors_init();
|
||||
pipelines_init();
|
||||
default_data_init();
|
||||
imgui_init();
|
||||
}
|
||||
|
||||
@@ -150,6 +151,10 @@ auto VulkanRenderer::vk_init() -> void
|
||||
features_13.pNext = nullptr;
|
||||
features_13.synchronization2 = VK_TRUE;
|
||||
features_13.dynamicRendering = VK_TRUE;
|
||||
VkPhysicalDeviceBufferDeviceAddressFeatures buffer_device_address_features {};
|
||||
buffer_device_address_features.sType
|
||||
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES;
|
||||
buffer_device_address_features.bufferDeviceAddress = VK_TRUE;
|
||||
phys_device_selector.set_surface(m_vk.surface)
|
||||
.add_desired_extensions({
|
||||
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
|
||||
@@ -163,8 +168,10 @@ auto VulkanRenderer::vk_init() -> void
|
||||
VK_KHR_MAINTENANCE1_EXTENSION_NAME,
|
||||
VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
|
||||
VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME,
|
||||
VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME,
|
||||
})
|
||||
.set_required_features_13(features_13);
|
||||
.set_required_features_13(features_13)
|
||||
.add_required_extension_features(buffer_device_address_features);
|
||||
auto physical_device_selector_return { phys_device_selector.select() };
|
||||
if (!physical_device_selector_return) {
|
||||
std::println(std::cerr,
|
||||
@@ -207,6 +214,7 @@ auto VulkanRenderer::vk_init() -> void
|
||||
allocator_ci.physicalDevice = m_vkb.phys_dev;
|
||||
allocator_ci.device = m_vkb.dev;
|
||||
allocator_ci.instance = m_vkb.instance;
|
||||
allocator_ci.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
|
||||
vmaCreateAllocator(&allocator_ci, &m_vk.allocator);
|
||||
|
||||
m_vk.deletion_queue.emplace(
|
||||
@@ -321,6 +329,7 @@ auto VulkanRenderer::pipelines_init() -> void
|
||||
{
|
||||
background_pipelines_init();
|
||||
triangle_pipeline_init();
|
||||
mesh_pipeline_init();
|
||||
}
|
||||
|
||||
auto VulkanRenderer::background_pipelines_init() -> void
|
||||
@@ -423,6 +432,70 @@ auto VulkanRenderer::triangle_pipeline_init() -> void
|
||||
});
|
||||
}
|
||||
|
||||
auto VulkanRenderer::mesh_pipeline_init() -> void
|
||||
{
|
||||
uint8_t triangle_vert_shader_data[] {
|
||||
#embed "triangle_mesh_vert.spv"
|
||||
};
|
||||
VkShaderModule triangle_vert_shader {};
|
||||
if (!vkutil::load_shader_module(
|
||||
std::span<uint8_t>(
|
||||
triangle_vert_shader_data, sizeof(triangle_vert_shader_data)),
|
||||
m_vkb.dev, &triangle_vert_shader)) {
|
||||
m_logger.err("Failed to load triangle vert shader");
|
||||
}
|
||||
|
||||
uint8_t triangle_frag_shader_data[] {
|
||||
#embed "triangle_mesh_frag.spv"
|
||||
};
|
||||
VkShaderModule triangle_frag_shader {};
|
||||
if (!vkutil::load_shader_module(
|
||||
std::span<uint8_t>(
|
||||
triangle_frag_shader_data, sizeof(triangle_frag_shader_data)),
|
||||
m_vkb.dev, &triangle_frag_shader)) {
|
||||
m_logger.err("Failed to load triangle frag shader");
|
||||
}
|
||||
|
||||
VkPushConstantRange push_constant_range {};
|
||||
push_constant_range.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
push_constant_range.offset = 0;
|
||||
push_constant_range.size = sizeof(GPUDrawPushConstants);
|
||||
|
||||
VkPipelineLayoutCreateInfo layout_ci {};
|
||||
layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
layout_ci.pNext = nullptr;
|
||||
layout_ci.pushConstantRangeCount = 1;
|
||||
layout_ci.pPushConstantRanges = &push_constant_range;
|
||||
|
||||
VK_CHECK(m_logger,
|
||||
vkCreatePipelineLayout(
|
||||
m_vkb.dev, &layout_ci, nullptr, &m_vk.mesh_pipeline_layout));
|
||||
|
||||
auto pip {
|
||||
GraphicsPipelineBuilder { m_logger }
|
||||
.set_pipeline_layout(m_vk.mesh_pipeline_layout)
|
||||
.set_shaders(triangle_vert_shader, triangle_frag_shader)
|
||||
.set_input_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
|
||||
.set_polygon_mode(VK_POLYGON_MODE_FILL)
|
||||
.set_cull_mode(VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE)
|
||||
.set_multisampling_none()
|
||||
.disable_blending()
|
||||
.disable_depth_testing()
|
||||
.set_color_attachment_format(m_vk.draw_image.format)
|
||||
.set_depth_format(VK_FORMAT_UNDEFINED)
|
||||
.build(m_vkb.dev),
|
||||
};
|
||||
m_vk.mesh_pipeline = pip;
|
||||
|
||||
vkDestroyShaderModule(m_vkb.dev, triangle_vert_shader, nullptr);
|
||||
vkDestroyShaderModule(m_vkb.dev, triangle_frag_shader, nullptr);
|
||||
|
||||
m_vk.deletion_queue.emplace([&]() {
|
||||
vkDestroyPipelineLayout(m_vkb.dev, m_vk.mesh_pipeline_layout, nullptr);
|
||||
vkDestroyPipeline(m_vkb.dev, m_vk.mesh_pipeline, nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
auto VulkanRenderer::imgui_init() -> void
|
||||
{
|
||||
VkDescriptorPoolSize pool_sizes[] = {
|
||||
@@ -488,6 +561,38 @@ auto VulkanRenderer::imgui_init() -> void
|
||||
});
|
||||
}
|
||||
|
||||
auto VulkanRenderer::default_data_init() -> void
|
||||
{
|
||||
std::array<Vertex, 4> rect_vertices;
|
||||
|
||||
rect_vertices[0].position = { 0.5, -0.5, 0 };
|
||||
rect_vertices[1].position = { 0.5, 0.5, 0 };
|
||||
rect_vertices[2].position = { -0.5, -0.5, 0 };
|
||||
rect_vertices[3].position = { -0.5, 0.5, 0 };
|
||||
|
||||
rect_vertices[0].color = { 0, 0, 0, 1 };
|
||||
rect_vertices[1].color = { 0.5, 0.5, 0.5, 1 };
|
||||
rect_vertices[2].color = { 1, 0, 0, 1 };
|
||||
rect_vertices[3].color = { 0, 1, 0, 1 };
|
||||
|
||||
std::array<uint32_t, 6> rect_indices;
|
||||
|
||||
rect_indices[0] = 0;
|
||||
rect_indices[1] = 1;
|
||||
rect_indices[2] = 2;
|
||||
|
||||
rect_indices[3] = 2;
|
||||
rect_indices[4] = 1;
|
||||
rect_indices[5] = 3;
|
||||
|
||||
m_vk.rectangle = upload_mesh(rect_indices, rect_vertices);
|
||||
|
||||
m_vk.deletion_queue.emplace([&]() {
|
||||
destroy_buffer(m_vk.rectangle.index_buffer);
|
||||
destroy_buffer(m_vk.rectangle.vertex_buffer);
|
||||
});
|
||||
}
|
||||
|
||||
auto VulkanRenderer::render() -> void
|
||||
{
|
||||
defer(m_vk.frame_number++);
|
||||
@@ -645,6 +750,19 @@ auto VulkanRenderer::draw_geometry(VkCommandBuffer cmd) -> void
|
||||
|
||||
vkCmdDraw(cmd, 3, 1, 0, 0);
|
||||
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_vk.mesh_pipeline);
|
||||
|
||||
GPUDrawPushConstants push_constants;
|
||||
push_constants.world_matrix = smath::Mat4 { 1.0f };
|
||||
push_constants.vertex_buffer = m_vk.rectangle.vertex_buffer_address;
|
||||
|
||||
vkCmdPushConstants(cmd, m_vk.mesh_pipeline_layout,
|
||||
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(push_constants), &push_constants);
|
||||
vkCmdBindIndexBuffer(
|
||||
cmd, m_vk.rectangle.index_buffer.buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
|
||||
vkCmdDrawIndexed(cmd, 6, 1, 0, 0, 0);
|
||||
|
||||
vkCmdEndRendering(cmd);
|
||||
}
|
||||
|
||||
@@ -804,4 +922,105 @@ auto VulkanRenderer::destroy_swapchain() -> void
|
||||
m_vk.swapchain_extent = { 0, 0 };
|
||||
}
|
||||
|
||||
auto VulkanRenderer::create_buffer(size_t alloc_size, VkBufferUsageFlags usage,
|
||||
VmaMemoryUsage memory_usage) -> AllocatedBuffer
|
||||
{
|
||||
VkBufferCreateInfo buffer_ci {};
|
||||
buffer_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
buffer_ci.pNext = nullptr;
|
||||
buffer_ci.flags = 0;
|
||||
buffer_ci.size = alloc_size;
|
||||
buffer_ci.usage = usage;
|
||||
buffer_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
|
||||
VmaAllocationCreateInfo alloc_ci {};
|
||||
alloc_ci.usage = memory_usage;
|
||||
alloc_ci.flags = 0;
|
||||
if (memory_usage == VMA_MEMORY_USAGE_CPU_ONLY) {
|
||||
alloc_ci.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT
|
||||
| VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
|
||||
}
|
||||
|
||||
AllocatedBuffer buffer;
|
||||
VK_CHECK(m_logger,
|
||||
vmaCreateBuffer(m_vk.allocator, &buffer_ci, &alloc_ci, &buffer.buffer,
|
||||
&buffer.allocation, &buffer.info));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
auto VulkanRenderer::destroy_buffer(AllocatedBuffer &buffer) -> void
|
||||
{
|
||||
vmaDestroyBuffer(m_vk.allocator, buffer.buffer, buffer.allocation);
|
||||
}
|
||||
|
||||
auto VulkanRenderer::upload_mesh(
|
||||
std::span<uint32_t> indices, std::span<Vertex> vertices) -> GPUMeshBuffers
|
||||
{
|
||||
auto const vertex_buffer_size { vertices.size() * sizeof(Vertex) };
|
||||
auto const index_buffer_size { indices.size() * sizeof(uint32_t) };
|
||||
|
||||
GPUMeshBuffers new_surface;
|
||||
new_surface.vertex_buffer = create_buffer(vertex_buffer_size,
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||
| VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
||||
VMA_MEMORY_USAGE_GPU_ONLY);
|
||||
|
||||
VkBufferDeviceAddressInfo device_address_info {};
|
||||
device_address_info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
|
||||
device_address_info.buffer = new_surface.vertex_buffer.buffer;
|
||||
|
||||
new_surface.vertex_buffer_address
|
||||
= vkGetBufferDeviceAddress(m_vkb.dev, &device_address_info);
|
||||
|
||||
new_surface.index_buffer = create_buffer(index_buffer_size,
|
||||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||
| VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
||||
VMA_MEMORY_USAGE_GPU_ONLY);
|
||||
|
||||
auto staging { create_buffer(vertex_buffer_size + index_buffer_size,
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) };
|
||||
|
||||
VmaAllocationInfo info {};
|
||||
vmaGetAllocationInfo(m_vk.allocator, staging.allocation, &info);
|
||||
|
||||
void *data = info.pMappedData;
|
||||
if (!data) {
|
||||
VkResult res = vmaMapMemory(m_vk.allocator, staging.allocation, &data);
|
||||
assert(res == VK_SUCCESS);
|
||||
}
|
||||
defer({
|
||||
if (info.pMappedData == nullptr) {
|
||||
vmaUnmapMemory(m_vk.allocator, staging.allocation);
|
||||
}
|
||||
});
|
||||
|
||||
memcpy(data, vertices.data(), vertex_buffer_size);
|
||||
memcpy(reinterpret_cast<void *>(
|
||||
reinterpret_cast<size_t>(data) + vertex_buffer_size),
|
||||
indices.data(), index_buffer_size);
|
||||
|
||||
immediate_submit([&](VkCommandBuffer cmd) {
|
||||
VkBufferCopy vertex_copy {};
|
||||
vertex_copy.dstOffset = 0;
|
||||
vertex_copy.srcOffset = 0;
|
||||
vertex_copy.size = vertex_buffer_size;
|
||||
|
||||
vkCmdCopyBuffer(cmd, staging.buffer, new_surface.vertex_buffer.buffer,
|
||||
1, &vertex_copy);
|
||||
|
||||
VkBufferCopy index_copy {};
|
||||
index_copy.dstOffset = 0;
|
||||
index_copy.srcOffset = vertex_buffer_size;
|
||||
index_copy.size = index_buffer_size;
|
||||
|
||||
vkCmdCopyBuffer(cmd, staging.buffer, new_surface.index_buffer.buffer, 1,
|
||||
&index_copy);
|
||||
});
|
||||
|
||||
destroy_buffer(staging);
|
||||
|
||||
return new_surface;
|
||||
}
|
||||
|
||||
} // namespace Lunar
|
||||
|
||||
@@ -5,16 +5,30 @@
|
||||
|
||||
#include <SDL3/SDL_video.h>
|
||||
#include <VkBootstrap.h>
|
||||
#include <smath.hpp>
|
||||
#include <vk_mem_alloc.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include "AllocatedImage.h"
|
||||
#include "DeletionQueue.h"
|
||||
#include "DescriptorAllocator.h"
|
||||
#include "Logger.h"
|
||||
#include "src/DescriptorAllocator.h"
|
||||
|
||||
namespace Lunar {
|
||||
|
||||
struct AllocatedImage {
|
||||
VkImage image;
|
||||
VkImageView image_view;
|
||||
VmaAllocation allocation;
|
||||
VkExtent3D extent;
|
||||
VkFormat format;
|
||||
};
|
||||
|
||||
struct AllocatedBuffer {
|
||||
VkBuffer buffer;
|
||||
VmaAllocation allocation;
|
||||
VmaAllocationInfo info;
|
||||
};
|
||||
|
||||
struct FrameData {
|
||||
VkCommandPool command_pool;
|
||||
VkCommandBuffer main_command_buffer;
|
||||
@@ -24,6 +38,24 @@ struct FrameData {
|
||||
DeletionQueue deletion_queue;
|
||||
};
|
||||
|
||||
struct Vertex {
|
||||
smath::Vec3 position;
|
||||
float uv_x;
|
||||
smath::Vec3 normal;
|
||||
float uv_y;
|
||||
smath::Vec4 color;
|
||||
};
|
||||
|
||||
struct GPUMeshBuffers {
|
||||
AllocatedBuffer index_buffer, vertex_buffer;
|
||||
VkDeviceAddress vertex_buffer_address;
|
||||
};
|
||||
|
||||
struct GPUDrawPushConstants {
|
||||
smath::Mat4 world_matrix;
|
||||
VkDeviceAddress vertex_buffer;
|
||||
};
|
||||
|
||||
constexpr unsigned FRAME_OVERLAP = 2;
|
||||
|
||||
class VulkanRenderer {
|
||||
@@ -46,7 +78,9 @@ private:
|
||||
auto pipelines_init() -> void;
|
||||
auto background_pipelines_init() -> void;
|
||||
auto triangle_pipeline_init() -> void;
|
||||
auto mesh_pipeline_init() -> void;
|
||||
auto imgui_init() -> void;
|
||||
auto default_data_init() -> void;
|
||||
|
||||
auto draw_background(VkCommandBuffer cmd) -> void;
|
||||
auto draw_geometry(VkCommandBuffer cmd) -> void;
|
||||
@@ -59,6 +93,12 @@ private:
|
||||
auto recreate_swapchain(uint32_t width, uint32_t height) -> void;
|
||||
auto destroy_swapchain() -> void;
|
||||
|
||||
auto create_buffer(size_t alloc_size, VkBufferUsageFlags usage,
|
||||
VmaMemoryUsage memory_usage) -> AllocatedBuffer;
|
||||
auto destroy_buffer(AllocatedBuffer &buffer) -> void;
|
||||
auto upload_mesh(std::span<uint32_t> indices, std::span<Vertex> vertices)
|
||||
-> GPUMeshBuffers;
|
||||
|
||||
struct {
|
||||
vkb::Instance instance;
|
||||
vkb::PhysicalDevice phys_dev;
|
||||
@@ -100,6 +140,11 @@ private:
|
||||
VkPipeline triangle_pipeline {};
|
||||
VkPipelineLayout triangle_pipeline_layout {};
|
||||
|
||||
VkPipeline mesh_pipeline {};
|
||||
VkPipelineLayout mesh_pipeline_layout {};
|
||||
|
||||
GPUMeshBuffers rectangle;
|
||||
|
||||
VkDescriptorPool imgui_descriptor_pool { VK_NULL_HANDLE };
|
||||
|
||||
DeletionQueue deletion_queue;
|
||||
|
||||
1
thirdparty/smath
vendored
Submodule
1
thirdparty/smath
vendored
Submodule
Submodule thirdparty/smath added at e32204db0c
Reference in New Issue
Block a user