From c7dfc64f267229cb1bfd5254958265b31590c10f Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Tue, 20 May 2025 23:12:54 +0200 Subject: [PATCH] improving allocator --- Application/Chunk.cpp | 9 ++- Application/World.h | 4 +- Application/main.cpp | 14 ++++- Makefile | 4 ++ Resources/Fragment.nzsl | 56 +++++++++++++++++++ ScopEngine/Runtime/Includes/Renderer/Buffer.h | 5 +- ScopEngine/Runtime/Includes/Renderer/Image.h | 10 ++-- .../Renderer/Memory/DeviceAllocator.h | 9 ++- .../Runtime/Includes/Renderer/Renderer.h | 7 ++- .../Runtime/Sources/Renderer/Buffer.cpp | 6 +- ScopEngine/Runtime/Sources/Renderer/Image.cpp | 6 +- .../Runtime/Sources/Renderer/Memory/Chunk.cpp | 9 +-- .../Renderer/Memory/DeviceAllocator.cpp | 22 +++++++- .../Sources/Renderer/RenderPasses/Passes.cpp | 2 +- .../Runtime/Sources/Renderer/Renderer.cpp | 17 ++++-- 15 files changed, 145 insertions(+), 35 deletions(-) create mode 100644 Resources/Fragment.nzsl diff --git a/Application/Chunk.cpp b/Application/Chunk.cpp index a3da12a..daf8065 100644 --- a/Application/Chunk.cpp +++ b/Application/Chunk.cpp @@ -28,7 +28,7 @@ void Chunk::GenerateChunk() for(std::uint32_t z = 0; z < CHUNK_SIZE.z; z++) { // Implement noise here - std::uint32_t height = std::min(static_cast(4 + (std::sin(m_position.x) * std::sin(m_position.y)) * 10 + x), CHUNK_SIZE.y); + std::uint32_t height = std::abs(std::sin((float)m_offset.x / 20.0f) * std::cos((float)m_offset.y / 20.0f) * 60.0f) + 1; for(std::uint32_t y = 0; y < height; y++) m_data[x][z][y] = 1; } @@ -37,12 +37,9 @@ void Chunk::GenerateChunk() void Chunk::GenerateMesh() { - if(p_actor) + if(!m_mesh_data.empty()) return; - m_mesh_data.clear(); - m_mesh_index_data.clear(); - std::size_t offset = 0; for(std::uint32_t x = 0; x < CHUNK_SIZE.x; x++) @@ -176,6 +173,8 @@ void Chunk::UploadMesh() std::uint32_t Chunk::GetBlock(Scop::Vec3i position) const noexcept { + //if(position.x < 0 || position.x >= m_data.size() || position.z < 0 || position.z >= m_data[position.x >= m_data.size() ? m_data.size() - 1 : position.x].size() || position.y < 0) + // return 1; if(position.x < m_data.size() && position.z < m_data[position.x].size() && position.y < m_data[position.x][position.z].size()) return m_data[position.x][position.z][position.y]; return 0; diff --git a/Application/World.h b/Application/World.h index 176cafc..1b0d171 100644 --- a/Application/World.h +++ b/Application/World.h @@ -9,8 +9,8 @@ #include #include -constexpr std::uint8_t RENDER_DISTANCE = 10; -constexpr std::uint8_t CHUNKS_UPLOAD_PER_FRAME = 1; +constexpr std::uint8_t RENDER_DISTANCE = 12; +constexpr std::uint8_t CHUNKS_UPLOAD_PER_FRAME = 3; enum class GenerationState: std::uint8_t { diff --git a/Application/main.cpp b/Application/main.cpp index c959fa6..2deec77 100644 --- a/Application/main.cpp +++ b/Application/main.cpp @@ -11,8 +11,20 @@ int main(int ac, char** av) std::shared_ptr splash_scene = SplashScreen(); + Scop::ShaderLayout shader_layout( + { + { 1, + Scop::ShaderSetLayout({ + { 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER }, + { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } + }) + } + }, {} + ); + std::shared_ptr shader = Scop::LoadShaderFromFile(GetExecutablePath().parent_path().parent_path() / "Resources/Fragment.spv", Scop::ShaderType::Fragment, std::move(shader_layout)); + Scop::SceneDescriptor main_scene_desc; - main_scene_desc.fragment_shader = Scop::RenderCore::Get().GetDefaultFragmentShader(); + main_scene_desc.fragment_shader = shader; main_scene_desc.camera = std::make_shared(Scop::Vec3f{ 0.0f, 20.0f, 0.0f }, 80.f); main_scene_desc.culling = Scop::CullMode::Front; Scop::Scene& main_scene = splash_scene->AddChildScene("main", std::move(main_scene_desc)); diff --git a/Makefile b/Makefile index 1dcbdba..096d38c 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,8 @@ LDFLAGS = -lSDL2 ScopEngine/Bin/engine.a DEBUG ?= false MODE = "release" +NZSLC = ./ScopEngine/Assets/Vendors/nzslc.x86_64 + TPUT = tput -T xterm-256color _RESET := $(shell $(TPUT) sgr0) _BOLD := $(shell $(TPUT) bold) @@ -57,6 +59,8 @@ $(OBJ_DIR)/%.o: %.cpp all: $(NAME) $(NAME): $(OBJ_DIR) $(BIN_DIR) engine $(OBJS) + @printf "$(COLOR)($(_BOLD)100%%$(_RESET)$(COLOR)) $(_RESET)Compiling $(_BOLD)Resources/Fragment.nzsl$(_RESET)\n" + @$(NZSLC) --compile=spv Resources/Fragment.nzsl -o Resources/ --optimize --module="ScopEngine/Assets/Shaders/Modules" @printf "Linking $(_BOLD)$(NAME)$(_RESET)\n" @$(CXX) -o $(BIN_DIR)/$(NAME) $(OBJS) $(LDFLAGS) @printf "$(_BOLD)$(NAME)$(_RESET) compiled $(COLOR)$(_BOLD)successfully$(_RESET)\n" diff --git a/Resources/Fragment.nzsl b/Resources/Fragment.nzsl new file mode 100644 index 0000000..0850f48 --- /dev/null +++ b/Resources/Fragment.nzsl @@ -0,0 +1,56 @@ +[nzsl_version("1.0")] +module; + +struct VertOut +{ + [location(0)] color: vec4[f32], + [location(1)] uv: vec2[f32], + [location(2)] norm: vec4[f32], + [location(3)] transformed_norm: vec3[f32], + [location(4)] frag_position: vec4[f32], + [location(5)] camera_position: vec3[f32], + [builtin(position)] pos: vec4[f32] +} + +struct FragmentData +{ + dissolve_texture_factor: f32, + dissolve_black_white_colors_factor: f32, + dissolve_normals_colors_factor: f32, +} + +struct FragOut +{ + [location(0)] color: vec4[f32] +} + +external +{ + [set(1), binding(0)] u_albedo: sampler2D[f32], + [set(1), binding(1)] u_fragment_data: uniform[FragmentData], +} + +[entry(frag)] +fn main(input: VertOut) -> FragOut +{ + if(input.color.a == 0.0) + discard; + + const ambient = vec3[f32](0.1, 0.1, 0.1); + const directional_color = vec3[f32](5.0, 5.0, 5.0); + const specular_strength = 0.5; + let directional_vector = normalize(vec3[f32](0.85, 0.8, 0.75)); + + let directional: f32 = max(dot(input.transformed_norm.xyz, directional_vector), 0.0); + + let view_dir: vec3[f32] = normalize(input.camera_position - input.frag_position.xyz); + let reflect_dir: vec3[f32] = reflect(-directional_vector, input.norm.xyz); + let spec: f32 = pow(max(dot(view_dir, reflect_dir), 0.0), 128.0); + let specular: vec3[f32] = specular_strength * spec * directional_color; + + let lighting: vec3[f32] = ambient + (directional_color * directional) + specular; + + let output: FragOut; + output.color = input.color * u_albedo.Sample(input.uv) * vec4[f32](lighting, 1.0); + return output; +} diff --git a/ScopEngine/Runtime/Includes/Renderer/Buffer.h b/ScopEngine/Runtime/Includes/Renderer/Buffer.h index 0f6130c..9c2a7d1 100644 --- a/ScopEngine/Runtime/Includes/Renderer/Buffer.h +++ b/ScopEngine/Runtime/Includes/Renderer/Buffer.h @@ -26,7 +26,7 @@ namespace Scop [[nodiscard]] inline VkBuffer operator()() const noexcept { return m_buffer; } [[nodiscard]] inline VkBuffer Get() const noexcept { return m_buffer; } [[nodiscard]] inline VkDeviceMemory GetMemory() const noexcept { return m_memory.memory; } - [[nodiscard]] inline VkDeviceSize GetSize() const noexcept { return m_memory.size; } + [[nodiscard]] inline VkDeviceSize GetSize() const noexcept { return m_size; } [[nodiscard]] inline VkDeviceSize GetOffset() const noexcept { return 0; } [[nodiscard]] inline static std::size_t GetBufferCount() noexcept { return s_buffer_count; } @@ -41,6 +41,7 @@ namespace Scop protected: VkBuffer m_buffer = VK_NULL_HANDLE; MemoryBlock m_memory = NULL_MEMORY_BLOCK; + VkDeviceSize m_size = 0; private: void CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, std::string_view name, bool dedicated_alloc); @@ -78,7 +79,7 @@ namespace Scop { m_vertex_offset = 0; m_index_offset = vertex_size; - GPUBuffer::Init(BufferType::LowDynamic, vertex_size + index_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | additional_flags, std::move(data), std::move(name), true); + GPUBuffer::Init(BufferType::LowDynamic, vertex_size + index_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | additional_flags, std::move(data), std::move(name), false); } void SetVertexData(CPUBuffer data); void SetIndexData(CPUBuffer data); diff --git a/ScopEngine/Runtime/Includes/Renderer/Image.h b/ScopEngine/Runtime/Includes/Renderer/Image.h index e603e13..5226081 100644 --- a/ScopEngine/Runtime/Includes/Renderer/Image.h +++ b/ScopEngine/Runtime/Includes/Renderer/Image.h @@ -36,7 +36,7 @@ namespace Scop #endif } - void Init(ImageType type, std::uint32_t width, std::uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, bool is_multisampled = false, std::string_view name = {}); + void Init(ImageType type, std::uint32_t width, std::uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, bool is_multisampled = false, std::string_view name = {}, bool dedicated_alloc = false); void CreateImageView(VkImageViewType type, VkImageAspectFlags aspectFlags, int layer_count = 1) noexcept; void CreateSampler() noexcept; void TransitionLayout(VkImageLayout new_layout, VkCommandBuffer cmd = VK_NULL_HANDLE); @@ -98,13 +98,13 @@ namespace Scop { public: Texture() = default; - Texture(CPUBuffer pixels, std::uint32_t width, std::uint32_t height, VkFormat format = VK_FORMAT_R8G8B8A8_SRGB, bool is_multisampled = false, std::string_view name = {}) + Texture(CPUBuffer pixels, std::uint32_t width, std::uint32_t height, VkFormat format = VK_FORMAT_R8G8B8A8_SRGB, bool is_multisampled = false, std::string_view name = {}, bool dedicated_alloc = false) { - Init(std::move(pixels), width, height, format, is_multisampled, std::move(name)); + Init(std::move(pixels), width, height, format, is_multisampled, std::move(name), dedicated_alloc); } - inline void Init(CPUBuffer pixels, std::uint32_t width, std::uint32_t height, VkFormat format = VK_FORMAT_R8G8B8A8_SRGB, bool is_multisampled = false, std::string_view name = {}) + inline void Init(CPUBuffer pixels, std::uint32_t width, std::uint32_t height, VkFormat format = VK_FORMAT_R8G8B8A8_SRGB, bool is_multisampled = false, std::string_view name = {}, bool dedicated_alloc = false) { - Image::Init(ImageType::Color, width, height, format, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, is_multisampled, std::move(name)); + Image::Init(ImageType::Color, width, height, format, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, is_multisampled, std::move(name), dedicated_alloc); Image::CreateImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT); Image::CreateSampler(); if(pixels) diff --git a/ScopEngine/Runtime/Includes/Renderer/Memory/DeviceAllocator.h b/ScopEngine/Runtime/Includes/Renderer/Memory/DeviceAllocator.h index f07d3dd..b431280 100644 --- a/ScopEngine/Runtime/Includes/Renderer/Memory/DeviceAllocator.h +++ b/ScopEngine/Runtime/Includes/Renderer/Memory/DeviceAllocator.h @@ -11,12 +11,15 @@ namespace Scop { + constexpr std::size_t SMALL_HEAP_MAX_SIZE = (1024ULL * 1024 * 1024); + constexpr std::size_t DEFAULT_LARGE_HEAP_BLOCK_SIZE = (256ULL * 1024 * 1024); + class DeviceAllocator { public: DeviceAllocator() = default; - inline void AttachToDevice(VkDevice device, VkPhysicalDevice physical) noexcept { m_device = device; m_physical = physical; } + void AttachToDevice(VkDevice device, VkPhysicalDevice physical) noexcept; inline void DetachFromDevice() noexcept { m_chunks.clear(); m_device = VK_NULL_HANDLE; m_physical = VK_NULL_HANDLE; } [[nodiscard]] inline std::size_t GetAllocationsCount() const noexcept { return m_allocations_count; } @@ -25,8 +28,12 @@ namespace Scop ~DeviceAllocator() = default; + private: + VkDeviceSize CalcPreferredChunkSize(std::uint32_t mem_type_index); + private: std::vector> m_chunks; + VkPhysicalDeviceMemoryProperties m_mem_props; VkDevice m_device = VK_NULL_HANDLE; VkPhysicalDevice m_physical = VK_NULL_HANDLE; std::size_t m_allocations_count = 0; diff --git a/ScopEngine/Runtime/Includes/Renderer/Renderer.h b/ScopEngine/Runtime/Includes/Renderer/Renderer.h index 8b56739..1455c6c 100644 --- a/ScopEngine/Runtime/Includes/Renderer/Renderer.h +++ b/ScopEngine/Runtime/Includes/Renderer/Renderer.h @@ -15,6 +15,8 @@ namespace Scop { + constexpr std::uint32_t SEMAPHORE_COUNT = 4; + class Renderer { public: @@ -41,12 +43,13 @@ namespace Scop private: Swapchain m_swapchain; - std::array m_image_available_semaphores; - std::array m_render_finished_semaphores; + std::array m_image_available_semaphores; + std::array m_render_finished_semaphores; std::array m_cmd_buffers; std::array m_cmd_fences; NonOwningPtr p_window; std::uint32_t m_current_frame_index = 0; + std::uint32_t m_current_semaphore_index = 0; std::size_t m_polygons_drawn = 0; std::size_t m_drawcalls = 0; }; diff --git a/ScopEngine/Runtime/Sources/Renderer/Buffer.cpp b/ScopEngine/Runtime/Sources/Renderer/Buffer.cpp index d6b9897..03aa5fa 100644 --- a/ScopEngine/Runtime/Sources/Renderer/Buffer.cpp +++ b/ScopEngine/Runtime/Sources/Renderer/Buffer.cpp @@ -49,8 +49,8 @@ namespace Scop VkMemoryRequirements mem_requirements; RenderCore::Get().vkGetBufferMemoryRequirements(device, m_buffer, &mem_requirements); - m_memory = RenderCore::Get().GetAllocator().Allocate(size, mem_requirements.alignment, *FindMemoryType(mem_requirements.memoryTypeBits, properties), dedicated_alloc); - //m_memory = RenderCore::Get().GetAllocator().Allocate(mem_requirements.size, mem_requirements.alignment, *FindMemoryType(mem_requirements.memoryTypeBits, properties)); + //m_memory = RenderCore::Get().GetAllocator().Allocate(size, mem_requirements.alignment, *FindMemoryType(mem_requirements.memoryTypeBits, properties), dedicated_alloc); + m_memory = RenderCore::Get().GetAllocator().Allocate(mem_requirements.size, mem_requirements.alignment, *FindMemoryType(mem_requirements.memoryTypeBits, properties), dedicated_alloc); RenderCore::Get().vkBindBufferMemory(device, m_buffer, m_memory.memory, m_memory.offset); #ifdef SCOP_HAS_DEBUG_UTILS_FUNCTIONS @@ -75,6 +75,8 @@ namespace Scop RenderCore::Get().vkSetDebugUtilsObjectNameEXT(RenderCore::Get().GetDevice(), &name_info); #endif + m_size = size; + m_is_dedicated_alloc = dedicated_alloc; s_buffer_count++; diff --git a/ScopEngine/Runtime/Sources/Renderer/Image.cpp b/ScopEngine/Runtime/Sources/Renderer/Image.cpp index 95627e8..22f10e8 100644 --- a/ScopEngine/Runtime/Sources/Renderer/Image.cpp +++ b/ScopEngine/Runtime/Sources/Renderer/Image.cpp @@ -4,7 +4,7 @@ namespace Scop { - void Image::Init(ImageType type, std::uint32_t width, std::uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, bool is_multisampled, std::string_view name) + void Image::Init(ImageType type, std::uint32_t width, std::uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, bool is_multisampled, std::string_view name, bool dedicated_alloc) { m_type = type; m_width = width; @@ -47,8 +47,8 @@ namespace Scop VkMemoryRequirements mem_requirements; RenderCore::Get().vkGetImageMemoryRequirements(RenderCore::Get().GetDevice(), m_image, &mem_requirements); - m_memory = RenderCore::Get().GetAllocator().Allocate(mem_requirements.size, mem_requirements.alignment, *FindMemoryType(mem_requirements.memoryTypeBits, properties), true); - RenderCore::Get().vkBindImageMemory(RenderCore::Get().GetDevice(), m_image, m_memory.memory, 0); + m_memory = RenderCore::Get().GetAllocator().Allocate(mem_requirements.size, mem_requirements.alignment, *FindMemoryType(mem_requirements.memoryTypeBits, properties), dedicated_alloc); + RenderCore::Get().vkBindImageMemory(RenderCore::Get().GetDevice(), m_image, m_memory.memory, m_memory.offset); #ifdef SCOP_HAS_DEBUG_UTILS_FUNCTIONS VkDebugUtilsObjectNameInfoEXT name_info{}; diff --git a/ScopEngine/Runtime/Sources/Renderer/Memory/Chunk.cpp b/ScopEngine/Runtime/Sources/Renderer/Memory/Chunk.cpp index 9d6ac7e..055dcc4 100644 --- a/ScopEngine/Runtime/Sources/Renderer/Memory/Chunk.cpp +++ b/ScopEngine/Runtime/Sources/Renderer/Memory/Chunk.cpp @@ -24,6 +24,7 @@ namespace Scop if(RenderCore::Get().vkMapMemory(m_device, m_memory, 0, VK_WHOLE_SIZE, 0, &p_map) != VK_SUCCESS) FatalError("Vulkan: failed to map a host visible chunk"); } + MemoryBlock& block = m_blocks.emplace_back(); block.memory = m_memory; block.offset = 0; @@ -37,7 +38,7 @@ namespace Scop { if(!m_blocks[i].free || m_blocks[i].size < size) continue; - VkDeviceSize offset_displacement = (m_blocks[i].offset % alignment > 0) ? alignment - m_blocks[i].offset % alignment : 0; + VkDeviceSize offset_displacement = (m_blocks[i].offset % alignment != 0) ? alignment - m_blocks[i].offset % alignment : 0; VkDeviceSize old_size_available = m_blocks[i].size - offset_displacement; if(size + offset_displacement <= m_blocks[i].size) @@ -51,7 +52,7 @@ namespace Scop MemoryBlock new_block; new_block.memory = m_memory; - new_block.offset = m_blocks[i].offset + size; + new_block.offset = m_blocks[i].offset + m_blocks[i].size; new_block.size = old_size_available - size; new_block.free = true; @@ -76,9 +77,9 @@ namespace Scop end = true; for(auto it = m_blocks.begin(); it != m_blocks.end(); ++it) { - if(it->free && (it + 1)->free) + if(it->free && it + 1 != m_blocks.end() && (it + 1)->free) { - it->size = (it + 1)->offset + (it + 1)->size - it->offset; + it->size += (it + 1)->size; m_blocks.erase(it + 1); end = false; break; diff --git a/ScopEngine/Runtime/Sources/Renderer/Memory/DeviceAllocator.cpp b/ScopEngine/Runtime/Sources/Renderer/Memory/DeviceAllocator.cpp index 77fde98..99a7e6c 100644 --- a/ScopEngine/Runtime/Sources/Renderer/Memory/DeviceAllocator.cpp +++ b/ScopEngine/Runtime/Sources/Renderer/Memory/DeviceAllocator.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -6,7 +7,15 @@ namespace Scop { - constexpr VkDeviceSize CHUNK_SIZE = MaxValue(); + #define AlignUp(val, alignment) (val + alignment - 1) & ~(alignment - 1) + + void DeviceAllocator::AttachToDevice(VkDevice device, VkPhysicalDevice physical) noexcept + { + m_device = device; + m_physical = physical; + + RenderCore::Get().vkGetPhysicalDeviceMemoryProperties(physical, &m_mem_props); + } [[nodiscard]] MemoryBlock DeviceAllocator::Allocate(VkDeviceSize size, VkDeviceSize alignment, std::int32_t memory_type_index, bool dedicated_chunk) { @@ -25,7 +34,8 @@ namespace Scop } } } - m_chunks.emplace_back(std::make_unique(m_device, m_physical, (CHUNK_SIZE < size + alignment ? size + alignment : CHUNK_SIZE), memory_type_index, dedicated_chunk)); + VkDeviceSize chunk_size = CalcPreferredChunkSize(memory_type_index); + m_chunks.emplace_back(std::make_unique(m_device, m_physical, chunk_size, memory_type_index, dedicated_chunk)); std::optional block = m_chunks.back()->Allocate(size, alignment); m_allocations_count++; if(block.has_value()) @@ -54,4 +64,12 @@ namespace Scop } Error("Device Allocator: unable to free a block; could not find it's chunk"); } + + VkDeviceSize DeviceAllocator::CalcPreferredChunkSize(std::uint32_t mem_type_index) + { + std::uint32_t heap_index = m_mem_props.memoryTypes[mem_type_index].heapIndex; + VkDeviceSize heap_size = m_mem_props.memoryHeaps[heap_index].size; + bool is_small_heap = heap_size <= SMALL_HEAP_MAX_SIZE; + return AlignUp((is_small_heap ? (heap_size / 8) : DEFAULT_LARGE_HEAP_BLOCK_SIZE), (VkDeviceSize)32); + } } diff --git a/ScopEngine/Runtime/Sources/Renderer/RenderPasses/Passes.cpp b/ScopEngine/Runtime/Sources/Renderer/RenderPasses/Passes.cpp index 0d00585..bda0893 100644 --- a/ScopEngine/Runtime/Sources/Renderer/RenderPasses/Passes.cpp +++ b/ScopEngine/Runtime/Sources/Renderer/RenderPasses/Passes.cpp @@ -23,7 +23,7 @@ namespace Scop if(!m_main_render_texture.IsInit()) { auto extent = kvfGetSwapchainImagesSize(renderer.GetSwapchain().Get()); - m_main_render_texture.Init({}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_UNORM, false, "scop_main_render_texture"); + m_main_render_texture.Init({}, extent.width, extent.height, VK_FORMAT_R8G8B8A8_UNORM, false, "scop_main_render_texture", true); } scene.GetDepth().Clear(renderer.GetActiveCommandBuffer(), {}); diff --git a/ScopEngine/Runtime/Sources/Renderer/Renderer.cpp b/ScopEngine/Runtime/Sources/Renderer/Renderer.cpp index 7636180..96d3bf1 100644 --- a/ScopEngine/Runtime/Sources/Renderer/Renderer.cpp +++ b/ScopEngine/Runtime/Sources/Renderer/Renderer.cpp @@ -18,12 +18,15 @@ namespace Scop { p_window = window; m_swapchain.Init(p_window); - for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + for(std::size_t i = 0; i < SEMAPHORE_COUNT; i++) { m_image_available_semaphores[i] = kvfCreateSemaphore(RenderCore::Get().GetDevice()); Message("Vulkan: image available semaphore created"); m_render_finished_semaphores[i] = kvfCreateSemaphore(RenderCore::Get().GetDevice()); Message("Vulkan: render finished semaphore created"); + } + for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + { m_cmd_buffers[i] = kvfCreateCommandBuffer(RenderCore::Get().GetDevice()); Message("Vulkan: command buffer created"); m_cmd_fences[i] = kvfCreateFence(RenderCore::Get().GetDevice()); @@ -34,7 +37,7 @@ namespace Scop void Renderer::BeginFrame() { kvfWaitForFence(RenderCore::Get().GetDevice(), m_cmd_fences[m_current_frame_index]); - m_swapchain.AquireFrame(m_image_available_semaphores[m_current_frame_index]); + m_swapchain.AquireFrame(m_image_available_semaphores[m_current_semaphore_index]); RenderCore::Get().vkResetCommandBuffer(m_cmd_buffers[m_current_frame_index], 0); kvfBeginCommandBuffer(m_cmd_buffers[m_current_frame_index], 0); m_drawcalls = 0; @@ -46,20 +49,24 @@ namespace Scop { VkPipelineStageFlags wait_stages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; kvfEndCommandBuffer(m_cmd_buffers[m_current_frame_index]); - kvfSubmitCommandBuffer(RenderCore::Get().GetDevice(), m_cmd_buffers[m_current_frame_index], KVF_GRAPHICS_QUEUE, m_render_finished_semaphores[m_current_frame_index], m_image_available_semaphores[m_current_frame_index], m_cmd_fences[m_current_frame_index], wait_stages); - m_swapchain.Present(m_render_finished_semaphores[m_current_frame_index]); + kvfSubmitCommandBuffer(RenderCore::Get().GetDevice(), m_cmd_buffers[m_current_frame_index], KVF_GRAPHICS_QUEUE, m_render_finished_semaphores[m_current_semaphore_index], m_image_available_semaphores[m_current_semaphore_index], m_cmd_fences[m_current_frame_index], wait_stages); + m_swapchain.Present(m_render_finished_semaphores[m_current_semaphore_index]); m_current_frame_index = (m_current_frame_index + 1) % MAX_FRAMES_IN_FLIGHT; + m_current_semaphore_index = (m_current_semaphore_index + 1) % SEMAPHORE_COUNT; } void Renderer::Destroy() noexcept { RenderCore::Get().WaitDeviceIdle(); - for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + for(std::size_t i = 0; i < SEMAPHORE_COUNT; i++) { kvfDestroySemaphore(RenderCore::Get().GetDevice(), m_image_available_semaphores[i]); Message("Vulkan: image available semaphore destroyed"); kvfDestroySemaphore(RenderCore::Get().GetDevice(), m_render_finished_semaphores[i]); Message("Vulkan: render finished semaphore destroyed"); + } + for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + { kvfDestroyCommandBuffer(RenderCore::Get().GetDevice(), m_cmd_buffers[i]); Message("Vulkan: command buffer destroyed"); kvfDestroyFence(RenderCore::Get().GetDevice(), m_cmd_fences[i]);