diff --git a/engine/core/src/engine.cpp b/engine/core/src/engine.cpp index 040cbac..0ceb1a9 100755 --- a/engine/core/src/engine.cpp +++ b/engine/core/src/engine.cpp @@ -758,7 +758,7 @@ void Engine::render(const int index) { _imgui->render(0); } - GFXCommandBuffer* commandbuffer = _gfx->acquire_command_buffer(); + GFXCommandBuffer* commandbuffer = _gfx->acquire_command_buffer(true); _app->render(commandbuffer); diff --git a/engine/gfx/public/gfx.hpp b/engine/gfx/public/gfx.hpp index 522b305..4bd5d0b 100755 --- a/engine/gfx/public/gfx.hpp +++ b/engine/gfx/public/gfx.hpp @@ -360,7 +360,7 @@ public: // misc operations virtual GFXSize get_alignment(const GFXSize size) { return size; } - virtual GFXCommandBuffer* acquire_command_buffer() { return nullptr; } + virtual GFXCommandBuffer* acquire_command_buffer(bool for_presentation_use = false) { return nullptr; } virtual void submit([[maybe_unused]] GFXCommandBuffer* command_buffer, [[maybe_unused]] const int window = -1) {} diff --git a/engine/gfx/vulkan/CMakeLists.txt b/engine/gfx/vulkan/CMakeLists.txt index bc3c276..9975d63 100755 --- a/engine/gfx/vulkan/CMakeLists.txt +++ b/engine/gfx/vulkan/CMakeLists.txt @@ -4,7 +4,8 @@ set(HEADERS src/gfx_vulkan_pipeline.hpp src/gfx_vulkan_texture.hpp src/gfx_vulkan_framebuffer.hpp - src/gfx_vulkan_renderpass.hpp) + src/gfx_vulkan_renderpass.hpp + src/gfx_vulkan_commandbuffer.hpp) find_package(Vulkan REQUIRED) diff --git a/engine/gfx/vulkan/include/gfx_vulkan.hpp b/engine/gfx/vulkan/include/gfx_vulkan.hpp index bf94b11..bc47046 100755 --- a/engine/gfx/vulkan/include/gfx_vulkan.hpp +++ b/engine/gfx/vulkan/include/gfx_vulkan.hpp @@ -57,7 +57,7 @@ public: // misc operations GFXSize get_alignment(const GFXSize size) override; - GFXCommandBuffer* acquire_command_buffer() override; + GFXCommandBuffer* acquire_command_buffer(bool for_presentation_use = false) override; void submit(GFXCommandBuffer* command_buffer, const int identifier) override; diff --git a/engine/gfx/vulkan/src/gfx_vulkan.cpp b/engine/gfx/vulkan/src/gfx_vulkan.cpp index aad37fc..183c988 100755 --- a/engine/gfx/vulkan/src/gfx_vulkan.cpp +++ b/engine/gfx/vulkan/src/gfx_vulkan.cpp @@ -16,6 +16,7 @@ #include "file.hpp" #include "log.hpp" #include "utility.hpp" +#include "gfx_vulkan_commandbuffer.hpp" void* windowNativeHandle; @@ -709,13 +710,13 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate VkShaderModule vertex_module = VK_NULL_HANDLE, fragment_module = VK_NULL_HANDLE; - const bool has_vertex_stage = !info.shaders.vertex_path.empty() || !info.shaders.vertex_src.empty(); - const bool has_fragment_stage = !info.shaders.fragment_path.empty() || !info.shaders.fragment_src.empty(); + const bool has_vertex_stage = !info.shaders.vertex_src.empty(); + const bool has_fragment_stage = !info.shaders.fragment_src.empty(); std::vector shaderStages; if (has_vertex_stage) { - const bool vertex_use_shader_source = info.shaders.vertex_path.empty(); + const bool vertex_use_shader_source = !info.shaders.vertex_src.is_path(); if (vertex_use_shader_source) { auto vertex_shader_vector = info.shaders.vertex_src.as_bytecode(); @@ -723,13 +724,14 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate vertex_module = createShaderModule(vertex_shader_vector.data(), vertex_shader_vector.size() * sizeof(uint32_t)); } else { - auto vertex_shader = file::open(file::internal_domain / (std::string(info.shaders.vertex_path) + ".spv"), true); + auto vertex_shader = file::open(file::internal_domain / (info.shaders.vertex_src.as_path().string() + ".spv"), true); vertex_shader->read_all(); vertex_module = createShaderModule(vertex_shader->cast_data(), vertex_shader->size()); } - name_object(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)vertex_module, info.shaders.vertex_path); + if(!vertex_use_shader_source) + name_object(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)vertex_module, info.shaders.vertex_src.as_path().string()); VkPipelineShaderStageCreateInfo vertShaderStageInfo = {}; vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; @@ -741,7 +743,7 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate } if (has_fragment_stage) { - const bool fragment_use_shader_source = info.shaders.fragment_path.empty(); + const bool fragment_use_shader_source = !info.shaders.fragment_src.is_path(); if (fragment_use_shader_source) { auto fragment_shader_vector = info.shaders.fragment_src.as_bytecode(); @@ -749,13 +751,14 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate fragment_module = createShaderModule(fragment_shader_vector.data(), fragment_shader_vector.size() * sizeof(uint32_t)); } else { - auto fragment_shader = file::open(file::internal_domain / (std::string(info.shaders.fragment_path) + ".spv"), true); + auto fragment_shader = file::open(file::internal_domain / (info.shaders.fragment_src.as_path().string() + ".spv"), true); fragment_shader->read_all(); fragment_module = createShaderModule(fragment_shader->cast_data(), fragment_shader->size()); } - name_object(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)fragment_module, info.shaders.fragment_path); + if(!fragment_use_shader_source) + name_object(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)fragment_module, info.shaders.fragment_src.as_path().string()); VkPipelineShaderStageCreateInfo fragShaderStageInfo = {}; fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; @@ -979,10 +982,7 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline->handle); - if (info.label.empty()) - pipeline->label = std::string(info.shaders.vertex_path) + std::string(info.shaders.fragment_path); - else - pipeline->label = info.label; + pipeline->label = info.label; name_object(device, VK_OBJECT_TYPE_PIPELINE, (uint64_t)pipeline->handle, pipeline->label); name_object(device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, (uint64_t)pipeline->layout, pipeline->label); @@ -998,19 +998,39 @@ GFXSize GFXVulkan::get_alignment(GFXSize size) { return (size + minUboAlignment / 2) & ~int(minUboAlignment - 1); } -GFXCommandBuffer* GFXVulkan::acquire_command_buffer() { - return new GFXCommandBuffer(); +GFXCommandBuffer* GFXVulkan::acquire_command_buffer(bool for_presentation_use) { + GFXVulkanCommandBuffer* cmdbuf = new GFXVulkanCommandBuffer(); + + if(!for_presentation_use) { + VkCommandBufferAllocateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + info.commandPool = commandPool; + info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + info.commandBufferCount = 1; + + vkAllocateCommandBuffers(device, &info, &cmdbuf->handle); + } + + return cmdbuf; } void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) { - vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, std::numeric_limits::max()); + uint32_t imageIndex = 0; + if(identifier != -1) { + vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, std::numeric_limits::max()); - uint32_t imageIndex = 0; - VkResult result = vkAcquireNextImageKHR(device, swapchain, std::numeric_limits::max(), imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); - if (result == VK_ERROR_OUT_OF_DATE_KHR) - return; + VkResult result = vkAcquireNextImageKHR(device, swapchain, std::numeric_limits::max(), imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); + if (result == VK_ERROR_OUT_OF_DATE_KHR) + return; + } + + VkCommandBuffer cmd = VK_NULL_HANDLE; - VkCommandBuffer& cmd = commandBuffers[currentFrame]; + GFXVulkanCommandBuffer* cmdbuf = (GFXVulkanCommandBuffer*)command_buffer; + if(cmdbuf->handle != VK_NULL_HANDLE) + cmd = cmdbuf->handle; + else + cmd = commandBuffers[currentFrame]; VkCommandBufferBeginInfo beginInfo = {}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -1240,41 +1260,50 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) { vkEndCommandBuffer(cmd); - // submit - VkSubmitInfo submitInfo = {}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + if(identifier == -1) { + VkSubmitInfo submitInfo = {}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &cmd; - VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] }; - VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; - submitInfo.waitSemaphoreCount = 1; - submitInfo.pWaitSemaphores = waitSemaphores; - submitInfo.pWaitDstStageMask = waitStages; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &cmd; - - VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame] }; - submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = signalSemaphores; - - vkResetFences(device, 1, &inFlightFences[currentFrame]); - - if(vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) - return; - - // present - VkPresentInfoKHR presentInfo = {}; - presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - - presentInfo.waitSemaphoreCount = 1; - presentInfo.pWaitSemaphores = signalSemaphores; - VkSwapchainKHR swapChains[] = { swapchain }; - presentInfo.swapchainCount = 1; - presentInfo.pSwapchains = swapChains; - presentInfo.pImageIndices = &imageIndex; - - vkQueuePresentKHR(presentQueue, &presentInfo); - - currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; + vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); + } else { + // submit + VkSubmitInfo submitInfo = {}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + + VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] }; + VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; + submitInfo.waitSemaphoreCount = 1; + submitInfo.pWaitSemaphores = waitSemaphores; + submitInfo.pWaitDstStageMask = waitStages; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &cmd; + + VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame] }; + submitInfo.signalSemaphoreCount = 1; + submitInfo.pSignalSemaphores = signalSemaphores; + + vkResetFences(device, 1, &inFlightFences[currentFrame]); + + if(vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) + return; + + // present + VkPresentInfoKHR presentInfo = {}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + + presentInfo.waitSemaphoreCount = 1; + presentInfo.pWaitSemaphores = signalSemaphores; + VkSwapchainKHR swapChains[] = { swapchain }; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = swapChains; + presentInfo.pImageIndices = &imageIndex; + + vkQueuePresentKHR(presentQueue, &presentInfo); + + currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; + } } const char* GFXVulkan::get_name() { diff --git a/engine/gfx/vulkan/src/gfx_vulkan_commandbuffer.hpp b/engine/gfx/vulkan/src/gfx_vulkan_commandbuffer.hpp new file mode 100644 index 0000000..39a373f --- /dev/null +++ b/engine/gfx/vulkan/src/gfx_vulkan_commandbuffer.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +#include "gfx_commandbuffer.hpp" + +class GFXVulkanCommandBuffer : public GFXCommandBuffer { +public: + VkCommandBuffer handle = VK_NULL_HANDLE; +}; diff --git a/engine/renderer/include/renderer.hpp b/engine/renderer/include/renderer.hpp index ce2a341..73ea239 100755 --- a/engine/renderer/include/renderer.hpp +++ b/engine/renderer/include/renderer.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "pass.hpp" #include "matrix.hpp" @@ -63,7 +64,7 @@ public: void render(GFXCommandBuffer* command_buffer, Scene* scene, RenderTarget& target, int index); void render_screen(GFXCommandBuffer* commandBuffer, ui::Screen* screen, prism::Extent extent, ControllerContinuity& continuity, RenderScreenOptions options = RenderScreenOptions()); - void render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Object camera_object, Camera& camera, prism::Extent extent, ControllerContinuity& continuity); + void render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Object camera_object, Camera& camera, prism::Extent extent, RenderTarget& target, ControllerContinuity& continuity); void create_mesh_pipeline(Material& material); @@ -121,7 +122,6 @@ public: private: void createDummyTexture(); void create_render_target_resources(RenderTarget& target); - void createMeshPipeline(); void createPostPipeline(); void createFontPipeline(); void createSkyPipeline(); @@ -134,10 +134,7 @@ private: std::vector> render_targets; ui::Screen* current_screen = nullptr; - - // mesh - GFXBuffer* sceneBuffer = nullptr; - + // sky GFXPipeline* skyPipeline = nullptr; diff --git a/engine/renderer/include/rendertarget.hpp b/engine/renderer/include/rendertarget.hpp index 03c1cad..2533a21 100755 --- a/engine/renderer/include/rendertarget.hpp +++ b/engine/renderer/include/rendertarget.hpp @@ -5,6 +5,7 @@ class GFXTexture; class GFXFramebuffer; +class GFXBuffer; class RenderTarget { public: @@ -20,7 +21,10 @@ public: GFXTexture* offscreenDepthTexture = nullptr; GFXFramebuffer* offscreenFramebuffer = nullptr; - + + // mesh + GFXBuffer* sceneBuffer = nullptr; + // smaa GFXTexture* edge_texture = nullptr; GFXTexture* blend_texture = nullptr; diff --git a/engine/renderer/src/renderer.cpp b/engine/renderer/src/renderer.cpp index 4e3fc41..7b476a8 100755 --- a/engine/renderer/src/renderer.cpp +++ b/engine/renderer/src/renderer.cpp @@ -112,7 +112,6 @@ Renderer::Renderer(GFX* gfx, const bool enable_imgui) : gfx(gfx) { offscreenRenderPass = gfx->create_render_pass(renderPassInfo); - createMeshPipeline(); createFontPipeline(); createSkyPipeline(); } @@ -251,28 +250,25 @@ void Renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge commandbuffer->set_render_pass(beginInfo); const auto& cameras = scene->get_all(); - for(auto& [obj, camera] : cameras) { - const int actual_width = render_extent.width / cameras.size(); - + for(auto& [obj, camera] : cameras) { const bool requires_limited_perspective = render_options.enable_depth_of_field; if(requires_limited_perspective) { - camera.perspective = transform::perspective(radians(camera.fov), static_cast(actual_width) / static_cast(render_extent.height), camera.near, 100.0f); + camera.perspective = transform::perspective(radians(camera.fov), static_cast(render_extent.width) / static_cast(render_extent.height), camera.near, 100.0f); } else { - camera.perspective = transform::infinite_perspective(radians(camera.fov), static_cast(actual_width) / static_cast(render_extent.height), camera.near); + camera.perspective = transform::infinite_perspective(radians(camera.fov), static_cast(render_extent.width) / static_cast(render_extent.height), camera.near); } camera.view = inverse(scene->get(obj).model); Viewport viewport = {}; - viewport.x = (actual_width * 0); - viewport.width = actual_width; + viewport.width = render_extent.width; viewport.height = render_extent.height; commandbuffer->set_viewport(viewport); commandbuffer->push_group("render camera"); - render_camera(commandbuffer, *scene, obj, camera, render_extent, continuity); + render_camera(commandbuffer, *scene, obj, camera, render_extent, target, continuity); commandbuffer->pop_group(); } @@ -377,7 +373,7 @@ void Renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge commandbuffer->pop_group(); } -void Renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Object camera_object, Camera& camera, prism::Extent extent, ControllerContinuity& continuity) { +void Renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Object camera_object, Camera& camera, prism::Extent extent, RenderTarget& target, ControllerContinuity& continuity) { // frustum test const auto frustum = normalize_frustum(camera_extract_frustum(scene, camera_object)); @@ -467,7 +463,7 @@ void Renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj command_buffer->set_graphics_pipeline(mesh.mesh->bones.empty() ? mesh.materials[material_index]->static_pipeline : mesh.materials[material_index]->skinned_pipeline); - command_buffer->bind_shader_buffer(sceneBuffer, 0, 1, sizeof(SceneInformation)); + command_buffer->bind_shader_buffer(target.sceneBuffer, 0, 1, sizeof(SceneInformation)); command_buffer->bind_texture(scene.depthTexture, 2); command_buffer->bind_texture(scene.pointLightArray, 3); @@ -525,7 +521,7 @@ void Renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj pass->render_scene(scene, command_buffer); } - gfx->copy_buffer(sceneBuffer, &sceneInfo, 0, sizeof(SceneInformation)); + gfx->copy_buffer(target.sceneBuffer, &sceneInfo, 0, sizeof(SceneInformation)); } void Renderer::render_screen(GFXCommandBuffer *commandbuffer, ui::Screen* screen, prism::Extent extent, ControllerContinuity& continuity, RenderScreenOptions options) { @@ -809,10 +805,8 @@ void Renderer::create_render_target_resources(RenderTarget& target) { renderToViewportPipeline = gfx->create_graphics_pipeline(pipelineInfo); } -} - -void Renderer::createMeshPipeline() { - sceneBuffer = gfx->create_buffer(nullptr, sizeof(SceneInformation), true, GFXBufferUsage::Storage); + + target.sceneBuffer = gfx->create_buffer(nullptr, sizeof(SceneInformation), true, GFXBufferUsage::Storage); } void Renderer::createPostPipeline() { diff --git a/tools/common/src/commoneditor.cpp b/tools/common/src/commoneditor.cpp index 6204dbb..4551ad8 100755 --- a/tools/common/src/commoneditor.cpp +++ b/tools/common/src/commoneditor.cpp @@ -956,6 +956,8 @@ GFXTexture* CommonEditor::generate_common_preview(Scene& scene, const Vector3 ca auto renderer = engine->get_renderer(); + RenderTarget* target = renderer->allocate_render_target({thumbnail_resolution, thumbnail_resolution}); + renderer->shadow_pass->create_scene_resources(scene); renderer->scene_capture->create_scene_resources(scene); @@ -1011,7 +1013,7 @@ GFXTexture* CommonEditor::generate_common_preview(Scene& scene, const Vector3 ca command_buffer->set_render_pass(begin_info); Renderer::ControllerContinuity continuity; - renderer->render_camera(command_buffer, scene, camera, scene.get(camera), begin_info.render_area.extent, continuity); + renderer->render_camera(command_buffer, scene, camera, scene.get(camera), begin_info.render_area.extent, *target, continuity); // render post begin_info.framebuffer = final_framebuffer; diff --git a/tools/cutsceneeditor/src/cutsceneeditor.cpp b/tools/cutsceneeditor/src/cutsceneeditor.cpp index 0568d61..27cb78a 100755 --- a/tools/cutsceneeditor/src/cutsceneeditor.cpp +++ b/tools/cutsceneeditor/src/cutsceneeditor.cpp @@ -18,8 +18,6 @@ PositionKeyFrame* currentFrame = nullptr; std::string currentPath; -std::unique_ptr renderer; - void app_main(Engine* engine) { CommonEditor* editor = (CommonEditor*)engine->get_app(); @@ -33,13 +31,6 @@ void app_main(Engine* engine) { CutsceneEditor::CutsceneEditor() : CommonEditor("CutsceneEditor") {} void CutsceneEditor::drawUI() { - if(!renderer) { - renderer = std::make_unique(engine->get_gfx(), false); - renderer->viewport_mode = true; - - renderer->resize_viewport({static_cast(viewport_width), static_cast(viewport_height)}); - } - createDockArea(); const ImGuiID editor_dockspace = ImGui::GetID("dockspace"); @@ -430,7 +421,7 @@ void CutsceneEditor::drawUI() { ImGui::End(); if(ImGui::Begin("Viewport")) { - drawViewport(*renderer); + drawViewport(engine->get_scene()); } ImGui::End(); @@ -440,6 +431,4 @@ void CutsceneEditor::drawUI() { if(ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow))) engine->current_cutscene_time += 1.0f; - - renderer->render(engine->get_scene(), -1); }