mirror of
https://github.com/slendidev/lunar.git
synced 2026-01-30 16:28:58 +02:00
Compare commits
2 Commits
59999f211d
...
ffe4712663
| Author | SHA1 | Date | |
|---|---|---|---|
| ffe4712663 | |||
| a99233fcbe |
@@ -45,6 +45,7 @@
|
||||
with pkgs;
|
||||
[
|
||||
llvmPackages_21.clang-tools
|
||||
llvmPackages_21.bintools
|
||||
lldb
|
||||
codespell
|
||||
doxygen
|
||||
|
||||
@@ -82,6 +82,8 @@ add_project_arguments(
|
||||
'-Wno-macro-redefined',
|
||||
'-DVULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE',
|
||||
'-DVULKAN_HPP_DISPATCH_LOADER_DYNAMIC=1',
|
||||
# Thanks forityf source
|
||||
'-Wno-#warnings'
|
||||
],
|
||||
language : 'cpp'
|
||||
)
|
||||
|
||||
21
shaders/gradient_fullscreen.frag
Normal file
21
shaders/gradient_fullscreen.frag
Normal file
@@ -0,0 +1,21 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
vec2 resolution;
|
||||
} pc;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 uv = (gl_FragCoord.xy + vec2(0.5)) / pc.resolution;
|
||||
|
||||
float v = sin(uv.x * 10.0) + cos(uv.y * 10.0);
|
||||
|
||||
float r = 0.5 + 0.5 * cos(6.2831 * (uv.x + v));
|
||||
float g = 0.5 + 0.5 * cos(6.2831 * (uv.y + v + 0.33));
|
||||
float b = 0.5 + 0.5 * cos(6.2831 * (uv.x - uv.y + 0.66));
|
||||
|
||||
out_color = vec4(r, g, b, 1.0);
|
||||
}
|
||||
|
||||
13
shaders/gradient_fullscreen.vert
Normal file
13
shaders/gradient_fullscreen.vert
Normal file
@@ -0,0 +1,13 @@
|
||||
#version 450
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 positions[3] = vec2[](
|
||||
vec2(-1.0, -1.0),
|
||||
vec2( 3.0, -1.0),
|
||||
vec2(-1.0, 3.0)
|
||||
);
|
||||
|
||||
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ else
|
||||
endif
|
||||
|
||||
shader_sources = files(
|
||||
'gradient.comp',
|
||||
'triangle.frag',
|
||||
'triangle.vert',
|
||||
'triangle_mesh.frag',
|
||||
|
||||
@@ -310,6 +310,8 @@ auto Application::run() -> void
|
||||
|
||||
ImGui::Render();
|
||||
|
||||
m_renderer->set_antialiasing(VulkanRenderer::AntiAliasingKind::MSAA_8X);
|
||||
|
||||
m_renderer->render([&](VulkanRenderer::GL &gl) {
|
||||
auto view { smath::matrix_look_at(smath::Vec3 { 0.0f, 0.0f, 3.0f },
|
||||
smath::Vec3 { 0.0f, 0.0f, 0.0f },
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "DescriptorAllocatorGrowable.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "Logger.h"
|
||||
#include "Util.h"
|
||||
|
||||
@@ -9,6 +11,10 @@ auto DescriptorAllocatorGrowable::init(VkDevice dev, uint32_t max_sets,
|
||||
std::span<PoolSizeRatio> pool_ratios) -> void
|
||||
{
|
||||
m_ratios.clear();
|
||||
m_current_pool = VK_NULL_HANDLE;
|
||||
m_full_pools.clear();
|
||||
m_used_pools.clear();
|
||||
m_ready_pools.clear();
|
||||
|
||||
m_ratios.insert(m_ratios.begin(), pool_ratios.begin(), pool_ratios.end());
|
||||
|
||||
@@ -23,25 +29,50 @@ auto DescriptorAllocatorGrowable::init(VkDevice dev, uint32_t max_sets,
|
||||
|
||||
auto DescriptorAllocatorGrowable::clear_pools(VkDevice dev) -> void
|
||||
{
|
||||
for (auto const p : m_ready_pools)
|
||||
std::vector<VkDescriptorPool> all_pools;
|
||||
all_pools.reserve(
|
||||
m_ready_pools.size() + m_used_pools.size() + m_full_pools.size());
|
||||
all_pools.insert(
|
||||
all_pools.end(), m_ready_pools.begin(), m_ready_pools.end());
|
||||
all_pools.insert(all_pools.end(), m_used_pools.begin(), m_used_pools.end());
|
||||
all_pools.insert(all_pools.end(), m_full_pools.begin(), m_full_pools.end());
|
||||
|
||||
std::sort(all_pools.begin(), all_pools.end());
|
||||
all_pools.erase(
|
||||
std::unique(all_pools.begin(), all_pools.end()), all_pools.end());
|
||||
|
||||
for (auto const p : all_pools) {
|
||||
vkResetDescriptorPool(dev, p, 0);
|
||||
for (auto const p : m_full_pools) {
|
||||
vkResetDescriptorPool(dev, p, 0);
|
||||
m_ready_pools.emplace_back(p);
|
||||
}
|
||||
|
||||
m_ready_pools = std::move(all_pools);
|
||||
m_used_pools.clear();
|
||||
m_full_pools.clear();
|
||||
m_current_pool = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
auto DescriptorAllocatorGrowable::destroy_pools(VkDevice dev) -> void
|
||||
{
|
||||
for (auto const p : m_ready_pools) {
|
||||
std::vector<VkDescriptorPool> all_pools;
|
||||
all_pools.reserve(
|
||||
m_ready_pools.size() + m_used_pools.size() + m_full_pools.size());
|
||||
all_pools.insert(
|
||||
all_pools.end(), m_ready_pools.begin(), m_ready_pools.end());
|
||||
all_pools.insert(all_pools.end(), m_used_pools.begin(), m_used_pools.end());
|
||||
all_pools.insert(all_pools.end(), m_full_pools.begin(), m_full_pools.end());
|
||||
|
||||
std::sort(all_pools.begin(), all_pools.end());
|
||||
all_pools.erase(
|
||||
std::unique(all_pools.begin(), all_pools.end()), all_pools.end());
|
||||
|
||||
for (auto const p : all_pools) {
|
||||
vkDestroyDescriptorPool(dev, p, nullptr);
|
||||
}
|
||||
|
||||
m_ready_pools.clear();
|
||||
for (auto const p : m_full_pools) {
|
||||
vkDestroyDescriptorPool(dev, p, nullptr);
|
||||
}
|
||||
m_used_pools.clear();
|
||||
m_full_pools.clear();
|
||||
m_current_pool = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
auto DescriptorAllocatorGrowable::allocate(Logger &logger, VkDevice dev,
|
||||
@@ -60,31 +91,36 @@ auto DescriptorAllocatorGrowable::allocate(Logger &logger, VkDevice dev,
|
||||
auto const res = vkAllocateDescriptorSets(dev, &alloci, &ds);
|
||||
if (res == VK_ERROR_OUT_OF_POOL_MEMORY || res == VK_ERROR_FRAGMENTED_POOL) {
|
||||
m_full_pools.emplace_back(pool_to_use);
|
||||
if (m_current_pool == pool_to_use) {
|
||||
m_current_pool = VK_NULL_HANDLE;
|
||||
}
|
||||
pool_to_use = get_pool(dev);
|
||||
alloci.descriptorPool = pool_to_use;
|
||||
VK_CHECK(logger, vkAllocateDescriptorSets(dev, &alloci, &ds));
|
||||
}
|
||||
|
||||
m_ready_pools.emplace_back(pool_to_use);
|
||||
return ds;
|
||||
}
|
||||
|
||||
auto DescriptorAllocatorGrowable::get_pool(VkDevice dev) -> VkDescriptorPool
|
||||
{
|
||||
VkDescriptorPool new_pool;
|
||||
if (m_current_pool != VK_NULL_HANDLE) {
|
||||
return m_current_pool;
|
||||
}
|
||||
|
||||
if (m_ready_pools.empty()) {
|
||||
new_pool = create_pool(dev, m_sets_per_pool, m_ratios);
|
||||
if (!m_ready_pools.empty()) {
|
||||
m_current_pool = m_ready_pools.back();
|
||||
m_ready_pools.pop_back();
|
||||
} else {
|
||||
m_current_pool = create_pool(dev, m_sets_per_pool, m_ratios);
|
||||
|
||||
m_sets_per_pool = static_cast<uint32_t>(m_sets_per_pool * 1.5);
|
||||
if (m_sets_per_pool > 4092)
|
||||
m_sets_per_pool = 4092;
|
||||
} else {
|
||||
new_pool = m_ready_pools.back();
|
||||
m_ready_pools.pop_back();
|
||||
}
|
||||
|
||||
return new_pool;
|
||||
m_used_pools.emplace_back(m_current_pool);
|
||||
return m_current_pool;
|
||||
}
|
||||
|
||||
auto DescriptorAllocatorGrowable::create_pool(VkDevice dev, uint32_t set_count,
|
||||
|
||||
@@ -30,7 +30,9 @@ private:
|
||||
std::span<PoolSizeRatio> pool_ratios) -> VkDescriptorPool;
|
||||
|
||||
std::vector<PoolSizeRatio> m_ratios;
|
||||
VkDescriptorPool m_current_pool { VK_NULL_HANDLE };
|
||||
std::vector<VkDescriptorPool> m_full_pools;
|
||||
std::vector<VkDescriptorPool> m_used_pools;
|
||||
std::vector<VkDescriptorPool> m_ready_pools;
|
||||
uint32_t m_sets_per_pool;
|
||||
};
|
||||
|
||||
@@ -79,9 +79,15 @@ auto GraphicsPipelineBuilder::set_cull_mode(VkCullModeFlags cull_mode,
|
||||
|
||||
auto GraphicsPipelineBuilder::set_multisampling_none()
|
||||
-> GraphicsPipelineBuilder &
|
||||
{
|
||||
return set_multisampling(VK_SAMPLE_COUNT_1_BIT);
|
||||
}
|
||||
|
||||
auto GraphicsPipelineBuilder::set_multisampling(VkSampleCountFlagBits samples)
|
||||
-> GraphicsPipelineBuilder &
|
||||
{
|
||||
m_multisampling.sampleShadingEnable = VK_FALSE;
|
||||
m_multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
m_multisampling.rasterizationSamples = samples;
|
||||
m_multisampling.minSampleShading = 1.0f;
|
||||
m_multisampling.pSampleMask = nullptr;
|
||||
m_multisampling.alphaToCoverageEnable = VK_FALSE;
|
||||
|
||||
@@ -25,6 +25,8 @@ struct GraphicsPipelineBuilder {
|
||||
auto set_cull_mode(VkCullModeFlags cull_mode, VkFrontFace front_face)
|
||||
-> GraphicsPipelineBuilder &;
|
||||
auto set_multisampling_none() -> GraphicsPipelineBuilder &;
|
||||
auto set_multisampling(VkSampleCountFlagBits samples)
|
||||
-> GraphicsPipelineBuilder &;
|
||||
auto disable_blending() -> GraphicsPipelineBuilder &;
|
||||
auto enable_blending_additive() -> GraphicsPipelineBuilder &;
|
||||
auto enable_blending_alpha_blend() -> GraphicsPipelineBuilder &;
|
||||
|
||||
@@ -89,7 +89,7 @@ auto load_shader_module(std::span<uint8_t> spirv_data, vk::Device device)
|
||||
namespace vkinit {
|
||||
|
||||
auto image_create_info(vk::Format format, vk::ImageUsageFlags usage_flags,
|
||||
vk::Extent3D extent) -> vk::ImageCreateInfo
|
||||
vk::Extent3D extent, vk::SampleCountFlagBits samples) -> vk::ImageCreateInfo
|
||||
{
|
||||
vk::ImageCreateInfo info {};
|
||||
info.imageType = vk::ImageType::e2D;
|
||||
@@ -97,7 +97,7 @@ auto image_create_info(vk::Format format, vk::ImageUsageFlags usage_flags,
|
||||
info.extent = extent;
|
||||
info.mipLevels = 1;
|
||||
info.arrayLayers = 1;
|
||||
info.samples = vk::SampleCountFlagBits::e1;
|
||||
info.samples = samples;
|
||||
info.tiling = vk::ImageTiling::eOptimal;
|
||||
info.usage = usage_flags;
|
||||
return info;
|
||||
|
||||
@@ -52,7 +52,9 @@ auto load_shader_module(std::span<uint8_t> spirv_data, vk::Device device)
|
||||
namespace vkinit {
|
||||
|
||||
auto image_create_info(vk::Format format, vk::ImageUsageFlags usage_flags,
|
||||
vk::Extent3D extent) -> vk::ImageCreateInfo;
|
||||
vk::Extent3D extent,
|
||||
vk::SampleCountFlagBits samples = vk::SampleCountFlagBits::e1)
|
||||
-> vk::ImageCreateInfo;
|
||||
auto imageview_create_info(vk::Format format, vk::Image image,
|
||||
vk::ImageAspectFlags aspect_flags) -> vk::ImageViewCreateInfo;
|
||||
auto command_buffer_submit_info(vk::CommandBuffer cmd)
|
||||
|
||||
@@ -56,8 +56,25 @@ auto VulkanRenderer::GL::begin_drawing(vk::CommandBuffer cmd,
|
||||
m_color_target->extent.height,
|
||||
};
|
||||
|
||||
auto color_att { vkinit::attachment_info(m_color_target->image_view,
|
||||
nullptr, vk::ImageLayout::eColorAttachmentOptimal) };
|
||||
vk::RenderingAttachmentInfo color_att {};
|
||||
vk::ClearValue clear {};
|
||||
clear.color = vk::ClearColorValue {
|
||||
smath::Vec4 { Colors::DARK_SLATE_GRAY, 1.0f },
|
||||
};
|
||||
if (m_renderer.m_vk.msaa_samples != vk::SampleCountFlagBits::e1) {
|
||||
assert(m_renderer.m_vk.msaa_color_image.image_view
|
||||
&& "MSAA enabled but MSAA color image is missing");
|
||||
color_att = vkinit::attachment_info(
|
||||
m_renderer.m_vk.msaa_color_image.image_view, &clear,
|
||||
vk::ImageLayout::eColorAttachmentOptimal);
|
||||
color_att.resolveMode = vk::ResolveModeFlagBits::eAverage;
|
||||
color_att.resolveImageView = m_color_target->image_view;
|
||||
color_att.resolveImageLayout = vk::ImageLayout::eColorAttachmentOptimal;
|
||||
color_att.storeOp = vk::AttachmentStoreOp::eDontCare;
|
||||
} else {
|
||||
color_att = vkinit::attachment_info(m_color_target->image_view, &clear,
|
||||
vk::ImageLayout::eColorAttachmentOptimal);
|
||||
}
|
||||
std::optional<vk::RenderingAttachmentInfo> depth_att;
|
||||
if (m_depth_target) {
|
||||
depth_att = vkinit::depth_attachment_info(m_depth_target->image_view,
|
||||
@@ -192,7 +209,8 @@ auto VulkanRenderer::GL::flush() -> void
|
||||
| vk::BufferUsageFlagBits::eTransferDst,
|
||||
VMA_MEMORY_USAGE_GPU_ONLY) };
|
||||
|
||||
m_renderer.immediate_submit([&](vk::CommandBuffer cmd) {
|
||||
m_renderer.immediate_submit(
|
||||
[&](vk::CommandBuffer cmd) {
|
||||
vk::BufferCopy vertex_copy {};
|
||||
vertex_copy.srcOffset = 0;
|
||||
vertex_copy.dstOffset = 0;
|
||||
@@ -204,8 +222,7 @@ auto VulkanRenderer::GL::flush() -> void
|
||||
index_copy.srcOffset = vertex_data_size;
|
||||
index_copy.dstOffset = 0;
|
||||
index_copy.size = index_data_size;
|
||||
cmd.copyBuffer(
|
||||
staging.buffer, index_buffer.buffer, 1, &index_copy);
|
||||
cmd.copyBuffer(staging.buffer, index_buffer.buffer, 1, &index_copy);
|
||||
},
|
||||
/*flush_frame_deletion_queue=*/false,
|
||||
/*clear_frame_descriptors=*/false);
|
||||
@@ -280,9 +297,8 @@ auto VulkanRenderer::GL::set_transform(smath::Mat4 const &transform) -> void
|
||||
m_transform = transform;
|
||||
}
|
||||
|
||||
auto VulkanRenderer::GL::draw_rectangle(
|
||||
smath::Vec2 pos, smath::Vec2 size, smath::Vec4 rect_color, float rotation)
|
||||
-> void
|
||||
auto VulkanRenderer::GL::draw_rectangle(smath::Vec2 pos, smath::Vec2 size,
|
||||
smath::Vec4 rect_color, float rotation) -> void
|
||||
{
|
||||
auto const half_size = size * 0.5f;
|
||||
auto const center = pos + half_size;
|
||||
@@ -293,10 +309,14 @@ auto VulkanRenderer::GL::draw_rectangle(
|
||||
return smath::Vec2 { c * p.x() - s * p.y(), s * p.x() + c * p.y() };
|
||||
};
|
||||
|
||||
auto const br = center + rotate(smath::Vec2 { half_size.x(), -half_size.y() });
|
||||
auto const tr = center + rotate(smath::Vec2 { half_size.x(), half_size.y() });
|
||||
auto const bl = center + rotate(smath::Vec2 { -half_size.x(), -half_size.y() });
|
||||
auto const tl = center + rotate(smath::Vec2 { -half_size.x(), half_size.y() });
|
||||
auto const br
|
||||
= center + rotate(smath::Vec2 { half_size.x(), -half_size.y() });
|
||||
auto const tr
|
||||
= center + rotate(smath::Vec2 { half_size.x(), half_size.y() });
|
||||
auto const bl
|
||||
= center + rotate(smath::Vec2 { -half_size.x(), -half_size.y() });
|
||||
auto const tl
|
||||
= center + rotate(smath::Vec2 { -half_size.x(), half_size.y() });
|
||||
|
||||
begin(GeometryKind::Quads);
|
||||
|
||||
@@ -473,7 +493,6 @@ VulkanRenderer::~VulkanRenderer()
|
||||
m_vk.imm_command_buffer.reset();
|
||||
m_vk.imm_command_pool.reset();
|
||||
m_vk.imm_fence.reset();
|
||||
m_vk.gradient_pipeline.reset();
|
||||
m_vk.triangle_pipeline.reset();
|
||||
m_vk.mesh_pipeline.reset();
|
||||
m_vk.default_sampler_linear.reset();
|
||||
@@ -481,6 +500,7 @@ VulkanRenderer::~VulkanRenderer()
|
||||
|
||||
destroy_swapchain();
|
||||
destroy_draw_image();
|
||||
destroy_msaa_color_image();
|
||||
destroy_depth_image();
|
||||
|
||||
m_vk.deletion_queue.flush();
|
||||
@@ -505,6 +525,97 @@ auto VulkanRenderer::resize(uint32_t width, uint32_t height) -> void
|
||||
recreate_swapchain(width, height);
|
||||
}
|
||||
|
||||
auto VulkanRenderer::set_antialiasing(AntiAliasingKind kind) -> void
|
||||
{
|
||||
auto requested_samples = [&](AntiAliasingKind aa) {
|
||||
switch (aa) {
|
||||
case AntiAliasingKind::NONE:
|
||||
return vk::SampleCountFlagBits::e1;
|
||||
case AntiAliasingKind::MSAA_2X:
|
||||
return vk::SampleCountFlagBits::e2;
|
||||
case AntiAliasingKind::MSAA_4X:
|
||||
return vk::SampleCountFlagBits::e4;
|
||||
case AntiAliasingKind::MSAA_8X:
|
||||
return vk::SampleCountFlagBits::e8;
|
||||
}
|
||||
return vk::SampleCountFlagBits::e1;
|
||||
}(kind);
|
||||
|
||||
auto best_supported = [&](vk::SampleCountFlagBits requested) {
|
||||
auto const supported = m_vk.supported_framebuffer_samples;
|
||||
|
||||
auto pick_if_supported = [&](vk::SampleCountFlagBits candidate) {
|
||||
return (supported & candidate) == candidate;
|
||||
};
|
||||
|
||||
if (requested >= vk::SampleCountFlagBits::e64
|
||||
&& pick_if_supported(vk::SampleCountFlagBits::e64)) {
|
||||
return vk::SampleCountFlagBits::e64;
|
||||
}
|
||||
if (requested >= vk::SampleCountFlagBits::e32
|
||||
&& pick_if_supported(vk::SampleCountFlagBits::e32)) {
|
||||
return vk::SampleCountFlagBits::e32;
|
||||
}
|
||||
if (requested >= vk::SampleCountFlagBits::e16
|
||||
&& pick_if_supported(vk::SampleCountFlagBits::e16)) {
|
||||
return vk::SampleCountFlagBits::e16;
|
||||
}
|
||||
if (requested >= vk::SampleCountFlagBits::e8
|
||||
&& pick_if_supported(vk::SampleCountFlagBits::e8)) {
|
||||
return vk::SampleCountFlagBits::e8;
|
||||
}
|
||||
if (requested >= vk::SampleCountFlagBits::e4
|
||||
&& pick_if_supported(vk::SampleCountFlagBits::e4)) {
|
||||
return vk::SampleCountFlagBits::e4;
|
||||
}
|
||||
if (requested >= vk::SampleCountFlagBits::e2
|
||||
&& pick_if_supported(vk::SampleCountFlagBits::e2)) {
|
||||
return vk::SampleCountFlagBits::e2;
|
||||
}
|
||||
return vk::SampleCountFlagBits::e1;
|
||||
}(requested_samples);
|
||||
|
||||
auto kind_for_samples = [](vk::SampleCountFlagBits samples) {
|
||||
switch (samples) {
|
||||
case vk::SampleCountFlagBits::e2:
|
||||
return AntiAliasingKind::MSAA_2X;
|
||||
case vk::SampleCountFlagBits::e4:
|
||||
return AntiAliasingKind::MSAA_4X;
|
||||
case vk::SampleCountFlagBits::e8:
|
||||
return AntiAliasingKind::MSAA_8X;
|
||||
default:
|
||||
return AntiAliasingKind::NONE;
|
||||
}
|
||||
};
|
||||
|
||||
auto const effective_kind = kind_for_samples(best_supported);
|
||||
if (m_vk.antialiasing_kind == effective_kind
|
||||
&& m_vk.msaa_samples == best_supported) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (best_supported != requested_samples) {
|
||||
m_logger.warn("Requested antialiasing {} but using {}",
|
||||
static_cast<int>(kind), static_cast<int>(effective_kind));
|
||||
}
|
||||
|
||||
m_vk.antialiasing_kind = effective_kind;
|
||||
m_vk.msaa_samples = best_supported;
|
||||
|
||||
if (!m_vk.swapchain || m_vk.swapchain_extent.width == 0
|
||||
|| m_vk.swapchain_extent.height == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_device.waitIdle();
|
||||
|
||||
create_msaa_color_image(
|
||||
m_vk.swapchain_extent.width, m_vk.swapchain_extent.height);
|
||||
create_depth_image(
|
||||
m_vk.swapchain_extent.width, m_vk.swapchain_extent.height);
|
||||
pipelines_init();
|
||||
}
|
||||
|
||||
auto VulkanRenderer::immediate_submit(
|
||||
std::function<void(vk::CommandBuffer cmd)> &&function,
|
||||
bool flush_frame_deletion_queue, bool clear_frame_descriptors) -> void
|
||||
@@ -637,6 +748,13 @@ auto VulkanRenderer::vk_init() -> void
|
||||
m_logger.info("Chosen Vulkan physical device: {}",
|
||||
m_vkb.phys_dev.properties.deviceName);
|
||||
|
||||
auto const props = m_physical_device.getProperties();
|
||||
m_vk.supported_framebuffer_samples
|
||||
= props.limits.framebufferColorSampleCounts
|
||||
& props.limits.framebufferDepthSampleCounts;
|
||||
m_vk.msaa_samples = vk::SampleCountFlagBits::e1;
|
||||
m_vk.antialiasing_kind = AntiAliasingKind::NONE;
|
||||
|
||||
vkb::DeviceBuilder device_builder { m_vkb.phys_dev };
|
||||
auto dev_ret { device_builder.build() };
|
||||
if (!dev_ret) {
|
||||
@@ -672,6 +790,7 @@ auto VulkanRenderer::swapchain_init() -> void
|
||||
SDL_GetWindowSize(m_window, &w, &h);
|
||||
create_swapchain(static_cast<uint32_t>(w), static_cast<uint32_t>(h));
|
||||
create_draw_image(static_cast<uint32_t>(w), static_cast<uint32_t>(h));
|
||||
create_msaa_color_image(static_cast<uint32_t>(w), static_cast<uint32_t>(h));
|
||||
create_depth_image(static_cast<uint32_t>(w), static_cast<uint32_t>(h));
|
||||
}
|
||||
|
||||
@@ -719,26 +838,7 @@ auto VulkanRenderer::sync_init() -> void
|
||||
|
||||
auto VulkanRenderer::descriptors_init() -> void
|
||||
{
|
||||
std::vector<DescriptorAllocator::PoolSizeRatio> sizes {
|
||||
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1 },
|
||||
};
|
||||
m_vk.descriptor_allocator.init_pool(m_vkb.dev.device, 10, sizes);
|
||||
|
||||
auto draw_layout_raw
|
||||
= DescriptorLayoutBuilder()
|
||||
.add_binding(0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
|
||||
.build(m_logger, m_vkb.dev.device, VK_SHADER_STAGE_COMPUTE_BIT);
|
||||
m_vk.draw_image_descriptor_layout
|
||||
= vk::DescriptorSetLayout { draw_layout_raw };
|
||||
|
||||
m_vk.draw_image_descriptors = m_vk.descriptor_allocator.allocate(
|
||||
m_logger, m_vkb.dev.device, m_vk.draw_image_descriptor_layout);
|
||||
|
||||
update_draw_image_descriptor();
|
||||
|
||||
m_vk.deletion_queue.emplace([&]() {
|
||||
m_vk.descriptor_allocator.destroy_pool(m_vkb.dev.device);
|
||||
m_device.destroyDescriptorSetLayout(m_vk.draw_image_descriptor_layout);
|
||||
m_device.destroyDescriptorSetLayout(
|
||||
m_vk.gpu_scene_data_descriptor_layout);
|
||||
m_device.destroyDescriptorSetLayout(
|
||||
@@ -780,34 +880,10 @@ auto VulkanRenderer::descriptors_init() -> void
|
||||
|
||||
auto VulkanRenderer::pipelines_init() -> void
|
||||
{
|
||||
background_pipelines_init();
|
||||
triangle_pipeline_init();
|
||||
mesh_pipeline_init();
|
||||
}
|
||||
|
||||
auto VulkanRenderer::background_pipelines_init() -> void
|
||||
{
|
||||
Pipeline::Builder builder { m_device, m_logger };
|
||||
std::array layout_handles { m_vk.draw_image_descriptor_layout };
|
||||
builder.set_descriptor_set_layouts(layout_handles);
|
||||
|
||||
uint8_t compute_draw_shader_data[] {
|
||||
#embed "gradient_comp.spv"
|
||||
};
|
||||
auto compute_draw_shader { vkutil::load_shader_module(
|
||||
std::span<uint8_t>(
|
||||
compute_draw_shader_data, sizeof(compute_draw_shader_data)),
|
||||
m_device) };
|
||||
if (!compute_draw_shader) {
|
||||
m_logger.err("Failed to load gradient compute shader");
|
||||
}
|
||||
|
||||
auto stage_ci { vkinit::pipeline_shader_stage(
|
||||
vk::ShaderStageFlagBits::eCompute, compute_draw_shader.get()) };
|
||||
|
||||
m_vk.gradient_pipeline = builder.build_compute(stage_ci);
|
||||
}
|
||||
|
||||
auto VulkanRenderer::triangle_pipeline_init() -> void
|
||||
{
|
||||
Pipeline::Builder builder { m_device, m_logger };
|
||||
@@ -842,7 +918,8 @@ auto VulkanRenderer::triangle_pipeline_init() -> void
|
||||
triangle_vert_shader.get(), triangle_frag_shader.get())
|
||||
.set_input_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
|
||||
.set_polygon_mode(VK_POLYGON_MODE_FILL)
|
||||
.set_multisampling_none()
|
||||
.set_multisampling(
|
||||
static_cast<VkSampleCountFlagBits>(m_vk.msaa_samples))
|
||||
.enable_blending_additive()
|
||||
.disable_depth_testing()
|
||||
.set_color_attachment_format(
|
||||
@@ -897,7 +974,8 @@ auto VulkanRenderer::mesh_pipeline_init() -> void
|
||||
.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()
|
||||
.set_multisampling(
|
||||
static_cast<VkSampleCountFlagBits>(m_vk.msaa_samples))
|
||||
.disable_blending()
|
||||
.enable_depth_testing()
|
||||
.set_color_attachment_format(
|
||||
@@ -1077,15 +1155,17 @@ auto VulkanRenderer::render(std::function<void(GL &)> const &record) -> void
|
||||
return;
|
||||
}
|
||||
|
||||
auto &frame = m_vk.get_current_frame();
|
||||
VK_CHECK(m_logger,
|
||||
m_device.waitForFences(
|
||||
m_vk.get_current_frame().render_fence.get(), true, 1'000'000'000));
|
||||
auto raw_fence
|
||||
= static_cast<VkFence>(m_vk.get_current_frame().render_fence.get());
|
||||
m_device.waitForFences(frame.render_fence.get(), true, 1'000'000'000));
|
||||
frame.deletion_queue.flush();
|
||||
frame.frame_descriptors.clear_pools(m_vkb.dev.device);
|
||||
|
||||
auto raw_fence = static_cast<VkFence>(frame.render_fence.get());
|
||||
VK_CHECK(m_logger, vkResetFences(m_vkb.dev.device, 1, &raw_fence));
|
||||
|
||||
auto const acquire_result = m_device.acquireNextImageKHR(m_vk.swapchain,
|
||||
1'000'000'000, m_vk.get_current_frame().swapchain_semaphore.get(), {});
|
||||
auto const acquire_result = m_device.acquireNextImageKHR(
|
||||
m_vk.swapchain, 1'000'000'000, frame.swapchain_semaphore.get(), {});
|
||||
if (acquire_result.result == vk::Result::eErrorOutOfDateKHR
|
||||
|| acquire_result.result == vk::Result::eSuboptimalKHR) {
|
||||
int width {}, height {};
|
||||
@@ -1097,7 +1177,7 @@ auto VulkanRenderer::render(std::function<void(GL &)> const &record) -> void
|
||||
VK_CHECK(m_logger, acquire_result.result);
|
||||
uint32_t const swapchain_image_idx { acquire_result.value };
|
||||
|
||||
auto cmd { m_vk.get_current_frame().main_command_buffer.get() };
|
||||
auto cmd { frame.main_command_buffer.get() };
|
||||
cmd.reset();
|
||||
|
||||
m_vk.draw_extent.width = m_vk.draw_image.extent.width;
|
||||
@@ -1109,15 +1189,22 @@ auto VulkanRenderer::render(std::function<void(GL &)> const &record) -> void
|
||||
vkBeginCommandBuffer(static_cast<VkCommandBuffer>(cmd),
|
||||
reinterpret_cast<VkCommandBufferBeginInfo *>(&cmd_begin_info)));
|
||||
|
||||
vkutil::transition_image(cmd, m_vk.draw_image.image,
|
||||
vk::ImageLayout::eUndefined, vk::ImageLayout::eGeneral);
|
||||
bool const msaa_enabled = m_vk.msaa_samples != vk::SampleCountFlagBits::e1;
|
||||
|
||||
draw_background(cmd);
|
||||
vkutil::transition_image(cmd, m_vk.draw_image.image, m_vk.draw_image_layout,
|
||||
vk::ImageLayout::eColorAttachmentOptimal);
|
||||
m_vk.draw_image_layout = vk::ImageLayout::eColorAttachmentOptimal;
|
||||
|
||||
if (msaa_enabled) {
|
||||
vkutil::transition_image(cmd, m_vk.msaa_color_image.image,
|
||||
m_vk.msaa_color_image_layout,
|
||||
vk::ImageLayout::eColorAttachmentOptimal);
|
||||
m_vk.msaa_color_image_layout = vk::ImageLayout::eColorAttachmentOptimal;
|
||||
}
|
||||
|
||||
vkutil::transition_image(cmd, m_vk.draw_image.image,
|
||||
vk::ImageLayout::eGeneral, vk::ImageLayout::eColorAttachmentOptimal);
|
||||
vkutil::transition_image(cmd, m_vk.depth_image.image,
|
||||
vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthAttachmentOptimal);
|
||||
m_vk.depth_image_layout, vk::ImageLayout::eDepthAttachmentOptimal);
|
||||
m_vk.depth_image_layout = vk::ImageLayout::eDepthAttachmentOptimal;
|
||||
|
||||
gl.begin_drawing(cmd, m_vk.draw_image, &m_vk.depth_image);
|
||||
if (record) {
|
||||
@@ -1125,9 +1212,9 @@ auto VulkanRenderer::render(std::function<void(GL &)> const &record) -> void
|
||||
}
|
||||
gl.end_drawing();
|
||||
|
||||
vkutil::transition_image(cmd, m_vk.draw_image.image,
|
||||
vk::ImageLayout::eColorAttachmentOptimal,
|
||||
vkutil::transition_image(cmd, m_vk.draw_image.image, m_vk.draw_image_layout,
|
||||
vk::ImageLayout::eTransferSrcOptimal);
|
||||
m_vk.draw_image_layout = vk::ImageLayout::eTransferSrcOptimal;
|
||||
|
||||
vkutil::transition_image(cmd, m_vk.swapchain_images.at(swapchain_image_idx),
|
||||
vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal);
|
||||
@@ -1180,18 +1267,6 @@ auto VulkanRenderer::render(std::function<void(GL &)> const &record) -> void
|
||||
VK_CHECK(m_logger, present_result);
|
||||
}
|
||||
|
||||
auto VulkanRenderer::draw_background(vk::CommandBuffer cmd) -> void
|
||||
{
|
||||
cmd.bindPipeline(
|
||||
vk::PipelineBindPoint::eCompute, m_vk.gradient_pipeline.get());
|
||||
auto compute_set = vk::DescriptorSet { m_vk.draw_image_descriptors };
|
||||
cmd.bindDescriptorSets(vk::PipelineBindPoint::eCompute,
|
||||
m_vk.gradient_pipeline.get_layout(), 0, compute_set, {});
|
||||
cmd.dispatch(
|
||||
static_cast<uint32_t>(std::ceil(m_vk.draw_extent.width / 16.0)),
|
||||
static_cast<uint32_t>(std::ceil(m_vk.draw_extent.height / 16.0)), 1);
|
||||
}
|
||||
|
||||
auto VulkanRenderer::draw_imgui(
|
||||
vk::CommandBuffer cmd, vk::ImageView target_image_view) -> void
|
||||
{
|
||||
@@ -1260,10 +1335,26 @@ auto VulkanRenderer::create_draw_image(uint32_t width, uint32_t height) -> void
|
||||
|
||||
auto const flags { vk::ImageUsageFlagBits::eTransferSrc
|
||||
| vk::ImageUsageFlagBits::eTransferDst
|
||||
| vk::ImageUsageFlagBits::eStorage
|
||||
| vk::ImageUsageFlagBits::eSampled
|
||||
| vk::ImageUsageFlagBits::eColorAttachment };
|
||||
m_vk.draw_image = create_image(
|
||||
{ width, height, 1 }, vk::Format::eR16G16B16A16Sfloat, flags);
|
||||
m_vk.draw_image_layout = vk::ImageLayout::eUndefined;
|
||||
}
|
||||
|
||||
auto VulkanRenderer::create_msaa_color_image(uint32_t width, uint32_t height)
|
||||
-> void
|
||||
{
|
||||
destroy_msaa_color_image();
|
||||
|
||||
if (m_vk.msaa_samples == vk::SampleCountFlagBits::e1) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto const flags { vk::ImageUsageFlagBits::eColorAttachment };
|
||||
m_vk.msaa_color_image = create_image(
|
||||
{ width, height, 1 }, m_vk.draw_image.format, flags, m_vk.msaa_samples);
|
||||
m_vk.msaa_color_image_layout = vk::ImageLayout::eUndefined;
|
||||
}
|
||||
|
||||
auto VulkanRenderer::create_depth_image(uint32_t width, uint32_t height) -> void
|
||||
@@ -1273,8 +1364,9 @@ auto VulkanRenderer::create_depth_image(uint32_t width, uint32_t height) -> void
|
||||
auto const flags { vk::ImageUsageFlagBits::eTransferSrc
|
||||
| vk::ImageUsageFlagBits::eTransferDst
|
||||
| vk::ImageUsageFlagBits::eDepthStencilAttachment };
|
||||
m_vk.depth_image
|
||||
= create_image({ width, height, 1 }, vk::Format::eD32Sfloat, flags);
|
||||
m_vk.depth_image = create_image(
|
||||
{ width, height, 1 }, vk::Format::eD32Sfloat, flags, m_vk.msaa_samples);
|
||||
m_vk.depth_image_layout = vk::ImageLayout::eUndefined;
|
||||
}
|
||||
|
||||
auto VulkanRenderer::destroy_depth_image() -> void
|
||||
@@ -1288,17 +1380,10 @@ auto VulkanRenderer::destroy_depth_image() -> void
|
||||
m_vk.depth_image.image = vk::Image {};
|
||||
m_vk.depth_image.allocation = nullptr;
|
||||
m_vk.depth_image.extent = vk::Extent3D { 0, 0, 0 };
|
||||
m_vk.depth_image_layout = vk::ImageLayout::eUndefined;
|
||||
}
|
||||
}
|
||||
|
||||
auto VulkanRenderer::update_draw_image_descriptor() -> void
|
||||
{
|
||||
DescriptorWriter()
|
||||
.write_image(0, m_vk.draw_image.image_view, VK_NULL_HANDLE,
|
||||
VK_IMAGE_LAYOUT_GENERAL, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
|
||||
.update_set(m_vkb.dev.device, m_vk.draw_image_descriptors);
|
||||
}
|
||||
|
||||
auto VulkanRenderer::destroy_draw_image() -> void
|
||||
{
|
||||
if (m_vk.draw_image.image) {
|
||||
@@ -1310,6 +1395,22 @@ auto VulkanRenderer::destroy_draw_image() -> void
|
||||
m_vk.draw_image.image = vk::Image {};
|
||||
m_vk.draw_image.allocation = nullptr;
|
||||
m_vk.draw_image.extent = vk::Extent3D { 0, 0, 0 };
|
||||
m_vk.draw_image_layout = vk::ImageLayout::eUndefined;
|
||||
}
|
||||
}
|
||||
|
||||
auto VulkanRenderer::destroy_msaa_color_image() -> void
|
||||
{
|
||||
if (m_vk.msaa_color_image.image) {
|
||||
m_device.destroyImageView(m_vk.msaa_color_image.image_view);
|
||||
m_vk.msaa_color_image.image_view = vk::ImageView {};
|
||||
vmaDestroyImage(m_vk.allocator,
|
||||
static_cast<VkImage>(m_vk.msaa_color_image.image),
|
||||
m_vk.msaa_color_image.allocation);
|
||||
m_vk.msaa_color_image.image = vk::Image {};
|
||||
m_vk.msaa_color_image.allocation = nullptr;
|
||||
m_vk.msaa_color_image.extent = vk::Extent3D { 0, 0, 0 };
|
||||
m_vk.msaa_color_image_layout = vk::ImageLayout::eUndefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1320,6 +1421,7 @@ auto VulkanRenderer::recreate_swapchain(uint32_t width, uint32_t height) -> void
|
||||
if (width == 0 || height == 0) {
|
||||
destroy_swapchain();
|
||||
destroy_draw_image();
|
||||
destroy_msaa_color_image();
|
||||
destroy_depth_image();
|
||||
m_vk.swapchain_extent = vk::Extent2D { 0, 0 };
|
||||
return;
|
||||
@@ -1327,12 +1429,13 @@ auto VulkanRenderer::recreate_swapchain(uint32_t width, uint32_t height) -> void
|
||||
|
||||
destroy_swapchain();
|
||||
destroy_draw_image();
|
||||
destroy_msaa_color_image();
|
||||
destroy_depth_image();
|
||||
|
||||
create_swapchain(width, height);
|
||||
create_draw_image(width, height);
|
||||
create_msaa_color_image(width, height);
|
||||
create_depth_image(width, height);
|
||||
update_draw_image_descriptor();
|
||||
}
|
||||
|
||||
auto VulkanRenderer::destroy_swapchain() -> void
|
||||
@@ -1351,13 +1454,14 @@ auto VulkanRenderer::destroy_swapchain() -> void
|
||||
}
|
||||
|
||||
auto VulkanRenderer::create_image(vk::Extent3D size, vk::Format format,
|
||||
vk::ImageUsageFlags flags, bool mipmapped) -> AllocatedImage
|
||||
vk::ImageUsageFlags flags, vk::SampleCountFlagBits samples, bool mipmapped)
|
||||
-> AllocatedImage
|
||||
{
|
||||
AllocatedImage new_image;
|
||||
new_image.format = format;
|
||||
new_image.extent = size;
|
||||
|
||||
auto img_ci { vkinit::image_create_info(format, flags, size) };
|
||||
auto img_ci { vkinit::image_create_info(format, flags, size, samples) };
|
||||
if (mipmapped) {
|
||||
img_ci.mipLevels = static_cast<uint32_t>(std::floor(
|
||||
std::log2(std::max(size.width, size.height))))
|
||||
@@ -1418,7 +1522,7 @@ auto VulkanRenderer::create_image(void const *data, vk::Extent3D size,
|
||||
create_image(size, format,
|
||||
flags | vk::ImageUsageFlagBits::eTransferDst
|
||||
| vk::ImageUsageFlagBits::eTransferSrc,
|
||||
mipmapped),
|
||||
vk::SampleCountFlagBits::e1, mipmapped),
|
||||
};
|
||||
|
||||
immediate_submit([&](vk::CommandBuffer cmd) {
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#include "Colors.h"
|
||||
#include "DeletionQueue.h"
|
||||
#include "DescriptorAllocator.h"
|
||||
#include "Loader.h"
|
||||
#include "Logger.h"
|
||||
#include "Pipeline.h"
|
||||
@@ -29,6 +28,13 @@ struct GPUDrawPushConstants {
|
||||
constexpr unsigned FRAME_OVERLAP = 2;
|
||||
|
||||
struct VulkanRenderer {
|
||||
enum class AntiAliasingKind {
|
||||
NONE,
|
||||
MSAA_2X,
|
||||
MSAA_4X,
|
||||
MSAA_8X,
|
||||
};
|
||||
|
||||
struct GL {
|
||||
enum class GeometryKind {
|
||||
Triangles,
|
||||
@@ -105,6 +111,11 @@ struct VulkanRenderer {
|
||||
|
||||
auto render(std::function<void(GL &)> const &record = {}) -> void;
|
||||
auto resize(uint32_t width, uint32_t height) -> void;
|
||||
auto set_antialiasing(AntiAliasingKind kind) -> void;
|
||||
auto antialiasing() const -> AntiAliasingKind
|
||||
{
|
||||
return m_vk.antialiasing_kind;
|
||||
}
|
||||
|
||||
auto immediate_submit(std::function<void(vk::CommandBuffer cmd)> &&function,
|
||||
bool flush_frame_deletion_queue = true,
|
||||
@@ -151,26 +162,27 @@ private:
|
||||
auto sync_init() -> void;
|
||||
auto descriptors_init() -> void;
|
||||
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(vk::CommandBuffer cmd) -> void;
|
||||
auto draw_imgui(vk::CommandBuffer cmd, vk::ImageView target_image_view)
|
||||
-> void;
|
||||
|
||||
auto create_swapchain(uint32_t width, uint32_t height) -> void;
|
||||
auto create_draw_image(uint32_t width, uint32_t height) -> void;
|
||||
auto update_draw_image_descriptor() -> void;
|
||||
auto create_msaa_color_image(uint32_t width, uint32_t height) -> void;
|
||||
auto destroy_draw_image() -> void;
|
||||
auto create_depth_image(uint32_t width, uint32_t height) -> void;
|
||||
auto destroy_depth_image() -> void;
|
||||
auto destroy_msaa_color_image() -> void;
|
||||
auto recreate_swapchain(uint32_t width, uint32_t height) -> void;
|
||||
auto destroy_swapchain() -> void;
|
||||
auto create_image(vk::Extent3D size, vk::Format format,
|
||||
vk::ImageUsageFlags flags, bool mipmapped = false) -> AllocatedImage;
|
||||
vk::ImageUsageFlags flags,
|
||||
vk::SampleCountFlagBits samples = vk::SampleCountFlagBits::e1,
|
||||
bool mipmapped = false) -> AllocatedImage;
|
||||
auto create_image(void const *data, vk::Extent3D size, vk::Format format,
|
||||
vk::ImageUsageFlags flags, bool mipmapped = false) -> AllocatedImage;
|
||||
auto destroy_image(AllocatedImage const &img) -> void;
|
||||
@@ -210,21 +222,23 @@ private:
|
||||
|
||||
std::array<FrameData, FRAME_OVERLAP> frames;
|
||||
AllocatedImage draw_image {};
|
||||
vk::ImageLayout draw_image_layout { vk::ImageLayout::eUndefined };
|
||||
AllocatedImage msaa_color_image {};
|
||||
vk::ImageLayout msaa_color_image_layout { vk::ImageLayout::eUndefined };
|
||||
AllocatedImage depth_image {};
|
||||
vk::ImageLayout depth_image_layout { vk::ImageLayout::eUndefined };
|
||||
vk::Extent2D draw_extent {};
|
||||
AntiAliasingKind antialiasing_kind { AntiAliasingKind::NONE };
|
||||
vk::SampleCountFlagBits msaa_samples { vk::SampleCountFlagBits::e1 };
|
||||
vk::SampleCountFlags supported_framebuffer_samples {};
|
||||
|
||||
VmaAllocator allocator;
|
||||
DescriptorAllocator descriptor_allocator;
|
||||
|
||||
VkDescriptorSet draw_image_descriptors {};
|
||||
vk::DescriptorSetLayout draw_image_descriptor_layout {};
|
||||
|
||||
GPUSceneData scene_data {};
|
||||
vk::DescriptorSetLayout gpu_scene_data_descriptor_layout {};
|
||||
|
||||
vk::DescriptorSetLayout single_image_descriptor_layout {};
|
||||
|
||||
Pipeline gradient_pipeline;
|
||||
Pipeline triangle_pipeline;
|
||||
Pipeline mesh_pipeline;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user