diff --git a/LNApp/Assets/Textures/HDRIs/pisa.hdr b/LNApp/Assets/Textures/HDRIs/pisa.hdr new file mode 100644 index 0000000..8342d11 Binary files /dev/null and b/LNApp/Assets/Textures/HDRIs/pisa.hdr differ diff --git a/LNApp/premake5.lua b/LNApp/premake5.lua index b44b084..d49c0e9 100644 --- a/LNApp/premake5.lua +++ b/LNApp/premake5.lua @@ -122,7 +122,8 @@ project "LNApp" } filter "configurations:Dist" + kind "WindowedApp" runtime "Release" symbols "Off" optimize "On" - defines "NDEBUG" + defines "NDEBUG" diff --git a/LNApp/src/AppLayer.cpp b/LNApp/src/AppLayer.cpp index 94ab219..7eb3e34 100644 --- a/LNApp/src/AppLayer.cpp +++ b/LNApp/src/AppLayer.cpp @@ -47,7 +47,7 @@ void AppLayer::SkyboxPass::OnBind(lne::FrameGraph* frameGraph, lne::FrameGraphNo techDesc.Passes.push_back(passDesc); SafePtr technique = renderer.CreateOrGetTechnique(techDesc); - m_MaterialV2 = lnnew Material(technique); + m_Material = lnnew Material(technique); for (FrameGraphResourceHandle resourceHandle : node->InputResources) { @@ -72,11 +72,11 @@ void AppLayer::SkyboxPass::Execute(vk::CommandBuffer cmdBuffer, lne::WorldRender if (m_Texture != worldRenderer->GetEnvironment()->SkyboxTexture) { m_Texture = worldRenderer->GetEnvironment()->SkyboxTexture; - m_MaterialV2->SetTexture("tCubeAlbedo", m_Texture); + m_Material->SetTexture("tCubeAlbedo", m_Texture); } lne::Renderer& renderer = lne::ApplicationBase::GetRenderer(); - renderer.DrawFullscreenQuad(cmdBuffer, m_MaterialV2, GetID()); + renderer.DrawFullscreenQuad(cmdBuffer, m_Material, GetID()); } void AppLayer::SkyboxPass::PostExecute(vk::CommandBuffer cmdBuffer, lne::FrameGraph* frameGraph, lne::FrameGraphNode* node) @@ -135,7 +135,7 @@ void AppLayer::ToneMappingPass::OnBind(lne::FrameGraph* frameGraph, lne::FrameGr techDesc.Passes.push_back(passDesc); SafePtr technique = renderer.CreateOrGetTechnique(techDesc); - SafePtr mat = lnnew Material(technique); + m_Material = lnnew Material(technique); for (FrameGraphResourceHandle resourceHandle : node->OutputResources) { @@ -154,9 +154,18 @@ void AppLayer::ToneMappingPass::OnBind(lne::FrameGraph* frameGraph, lne::FrameGr { lne::FrameGraphResource* resource = frameGraph->GetResource(handle); lne::SafePtr sceneTexture = resource->Resource.GetAs(); - mat->SetTexture("tSceneTexture", sceneTexture); + m_Material->SetTexture("tSceneTexture", sceneTexture); + } +} + +void AppLayer::ToneMappingPass::OnResize(lne::FrameGraph* frameGraph, lne::FrameGraphNode* node) +{ + for (lne::FrameGraphResourceHandle handle : node->InputResources) + { + lne::FrameGraphResource* resource = frameGraph->GetResource(handle); + lne::SafePtr sceneTexture = resource->Resource.GetAs(); + m_Material->SetTexture("tSceneTexture", sceneTexture); } - m_MaterialV2 = mat; } void AppLayer::ToneMappingPass::Execute(vk::CommandBuffer cmdBuffer, class lne::WorldRenderer* worldRenderer, lne::FrameGraph* frameGraph, lne::FrameGraphNode* node) @@ -168,7 +177,7 @@ void AppLayer::ToneMappingPass::Execute(vk::CommandBuffer cmdBuffer, class lne:: lne::FrameGraphResource* resource = frameGraph->GetResource(handle); lne::SafePtr sceneTexture = resource->Resource.GetAs(); } - renderer.DrawFullscreenQuad(cmdBuffer, m_MaterialV2, GetID()); + renderer.DrawFullscreenQuad(cmdBuffer, m_Material, GetID()); } void AppLayer::ToneMappingPass::PostExecute(vk::CommandBuffer cmdBuffer, lne::FrameGraph* frameGraph, lne::FrameGraphNode* node) @@ -219,39 +228,10 @@ void AppLayer::OnAttach() SafePtr uvChecker = renderer.CreateTexture(lne::ApplicationBase::GetAssetsPath() + "Textures\\UVChecker.png"); - SafePtr gbufferEffect = renderer.CreateOrGetEffect(ApplicationBase::GetAssetsPath() + "Engine\\Shaders\\GBuffer.glsl"); - SafePtr forwardTransparentEffect = renderer.CreateOrGetEffect(ApplicationBase::GetAssetsPath() + "Engine\\Shaders\\ForwardTransparent.glsl"); - SafePtr depthPrePassEffect = renderer.CreateOrGetEffect(ApplicationBase::GetAssetsPath() + "Engine\\Shaders\\DepthPrePass.glsl"); - - GfxTechniqueDesc techDesc{}; - techDesc.Name = "DefaultMeshOpaque"; - techDesc.TechniqueState.Cull = ECullMode::Back; - techDesc.TechniqueState.Fill = EFillMode::Solid; - techDesc.TechniqueState.Transparency = TransparencyMode::eOpaque; - techDesc.TechniqueState.DepthMode = DepthMode::eReadWrite; - - PassBindingDesc passDesc{}; - passDesc.PassName = "GBufferPass"; - passDesc.PassEffect = gbufferEffect; - techDesc.Passes.push_back(passDesc); - passDesc.PassName = "DepthPrePass"; - passDesc.PassEffect = depthPrePassEffect; - techDesc.Passes.push_back(passDesc); - m_OpaqueTechnique = renderer.CreateOrGetTechnique(techDesc); - - techDesc.Name = "DefaultMeshTransparent"; - techDesc.TechniqueState.Cull = ECullMode::Back; - techDesc.TechniqueState.Fill = EFillMode::Solid; - techDesc.TechniqueState.Transparency = TransparencyMode::eTransparent; - techDesc.TechniqueState.DepthMode = DepthMode::eReadOnly; - techDesc.Passes.clear(); - passDesc.PassName = "TransparentForwardPass"; - passDesc.PassEffect = forwardTransparentEffect; - techDesc.Passes.push_back(passDesc); - m_TransparentTechnique = renderer.CreateOrGetTechnique(techDesc); + SafePtr opaqueTechnique = renderer.GetTechnique("DefaultMeshOpaque"); - m_BasicMaterial = lnnew Material(m_OpaqueTechnique); - m_BasicMaterial2 = lnnew Material(m_OpaqueTechnique); + m_BasicMaterial = lnnew Material(opaqueTechnique); + m_BasicMaterial2 = lnnew Material(opaqueTechnique); m_BasicMaterial->SetProperty("uColor", glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); m_BasicMaterial->SetTexture("tAlbedo", uvChecker); @@ -284,8 +264,8 @@ void AppLayer::OnAttach() cubeMesh->SetMaterial(m_BasicMaterial, 0); SafePtr sphereMesh = StaticMesh::GenerateUVSphere(1.0f, 32, 32); sphereMesh->SetMaterial(m_BasicMaterial2, 0); - modelMeshComponent.Mesh = lnnew StaticMesh(ApplicationBase::GetAssetsPath() + "Models\\gltf\\Models\\Sponza\\glTF\\Sponza.gltf", m_OpaqueTechnique, m_TransparentTechnique); - modelSphereMeshComponent.Mesh = lnnew StaticMesh(ApplicationBase::GetAssetsPath() + "Models\\gltf\\Models\\SpecularTest\\glTF\\SpecularTest.gltf", m_OpaqueTechnique, m_TransparentTechnique); + modelMeshComponent.Mesh = lnnew StaticMesh(ApplicationBase::GetAssetsPath() + "Models\\gltf\\Models\\Sponza\\glTF\\Sponza.gltf"); + modelSphereMeshComponent.Mesh = lnnew StaticMesh(ApplicationBase::GetAssetsPath() + "Models\\gltf\\Models\\MetalRoughSpheres\\glTF\\MetalRoughSpheres.gltf"); cubeMeshComponent.Mesh = cubeMesh; sphereMeshComponent.Mesh = sphereMesh; @@ -334,7 +314,7 @@ void AppLayer::OnAttach() m_CameraTarget.Rotation = cameraTransform.EulerAngles; cameraComponent.UpdateView(cameraTransform); - m_WorldRenderer->SetEnvironmentMap(ApplicationBase::GetAssetsPath() + "Textures\\HDRIs\\OvercastIndustrialCourtyard.hdr"); + m_WorldRenderer->SetEnvironmentMap(ApplicationBase::GetAssetsPath() + "Textures\\HDRIs\\pisa.hdr"); m_WorldRenderer->SetSunLightDirection(m_LightDirection); m_WorldRenderer->SetAmbientLight(m_AmbientLight); } diff --git a/LNApp/src/AppLayer.h b/LNApp/src/AppLayer.h index e385794..b417324 100644 --- a/LNApp/src/AppLayer.h +++ b/LNApp/src/AppLayer.h @@ -51,7 +51,7 @@ class AppLayer final : public lne::Layer void PostExecute(vk::CommandBuffer cmdBuffer, lne::FrameGraph* frameGraph, lne::FrameGraphNode* node) override; void OnImGuiRender() override; private: - lne::SafePtr m_MaterialV2{}; + lne::SafePtr m_Material{}; lne::SafePtr m_Texture{}; @@ -67,11 +67,12 @@ class AppLayer final : public lne::Layer m_Name = "ToneMappingPass"; } void OnBind(lne::FrameGraph* frameGraph, lne::FrameGraphNode* node) override; + void OnResize(lne::FrameGraph* frameGraph, lne::FrameGraphNode* node) override; void Execute(vk::CommandBuffer cmdBuffer, class lne::WorldRenderer* worldRenderer, lne::FrameGraph* frameGraph, lne::FrameGraphNode* node) override; void PostExecute(vk::CommandBuffer cmdBuffer, lne::FrameGraph* frameGraph, lne::FrameGraphNode* node) override; void OnImGuiRender() override; private: - lne::SafePtr m_MaterialV2{}; + lne::SafePtr m_Material{}; lne::SafePtr m_DebugTexture{}; bool m_IsDebugOpen{ false }; }; @@ -98,9 +99,6 @@ class AppLayer final : public lne::Layer lne::SafePtr m_BasicMaterial{}; lne::SafePtr m_BasicMaterial2{}; - lne::SafePtr m_OpaqueTechnique{}; - lne::SafePtr m_TransparentTechnique{}; - struct CameraTarget { glm::vec3 Position; diff --git a/LNEngine/Assets/Shaders/ForwardTransparent.glsl b/LNEngine/Assets/Shaders/ForwardTransparent.glsl index 2544ca8..0ebff41 100644 --- a/LNEngine/Assets/Shaders/ForwardTransparent.glsl +++ b/LNEngine/Assets/Shaders/ForwardTransparent.glsl @@ -68,8 +68,16 @@ void main() mat3 normalMatrix = transpose(inverse(mat3(model))); oNormal = normalize(normalMatrix * vertexBuffer.vertices[currentIndex].normal); - oTangent = normalize(normalMatrix * vertexBuffer.vertices[currentIndex].tangent.xyz); - oBitangent = vertexBuffer.vertices[currentIndex].tangent.w * cross(oNormal, oTangent); // tangent.w = normal space handedness + if (vertexBuffer.vertices[currentIndex].tangent.xyz == vec3(0.0)) + { + oTangent = vec3(0.0); + oBitangent = vec3(0.0); + } + else + { + oTangent = normalize(normalMatrix * vertexBuffer.vertices[currentIndex].tangent.xyz); + oBitangent = vertexBuffer.vertices[currentIndex].tangent.w * cross(oNormal, oTangent); // tangent.w = normal space handedness + } } #endif @@ -114,14 +122,15 @@ void main() roughness = texture(globalTextures[nonuniformEXT(mat.tRoughness)], iUVs).y; vec3 normal = normalize(iNormal); - if (mat.tNormal != 0) + if (mat.tNormal != 0 && iTangent != vec3(0.0)) { vec3 tangent = normalize(iTangent - normal * dot(normal, iTangent)); vec3 bitangent = normalize(iBitangent); mat3 TBN = mat3(tangent, bitangent, normal); - normal = vec3(TBN * (texture(globalTextures[nonuniformEXT(mat.tNormal)], iUVs).xyz * 2.0 - vec3(1.0))); + normal = vec4(TBN * (texture(globalTextures[nonuniformEXT(mat.tNormal)], iUVs).xyz * 2.0 - vec3(1.0)), 1.0).xyz; } + vec3 viewDir = normalize(uEyePos - iWorldPos); vec3 lightDir = normalize(-uSunDir); vec3 lightColor = length(uSunDir) * vec3(1.0); diff --git a/LNEngine/src/Engine/Core/ApplicationBase.cpp b/LNEngine/src/Engine/Core/ApplicationBase.cpp index 46f3c6f..03297a6 100644 --- a/LNEngine/src/Engine/Core/ApplicationBase.cpp +++ b/LNEngine/src/Engine/Core/ApplicationBase.cpp @@ -129,7 +129,6 @@ void ApplicationBase::Run() LNE_PROFILE_SCOPE("Frame") m_Clock.Tick(); - m_Window->BeginFrame(); m_Renderer->BeginFrame(); for (auto layer : m_LayerStack) diff --git a/LNEngine/src/Engine/Core/Utils/Profiling.h b/LNEngine/src/Engine/Core/Utils/Profiling.h index d88eca0..96c6a70 100644 --- a/LNEngine/src/Engine/Core/Utils/Profiling.h +++ b/LNEngine/src/Engine/Core/Utils/Profiling.h @@ -3,13 +3,19 @@ #if defined(TRACY_ENABLE) && defined(LNE_DEBUG) # define LNE_PROFILE_SCOPE(name) ZoneScopedN(name); # define LNE_PROFILE_SCOPE_C(name, color) ZoneScopedNC(name, color); -# define LNE_PROFILE_FUNCTION() LNE_PROFILE_SCOPE(__FUNCSIG__); -# define LNE_PROFILE_FUNCTION_C(color) LNE_PROFILE_SCOPE_C(__FUNCSIG__, color); +# define LNE_PROFILE_FUNCTION() LNE_PROFILE_SCOPE(__FUNCTION__); +# define LNE_PROFILE_FUNCTION_C(color) LNE_PROFILE_SCOPE_C(__FUNCTION__, color); # define LNE_PROFILE_SCOPE_STR(name) ZoneScoped; ZoneName(name.c_str(), name.size()); # define LNE_PROFILE_SCOPE_STR_C(name, color) ZoneScoped; ZoneName(name.c_str(), name.size()); ZoneColor(color); # define LNE_PROFILE_FRAME FrameMark; +# define SET_PROFILING_THREAD_NAME(name) tracy::SetThreadName(name); #else # define LNE_PROFILE_SCOPE(name) +# define LNE_PROFILE_SCOPE_C(name, color) # define LNE_PROFILE_FUNCTION() +# define LNE_PROFILE_FUNCTION_C(color) +# define LNE_PROFILE_SCOPE_STR(name) +# define LNE_PROFILE_SCOPE_STR_C(name, color) # define LNE_PROFILE_FRAME +# define SET_PROFILING_THREAD_NAME(name) #endif diff --git a/LNEngine/src/Engine/Core/Window.cpp b/LNEngine/src/Engine/Core/Window.cpp index 85f23fa..4ec7c69 100644 --- a/LNEngine/src/Engine/Core/Window.cpp +++ b/LNEngine/src/Engine/Core/Window.cpp @@ -3,6 +3,7 @@ #include "ApplicationBase.h" #include "Utils/_Defines.h" #include "Utils/Log.h" +#include "Utils/Profiling.h" #include "Events/WindowEvents.h" #include "Events/KeyboardEvents.h" #include "Events/MouseEvents.h" @@ -13,10 +14,8 @@ namespace lne { -/** - * \brief Creates a window with the specified settings - * \param settings specifies the window settings - */ +#define PROFILING_COLOR 0x7171AB + Window::Window(WindowSettings&& settings) : m_Settings{std::move(settings)} { @@ -52,7 +51,7 @@ Window::Window(WindowSettings&& settings) m_GfxContext.Reset(lnnew GfxContext(surface)); m_GfxContext->InitDefaultResources(); - m_SwapChain.Reset(lnnew Swapchain(m_GfxContext, surface)); + m_Swapchain.Reset(lnnew Swapchain(m_GfxContext, surface)); ApplicationBase::GetEventHub().RegisterListener(this, &Window::OnWindowResize); } @@ -66,23 +65,20 @@ Window::~Window() lne::Framebuffer& Window::GetFramebuffer(uint32_t index) const { - return m_SwapChain->GetFramebuffer(index); + return m_Swapchain->GetFramebuffer(index); } void Window::PollEvents() const { + LNE_PROFILE_FUNCTION_C(PROFILING_COLOR); glfwPollEvents(); } -void Window::BeginFrame() const -{ - //m_SwapChain->BeginFrame(); -} - void Window::Present() { - bool hasPresented = m_SwapChain->Present(); - if (hasPresented == false || m_IsDirty == true) + LNE_PROFILE_FUNCTION_C(PROFILING_COLOR); + m_Swapchain->Present(); + if (m_IsDirty == true || m_Swapchain->IsDirty()) { while (m_Settings.Width == 0 || m_Settings.Height == 0) { @@ -90,7 +86,8 @@ void Window::Present() glfwWaitEvents(); } LNE_INFO("Recreating swapchain"); - m_SwapChain->CreateSwapchain(); + m_Swapchain->CreateSwapchain(); + m_Swapchain->ResetDirty(); for (auto&[_, callback] : m_SwapchainRecreateCallback) callback(); diff --git a/LNEngine/src/Engine/Core/Window.h b/LNEngine/src/Engine/Core/Window.h index 4f5a32e..286a818 100644 --- a/LNEngine/src/Engine/Core/Window.h +++ b/LNEngine/src/Engine/Core/Window.h @@ -18,38 +18,38 @@ class Window final Window(WindowSettings&& settings); ~Window(); - [[nodiscard]] SafePtr GetGfxContext() const { return m_GfxContext; } - [[nodiscard]] SafePtr GetSwapchain() const { return m_SwapChain; } - [[nodiscard]] struct GLFWwindow* GetHandle() const { return m_Handle; } + [[nodiscard]] SafePtr GetGfxContext() const { return m_GfxContext; } + [[nodiscard]] SafePtr GetSwapchain() const { return m_Swapchain; } + [[nodiscard]] struct GLFWwindow* GetHandle() const { return m_Handle; } - [[nodiscard]] uint32_t GetWidth() const { return m_Settings.Width; } - [[nodiscard]] uint32_t GetHeight() const { return m_Settings.Height; } - [[nodiscard]] const WindowSettings& GetSettings() const { return m_Settings; } + [[nodiscard]] uint32_t GetWidth() const { return m_Settings.Width; } + [[nodiscard]] uint32_t GetHeight() const { return m_Settings.Height; } + [[nodiscard]] const WindowSettings& GetSettings() const { return m_Settings; } - [[nodiscard]] Framebuffer& GetFramebuffer(uint32_t index) const; + [[nodiscard]] Framebuffer& GetFramebuffer(uint32_t index) const; - void PollEvents() const; - void BeginFrame() const; - void Present(); - [[nodiscard]] bool ShouldClose() const; + void PollEvents() const; + void Present(); + [[nodiscard]] bool ShouldClose() const; - void AddSwapchainRecreateCallback(void* key, std::function callback); - void RemoveSwapchainRecreateCallback(void* key); + void AddSwapchainRecreateCallback(void* key, + std::function callback); + void RemoveSwapchainRecreateCallback(void* key); private: - struct GLFWwindow* m_Handle; - WindowSettings m_Settings; - bool m_IsDirty{ false }; + struct GLFWwindow* m_Handle; + WindowSettings m_Settings; + bool m_IsDirty{ false }; - std::unique_ptr m_InputManager; - SafePtr m_SwapChain; - SafePtr m_GfxContext; + std::unique_ptr m_InputManager; + SafePtr m_Swapchain; + SafePtr m_GfxContext; - std::map> m_SwapchainRecreateCallback; + std::map> m_SwapchainRecreateCallback; private: - void InitEventCallbacks(); - bool OnWindowResize(class WindowResizeEvent& e); + void InitEventCallbacks(); + bool OnWindowResize(class WindowResizeEvent& e); friend class ApplicationBase; }; diff --git a/LNEngine/src/Engine/Graphics/DynamicDescriptorAllocator.cpp b/LNEngine/src/Engine/Graphics/DynamicDescriptorAllocator.cpp index d50b0e4..7883513 100644 --- a/LNEngine/src/Engine/Graphics/DynamicDescriptorAllocator.cpp +++ b/LNEngine/src/Engine/Graphics/DynamicDescriptorAllocator.cpp @@ -105,6 +105,7 @@ vk::DescriptorSet DynamicDescriptorAllocator::Allocate(vk::DescriptorSetLayout l } catch (std::exception& e) { + (void)e; LNE_WARN("DynamicDescriptorAllocator: {} \n Exception: {}", m_DebugName, e.what()); AllocateNewPool(); poolIdx = m_FreePoolIndices.back(); @@ -146,6 +147,7 @@ vk::DescriptorSet DynamicDescriptorAllocator::Allocate(vk::DescriptorSetLayout l } catch (std::exception& e) { + (void)e; LNE_WARN("DynamicDescriptorAllocator: {} \n Exception: {}", m_DebugName, e.what()); AllocateNewPool(); poolIdx = m_FreePoolIndices.back(); diff --git a/LNEngine/src/Engine/Graphics/FrameGraph/FrameGraph.cpp b/LNEngine/src/Engine/Graphics/FrameGraph/FrameGraph.cpp index cdbf2fd..2e74c93 100644 --- a/LNEngine/src/Engine/Graphics/FrameGraph/FrameGraph.cpp +++ b/LNEngine/src/Engine/Graphics/FrameGraph/FrameGraph.cpp @@ -228,7 +228,8 @@ void FrameGraph::Execute(vk::CommandBuffer commandBuffer, WorldRenderer* worldRe void FrameGraph::OnResize(WindowResizeEvent& e) { - // TODO: resize framebuffers + std::list> freeTextures; + for (FrameGraphNodeHandle nodeHandle : m_Nodes) { FrameGraphNode& node = *m_NodeCache.GetPool().Access(nodeHandle); @@ -249,7 +250,9 @@ void FrameGraph::OnResize(WindowResizeEvent& e) || imageInfo.Format == vk::Format::eD16UnormS8Uint || imageInfo.Format == vk::Format::eD24UnormS8Uint || imageInfo.Format == vk::Format::eD32SfloatS8Uint); - + + imageInfo.Extent.width = e.GetWidth(); + imageInfo.Extent.height = e.GetHeight(); if (isDepth) { @@ -270,11 +273,53 @@ void FrameGraph::OnResize(WindowResizeEvent& e) } } } + + for (FrameGraphResourceHandle inputResourceHandle : node.InputResources) + { + FrameGraphResource& inputResource = *m_ResourceCache.GetPool().Access(inputResourceHandle); + FrameGraphResource* associatedOutputResource = m_ResourceCache.Access(inputResource.Name); + + LNE_ASSERT(associatedOutputResource != nullptr, "Input resource has no associated output resource"); + + if (associatedOutputResource->Type == FrameGraphResourceType::eProxy) + associatedOutputResource = GetProxyRealResource(associatedOutputResource); + + --associatedOutputResource->RefCount; + + switch (associatedOutputResource->Type) + { + case FrameGraphResourceType::eAttachment: + case FrameGraphResourceType::eTexture: + { + const auto& outputImageInfo = std::get(associatedOutputResource->Info.Variant); + auto& imageInfo = std::get(inputResource.Info.Variant); + imageInfo.Extent.width = e.GetWidth(); + imageInfo.Extent.height = e.GetHeight(); + + if (associatedOutputResource->RefCount != 0 || associatedOutputResource->Info.External) + continue; + + freeTextures.push_back(associatedOutputResource->Resource.GetAs()); + break; + } + case FrameGraphResourceType::eBuffer: + { + LNE_ASSERT(false, "Buffer resource not implemented yet"); + if (associatedOutputResource->RefCount != 0 || associatedOutputResource->Info.External) + continue; + break; + } + } + } } for (FrameGraphNodeHandle nodeHandle : m_Nodes) - { CreateFramebuffers(nodeHandle); + + for (FrameGraphNodeHandle nodeHandle : m_Nodes) + { + FrameGraphNode* node = m_NodeCache.GetPool().Access(nodeHandle); + node->RenderPass->OnResize(this, node); } } diff --git a/LNEngine/src/Engine/Graphics/FrameGraph/FrameGraph.h b/LNEngine/src/Engine/Graphics/FrameGraph/FrameGraph.h index 7c6d170..438a560 100644 --- a/LNEngine/src/Engine/Graphics/FrameGraph/FrameGraph.h +++ b/LNEngine/src/Engine/Graphics/FrameGraph/FrameGraph.h @@ -51,6 +51,7 @@ struct FrameGraphResourceInfo struct FrameGraphResource { FrameGraphResourceType::Enum Type{}; + // TODO: This ref count does not work on resize. uint32_t RefCount{ 0 }; FrameGraphResourceInfo Info{}; SafePtr Resource{}; // Texture, Buffer, etc. diff --git a/LNEngine/src/Engine/Graphics/FrameGraph/RenderPass/IRenderPass.h b/LNEngine/src/Engine/Graphics/FrameGraph/RenderPass/IRenderPass.h index 62bf210..8b3e133 100644 --- a/LNEngine/src/Engine/Graphics/FrameGraph/RenderPass/IRenderPass.h +++ b/LNEngine/src/Engine/Graphics/FrameGraph/RenderPass/IRenderPass.h @@ -58,7 +58,7 @@ class IRenderPass : public RefCountBase */ virtual void EndFrame() {} - virtual void OnResize(glm::vec2 dimension) {} + virtual void OnResize(FrameGraph* frameGraph, FrameGraphNode* node) {} /** * This is called on the main thread to render any ImGui widgets for this render pass. diff --git a/LNEngine/src/Engine/Graphics/FrameGraph/RenderPass/LightingPass.cpp b/LNEngine/src/Engine/Graphics/FrameGraph/RenderPass/LightingPass.cpp index 2ac0beb..18addad 100644 --- a/LNEngine/src/Engine/Graphics/FrameGraph/RenderPass/LightingPass.cpp +++ b/LNEngine/src/Engine/Graphics/FrameGraph/RenderPass/LightingPass.cpp @@ -21,20 +21,20 @@ void LightingPass::OnBind(FrameGraph* frameGraph, FrameGraphNode* node) SafePtr skyboxEffect = renderer.CreateOrGetEffect(ApplicationBase::GetAssetsPath() + "Engine\\Shaders\\Lighting.glsl"); - GfxTechniqueDesc techDesc{}; - techDesc.Name = "LightingTechnique"; - techDesc.TechniqueState.Cull = ECullMode::None; - techDesc.TechniqueState.Fill = EFillMode::Solid; - techDesc.TechniqueState.Transparency = TransparencyMode::eOpaque; - techDesc.TechniqueState.DepthMode = DepthMode::eNone; + GfxTechniqueDesc techDesc{}; + techDesc.Name = "LightingTechnique"; + techDesc.TechniqueState.Cull = ECullMode::None; + techDesc.TechniqueState.Fill = EFillMode::Solid; + techDesc.TechniqueState.Transparency = TransparencyMode::eOpaque; + techDesc.TechniqueState.DepthMode = DepthMode::eNone; - PassBindingDesc passDesc{}; - passDesc.PassName = "LightingPass"; - passDesc.PassEffect = skyboxEffect; - techDesc.Passes.push_back(passDesc); + PassBindingDesc passDesc{}; + passDesc.PassName = "LightingPass"; + passDesc.PassEffect = skyboxEffect; + techDesc.Passes.push_back(passDesc); SafePtr technique = renderer.CreateOrGetTechnique(techDesc); - m_Material = lnnew Material(technique); + m_Material = lnnew Material(technique); for (FrameGraphResourceHandle resourceHandle : node->OutputResources) { @@ -47,18 +47,46 @@ void LightingPass::OnBind(FrameGraph* frameGraph, FrameGraphNode* node) texture->GetDimensions().width / 2, texture->GetDimensions().height / 2, texture->GetFormat(), TextureUsageType::eSampled, false, texture->GetName() + "ImGUI Debug"); m_DebugTexture = debugTexture; } - } - for (FrameGraphResourceHandle handle : node->InputResources) - { - FrameGraphResource* resource = frameGraph->GetResource(handle); - if (resource->Name == "GBufferPosition") - { - SafePtr positionTexture = resource->Resource.GetAs(); + } + for (FrameGraphResourceHandle handle : node->InputResources) + { + FrameGraphResource* resource = frameGraph->GetResource(handle); + if (resource->Name == "GBufferPosition") + { + SafePtr positionTexture = resource->Resource.GetAs(); + m_Material->SetTexture("tPosition", positionTexture); + } + if (resource->Name == "GBufferNormal") + { + SafePtr normalTexture = resource->Resource.GetAs(); + m_Material->SetTexture("tNormal", normalTexture); + } + if (resource->Name == "GBufferColor") + { + SafePtr colorTexture = resource->Resource.GetAs(); + m_Material->SetTexture("tAlbedo", colorTexture); + } + if (resource->Name == "GBufferMetalRough") + { + SafePtr colorTexture = resource->Resource.GetAs(); + m_Material->SetTexture("tMetalnessRoughness", colorTexture); + } + } +} + +void LightingPass::OnResize(FrameGraph* frameGraph, FrameGraphNode* node) +{ + for (FrameGraphResourceHandle handle : node->InputResources) + { + FrameGraphResource* resource = frameGraph->GetResource(handle); + if (resource->Name == "GBufferPosition") + { + SafePtr positionTexture = resource->Resource.GetAs(); m_Material->SetTexture("tPosition", positionTexture); - } - if (resource->Name == "GBufferNormal") - { - SafePtr normalTexture = resource->Resource.GetAs(); + } + if (resource->Name == "GBufferNormal") + { + SafePtr normalTexture = resource->Resource.GetAs(); m_Material->SetTexture("tNormal", normalTexture); } if (resource->Name == "GBufferColor") @@ -70,8 +98,8 @@ void LightingPass::OnBind(FrameGraph* frameGraph, FrameGraphNode* node) { SafePtr colorTexture = resource->Resource.GetAs(); m_Material->SetTexture("tMetalnessRoughness", colorTexture); - } - } + } + } } void LightingPass::Execute(vk::CommandBuffer cmdBuffer, lne::WorldRenderer* worldRenderer, lne::FrameGraph* frameGraph, lne::FrameGraphNode* node) diff --git a/LNEngine/src/Engine/Graphics/FrameGraph/RenderPass/LightingPass.h b/LNEngine/src/Engine/Graphics/FrameGraph/RenderPass/LightingPass.h index 40b4228..4e0f85e 100644 --- a/LNEngine/src/Engine/Graphics/FrameGraph/RenderPass/LightingPass.h +++ b/LNEngine/src/Engine/Graphics/FrameGraph/RenderPass/LightingPass.h @@ -13,12 +13,13 @@ class LightingPass : public lne::IRenderPass m_Name = "LightingPass"; } void OnBind(FrameGraph* frameGraph, FrameGraphNode* node) override; + void OnResize(FrameGraph* frameGraph, FrameGraphNode* node) override; void Execute(vk::CommandBuffer cmdBuffer, class WorldRenderer* worldRenderer, FrameGraph* frameGraph, FrameGraphNode* node) override; void PostExecute(vk::CommandBuffer cmdBuffer, FrameGraph* frameGraph, FrameGraphNode* node) override; void OnImGuiRender() override; private: - SafePtr m_Material; + SafePtr m_Material; SafePtr m_DebugTexture{}; bool m_IsDebugOpen{false}; diff --git a/LNEngine/src/Engine/Graphics/GfxContext.h b/LNEngine/src/Engine/Graphics/GfxContext.h index 5504030..d3c8623 100644 --- a/LNEngine/src/Engine/Graphics/GfxContext.h +++ b/LNEngine/src/Engine/Graphics/GfxContext.h @@ -22,7 +22,7 @@ struct QueueFamilyIndices std::optional TransferFamily; std::optional PresentFamily; - [[nodiscard]] bool IsComplete() const + bool IsComplete() const { return GraphicsFamily.has_value() && ComputeFamily.has_value() @@ -40,113 +40,121 @@ class GfxContext : public RefCountBase GfxContext(vk::SurfaceKHR surface); virtual ~GfxContext(); - static bool InitVulkan(std::string appName); - static void NukeVulkan(); + static bool InitVulkan(std::string appName); + static void NukeVulkan(); - void InitDefaultResources(); - void UploadDefaultResources(); - void NukeDefaultResources(); - void DeferredNukeResources(); + void InitDefaultResources(); + void UploadDefaultResources(); + void NukeDefaultResources(); + void DeferredNukeResources(); - void EnqueueResourceDeletion(const ResourceDeletion& deletion) + void EnqueueResourceDeletion(const ResourceDeletion& deletion) { std::lock_guard lock(m_ResourceDeletionMutex); m_ResourceDeletionQueue.push_back(deletion); } - void WaitIdle() const; + void WaitIdle() const; - static vk::Instance VulkanInstance() { return s_VulkanInstance; } - vk::PhysicalDevice GetPhysicalDevice() const { return m_PhysicalDevice; } - vk::Device GetDevice() const { return m_Device; } + static vk::Instance VulkanInstance() { return s_VulkanInstance; } + vk::PhysicalDevice GetPhysicalDevice() const { return m_PhysicalDevice; } + vk::Device GetDevice() const { return m_Device; } // Gets the current frame in flight on the main thread - [[nodiscard]] constexpr uint32_t GetCurrentFrameIndex() const { return m_CurrentFrameInFlight; } - [[nodiscard]] constexpr uint32_t GetMaxFramesInFlight() const { return m_MaxFramesInFlight; } - [[nodiscard]] VmaAllocator GetMemoryAllocator() const { return m_MemoryAllocator; } + [[nodiscard]] constexpr uint32_t GetCurrentFrameIndex() const { return m_CurrentFrameInFlight; } + [[nodiscard]] constexpr uint32_t GetMaxFramesInFlight() const { return m_MaxFramesInFlight; } + [[nodiscard]] VmaAllocator GetMemoryAllocator() const { return m_MemoryAllocator; } [[nodiscard]] class CommandPoolManager& GetCommandPoolManager() const { return *m_CommandPoolManager; }; - [[nodiscard]] const class Geometry& GetDefaultFullscreenQuad() const { return *m_DefaultFullscreenQuad; } - [[nodiscard]] SafePtr GetDefaultTexture() const; - [[nodiscard]] SafePtr GetWhiteTexture() const; - [[nodiscard]] vk::Sampler GetDefaultSampler() const { return m_DefaultSampler; } + [[nodiscard]] const class Geometry& GetDefaultFullscreenQuad() const { return *m_DefaultFullscreenQuad; } + [[nodiscard]] SafePtr GetDefaultTexture() const; + [[nodiscard]] SafePtr GetWhiteTexture() const; + [[nodiscard]] vk::Sampler GetDefaultSampler() const { return m_DefaultSampler; } // numBindings MUST be in range [1, 4] - [[nodiscard]] vk::DescriptorSetLayout GetStorageOnlyDescriptorSetLayout(uint32_t numBindings) const + [[nodiscard]] vk::DescriptorSetLayout GetStorageOnlyDescriptorSetLayout(uint32_t numBindings) const { LNE_ASSERT(numBindings >= 1 && numBindings <= s_MaxSSBOsPerSet, "numBindings must be in range [1, 4]"); return m_StorageOnlyDescriptorSetLayouts[(numBindings) > s_MaxSSBOsPerSet ? s_MaxSSBOsPerSet - 1 : numBindings - 1]; } #pragma region PhysicalDevice - [[nodiscard]] const vk::PhysicalDeviceProperties& GetProperties() const { return m_Properties; } - [[nodiscard]] const vk::PhysicalDeviceFeatures& GetEnabledFeatures() const { return m_EnabledFeatures; } - [[nodiscard]] const vk::PhysicalDeviceMemoryProperties& GetMemoryProperties() const { return m_MemoryProperties; } + [[nodiscard]] const vk::PhysicalDeviceProperties& GetProperties() const { return m_Properties; } + [[nodiscard]] const vk::PhysicalDeviceFeatures& GetEnabledFeatures() const { return m_EnabledFeatures; } + [[nodiscard]] const vk::PhysicalDeviceMemoryProperties& GetMemoryProperties() const { return m_MemoryProperties; } [[nodiscard]] const std::vector& GetQueueFamilyProperties() const { return m_QueueFamilyProperties; } - [[nodiscard]] vk::SurfaceCapabilitiesKHR GetSurfaceCapabilities(vk::SurfaceKHR surface) const; - [[nodiscard]] std::vector GetSurfaceFormats(vk::SurfaceKHR surface) const; - [[nodiscard]] std::vector GetSurfacePresentModes(vk::SurfaceKHR surface) const; + [[nodiscard]] vk::SurfaceCapabilitiesKHR GetSurfaceCapabilities(vk::SurfaceKHR surface) const; + [[nodiscard]] std::vector GetSurfaceFormats(vk::SurfaceKHR surface) const; + [[nodiscard]] std::vector GetSurfacePresentModes(vk::SurfaceKHR surface) const; #pragma endregion #pragma region Queues [[nodiscard]] const QueueFamilyIndices& GetQueueFamilyIndices() const { return m_QueueFamilyIndices; } - [[nodiscard]] std::string GetQueueFamilyName(EQueueFamilyType type) const; - [[nodiscard]] uint32_t GetQueueFamilyIndex(EQueueFamilyType type) const; - [[nodiscard]] vk::Queue GetQueue(EQueueFamilyType type) const; + [[nodiscard]] std::string GetQueueFamilyName(EQueueFamilyType type) const; + [[nodiscard]] uint32_t GetQueueFamilyIndex(EQueueFamilyType type) const; + [[nodiscard]] vk::Queue GetQueue(EQueueFamilyType type) const; - void SubmitToQueue(EQueueFamilyType type, const vk::SubmitInfo& submitInfo, vk::Fence fence); + void SubmitToQueue(EQueueFamilyType type, + const vk::SubmitInfo& submitInfo, + vk::Fence fence); #pragma endregion #pragma region CommandBuffers - [[nodiscard]] vk::CommandPool CreateCommandPool(uint32_t queueFamilyIndex, vk::CommandPoolCreateFlags flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer) const; + [[nodiscard]] vk::CommandPool CreateCommandPool(uint32_t queueFamilyIndex, + vk::CommandPoolCreateFlags flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer) const; - [[nodiscard]] vk::CommandBuffer GetPrimaryCommandBuffer() const; + [[nodiscard]] vk::CommandBuffer GetPrimaryCommandBuffer() const; #pragma endregion #pragma region Images - [[nodiscard]] vk::ImageView CreateImageView(vk::Image image, vk::ImageViewType viewType, + [[nodiscard]] vk::ImageView CreateImageView(vk::Image image, vk::ImageViewType viewType, vk::Format format, uint32_t numMipLevels = 1, uint32_t layers = 1, vk::ImageAspectFlags aspect = vk::ImageAspectFlagBits::eColor, const std::string& name = ""); - [[nodiscard]] BindlessImageHandle RegisterBindlessTexture(class Texture* texture); - [[nodiscard]] BindlessImageHandle RegisterBindlessImage(vk::ImageView imageView); - - [[nodiscard]] vk::Sampler CreateSampler(vk::Filter magFilter = vk::Filter::eLinear, vk::Filter minFilter = vk::Filter::eLinear, - vk::SamplerMipmapMode mipmapMode = vk::SamplerMipmapMode::eLinear, - vk::SamplerAddressMode addressMode = vk::SamplerAddressMode::eRepeat, float maxAnisotropy = 1.0f, bool compareEnable = false, - vk::CompareOp compareOp = vk::CompareOp::eAlways, vk::BorderColor borderColor = vk::BorderColor::eFloatOpaqueWhite, - vk::SamplerReductionMode reductionMode = vk::SamplerReductionMode::eWeightedAverage, const std::string& name = ""); - - [[nodiscard]] vk::DescriptorSetLayout GetBindlessDescriptorSetLayout() const { return m_BindlessDescriptorSetLayout; } - [[nodiscard]] vk::DescriptorSet GetBindlessDescriptorSet() const { return m_BindlessDescriptorSet; } + [[nodiscard]] BindlessImageHandle RegisterBindlessTexture(class Texture* texture); + [[nodiscard]] BindlessImageHandle RegisterBindlessImage(vk::ImageView imageView); + + [[nodiscard]] vk::Sampler CreateSampler(vk::Filter magFilter = vk::Filter::eLinear, + vk::Filter minFilter = vk::Filter::eLinear, + vk::SamplerMipmapMode mipmapMode = vk::SamplerMipmapMode::eLinear, + vk::SamplerAddressMode addressMode = vk::SamplerAddressMode::eRepeat, + float maxAnisotropy = 1.0f, + bool compareEnable = false, + vk::CompareOp compareOp = vk::CompareOp::eAlways, + vk::BorderColor borderColor = vk::BorderColor::eFloatOpaqueWhite, + vk::SamplerReductionMode reductionMode = vk::SamplerReductionMode::eWeightedAverage, + const std::string& name = ""); + + [[nodiscard]] vk::DescriptorSetLayout GetBindlessDescriptorSetLayout() const { return m_BindlessDescriptorSetLayout; } + [[nodiscard]] vk::DescriptorSet GetBindlessDescriptorSet() const { return m_BindlessDescriptorSet; } #pragma endregion #pragma region Allocations - void AllocateBuffer(BufferAllocation& allocation, VkBufferCreateInfo bufferCI, VmaAllocationCreateInfo allocCI); - BufferAllocation AllocateStagingBuffer(uint64_t size); - void FreeBufferAllocation(const BufferAllocation& allocation); + void AllocateBuffer(BufferAllocation& allocation, VkBufferCreateInfo bufferCI, VmaAllocationCreateInfo allocCI); + BufferAllocation AllocateStagingBuffer(uint64_t size); + void FreeBufferAllocation(const BufferAllocation& allocation); - void AllocateImage(ImageAllocation& allocation, VkImageCreateInfo imageCI, VmaAllocationCreateInfo allocCI); - void FreeImageAllocation(const ImageAllocation& allocation); + void AllocateImage(ImageAllocation& allocation, VkImageCreateInfo imageCI, VmaAllocationCreateInfo allocCI); + void FreeImageAllocation(const ImageAllocation& allocation); - [[nodiscard]] vk::DescriptorSet AllocateDescriptorSet(vk::DescriptorSetLayout layout, DescriptorType::Enum descriptorType); - void FreeDescriptorSet(vk::DescriptorSet descriptorSet, DescriptorType:: Enum descriptorType); + [[nodiscard]] vk::DescriptorSet AllocateDescriptorSet(vk::DescriptorSetLayout layout, DescriptorType::Enum descriptorType); + void FreeDescriptorSet(vk::DescriptorSet descriptorSet, DescriptorType:: Enum descriptorType); #pragma endregion #pragma region Shader - [[nodiscard]] SafePtr CreateShader(std::string_view filePath); - [[nodiscard]] vk::DescriptorSetLayout CreateDescriptorSetLayout(const std::vector&bindings, const std::string & name = ""); + [[nodiscard]] SafePtr CreateShader(std::string_view filePath); + [[nodiscard]] vk::DescriptorSetLayout CreateDescriptorSetLayout(const std::vector&bindings, const std::string & name = ""); #pragma endregion #pragma region Utils template - void SetVkObjectName(T handle, std::string_view name) const + void SetVkObjectName(T handle, std::string_view name) const { #if defined(VK_EXT_debug_utils) && defined(LNE_DEBUG) const vk::DebugUtilsObjectNameInfoEXT objectNameInfo( @@ -164,9 +172,9 @@ class GfxContext : public RefCountBase #pragma endregion private: - static class vk::Instance s_VulkanInstance; - static vkb::Instance s_VkbInstance; - static bool s_DynamicLoaderInitialized; + static class vk::Instance s_VulkanInstance; + static vkb::Instance s_VkbInstance; + static bool s_DynamicLoaderInitialized; using SSBODescriptorSetLayoutArray = std::array; vk::PhysicalDevice m_PhysicalDevice; @@ -177,64 +185,62 @@ class GfxContext : public RefCountBase vk::PhysicalDeviceMemoryProperties m_MemoryProperties; std::vector m_QueueFamilyProperties; - QueueFamilyIndices m_QueueFamilyIndices; - vk::Queue m_GraphicsQueue; - vk::Queue m_ComputeQueue; - vk::Queue m_TransferQueue; - vk::Queue m_PresentQueue; - - std::mutex m_GraphicsQueueMutex; - std::mutex m_ComputeQueueMutex; - std::mutex m_TransferQueueMutex; - std::mutex m_PresentQueueMutex; + QueueFamilyIndices m_QueueFamilyIndices; + vk::Queue m_GraphicsQueue; + vk::Queue m_ComputeQueue; + vk::Queue m_TransferQueue; + vk::Queue m_PresentQueue; - uint32_t m_CurrentFrameInFlight{ 0 }; - uint32_t m_MaxFramesInFlight{ 2 }; + std::mutex m_GraphicsQueueMutex; + std::mutex m_ComputeQueueMutex; + std::mutex m_TransferQueueMutex; + std::mutex m_PresentQueueMutex; - std::unique_ptr m_CommandPoolManager; + uint32_t m_CurrentFrameInFlight{ 0 }; + uint32_t m_MaxFramesInFlight{ 2 }; + std::unique_ptr m_CommandPoolManager; - vk::Sampler m_DefaultSampler; - SafePtr m_DefaultTexture; - SafePtr m_WhitePixel; - class Geometry* m_DefaultFullscreenQuad; + vk::Sampler m_DefaultSampler; + SafePtr m_DefaultTexture; + SafePtr m_WhitePixel; + class Geometry* m_DefaultFullscreenQuad; - vk::DescriptorPool m_BindlessDescriptorPool; - vk::DescriptorSetLayout m_BindlessDescriptorSetLayout; - vk::DescriptorSet m_BindlessDescriptorSet; - std::queue m_FreeBindlessTextureIndices{}; - std::queue m_FreeBindlessImageIndices{}; - std::mutex m_BindlessMutex{}; + vk::DescriptorPool m_BindlessDescriptorPool; + vk::DescriptorSetLayout m_BindlessDescriptorSetLayout; + vk::DescriptorSet m_BindlessDescriptorSet; + std::queue m_FreeBindlessTextureIndices{}; + std::queue m_FreeBindlessImageIndices{}; + std::mutex m_BindlessMutex{}; std::unique_ptr m_UniformOnlyDescriptorAllocator{}; std::unique_ptr m_StorageOnlyDescriptorAllocator{}; std::unique_ptr m_UniformStorageDescriptorAllocator{}; - SSBODescriptorSetLayoutArray m_StorageOnlyDescriptorSetLayouts{}; + SSBODescriptorSetLayoutArray m_StorageOnlyDescriptorSetLayouts{}; - std::mutex m_ResourceDeletionMutex{}; - std::vector m_ResourceDeletionQueue{}; + std::mutex m_ResourceDeletionMutex{}; + std::vector m_ResourceDeletionQueue{}; friend class Swapchain; friend class Renderer; private: - static VkBool32 VKAPI_CALL DebugPrintfCallback( - VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, - VkDebugUtilsMessageTypeFlagsEXT messageType, - const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, - void* pUserData); + static VkBool32 VKAPI_CALL DebugPrintfCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void* pUserData); private: - vkb::PhysicalDevice VkbSelectPhysicalDevice(const vkb::Instance& instance, vk::SurfaceKHR surface); + vkb::PhysicalDevice VkbSelectPhysicalDevice(const vkb::Instance& instance, vk::SurfaceKHR surface); - void NukeResource(const ResourceDeletion& resource); - void NukeBuffer(const BufferResourceDeletion& buffer); - void NukeImage(const TextureResourceDeletion& image); - void NukePipeline(const PipelineResourceDeletion& pipeline); - void NukeShader(const ShaderResourceDeletion& shader); - void NukeImageView(const ImageViewDeletion& imageView); + void NukeResource(const ResourceDeletion& resource); + void NukeBuffer(const BufferResourceDeletion& buffer); + void NukeImage(const TextureResourceDeletion& image); + void NukePipeline(const PipelineResourceDeletion& pipeline); + void NukeShader(const ShaderResourceDeletion& shader); + void NukeImageView(const ImageViewDeletion& imageView); - void CreateMemoryAllocator(); - void DumpMemoryStats(std::string_view fileName) const; + void CreateMemoryAllocator(); + void DumpMemoryStats(std::string_view fileName) const; }; } diff --git a/LNEngine/src/Engine/Graphics/Renderer.cpp b/LNEngine/src/Engine/Graphics/Renderer.cpp index d51ba08..8a350e0 100644 --- a/LNEngine/src/Engine/Graphics/Renderer.cpp +++ b/LNEngine/src/Engine/Graphics/Renderer.cpp @@ -107,6 +107,37 @@ void Renderer::InitResources() Dispatch(cmdBuffer, brdfProgram, 512 / 32, 512 / 32, 1); m_BRDFLut->TransitionLayout(cmdBuffer, vk::ImageLayout::eShaderReadOnlyOptimal); + + SafePtr gbufferEffect = CreateOrGetEffect(ApplicationBase::GetAssetsPath() + "Engine\\Shaders\\GBuffer.glsl"); + SafePtr forwardTransparentEffect = CreateOrGetEffect(ApplicationBase::GetAssetsPath() + "Engine\\Shaders\\ForwardTransparent.glsl"); + SafePtr depthPrePassEffect = CreateOrGetEffect(ApplicationBase::GetAssetsPath() + "Engine\\Shaders\\DepthPrePass.glsl"); + + GfxTechniqueDesc techDesc{}; + techDesc.Name = "DefaultMeshOpaque"; + techDesc.TechniqueState.Cull = ECullMode::Back; + techDesc.TechniqueState.Fill = EFillMode::Solid; + techDesc.TechniqueState.Transparency = TransparencyMode::eOpaque; + techDesc.TechniqueState.DepthMode = DepthMode::eReadWrite; + + PassBindingDesc passDesc{}; + passDesc.PassName = "GBufferPass"; + passDesc.PassEffect = gbufferEffect; + techDesc.Passes.push_back(passDesc); + passDesc.PassName = "DepthPrePass"; + passDesc.PassEffect = depthPrePassEffect; + techDesc.Passes.push_back(passDesc); + CreateOrGetTechnique(techDesc); + + techDesc.Name = "DefaultMeshTransparent"; + techDesc.TechniqueState.Cull = ECullMode::Back; + techDesc.TechniqueState.Fill = EFillMode::Solid; + techDesc.TechniqueState.Transparency = TransparencyMode::eTransparent; + techDesc.TechniqueState.DepthMode = DepthMode::eReadOnly; + techDesc.Passes.clear(); + passDesc.PassName = "TransparentForwardPass"; + passDesc.PassEffect = forwardTransparentEffect; + techDesc.Passes.push_back(passDesc); + CreateOrGetTechnique(techDesc); } void Renderer::NukeResources() @@ -146,8 +177,8 @@ void Renderer::BeginFrame() { LNE_PROFILE_FUNCTION_C(PROFILING_COL); m_Swapchain->BeginFrame(); - uint32_t currentImageIndex = m_Swapchain->GetCurrentFrameIndex(); - uint32_t frameIndex = m_Context->GetCurrentFrameIndex(); + uint32_t currentImageIndex = m_Swapchain->GetCurrentFrameIndex(); + uint32_t frameIndex = m_Context->GetCurrentFrameIndex(); m_CurrentFrameInFlight = frameIndex; m_Context->GetCommandPoolManager().ResetFrameCommands(frameIndex); vk::CommandBuffer cmdBuffer = m_Context->GetPrimaryCommandBuffer(); @@ -163,14 +194,6 @@ void Renderer::BeginFrame() m_GfxLoader->Update(); UpdateTextures(cmdBuffer); - // Do we need this??? - auto viewport = m_Swapchain->GetViewport(); - cmdBuffer.setScissor(0, viewport.GetScissor()); - auto vp = viewport.GetViewport(); - vp.y += vp.height; - vp.height *= -1; - cmdBuffer.setViewport(0, vp); - m_FrameData[m_CurrentFrameInFlight].DescriptorAllocator->Clear(); }; @@ -558,6 +581,9 @@ SafePtr Renderer::CreateOrGetTechnique(const GfxTechniqueDesc& tec lne::SafePtr Renderer::GetTechnique(const std::string& name) { + std::lock_guard lock(m_TechniquesLibraryMutex); + if (m_TechniquesLibrary.contains(name)) + return m_TechniquesLibrary[name]; return {}; } @@ -611,6 +637,7 @@ void Renderer::AddRenderTask(RenderTaskFunction renderTaskFunc) void Renderer::RunRenderTasks() { + LNE_PROFILE_FUNCTION_C(PROFILING_COL); auto& tasks = m_FrameRenderTasks[m_CurrentFrameInFlightMain]; auto* taskLauncher = m_RenderTasksLauncher[m_CurrentFrameInFlightMain]; if (tasks.empty()) @@ -627,11 +654,15 @@ void Renderer::RunRenderTasks() void Renderer::WaitForRenderTasksToFinish() { + LNE_PROFILE_FUNCTION_C(PROFILING_COL); auto& tasks = m_FrameRenderTasks[m_PrevFrameInFlightMain]; auto* taskLauncher = m_RenderTasksLauncher[m_PrevFrameInFlightMain]; if (tasks.empty()) return; - m_TaskScheduler->WaitforTask(tasks.back()); + { + LNE_PROFILE_SCOPE_C("Wait for Render Tasks", PROFILING_COL) + m_TaskScheduler->WaitforTask(tasks.back()); + } for (auto& task : tasks) delete task; tasks.clear(); diff --git a/LNEngine/src/Engine/Graphics/Renderer.h b/LNEngine/src/Engine/Graphics/Renderer.h index b5cdc50..3dd6661 100644 --- a/LNEngine/src/Engine/Graphics/Renderer.h +++ b/LNEngine/src/Engine/Graphics/Renderer.h @@ -124,9 +124,9 @@ class Renderer [[nodiscard]] SafePtr CreateEnvironmentMap(std::string_view pathToEnvMap, uint32_t dimensions = 1024); - [[nodiscard]] SafePtr CreateOrGetShader(const std::string& path); - [[nodiscard]] SafePtr CreateOrGetEffect(const std::string& path); - [[nodiscard]] SafePtr CreateOrGetTechnique(const GfxTechniqueDesc& techniqueDesc); + SafePtr CreateOrGetShader(const std::string& path); + SafePtr CreateOrGetEffect(const std::string& path); + SafePtr CreateOrGetTechnique(const GfxTechniqueDesc& techniqueDesc); [[nodiscard]] SafePtr GetTechnique(const std::string& name); void AddTextureToUpdate(SafePtr texture); diff --git a/LNEngine/src/Engine/Graphics/Resources/Mesh.cpp b/LNEngine/src/Engine/Graphics/Resources/Mesh.cpp index 733b11a..97b199a 100644 --- a/LNEngine/src/Engine/Graphics/Resources/Mesh.cpp +++ b/LNEngine/src/Engine/Graphics/Resources/Mesh.cpp @@ -24,12 +24,9 @@ StaticMesh::StaticMesh() m_Materials.resize(1); } -StaticMesh::StaticMesh(std::filesystem::path path, SafePtr opaqueTechnique, SafePtr transparentTechnique) +StaticMesh::StaticMesh(std::filesystem::path path) : m_Path(path), m_Geometry{ nullptr }, - m_Materials{}, - m_OpaqueTechnique(opaqueTechnique), - m_TransparentTechnique(transparentTechnique), m_Textures{} { Assimp::Importer importer; @@ -204,7 +201,6 @@ void StaticMesh::LoadMaterials(const aiScene* scene) { int x, y, comp; stbi_info(texPath.string().c_str(), &x, &y, &comp); - isTransparent = (comp == 4); } } @@ -212,9 +208,9 @@ void StaticMesh::LoadMaterials(const aiScene* scene) SafePtr material{}; if (isTransparent) - material = lnnew Material(m_TransparentTechnique); + material = lnnew Material(renderer.GetTechnique("DefaultMeshTransparent")); else - material = lnnew Material(m_OpaqueTechnique); + material = lnnew Material(renderer.GetTechnique("DefaultMeshOpaque")); m_Materials.push_back(material); aiColor3D aiColor(1.0f); diff --git a/LNEngine/src/Engine/Graphics/Resources/Mesh.h b/LNEngine/src/Engine/Graphics/Resources/Mesh.h index 8b3ad7d..16c9827 100644 --- a/LNEngine/src/Engine/Graphics/Resources/Mesh.h +++ b/LNEngine/src/Engine/Graphics/Resources/Mesh.h @@ -86,14 +86,12 @@ class StaticMesh : public RefCountBase { public: // TODO: probably make a mesh importer class or something - StaticMesh(std::filesystem::path path, - SafePtr opaqueTechnique, - SafePtr transparentTechnique); + StaticMesh(std::filesystem::path path); std::vector& GetSubMeshes() { return m_SubMeshes; } const Geometry& GetGeometry() const { return *m_Geometry.get(); } - [[nodiscard]] SafePtr GetMaterial(uint32_t index) + [[nodiscard]] SafePtr GetMaterial(uint32_t index) { return m_Materials[index]; } @@ -123,11 +121,7 @@ class StaticMesh : public RefCountBase uint32_t m_TotalIndexCount{}; // TODO: move to a resource manager - std::vector> m_Materials; - SafePtr m_Pipeline; - SafePtr m_TransparentPipeline; - SafePtr m_OpaqueTechnique; - SafePtr m_TransparentTechnique; + std::vector> m_Materials; std::vector> m_Textures; private: StaticMesh(); diff --git a/LNEngine/src/Engine/Graphics/Resources/StorageBuffer.cpp b/LNEngine/src/Engine/Graphics/Resources/StorageBuffer.cpp index e599964..89d74f4 100644 --- a/LNEngine/src/Engine/Graphics/Resources/StorageBuffer.cpp +++ b/LNEngine/src/Engine/Graphics/Resources/StorageBuffer.cpp @@ -184,6 +184,7 @@ void StorageBuffer::Grow(vk::CommandBuffer cb, uint64_t newSize) m_HasStagingBuffer = false; } + cb.fillBuffer(newAllocation.Buffer, oldSize, newSize - oldSize, 0); // 2. Copy old data to new buffer CopyBufferToBuffer(cb, m_Allocation, newAllocation, oldSize); diff --git a/LNEngine/src/Engine/Graphics/SwapChain.cpp b/LNEngine/src/Engine/Graphics/SwapChain.cpp index 52d5e95..98ba368 100644 --- a/LNEngine/src/Engine/Graphics/SwapChain.cpp +++ b/LNEngine/src/Engine/Graphics/SwapChain.cpp @@ -4,11 +4,14 @@ #include "Framebuffer.h" #include "Core/Utils/_Defines.h" #include "Core/Utils/Log.h" +#include "Core/Utils/Profiling.h" #include "Core/ApplicationBase.h" #include "Graphics/Renderer.h" namespace lne { +#define PROFILING_COLOR 0xAA7471 + Swapchain::Swapchain(SafePtr ctx, vk::SurfaceKHR surface) { m_Context = ctx; @@ -68,23 +71,25 @@ class Framebuffer& Swapchain::GetFramebuffer(uint32_t index) void Swapchain::BeginFrame() { - auto device = m_Context->GetDevice(); - uint32_t currentFrameInFlight = m_Context->GetCurrentFrameIndex(); - VK_CHECK(device.waitForFences(m_AcquireFences[currentFrameInFlight], VK_TRUE, UINT64_MAX)); - device.resetFences(m_AcquireFences[currentFrameInFlight]); - auto result = device.acquireNextImageKHR(m_Swapchain, UINT64_MAX, m_Semaphores[currentFrameInFlight].ImageAvailable, m_AcquireFences[currentFrameInFlight]); - m_CurrentImageIndex = result.value; - - if (result.result == vk::Result::eErrorOutOfDateKHR) - CreateSwapchain(); - else if (result.result != vk::Result::eSuccess && result.result != vk::Result::eSuboptimalKHR) - VK_CHECK(result.result); + LNE_PROFILE_FUNCTION_C(PROFILING_COLOR); + auto device = m_Context->GetDevice(); + uint32_t currentFrameInFlight = m_Context->GetCurrentFrameIndex(); + VK_CHECK(device.waitForFences(m_AcquireFences[currentFrameInFlight], VK_TRUE, UINT64_MAX)); + device.resetFences(m_AcquireFences[currentFrameInFlight]); + auto result = device.acquireNextImageKHR(m_Swapchain, UINT64_MAX, m_Semaphores[currentFrameInFlight].ImageAvailable, m_AcquireFences[currentFrameInFlight]); + m_CurrentImageIndex = result.value; + + if (result.result == vk::Result::eErrorOutOfDateKHR) + CreateSwapchain(); + else if (result.result != vk::Result::eSuccess && result.result != vk::Result::eSuboptimalKHR) + VK_CHECK(result.result); } -bool Swapchain::Present() +void Swapchain::Present() { auto present = [this]() { + LNE_PROFILE_FUNCTION_C(PROFILING_COLOR); auto presentQueue = m_Context->GetQueue(EQueueFamilyType::Present); const auto presentInfo = vk::PresentInfoKHR( @@ -100,16 +105,15 @@ bool Swapchain::Present() { m_Context->m_CurrentFrameInFlight = (m_Context->m_CurrentFrameInFlight + 1) % m_Context->m_MaxFramesInFlight; result = presentQueue.presentKHR(presentInfo); - m_FrameIndex = (m_FrameIndex + 1) % m_ColorAttachments.size(); - // TODO: this is a temporary solution, m_CurrentFrameIndex should be current frame in flight not just the current frame index - return true; } catch (vk::SystemError& error) { if (error.code() == vk::Result::eErrorOutOfDateKHR || error.code() == vk::Result::eSuboptimalKHR) - return false; + { + m_IsDirty.store(true, std::memory_order_release); + return; + } LNE_ASSERT(false, "Failed to present swapchain image: {}", error.what()); - return false; } }; auto& renderer = ApplicationBase::GetRenderer(); @@ -117,7 +121,6 @@ bool Swapchain::Present() renderer.AddRenderTask(present); else present(); - return true; } void Swapchain::CreateSwapchain() diff --git a/LNEngine/src/Engine/Graphics/SwapChain.h b/LNEngine/src/Engine/Graphics/SwapChain.h index 8fcb2eb..9216911 100644 --- a/LNEngine/src/Engine/Graphics/SwapChain.h +++ b/LNEngine/src/Engine/Graphics/SwapChain.h @@ -19,12 +19,18 @@ struct Viewport m_Viewport = vk::Viewport(0.0f, 0.0f, static_cast(extent.width), static_cast(extent.height), 0.0f, 1.0f); return *this; } - vk::Extent2D GetExtent() const { return vk::Extent2D(static_cast(m_Viewport.width), static_cast(m_Viewport.height)); } + vk::Extent2D GetExtent() const + { return { static_cast(m_Viewport.width), static_cast(m_Viewport.height) }; } + + vk::Viewport& GetViewport() + { return m_Viewport; } + + const vk::Viewport& GetViewport() const + { return m_Viewport; } + + const vk::Rect2D GetScissor() const + { return vk::Rect2D({ 0, 0 }, GetExtent()); } - vk::Viewport& GetViewport() { return m_Viewport; } - const vk::Viewport& GetViewport() const { return m_Viewport; } - const vk::Rect2D GetScissor() const { return vk::Rect2D({ 0, 0 }, GetExtent()); } - private: vk::Viewport m_Viewport; }; @@ -39,7 +45,7 @@ class Swapchain : public RefCountBase Swapchain(SafePtr ctx, vk::SurfaceKHR surface); virtual ~Swapchain(); - void CreateSwapchain(); + void CreateSwapchain(); [[nodiscard]] uint32_t GetImageCount() const { @@ -57,8 +63,11 @@ class Swapchain : public RefCountBase [[nodiscard]] class Framebuffer& GetFramebuffer(uint32_t index); [[nodiscard]] std::vector& GetFramebuffers() { return m_Framebuffers; } - void BeginFrame(); - [[nodiscard]] bool Present(); + [[nodiscard]] bool IsDirty() const { return m_IsDirty.load(std::memory_order_acquire); } + void ResetDirty() { m_IsDirty.store(false, std::memory_order_release); } + + void BeginFrame(); + void Present(); private: SafePtr m_Context; @@ -80,11 +89,11 @@ class Swapchain : public RefCountBase std::vector m_AcquireFences; uint32_t m_CurrentImageIndex{ 0 }; - uint32_t m_FrameIndex{ 0 }; + std::atomic m_IsDirty{ false }; private: - void CreateSyncObjects(); + void CreateSyncObjects(); - vk::SurfaceFormatKHR PickSwapchainSurfaceFormat(const std::vector& availableFormats); - vk::PresentModeKHR PickSwapchainPresentMode(const std::vector& availablePresentModes); + vk::SurfaceFormatKHR PickSwapchainSurfaceFormat(const std::vector& availableFormats); + vk::PresentModeKHR PickSwapchainPresentMode(const std::vector& availablePresentModes); }; } diff --git a/LNEngine/src/Engine/Main.h b/LNEngine/src/Engine/Main.h index 0208f33..c8c1f05 100644 --- a/LNEngine/src/Engine/Main.h +++ b/LNEngine/src/Engine/Main.h @@ -1,6 +1,8 @@ #pragma once extern lne::ApplicationBase* lne::CreateApplication(); +#if defined(LNE_DEBUG) || !defined(LNE_PLATFORM_WINDOWS) + int main(int argc, char** argv) { #if defined(LNE_DEBUG) && defined(LNE_PLATFORM_WINDOWS) @@ -11,3 +13,15 @@ int main(int argc, char** argv) app->Run(); delete app; } + +#elif defined(LNE_PLATFORM_WINDOWS) && !defined(LNE_DEBUG) + +INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pScmdline, INT iCmdshow) +{ + auto app = lne::CreateApplication(); + app->Run(); + delete app; + return 0; +} + +#endif diff --git a/LNEngine/src/Engine/Resources/GfxLoader.cpp b/LNEngine/src/Engine/Resources/GfxLoader.cpp index 36cdc35..c486cb1 100644 --- a/LNEngine/src/Engine/Resources/GfxLoader.cpp +++ b/LNEngine/src/Engine/Resources/GfxLoader.cpp @@ -3,6 +3,11 @@ #include #include "Core/Utils/Log.h" +#include "Core/ApplicationBase.h" +#include "Core/Utils/Profiling.h" + +#include +#include "Graphics/Resources/Material.h" #include "Graphics/Resources/Texture.h" #include "Graphics/Resources/StorageBuffer.h" #include "Graphics/GfxContext.h" @@ -12,9 +17,6 @@ #include "Graphics/WorldEnvironment.h" #include "GfxLoader.h" -#include "Core/ApplicationBase.h" -#include -#include "Graphics/Resources/Material.h" namespace lne { @@ -36,7 +38,7 @@ std::string_view ToString(Enum type) void GfxLoaderTask::Execute() { - tracy::SetThreadName("Graphics Loader"); + SET_PROFILING_THREAD_NAME("Graphics Loader"); while (TaskScheduler.lock()->GetIsShutdownRequested() == false) Loader->Update(); } @@ -289,9 +291,6 @@ void GfxLoader::ProcessUploadRequests() if (m_UploadRequests.empty()) return; - auto& cpManager = m_GraphicsContext->GetCommandPoolManager(); - vk::CommandBuffer cb = cpManager.BeginOrGetSingleUseCommandBuffer(EQueueFamilyType::Transfer); - UploadRequest request = {}; { std::lock_guard lock(m_UploadRequestsMutex); @@ -299,6 +298,31 @@ void GfxLoader::ProcessUploadRequests() m_UploadRequests.pop_back(); } + BufferAllocation stagingBuffer = m_StagingBuffer; + bool tempStagingBufferUsed = false; + if (m_StagingBuffer.AllocationInfo.size < request.Size) + { + // create temporary staging buffer if the common one is not enough + tempStagingBufferUsed = true; + vk::BufferCreateInfo bufferCI{ + {}, + request.Size, + vk::BufferUsageFlagBits::eTransferSrc, + vk::SharingMode::eExclusive, + }; + VmaAllocationCreateInfo allocCI{ + .flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | + VMA_ALLOCATION_CREATE_MAPPED_BIT, + .usage = VMA_MEMORY_USAGE_AUTO, + }; + BufferAllocation tempStagingBuffer; + m_GraphicsContext->AllocateBuffer(tempStagingBuffer, bufferCI, allocCI); + m_StagingBuffer = tempStagingBuffer; + } + + auto& cpManager = m_GraphicsContext->GetCommandPoolManager(); + vk::CommandBuffer cb = cpManager.BeginOrGetSingleUseCommandBuffer(EQueueFamilyType::Transfer); + switch (request.Type) { case ResourceTypes::eTexture: @@ -322,6 +346,12 @@ void GfxLoader::ProcessUploadRequests() vk::PipelineStageFlags waitDst = vk::PipelineStageFlagBits::eTransfer; vk::SubmitInfo submitInfo{}; cpManager.EndSingleUseCommandBuffer(EQueueFamilyType::Transfer, &waitDst, &m_TransferSemaphore); + + if (tempStagingBufferUsed) + { + m_GraphicsContext->FreeBufferAllocation(m_StagingBuffer); + m_StagingBuffer = stagingBuffer; + } } void GfxLoader::ProcessLoadRequests() diff --git a/LNEngine/src/lnepch.h b/LNEngine/src/lnepch.h index f26269f..0d65a2f 100644 --- a/LNEngine/src/lnepch.h +++ b/LNEngine/src/lnepch.h @@ -31,6 +31,12 @@ # include #endif // LNE_PLATFORM_WINDOWS +#ifdef _MSC_VER +# pragma warning(disable : 4390) +# pragma warning(disable : 4552) +# pragma warning(disable : 4553) +#endif + // Third Party // Math #define GLM_FORCE_RADIANS