diff --git a/include/inexor/vulkan-renderer/render-graph/image.hpp b/include/inexor/vulkan-renderer/render-graph/image.hpp index 0790e4a0a..7bc188213 100644 --- a/include/inexor/vulkan-renderer/render-graph/image.hpp +++ b/include/inexor/vulkan-renderer/render-graph/image.hpp @@ -42,8 +42,12 @@ class Image { VkImage m_img{VK_NULL_HANDLE}; VkImageView m_img_view{VK_NULL_HANDLE}; VmaAllocation m_alloc{VK_NULL_HANDLE}; + VmaAllocationInfo m_alloc_info{}; - VmaAllocationCreateInfo m_alloc_ci{}; + + const VmaAllocationCreateInfo m_alloc_ci{ + .usage = VMA_MEMORY_USAGE_AUTO, + }; /// The combined image sampler for the texture /// This is only relevant if the texture is used as TextureUsage::NORMAL @@ -60,7 +64,9 @@ class Image { public: /// Default constructor /// @param device The device wrapper - Image(const Device &device); + /// @param name The name of the Image + Image(const Device &device, std::string name); + Image(const Image &) = delete; Image(Image &&) noexcept; ~Image(); diff --git a/include/inexor/vulkan-renderer/render-graph/render_graph.hpp b/include/inexor/vulkan-renderer/render-graph/render_graph.hpp index cd8a5f648..87184855e 100644 --- a/include/inexor/vulkan-renderer/render-graph/render_graph.hpp +++ b/include/inexor/vulkan-renderer/render-graph/render_graph.hpp @@ -239,8 +239,7 @@ class RenderGraph { /// Record all command buffers required for the passes /// @param cmd_buf The command buffer to record all passes with - /// @param img_index The swapchain image index - void record_command_buffers(const CommandBuffer &cmd_buf, std::uint32_t img_index); + void record_command_buffers(const CommandBuffer &cmd_buf); /// Update the vertex-, index-, and uniform-buffers /// @note If a uniform buffer has been updated, an update of the associated descriptor set will be performed @@ -304,6 +303,7 @@ class RenderGraph { /// @param texture_name The name of the texture /// @param usage The usage of the texture inside of rendergraph /// @param format The format of the texture + /// @param sample_count The sample count of the texture /// @param on_init The texture initialization function /// @param on_update The texture update function /// @return A weak pointer to the texture that was created @@ -312,6 +312,7 @@ class RenderGraph { VkFormat format, std::uint32_t width, std::uint32_t height, + VkSampleCountFlagBits sample_count = VK_SAMPLE_COUNT_1_BIT, std::optional> on_init = std::nullopt, std::optional> on_update = std::nullopt); diff --git a/include/inexor/vulkan-renderer/render-graph/texture.hpp b/include/inexor/vulkan-renderer/render-graph/texture.hpp index 6aa5e15bc..180d200ca 100644 --- a/include/inexor/vulkan-renderer/render-graph/texture.hpp +++ b/include/inexor/vulkan-renderer/render-graph/texture.hpp @@ -108,6 +108,7 @@ class Texture { /// @param format The format of the texture /// @param width The width of the texture /// @param height The height of the texture + /// @param sample_count The sample count of the texture /// @param on_init The initialization function of the texture /// @param on_update The update function of the texture Texture(const Device &device, @@ -116,6 +117,7 @@ class Texture { VkFormat format, std::uint32_t width, std::uint32_t height, + VkSampleCountFlagBits sample_count, std::optional> on_init = std::nullopt, std::optional> on_update = std::nullopt); diff --git a/include/inexor/vulkan-renderer/wrapper/swapchain.hpp b/include/inexor/vulkan-renderer/wrapper/swapchain.hpp index d9df99fef..319e43427 100644 --- a/include/inexor/vulkan-renderer/wrapper/swapchain.hpp +++ b/include/inexor/vulkan-renderer/wrapper/swapchain.hpp @@ -18,9 +18,6 @@ namespace inexor::vulkan_renderer::render_graph { class RenderGraph; } // namespace inexor::vulkan_renderer::render_graph -// Using declaration -using inexor::vulkan_renderer::render_graph::RenderGraph; - namespace inexor::vulkan_renderer::wrapper { // Forward declaration @@ -28,7 +25,7 @@ class Device; /// RAII wrapper class for swapchains class Swapchain { - friend class RenderGraph; + friend class render_graph::RenderGraph; private: Device &m_device; @@ -41,6 +38,7 @@ class Swapchain { std::unique_ptr m_img_available; bool m_vsync_enabled{false}; std::uint32_t m_img_index; + VkImage m_current_img{VK_NULL_HANDLE}; VkImageView m_current_img_view{VK_NULL_HANDLE}; /// Call vkGetSwapchainImagesKHR diff --git a/src/vulkan-renderer/application.cpp b/src/vulkan-renderer/application.cpp index da8cb0824..a58c3923b 100644 --- a/src/vulkan-renderer/application.cpp +++ b/src/vulkan-renderer/application.cpp @@ -420,13 +420,13 @@ void Application::run() { void Application::setup_render_graph() { const auto swapchain_extent = m_swapchain->extent(); - m_back_buffer = - m_render_graph->add_texture("Color", render_graph::TextureUsage::BACK_BUFFER, m_swapchain->image_format(), - swapchain_extent.width, swapchain_extent.height); + m_back_buffer = m_render_graph->add_texture("Color", render_graph::TextureUsage::BACK_BUFFER, + m_swapchain->image_format(), swapchain_extent.width, + swapchain_extent.height, m_device->get_max_usable_sample_count()); - m_depth_buffer = - m_render_graph->add_texture("Depth", render_graph::TextureUsage::DEPTH_STENCIL_BUFFER, - VK_FORMAT_D32_SFLOAT_S8_UINT, swapchain_extent.width, swapchain_extent.height); + m_depth_buffer = m_render_graph->add_texture("Depth", render_graph::TextureUsage::DEPTH_STENCIL_BUFFER, + VK_FORMAT_D32_SFLOAT_S8_UINT, swapchain_extent.width, + swapchain_extent.height, m_device->get_max_usable_sample_count()); m_vertex_buffer = m_render_graph->add_buffer("Octree", render_graph::BufferType::VERTEX_BUFFER, [&]() { // If the key N was pressed once, generate a new octree diff --git a/src/vulkan-renderer/render-graph/buffer.cpp b/src/vulkan-renderer/render-graph/buffer.cpp index 87f2c9ab8..11028d277 100644 --- a/src/vulkan-renderer/render-graph/buffer.cpp +++ b/src/vulkan-renderer/render-graph/buffer.cpp @@ -121,10 +121,11 @@ void Buffer::create(const CommandBuffer &cmd_buf) { throw VulkanException("Error: vmaCreateBuffer failed for staging buffer " + m_name + " !", result); } + const std::string staging_buf_name = "staging:" + m_name; // Set the staging buffer's internal debug name in Vulkan Memory Allocator (VMA) - vmaSetAllocationName(m_device.allocator(), m_staging_alloc, m_name.c_str()); + vmaSetAllocationName(m_device.allocator(), m_staging_alloc, staging_buf_name.c_str()); // Set the staging buffer's internal debug name through Vulkan debug utils - m_device.set_debug_name(m_staging_buffer, m_name); + m_device.set_debug_name(m_staging_buffer, staging_buf_name); // Copy the memory into the staging buffer std::memcpy(m_staging_alloc_info.pMappedData, m_src_data, m_src_data_size); @@ -153,11 +154,8 @@ void Buffer::destroy() { } void Buffer::request_update(void *src_data, const std::size_t src_data_size) { - if (src_data == nullptr) { - throw std::invalid_argument("Error: Update of buffer resource failed (data pointer is nullptr)!"); - } - if (src_data_size == 0) { - throw std::invalid_argument("Error: Update of buffer resource failed (data size is 0)!"); + if (src_data == nullptr || src_data_size == 0) { + return; } m_src_data = src_data; m_src_data_size = src_data_size; diff --git a/src/vulkan-renderer/render-graph/graphics_pass.cpp b/src/vulkan-renderer/render-graph/graphics_pass.cpp index edc87487b..a3897f84b 100644 --- a/src/vulkan-renderer/render-graph/graphics_pass.cpp +++ b/src/vulkan-renderer/render-graph/graphics_pass.cpp @@ -14,11 +14,17 @@ GraphicsPass::GraphicsPass(std::string name, m_stencil_attachment(std::move(stencil_attachment)) {} GraphicsPass::GraphicsPass(GraphicsPass &&other) noexcept { - // TODO: Fix me! m_name = std::move(other.m_name); m_on_record_cmd_buffer = std::move(other.m_on_record_cmd_buffer); + m_color_attachments = std::move(other.m_color_attachments); + m_depth_attachment = std::move(other.m_depth_attachment); + m_stencil_attachment = std::move(other.m_stencil_attachment); m_descriptor_set_layout = std::exchange(other.m_descriptor_set_layout, nullptr); m_descriptor_set = std::exchange(other.m_descriptor_set, VK_NULL_HANDLE); + m_rendering_info = std::move(other.m_rendering_info); + m_color_attachment_infos = std::move(other.m_color_attachment_infos); + m_depth_attachment_info = std::move(other.m_depth_attachment_info); + m_stencil_attachment_info = std::move(other.m_stencil_attachment_info); } } // namespace inexor::vulkan_renderer::render_graph diff --git a/src/vulkan-renderer/render-graph/graphics_pass_builder.cpp b/src/vulkan-renderer/render-graph/graphics_pass_builder.cpp index ac1998bb3..191d09144 100644 --- a/src/vulkan-renderer/render-graph/graphics_pass_builder.cpp +++ b/src/vulkan-renderer/render-graph/graphics_pass_builder.cpp @@ -64,7 +64,7 @@ void GraphicsPassBuilder::reset() { GraphicsPassBuilder & GraphicsPassBuilder::set_on_record(std::function on_record_cmd_buffer) { - on_record_cmd_buffer = std::move(on_record_cmd_buffer); + m_on_record_cmd_buffer = std::move(on_record_cmd_buffer); return *this; } diff --git a/src/vulkan-renderer/render-graph/image.cpp b/src/vulkan-renderer/render-graph/image.cpp index e5e4fcb10..cba5d5664 100644 --- a/src/vulkan-renderer/render-graph/image.cpp +++ b/src/vulkan-renderer/render-graph/image.cpp @@ -6,10 +6,15 @@ namespace inexor::vulkan_renderer::render_graph { -Image::Image(const Device &device) : m_device(device) {} - -Image::Image(Image &&other) noexcept : m_device(other.m_device) { - // TODO: Fix me! +Image::Image(const Device &device, std::string name) : m_device(device), m_name(std::move(name)) {} + +Image::Image(Image &&other) noexcept : m_device(other.m_device), m_alloc_ci(other.m_alloc_ci) { + other.m_name = std::move(other.m_name); + m_img = std::exchange(other.m_img, VK_NULL_HANDLE); + m_img_view = std::exchange(other.m_img_view, VK_NULL_HANDLE); + m_alloc = std::exchange(other.m_alloc, VK_NULL_HANDLE); + m_alloc_info = other.m_alloc_info; + m_sampler = std::exchange(other.m_sampler, nullptr); } Image::~Image() { diff --git a/src/vulkan-renderer/render-graph/render_graph.cpp b/src/vulkan-renderer/render-graph/render_graph.cpp index 128c6d3f5..1a7c142b2 100644 --- a/src/vulkan-renderer/render-graph/render_graph.cpp +++ b/src/vulkan-renderer/render-graph/render_graph.cpp @@ -48,10 +48,11 @@ std::weak_ptr RenderGraph::add_texture(std::string texture_name, const VkFormat format, const std::uint32_t width, const std::uint32_t height, + const VkSampleCountFlagBits sample_count, std::optional> on_init, std::optional> on_update) { m_textures.emplace_back(std::make_shared(m_device, std::move(texture_name), usage, format, width, height, - std::move(on_init), std::move(on_update))); + sample_count, std::move(on_init), std::move(on_update))); return m_textures.back(); } @@ -113,41 +114,108 @@ void RenderGraph::create_rendering_infos() { const auto img_layout = [&]() -> VkImageLayout { switch (attach_ptr->m_usage) { case TextureUsage::BACK_BUFFER: + case TextureUsage::NORMAL: { + return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } case TextureUsage::DEPTH_STENCIL_BUFFER: { return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; } default: - return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + return VK_IMAGE_LAYOUT_UNDEFINED; } }(); // Invoke the lambda, not just define it! + auto is_integer_format = [](const VkFormat format) { + switch (format) { + // 8-bit integer formats + case VK_FORMAT_R8_UINT: + case VK_FORMAT_R8_SINT: + case VK_FORMAT_R8G8_UINT: + case VK_FORMAT_R8G8_SINT: + case VK_FORMAT_R8G8B8_UINT: + case VK_FORMAT_R8G8B8_SINT: + case VK_FORMAT_B8G8R8_UINT: + case VK_FORMAT_B8G8R8_SINT: + case VK_FORMAT_R8G8B8A8_UINT: + case VK_FORMAT_R8G8B8A8_SINT: + case VK_FORMAT_B8G8R8A8_UINT: + case VK_FORMAT_B8G8R8A8_SINT: + case VK_FORMAT_A2R10G10B10_UINT_PACK32: + case VK_FORMAT_A2B10G10R10_UINT_PACK32: + + // 16-bit integer formats + case VK_FORMAT_R16_UINT: + case VK_FORMAT_R16_SINT: + case VK_FORMAT_R16G16_UINT: + case VK_FORMAT_R16G16_SINT: + case VK_FORMAT_R16G16B16_UINT: + case VK_FORMAT_R16G16B16_SINT: + case VK_FORMAT_R16G16B16A16_UINT: + case VK_FORMAT_R16G16B16A16_SINT: + + // 32-bit integer formats + case VK_FORMAT_R32_UINT: + case VK_FORMAT_R32_SINT: + case VK_FORMAT_R32G32_UINT: + case VK_FORMAT_R32G32_SINT: + case VK_FORMAT_R32G32B32_UINT: + case VK_FORMAT_R32G32B32_SINT: + case VK_FORMAT_R32G32B32A32_UINT: + case VK_FORMAT_R32G32B32A32_SINT: + + // 64-bit integer formats + case VK_FORMAT_R64_UINT: + case VK_FORMAT_R64_SINT: + case VK_FORMAT_R64G64_UINT: + case VK_FORMAT_R64G64_SINT: + case VK_FORMAT_R64G64B64_UINT: + case VK_FORMAT_R64G64B64_SINT: + case VK_FORMAT_R64G64B64A64_UINT: + case VK_FORMAT_R64G64B64A64_SINT: + return true; + + // Non-integer formats + default: + return false; + } + }; + // This decides if MSAA is enabled on a per-texture basis return wrapper::make_info({ .imageView = attach_ptr->m_img->m_img_view, .imageLayout = img_layout, - .resolveMode = attach_ptr ? VK_RESOLVE_MODE_MIN_BIT : VK_RESOLVE_MODE_NONE, - .resolveImageView = attach_ptr ? attach_ptr->m_msaa_img->m_img_view : VK_NULL_HANDLE, + .resolveMode = (attach_ptr->m_sample_count > VK_SAMPLE_COUNT_1_BIT) + // The resolve mode must be chosen on whether it's an integer format + ? (!is_integer_format(attach_ptr->m_format) ? VK_RESOLVE_MODE_AVERAGE_BIT + : VK_RESOLVE_MODE_MIN_BIT) + : VK_RESOLVE_MODE_NONE, + .resolveImageView = attach_ptr->m_msaa_img ? attach_ptr->m_msaa_img->m_img_view : VK_NULL_HANDLE, .resolveImageLayout = attach_ptr ? img_layout : VK_IMAGE_LAYOUT_UNDEFINED, .loadOp = attachment.second ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .clearValue = attachment.second.value_or(VkClearValue{}), + .clearValue = attachment.second ? attachment.second.value() : VkClearValue{}, }); }; - // Fill the color attachments + + // Reserve memory for the color attachments pass->m_color_attachment_infos.reserve(pass->m_color_attachments.size()); + // Fill the color attachments for (const auto &color_attachment : pass->m_color_attachments) { pass->m_color_attachment_infos.push_back(fill_rendering_info(color_attachment)); } + // Fill the color attachment (if specified) const bool has_depth_attachment = !pass->m_depth_attachment.first.expired(); if (has_depth_attachment) { pass->m_depth_attachment_info = fill_rendering_info(pass->m_depth_attachment); } + // Fill the stencil attachment (if specified) const bool has_stencil_attachment = !pass->m_stencil_attachment.first.expired(); if (has_stencil_attachment) { pass->m_stencil_attachment_info = fill_rendering_info(pass->m_stencil_attachment); } + // We store all this data in the rendering info in the graphics pass itself // The advantage of this is that we don't have to fill this during the actual rendering pass->m_rendering_info = std::move(wrapper::make_info({ @@ -172,7 +240,10 @@ void RenderGraph::create_textures() { std::invoke(texture->m_on_init.value()); } texture->create(); - texture->update(cmd_buf); + if (texture->m_usage == TextureUsage::NORMAL) { + // Only external textures are updated, not back or depth buffers used internally in rendergraph + texture->update(cmd_buf); + } } }); } @@ -200,23 +271,24 @@ void RenderGraph::record_command_buffer_for_pass(const CommandBuffer &cmd_buf, c cmd_buf.end_debug_label_region(); } -void RenderGraph::record_command_buffers(const CommandBuffer &cmd_buf, const std::uint32_t img_index) { +void RenderGraph::record_command_buffers(const CommandBuffer &cmd_buf) { // Transform the image layout of the swapchain (it comes in undefined layout after presenting) - cmd_buf.change_image_layout(m_swapchain.image(img_index), VK_IMAGE_LAYOUT_UNDEFINED, + cmd_buf.change_image_layout(m_swapchain.m_current_img, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); for (const auto &pass : m_graphics_passes) { + // TODO: Name command buffer on a per-pass basis like [RenderGraph::record_command_buffer|Pass:ImGui] record_command_buffer_for_pass(cmd_buf, *pass); } // Change the layout of the swapchain image to make it ready for presenting - cmd_buf.change_image_layout(m_swapchain.image(img_index), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + cmd_buf.change_image_layout(m_swapchain.m_current_img, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); } void RenderGraph::render() { const auto &cmd_buf = m_device.request_command_buffer("[RenderGraph::render]"); // TODO: Record command buffers for passes in parallel! - record_command_buffers(cmd_buf, m_swapchain.acquire_next_image_index()); + record_command_buffers(cmd_buf); // TODO: Further abstract this away? const std::array stage_mask{VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; diff --git a/src/vulkan-renderer/render-graph/texture.cpp b/src/vulkan-renderer/render-graph/texture.cpp index 67ccb8d76..b0a888d82 100644 --- a/src/vulkan-renderer/render-graph/texture.cpp +++ b/src/vulkan-renderer/render-graph/texture.cpp @@ -17,13 +17,19 @@ Texture::Texture(const Device &device, const VkFormat format, const std::uint32_t width, const std::uint32_t height, + const VkSampleCountFlagBits sample_count, std::optional> on_init, std::optional> on_update) : m_device(device), m_name(std::move(name)), m_usage(usage), m_format(format), m_width(width), m_height(height), - m_on_init(std::move(on_init)), m_on_update(std::move(on_update)) { + m_sample_count(sample_count), m_on_init(std::move(on_init)), m_on_update(std::move(on_update)) { if (m_name.empty()) { throw std::invalid_argument("[Texture::Texture] Error: Parameter 'name' is empty!"); } + m_img = std::make_unique(m_device, m_name); + + if (sample_count > VK_SAMPLE_COUNT_1_BIT) { + m_msaa_img = std::make_unique(m_device, m_name); + } } Texture::~Texture() { @@ -47,10 +53,14 @@ void Texture::create() { .usage = [&]() -> VkImageUsageFlags { switch (m_usage) { case TextureUsage::NORMAL: { - return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT; } - case TextureUsage::DEPTH_STENCIL_BUFFER: case TextureUsage::BACK_BUFFER: { + return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + } + default: { + // TextureUsage::DEPTH_STENCIL_BUFFER return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; } } @@ -67,13 +77,13 @@ void Texture::create() { { .aspectMask = [&]() -> VkImageAspectFlags { switch (m_usage) { - case TextureUsage::NORMAL: { - return VK_IMAGE_ASPECT_COLOR_BIT; - } - case TextureUsage::DEPTH_STENCIL_BUFFER: - case TextureUsage::BACK_BUFFER: { + case TextureUsage::DEPTH_STENCIL_BUFFER: { return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; } + default: { + // TextureUsage::NORMAL and TextureUsage::BACK_BUFFER + return VK_IMAGE_ASPECT_COLOR_BIT; + } } }(), .baseMipLevel = 0, @@ -87,7 +97,7 @@ void Texture::create() { m_img->create(img_ci, img_view_ci); // If MSAA is enabled, create the MSAA texture as well - if (m_sample_count != VK_SAMPLE_COUNT_1_BIT) { + if (m_sample_count > VK_SAMPLE_COUNT_1_BIT) { // Just overwrite the sample count and re-use the image create info img_ci.samples = m_sample_count; m_msaa_img->create(img_ci, img_view_ci); @@ -109,11 +119,16 @@ void Texture::destroy_staging_buffer() { } void Texture::update(const CommandBuffer &cmd_buf) { + if (m_src_texture_data_size == 0) { + // We can't create buffers of size 0! + return; + } if (m_staging_buffer != VK_NULL_HANDLE) { destroy_staging_buffer(); } const auto staging_buffer_ci = wrapper::make_info({ - .size = m_src_texture_data_size, + // TODO: How to deduce channel count? By format? + .size = m_width * m_height * 4, // 4 channels .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, }); @@ -129,6 +144,12 @@ void Texture::update(const CommandBuffer &cmd_buf) { throw VulkanException("Error: vmaCreateBuffer failed for staging buffer " + m_name + "!", result); } + const std::string staging_buf_name = "staging:" + m_name; + // Set the buffer's internal debug name in Vulkan Memory Allocator (VMA) + vmaSetAllocationName(m_device.allocator(), m_alloc, staging_buf_name.c_str()); + // Set the buffer's internal debug name through Vulkan debug utils + m_device.set_debug_name(m_staging_buffer, staging_buf_name); + cmd_buf.pipeline_image_memory_barrier_before_copy_buffer_to_image(m_img->m_img) .copy_buffer_to_image(m_staging_buffer, m_img->m_img, { @@ -138,13 +159,15 @@ void Texture::update(const CommandBuffer &cmd_buf) { }) .pipeline_image_memory_barrier_after_copy_buffer_to_image(m_img->m_img); - // TODO: Do we need to create sampler and image view here? or in create()? - // Update the descriptor image info - m_descriptor_img_info = VkDescriptorImageInfo{ - .sampler = m_img->m_sampler->m_sampler, - .imageView = m_img->m_img_view, - .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - }; + // This is necessary for external textures only, not depth or back buffers used internally in rendergraph + if (m_usage == TextureUsage::NORMAL) { + // Update the descriptor image info + m_descriptor_img_info = VkDescriptorImageInfo{ + .sampler = m_img->m_sampler->m_sampler, + .imageView = m_img->m_img_view, + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + } // NOTE: The staging buffer needs to stay valid until command buffer finished executing! // It will be destroyed either in the destructor or the next time execute_update is called diff --git a/src/vulkan-renderer/renderers/imgui.cpp b/src/vulkan-renderer/renderers/imgui.cpp index 862063b29..e46f45bea 100644 --- a/src/vulkan-renderer/renderers/imgui.cpp +++ b/src/vulkan-renderer/renderers/imgui.cpp @@ -65,7 +65,7 @@ ImGuiRenderer::ImGuiRenderer(const Device &device, m_imgui_texture = render_graph.add_texture( "ImGui-Font", render_graph::TextureUsage::NORMAL, VK_FORMAT_R8G8B8A8_UNORM, m_font_texture_width, - m_font_texture_width, [&]() { + m_font_texture_width, VK_SAMPLE_COUNT_1_BIT, [&]() { // Initialize the ImGui font texture m_imgui_texture.lock()->request_update(m_font_texture_data, m_font_texture_data_size); }); diff --git a/src/vulkan-renderer/wrapper/commands/command_buffer.cpp b/src/vulkan-renderer/wrapper/commands/command_buffer.cpp index c9021d82e..037d03595 100644 --- a/src/vulkan-renderer/wrapper/commands/command_buffer.cpp +++ b/src/vulkan-renderer/wrapper/commands/command_buffer.cpp @@ -190,12 +190,15 @@ const CommandBuffer &CommandBuffer::change_image_layout(const VkImage image, const std::uint32_t base_array_layer, const VkPipelineStageFlags src_mask, const VkPipelineStageFlags dst_mask) const { + assert(image); return change_image_layout(image, old_layout, new_layout, - {.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = base_mip_level, - .levelCount = mip_level_count, - .baseArrayLayer = base_array_layer, - .layerCount = array_layer_count}, + { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = base_mip_level, + .levelCount = mip_level_count, + .baseArrayLayer = base_array_layer, + .layerCount = array_layer_count, + }, src_mask, dst_mask); } diff --git a/src/vulkan-renderer/wrapper/swapchain.cpp b/src/vulkan-renderer/wrapper/swapchain.cpp index c0e3277ba..34e2039bb 100644 --- a/src/vulkan-renderer/wrapper/swapchain.cpp +++ b/src/vulkan-renderer/wrapper/swapchain.cpp @@ -50,6 +50,7 @@ std::uint32_t Swapchain::acquire_next_image_index(const std::uint64_t timeout) { } } m_current_img_view = m_img_views[m_img_index]; + m_current_img = m_imgs[m_img_index]; return m_img_index; } @@ -291,6 +292,7 @@ void Swapchain::setup(const std::uint32_t width, const std::uint32_t height, con throw VulkanException("Error: vkCreateImageView failed for swapchain image view!", result); } } + acquire_next_image_index(); } Swapchain::~Swapchain() {