From 8c50a6d9d8ac5a4647276322a4e47778a9bbd009 Mon Sep 17 00:00:00 2001 From: Kirill Markin Date: Mon, 6 Oct 2025 16:30:52 +0300 Subject: [PATCH 01/13] Allow to render different scene using same renderer each tick (to support rendering prev game state while processing new one) --- .../DeferredRendering/Source/Application.cpp | 4 +-- .../Include/Runtime/Renderer/Core/Renderer.h | 15 ++++---- .../Renderer/Deferred/DeferredRenderer.h | 20 +++++------ .../Deferred/Source/DeferredRenderer.cpp | 34 +++++++++---------- 4 files changed, 35 insertions(+), 38 deletions(-) diff --git a/Source/Examples/DeferredRendering/Source/Application.cpp b/Source/Examples/DeferredRendering/Source/Application.cpp index a4ddea4..784b495 100644 --- a/Source/Examples/DeferredRendering/Source/Application.cpp +++ b/Source/Examples/DeferredRendering/Source/Application.cpp @@ -86,7 +86,7 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::Initialize(const R SetupSponzaScene(); Renderer = std::make_unique(); - if (!Renderer->Initialize(RenderApi, TfExecutor, Scene)) + if (!Renderer->Initialize(RenderApi, TfExecutor)) { // TODO: log error return false; @@ -129,7 +129,7 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::Tick(float DeltaTi std::array Views = { SceneView }; - if (!Renderer->Render(Views)) + if (!Renderer->Render(Scene.get(), Views)) { // TODO: add error log return false; diff --git a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h index 3bc40e7..2d8dc26 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h +++ b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h @@ -19,22 +19,23 @@ namespace krendrr::Runtime::Renderer::Core class Scene; /** - * Renderer implements the way we render render-scene into scene view, + * Renderer implements the way we render scene into scene view, * e.g. deferred, forward, forward+, etc. This is implementation of our rendering pipeline. * - * It is initialized for one render scene only. You can call Shutdown and then initialize it again for another render scene. + * Scene and views should not change when renderer renders it. + * But, renderer is allowed to save data into scene's buffers, + * e.g. saving a shadow map into point light object. * - * Render scene, scene view, etc. should not change when renderer renders it. - * - * Renderer may hold data between render calls, e.g. it can keep multiple GBuffers between Render calls when rendering into multiple scene views at the same time. + * Renderer may hold data between render calls, e.g. it can keep multiple + * GBuffers between render calls when rendering into multiple scene views at the same time. */ class Renderer { public: - virtual bool Initialize(std::shared_ptr NewRenderApi, std::shared_ptr TfExecutor, std::shared_ptr NewScene) = 0; + virtual bool Initialize(std::shared_ptr NewRenderApi, std::shared_ptr NewTfExecutor) = 0; - virtual bool Render(const std::span& SceneViews) = 0; + virtual bool Render(const Scene* Scene, const std::span& SceneViews) = 0; virtual bool Shutdown() = 0; diff --git a/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h index 1fb89ab..d76aea0 100644 --- a/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h +++ b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h @@ -12,17 +12,15 @@ namespace krendrr::Runtime::Renderer::Deferred { public: - bool Initialize(std::shared_ptr NewRenderApi, std::shared_ptr NewTfExecutor, std::shared_ptr NewScene) override; + bool Initialize(std::shared_ptr NewRenderApi, std::shared_ptr NewTfExecutor) override; - bool Render(const std::span& SceneViews) override; + bool Render(const Core::Scene* Scene, const std::span& SceneViews) override; bool Shutdown() override; private: std::shared_ptr RenderApi {}; - std::shared_ptr Scene {}; - std::shared_ptr TfExecutor {}; std::shared_ptr FullscreenQuadMesh {}; @@ -38,7 +36,7 @@ namespace krendrr::Runtime::Renderer::Deferred PrePostRenderData PrePostRenderData {}; bool InitPrePostRender(); - bool PreRender(const Core::SceneView& SceneView); + bool PreRender(const Core::Scene* Scene, const Core::SceneView& SceneView); bool PostRender(const Core::SceneView& SceneView); Microsoft::WRL::ComPtr FrameFence {}; @@ -124,9 +122,9 @@ namespace krendrr::Runtime::Renderer::Deferred FrameData FrameData {}; - bool UpdateFrameDataConstantBuffer(const Core::SceneView& SceneView); - bool UpdateTexturedMeshConstantBuffers(); - bool UpdatePointLightConstantBuffers(); + bool UpdateFrameDataConstantBuffer(const Core::Scene* Scene, const Core::SceneView& SceneView); + bool UpdateTexturedMeshConstantBuffers(const Core::Scene* Scene); + bool UpdatePointLightConstantBuffers(const Core::Scene* Scene); struct GeometryPassData { @@ -150,7 +148,7 @@ namespace krendrr::Runtime::Renderer::Deferred GeometryPassData GeometryPassData {}; bool InitializeGeometryPass(); - bool GeometryPass(const Core::SceneView& SceneView); + bool GeometryPass(const Core::Scene* Scene, const Core::SceneView& SceneView); struct LightPassData { @@ -200,7 +198,7 @@ namespace krendrr::Runtime::Renderer::Deferred PointLightShadowCubeMapData PointLightShadowCubeMapData {}; bool InitPointLightShadowCubeMapPass(); - bool PointLightShadowCubeMapsPass(); + bool PointLightShadowCubeMapsPass(const Core::Scene* Scene); struct PointLightVolumePassData { @@ -221,7 +219,7 @@ namespace krendrr::Runtime::Renderer::Deferred PointLightVolumePassData PointLightVolumePassData{}; bool InitPointLightVolumePass(); - bool PointLightVolumesPass(const Core::SceneView& SceneView); + bool PointLightVolumesPass(const Core::Scene* Scene, const Core::SceneView& SceneView); struct PostProcessingPassData { diff --git a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp index 7c0f0ae..c99e55b 100644 --- a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp +++ b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp @@ -15,13 +15,11 @@ namespace krendrr::Runtime::Renderer::Deferred { -bool DeferredRenderer::Initialize(std::shared_ptr NewRenderApi, std::shared_ptr NewTfExecutor, std::shared_ptr NewScene) +bool DeferredRenderer::Initialize(std::shared_ptr NewRenderApi, std::shared_ptr NewTfExecutor) { nvtx3::scoped_range InitRange {"Deferred Renderer: Initialize"}; RenderApi = std::move(NewRenderApi); - Scene = std::move(NewScene); - TfExecutor = std::move(NewTfExecutor); CHECKED( @@ -63,7 +61,7 @@ bool DeferredRenderer::Initialize(std::shared_ptr Ne return true; } -bool DeferredRenderer::Render(const std::span& SceneViews) +bool DeferredRenderer::Render(const Core::Scene* Scene, const std::span& SceneViews) { if (Scene->GetPointLights().size() > PointLightVolumePassData.MAX_DYNAMIC_POINT_LIGHTS_COUNT) { @@ -73,22 +71,22 @@ bool DeferredRenderer::Render(const std::span& SceneViews) for (const Core::SceneView& SceneView : SceneViews) { - if (!UpdateFrameDataConstantBuffer(SceneView)) + if (!UpdateFrameDataConstantBuffer(Scene, SceneView)) return false; - if (!UpdateTexturedMeshConstantBuffers()) + if (!UpdateTexturedMeshConstantBuffers(Scene)) return false; - if (!UpdatePointLightConstantBuffers()) + if (!UpdatePointLightConstantBuffers(Scene)) return false; - if (!PreRender(SceneView)) + if (!PreRender(Scene, SceneView)) return false; if (!InitGBufferForView(SceneView)) return false; - if (!GeometryPass(SceneView)) + if (!GeometryPass(Scene, SceneView)) return false; if (!TransitionGBufferFromRenderTargetToReadState()) @@ -100,10 +98,10 @@ bool DeferredRenderer::Render(const std::span& SceneViews) if (!AmbientDirectionalLightPass(SceneView)) return false; - if (!PointLightShadowCubeMapsPass()) + if (!PointLightShadowCubeMapsPass(Scene)) return false; - if (!PointLightVolumesPass(SceneView)) + if (!PointLightVolumesPass(Scene, SceneView)) return false; if (!TransitionLightPassFromRenderTargetToReadState()) @@ -128,7 +126,7 @@ bool DeferredRenderer::Render(const std::span& SceneViews) return true; } -bool DeferredRenderer::UpdateFrameDataConstantBuffer(const Core::SceneView& SceneView) +bool DeferredRenderer::UpdateFrameDataConstantBuffer(const Core::Scene* Scene, const Core::SceneView& SceneView) { nvtx3::scoped_range ConstBufUpdateRange {"Update Frame Data Constant Buffer"}; @@ -163,7 +161,7 @@ bool DeferredRenderer::UpdateFrameDataConstantBuffer(const Core::SceneView& Scen return true; } -bool DeferredRenderer::UpdateTexturedMeshConstantBuffers() +bool DeferredRenderer::UpdateTexturedMeshConstantBuffers(const Core::Scene* Scene) { nvtx3::scoped_range ConstBufUpdateRange {"Update Textured Mesh Constant Buffers"}; @@ -176,7 +174,7 @@ bool DeferredRenderer::UpdateTexturedMeshConstantBuffers() return true; } -bool DeferredRenderer::UpdatePointLightConstantBuffers() +bool DeferredRenderer::UpdatePointLightConstantBuffers(const Core::Scene* Scene) { nvtx3::scoped_range ConstBufUpdateRange {"Update Point Light Constant Buffers"}; @@ -271,7 +269,7 @@ bool DeferredRenderer::InitializeGeometryPass() return true; } -bool DeferredRenderer::GeometryPass(const Core::SceneView& SceneView) +bool DeferredRenderer::GeometryPass(const Core::Scene* Scene, const Core::SceneView& SceneView) { nvtx3::scoped_range PassRange {"Geometry Pass"}; @@ -833,7 +831,7 @@ bool DeferredRenderer::InitPointLightShadowCubeMapPass() return true; } -bool DeferredRenderer::PointLightShadowCubeMapsPass() +bool DeferredRenderer::PointLightShadowCubeMapsPass(const Core::Scene* Scene) { nvtx3::scoped_range PassRange {"Point Light Shadow Cube Maps Pass"}; @@ -1127,7 +1125,7 @@ bool DeferredRenderer::InitPointLightVolumePass() return true; } -bool DeferredRenderer::PointLightVolumesPass(const Core::SceneView& SceneView) +bool DeferredRenderer::PointLightVolumesPass(const Core::Scene* Scene, const Core::SceneView& SceneView) { nvtx3::scoped_range PassRange {"Point Light Volumes Pass"}; @@ -1533,7 +1531,7 @@ bool DeferredRenderer::InitPrePostRender() return true; } -bool DeferredRenderer::PreRender(const Core::SceneView& SceneView) +bool DeferredRenderer::PreRender(const Core::Scene* Scene, const Core::SceneView& SceneView) { CHECKED_S(PrePostRenderData.CommandAllocator->Reset()); From ea95083e17b980241724d062a0c79d1e9e217918 Mon Sep 17 00:00:00 2001 From: Kirill Markin Date: Mon, 6 Oct 2025 16:37:57 +0300 Subject: [PATCH 02/13] Rename rendering resources, make stored mesh and textures const in scene objects --- .../Include/Runtime/ModelLoader/Loader.h | 4 +- Source/Runtime/ModelLoader/Source/Loader.cpp | 20 ++++----- .../Runtime/Renderer/Core/Scene/Scene.h | 12 ++--- .../TexturedMesh/{Mesh.h => StaticMesh.h} | 14 +++--- .../TexturedMesh/{Texture.h => Texture2D.h} | 15 +++---- .../{TexturedMesh.h => TexturedStaticMesh.h} | 18 ++++---- .../Renderer/Core/Source/Scene/Scene.cpp | 12 ++--- .../TexturedMesh/{Mesh.cpp => StaticMesh.cpp} | 22 +++++----- .../{Texture.cpp => Texture2D.cpp} | 20 ++++----- ...exturedMesh.cpp => TexturedStaticMesh.cpp} | 44 +++++++++---------- .../Renderer/Deferred/DeferredRenderer.h | 8 ++-- .../Deferred/Source/DeferredRenderer.cpp | 10 +++-- 12 files changed, 100 insertions(+), 99 deletions(-) rename Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/{Mesh.h => StaticMesh.h} (88%) rename Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/{Texture.h => Texture2D.h} (86%) rename Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/{TexturedMesh.h => TexturedStaticMesh.h} (81%) rename Source/Runtime/Renderer/Core/Source/TexturedMesh/{Mesh.cpp => StaticMesh.cpp} (81%) rename Source/Runtime/Renderer/Core/Source/TexturedMesh/{Texture.cpp => Texture2D.cpp} (89%) rename Source/Runtime/Renderer/Core/Source/TexturedMesh/{TexturedMesh.cpp => TexturedStaticMesh.cpp} (60%) diff --git a/Source/Runtime/ModelLoader/Include/Runtime/ModelLoader/Loader.h b/Source/Runtime/ModelLoader/Include/Runtime/ModelLoader/Loader.h index a922b43..06ab23a 100644 --- a/Source/Runtime/ModelLoader/Include/Runtime/ModelLoader/Loader.h +++ b/Source/Runtime/ModelLoader/Include/Runtime/ModelLoader/Loader.h @@ -3,7 +3,7 @@ #include #include #include "Runtime/RenderApi/Core/RenderApi.h" -#include "Runtime/Renderer/Core/TexturedMesh/TexturedMesh.h" +#include "Runtime/Renderer/Core/TexturedMesh/TexturedStaticMesh.h" #include "taskflow/taskflow.hpp" namespace krendrr::Runtime::ModelLoader @@ -33,7 +33,7 @@ namespace krendrr::Runtime::ModelLoader struct LoadResult { bool bSuccess {}; - std::vector> TexturedMeshes {}; + std::vector> TexturedMeshes {}; [[nodiscard]] bool HasLoadedAtLeastOne() const { diff --git a/Source/Runtime/ModelLoader/Source/Loader.cpp b/Source/Runtime/ModelLoader/Source/Loader.cpp index b6cfa46..3a6b1a4 100644 --- a/Source/Runtime/ModelLoader/Source/Loader.cpp +++ b/Source/Runtime/ModelLoader/Source/Loader.cpp @@ -8,15 +8,15 @@ #include #include "Runtime/MipMapsGenerator/Generator.h" #include "Runtime/RenderApi/Core/ApiCallCheck.h" -#include "Runtime/Renderer/Core/TexturedMesh/Mesh.h" -#include "Runtime/Renderer/Core/TexturedMesh/Texture.h" +#include "Runtime/Renderer/Core/TexturedMesh/StaticMesh.h" +#include "Runtime/Renderer/Core/TexturedMesh/Texture2D.h" namespace krendrr::Runtime::ModelLoader { // a bunch of data shared between thread pool jobs struct LoadData { - std::unordered_map> TextureCache {}; + std::unordered_map> TextureCache {}; std::vector TexturesToGenerateMipMaps {}; std::mutex TextureCacheMutex {}; @@ -155,7 +155,7 @@ namespace krendrr::Runtime::ModelLoader return; // Create final object - std::shared_ptr NewTexturedMesh = std::make_shared(); + std::shared_ptr NewTexturedMesh = std::make_shared(); NewTexturedMesh->SetMeshColor(glm::vec3{ static_cast(rand()) / (RAND_MAX + 1.0), @@ -184,10 +184,10 @@ namespace krendrr::Runtime::ModelLoader // Create Mesh { - std::shared_ptr NewMesh = std::make_shared(); + std::shared_ptr NewMesh = std::make_shared(); NewTexturedMesh->AssignMesh(NewMesh); - Renderer::Core::Mesh::MeshLoadOperation MeshLoadOperation = NewMesh->LoadIndexed( + Renderer::Core::StaticMesh::MeshLoadOperation MeshLoadOperation = NewMesh->LoadIndexed( RenderApi, *NewCommandList.Get(), RenderApi::Core::RenderApi::ContainerToBytes(Vertices), Indices); if (!MeshLoadOperation.WasSuccessful()) @@ -214,7 +214,7 @@ namespace krendrr::Runtime::ModelLoader return; const aiMaterial* Material = Scene->mMaterials[Mesh->mMaterialIndex]; - auto LoadTexture = [&](aiTextureType Type, Renderer::Core::TexturedMesh& TargetMesh, const std::string_view& TextureName) -> bool + auto LoadTexture = [&](aiTextureType Type, Renderer::Core::TexturedStaticMesh& TargetMesh, const std::string_view& TextureName) -> bool { if(Material->GetTextureCount(Type) > 0) { @@ -225,7 +225,7 @@ namespace krendrr::Runtime::ModelLoader TexturePath.append("/"); TexturePath.append(RelativeTexturePath.C_Str()); - std::shared_ptr Texture {}; + std::shared_ptr Texture {}; std::unique_lock TextureCacheLock(LoadData.TextureCacheMutex); @@ -238,9 +238,9 @@ namespace krendrr::Runtime::ModelLoader // Since texture loading may take a while, do not keep the mutex ownership TextureCacheLock.unlock(); - Texture = std::make_shared(); + Texture = std::make_shared(); - const Renderer::Core::Texture::TextureLoadOperation TextureLoadOperation = Texture->Load(RenderApi, *NewCommandList.Get(), TexturePath); + const Renderer::Core::Texture2D::TextureLoadOperation TextureLoadOperation = Texture->Load(RenderApi, *NewCommandList.Get(), TexturePath); if (!TextureLoadOperation.WasSuccessful()) { diff --git a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Scene.h b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Scene.h index 5bede42..dc7f7a3 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Scene.h +++ b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Scene.h @@ -14,16 +14,16 @@ namespace krendrr::Runtime::Renderer::Core namespace krendrr::Runtime::Renderer::Core { - class TexturedMesh; + class TexturedStaticMesh; class Scene { public: - std::shared_ptr SpawnTexturedMesh(); - bool InsertTexturedMesh(const std::shared_ptr& NewMesh); - bool RemoveTexturedMesh(const std::shared_ptr& MeshToRemove); - [[nodiscard]] std::span> GetTexturedMeshes() const; + std::shared_ptr SpawnTexturedMesh(); + bool InsertTexturedMesh(const std::shared_ptr& NewMesh); + bool RemoveTexturedMesh(const std::shared_ptr& MeshToRemove); + [[nodiscard]] std::span> GetTexturedMeshes() const; std::shared_ptr SpawnPointLight(); bool RemovePointLight(const std::shared_ptr& PointLightToRemove); @@ -54,7 +54,7 @@ namespace krendrr::Runtime::Renderer::Core private: - std::vector> TexturedMeshes {}; + std::vector> TexturedMeshes {}; std::vector> PointLights {}; diff --git a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/Mesh.h b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/StaticMesh.h similarity index 88% rename from Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/Mesh.h rename to Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/StaticMesh.h index 9e06876..aec2619 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/Mesh.h +++ b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/StaticMesh.h @@ -7,16 +7,16 @@ namespace krendrr::Runtime::Renderer::Core { - class Mesh + class StaticMesh { public: - Mesh() = default; - Mesh(const Mesh& Other) = delete; - Mesh& operator=(const Mesh& Other) = delete; - Mesh(Mesh&& Other) noexcept = default; - Mesh& operator=(Mesh&& Other) noexcept = default; - ~Mesh() = default; + StaticMesh() = default; + StaticMesh(const StaticMesh& Other) = delete; + StaticMesh& operator=(const StaticMesh& Other) = delete; + StaticMesh(StaticMesh&& Other) noexcept = default; + StaticMesh& operator=(StaticMesh&& Other) noexcept = default; + ~StaticMesh() = default; struct MeshLoadOperation { diff --git a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/Texture.h b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/Texture2D.h similarity index 86% rename from Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/Texture.h rename to Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/Texture2D.h index b74541f..2469f2a 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/Texture.h +++ b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/Texture2D.h @@ -3,22 +3,21 @@ #include #include #include - #include "glm/vec2.hpp" #include "Runtime/RenderApi/Core/RenderApi.h" namespace krendrr::Runtime::Renderer::Core { - class Texture + class Texture2D { public: - Texture() = default; - Texture(const Texture& Other) = delete; - Texture& operator=(const Texture& Other) = delete; - Texture(Texture&& Other) noexcept = default; - Texture& operator=(Texture&& Other) noexcept = default; - ~Texture() = default; + Texture2D() = default; + Texture2D(const Texture2D& Other) = delete; + Texture2D& operator=(const Texture2D& Other) = delete; + Texture2D(Texture2D&& Other) noexcept = default; + Texture2D& operator=(Texture2D&& Other) noexcept = default; + ~Texture2D() = default; struct TextureLoadParams { diff --git a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/TexturedMesh.h b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/TexturedStaticMesh.h similarity index 81% rename from Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/TexturedMesh.h rename to Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/TexturedStaticMesh.h index 585f6f4..18ccb82 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/TexturedMesh.h +++ b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/TexturedStaticMesh.h @@ -11,26 +11,26 @@ namespace krendrr::Runtime::Renderer::Core { - class Texture; - class Mesh; + class Texture2D; + class StaticMesh; /** * Represents a textured mesh on scene * * Consists of a single mesh, set of textures and a bunch of parameters used by renderer */ - class TexturedMesh + class TexturedStaticMesh { public: [[nodiscard]] bool IsValid() const; - void AssignTexture(std::string Name, std::shared_ptr NewTexture); - [[nodiscard]] std::shared_ptr GetTexture(const std::string_view& Name) const; + void AssignTexture(std::string Name, std::shared_ptr NewTexture); + [[nodiscard]] std::shared_ptr GetTexture(const std::string_view& Name) const; [[nodiscard]] bool HasTexture(const std::string_view& Name) const; - void AssignMesh(std::shared_ptr NewMesh); - [[nodiscard]] std::shared_ptr GetMesh() const; + void AssignMesh(std::shared_ptr NewMesh); + [[nodiscard]] std::shared_ptr GetMesh() const; [[nodiscard]] const glm::vec3& GetMeshColor() const; void SetMeshColor(const glm::vec3& NewMeshColor); @@ -59,8 +59,8 @@ namespace krendrr::Runtime::Renderer::Core glm::quat Rotation {}; glm::vec3 Scale {1.f, 1.f, 1.f}; - std::shared_ptr Mesh {}; - std::map, std::less<>> Textures {}; + std::shared_ptr Mesh {}; + std::map, std::less<>> Textures {}; glm::vec3 MeshColor {}; bool bCanCastShadow {true}; diff --git a/Source/Runtime/Renderer/Core/Source/Scene/Scene.cpp b/Source/Runtime/Renderer/Core/Source/Scene/Scene.cpp index 8a071b5..102847f 100644 --- a/Source/Runtime/Renderer/Core/Source/Scene/Scene.cpp +++ b/Source/Runtime/Renderer/Core/Source/Scene/Scene.cpp @@ -1,13 +1,13 @@ #include "Runtime/Renderer/Core/Scene/Scene.h" #include "Runtime/Renderer/Core/Lights/PointLight.h" -#include "Runtime/Renderer/Core/TexturedMesh/TexturedMesh.h" +#include "Runtime/Renderer/Core/TexturedMesh/TexturedStaticMesh.h" namespace krendrr::Runtime::Renderer::Core { - std::shared_ptr Scene::SpawnTexturedMesh() + std::shared_ptr Scene::SpawnTexturedMesh() { - auto NewMesh = std::make_shared(); + auto NewMesh = std::make_shared(); TexturedMeshes.push_back(NewMesh); @@ -16,7 +16,7 @@ namespace krendrr::Runtime::Renderer::Core return NewMesh; } - bool Scene::InsertTexturedMesh(const std::shared_ptr& NewMesh) + bool Scene::InsertTexturedMesh(const std::shared_ptr& NewMesh) { auto Iter = std::ranges::find(TexturedMeshes, NewMesh); if (Iter != TexturedMeshes.end()) @@ -32,7 +32,7 @@ namespace krendrr::Runtime::Renderer::Core return true; } - bool Scene::RemoveTexturedMesh(const std::shared_ptr& MeshToRemove) + bool Scene::RemoveTexturedMesh(const std::shared_ptr& MeshToRemove) { auto Iter = std::ranges::find(TexturedMeshes, MeshToRemove); @@ -47,7 +47,7 @@ namespace krendrr::Runtime::Renderer::Core return true; } - std::span> Scene::GetTexturedMeshes() const + std::span> Scene::GetTexturedMeshes() const { return TexturedMeshes; } diff --git a/Source/Runtime/Renderer/Core/Source/TexturedMesh/Mesh.cpp b/Source/Runtime/Renderer/Core/Source/TexturedMesh/StaticMesh.cpp similarity index 81% rename from Source/Runtime/Renderer/Core/Source/TexturedMesh/Mesh.cpp rename to Source/Runtime/Renderer/Core/Source/TexturedMesh/StaticMesh.cpp index 3f4d995..a3a21fa 100644 --- a/Source/Runtime/Renderer/Core/Source/TexturedMesh/Mesh.cpp +++ b/Source/Runtime/Renderer/Core/Source/TexturedMesh/StaticMesh.cpp @@ -1,9 +1,9 @@ -#include "Runtime/Renderer/Core/TexturedMesh/Mesh.h" +#include "Runtime/Renderer/Core/TexturedMesh/StaticMesh.h" #include "Runtime/RenderApi/Core/ApiCallCheck.h" namespace krendrr::Runtime::Renderer::Core { - Mesh::MeshLoadOperation Mesh::Load(const RenderApi::Core::RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::span& VertexData) + StaticMesh::MeshLoadOperation StaticMesh::Load(const RenderApi::Core::RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::span& VertexData) { if(IsLoaded()) { @@ -29,7 +29,7 @@ namespace krendrr::Runtime::Renderer::Core }; } - Mesh::MeshLoadOperation Mesh::LoadIndexed(const RenderApi::Core::RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::span& VertexData, const std::span& IndexData) + StaticMesh::MeshLoadOperation StaticMesh::LoadIndexed(const RenderApi::Core::RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::span& VertexData, const std::span& IndexData) { if(IsLoaded()) { @@ -77,7 +77,7 @@ namespace krendrr::Runtime::Renderer::Core }; } - Microsoft::WRL::ComPtr Mesh::LoadVertexBuffer(const RenderApi::Core::RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::span& VertexData) + Microsoft::WRL::ComPtr StaticMesh::LoadVertexBuffer(const RenderApi::Core::RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::span& VertexData) { Microsoft::WRL::ComPtr VertexBufferUpload = RenderApi.CreateUploadBufferAndMap(VertexData); @@ -105,12 +105,12 @@ namespace krendrr::Runtime::Renderer::Core return VertexBufferUpload; } - bool Mesh::IsLoaded() const + bool StaticMesh::IsLoaded() const { return VertexBuffer != nullptr; } - bool Mesh::IsUsingIndices() const + bool StaticMesh::IsUsingIndices() const { if (!CheckLoaded()) return false; @@ -118,7 +118,7 @@ namespace krendrr::Runtime::Renderer::Core return IndexBuffer != nullptr; } - std::int32_t Mesh::GetPrimitivesCount() const + std::int32_t StaticMesh::GetPrimitivesCount() const { if (!CheckLoaded()) return 0; @@ -126,7 +126,7 @@ namespace krendrr::Runtime::Renderer::Core return PrimitivesCount; } - std::ptrdiff_t Mesh::GetPrimitivesOffset() const + std::ptrdiff_t StaticMesh::GetPrimitivesOffset() const { if (!CheckLoaded()) return 0; @@ -134,7 +134,7 @@ namespace krendrr::Runtime::Renderer::Core return PrimitivesOffset; } - D3D12_VERTEX_BUFFER_VIEW Mesh::GetVertexBufferView() const + D3D12_VERTEX_BUFFER_VIEW StaticMesh::GetVertexBufferView() const { const D3D12_RESOURCE_DESC Desc = VertexBuffer->GetDesc(); @@ -145,7 +145,7 @@ namespace krendrr::Runtime::Renderer::Core }; } - D3D12_INDEX_BUFFER_VIEW Mesh::GetIndexBufferView() const + D3D12_INDEX_BUFFER_VIEW StaticMesh::GetIndexBufferView() const { const D3D12_RESOURCE_DESC Desc = IndexBuffer->GetDesc(); @@ -156,7 +156,7 @@ namespace krendrr::Runtime::Renderer::Core }; } - bool Mesh::CheckLoaded() const + bool StaticMesh::CheckLoaded() const { if(!IsLoaded()) { diff --git a/Source/Runtime/Renderer/Core/Source/TexturedMesh/Texture.cpp b/Source/Runtime/Renderer/Core/Source/TexturedMesh/Texture2D.cpp similarity index 89% rename from Source/Runtime/Renderer/Core/Source/TexturedMesh/Texture.cpp rename to Source/Runtime/Renderer/Core/Source/TexturedMesh/Texture2D.cpp index 64bf9b2..147d49d 100644 --- a/Source/Runtime/Renderer/Core/Source/TexturedMesh/Texture.cpp +++ b/Source/Runtime/Renderer/Core/Source/TexturedMesh/Texture2D.cpp @@ -1,4 +1,4 @@ -#include "Runtime/Renderer/Core/TexturedMesh/Texture.h" +#include "Runtime/Renderer/Core/TexturedMesh/Texture2D.h" #include #include #include @@ -10,12 +10,12 @@ namespace krendrr::Runtime::Renderer::Core { -bool Texture::IsLoaded() const +bool Texture2D::IsLoaded() const { return TextureBuffer != nullptr; } -Texture::TextureLoadOperation Texture::Load(const RenderApi::Core::RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, +Texture2D::TextureLoadOperation Texture2D::Load(const RenderApi::Core::RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::string_view& TextureFileName, const TextureLoadParams& Params) { if(IsLoaded()) @@ -155,7 +155,7 @@ Texture::TextureLoadOperation Texture::Load(const RenderApi::Core::RenderApi& Re }; } -D3D12_CPU_DESCRIPTOR_HANDLE Texture::GetTextureHandle() const +D3D12_CPU_DESCRIPTOR_HANDLE Texture2D::GetTextureHandle() const { if (CpuSrvHeap == nullptr) return {}; @@ -163,32 +163,32 @@ D3D12_CPU_DESCRIPTOR_HANDLE Texture::GetTextureHandle() const return CpuSrvHeap->GetCPUDescriptorHandleForHeapStart(); } -D3D12_GPU_VIRTUAL_ADDRESS Texture::GetTextureGpuAddress() const +D3D12_GPU_VIRTUAL_ADDRESS Texture2D::GetTextureGpuAddress() const { return TextureBuffer->GetGPUVirtualAddress(); } -Microsoft::WRL::ComPtr Texture::GetResource() const +Microsoft::WRL::ComPtr Texture2D::GetResource() const { return TextureBuffer; } -DXGI_FORMAT Texture::GetFormat() const +DXGI_FORMAT Texture2D::GetFormat() const { return Format; } -glm::uvec2 Texture::GetSize() const +glm::uvec2 Texture2D::GetSize() const { return Size; } -unsigned Texture::GetMipsCount() const +unsigned Texture2D::GetMipsCount() const { return MipsCount; } -bool Texture::CheckLoaded() const +bool Texture2D::CheckLoaded() const { if (!IsLoaded()) { diff --git a/Source/Runtime/Renderer/Core/Source/TexturedMesh/TexturedMesh.cpp b/Source/Runtime/Renderer/Core/Source/TexturedMesh/TexturedStaticMesh.cpp similarity index 60% rename from Source/Runtime/Renderer/Core/Source/TexturedMesh/TexturedMesh.cpp rename to Source/Runtime/Renderer/Core/Source/TexturedMesh/TexturedStaticMesh.cpp index f1ebb39..295c114 100644 --- a/Source/Runtime/Renderer/Core/Source/TexturedMesh/TexturedMesh.cpp +++ b/Source/Runtime/Renderer/Core/Source/TexturedMesh/TexturedStaticMesh.cpp @@ -1,26 +1,26 @@ -#include "Runtime/Renderer/Core/TexturedMesh/TexturedMesh.h" +#include "Runtime/Renderer/Core/TexturedMesh/TexturedStaticMesh.h" #include "glm/gtc/quaternion.hpp" #include "Runtime/RenderApi/Core/ApiCallCheck.h" #include "Runtime/RenderApi/Core/Builders/ConstBufferBuilder.h" namespace krendrr::Runtime::Renderer::Core { - bool TexturedMesh::IsValid() const + bool TexturedStaticMesh::IsValid() const { return Mesh != nullptr; } - void TexturedMesh::AssignMesh(std::shared_ptr NewMesh) + void TexturedStaticMesh::AssignMesh(std::shared_ptr NewMesh) { Mesh = std::move(NewMesh); } - void TexturedMesh::AssignTexture(std::string Name, std::shared_ptr NewTexture) + void TexturedStaticMesh::AssignTexture(std::string Name, std::shared_ptr NewTexture) { Textures.insert_or_assign(std::move(Name), std::move(NewTexture)); } - std::shared_ptr TexturedMesh::GetTexture(const std::string_view& Name) const + std::shared_ptr TexturedStaticMesh::GetTexture(const std::string_view& Name) const { auto Iter = Textures.find(Name); @@ -30,67 +30,67 @@ namespace krendrr::Runtime::Renderer::Core return Iter->second; } - bool TexturedMesh::HasTexture(const std::string_view& Name) const + bool TexturedStaticMesh::HasTexture(const std::string_view& Name) const { return Textures.contains(Name); } - std::shared_ptr TexturedMesh::GetMesh() const + std::shared_ptr TexturedStaticMesh::GetMesh() const { return Mesh; } - const glm::vec3& TexturedMesh::GetMeshColor() const + const glm::vec3& TexturedStaticMesh::GetMeshColor() const { return MeshColor; } - void TexturedMesh::SetMeshColor(const glm::vec3& NewMeshColor) + void TexturedStaticMesh::SetMeshColor(const glm::vec3& NewMeshColor) { MeshColor = NewMeshColor; } - bool TexturedMesh::CanCastShadow() const + bool TexturedStaticMesh::CanCastShadow() const { return bCanCastShadow; } - void TexturedMesh::SetCanCastShadow(bool bNewCanCastShadow) + void TexturedStaticMesh::SetCanCastShadow(bool bNewCanCastShadow) { bCanCastShadow = bNewCanCastShadow; } - const glm::vec3& TexturedMesh::GetPosition() const + const glm::vec3& TexturedStaticMesh::GetPosition() const { return Position; } - void TexturedMesh::SetPosition(const glm::vec3& NewPosition) + void TexturedStaticMesh::SetPosition(const glm::vec3& NewPosition) { Position = NewPosition; } - const glm::quat& TexturedMesh::GetRotation() const + const glm::quat& TexturedStaticMesh::GetRotation() const { return Rotation; } - void TexturedMesh::SetRotation(const glm::quat& NewRotation) + void TexturedStaticMesh::SetRotation(const glm::quat& NewRotation) { Rotation = NewRotation; } - const glm::vec3& TexturedMesh::GetScale() const + const glm::vec3& TexturedStaticMesh::GetScale() const { return Scale; } - void TexturedMesh::SetScale(const glm::vec3& NewScale) + void TexturedStaticMesh::SetScale(const glm::vec3& NewScale) { Scale = NewScale; } - glm::mat4 TexturedMesh::GetModelMatrix() const + glm::mat4 TexturedStaticMesh::GetModelMatrix() const { glm::mat4 ModelMatrix = glm::mat4(1.0f); @@ -103,12 +103,12 @@ namespace krendrr::Runtime::Renderer::Core return ModelMatrix; } - glm::mat3 TexturedMesh::GetNormalMatrix() const + glm::mat3 TexturedStaticMesh::GetNormalMatrix() const { return glm::transpose(glm::inverse(glm::mat3(GetModelMatrix()))); } - bool TexturedMesh::UpdateConstantBuffer(const RenderApi::Core::RenderApi& RenderApi) + bool TexturedStaticMesh::UpdateConstantBuffer(const RenderApi::Core::RenderApi& RenderApi) { // Create buffer if not created if (ConstantBuffer == nullptr) @@ -133,7 +133,7 @@ namespace krendrr::Runtime::Renderer::Core return true; } - D3D12_CPU_DESCRIPTOR_HANDLE TexturedMesh::GetConstantBufferHandle() const + D3D12_CPU_DESCRIPTOR_HANDLE TexturedStaticMesh::GetConstantBufferHandle() const { if (CpuSrvHeap == nullptr) return {}; @@ -143,7 +143,7 @@ namespace krendrr::Runtime::Renderer::Core }; } - D3D12_GPU_VIRTUAL_ADDRESS TexturedMesh::GetConstantBufferGpuAddress() const + D3D12_GPU_VIRTUAL_ADDRESS TexturedStaticMesh::GetConstantBufferGpuAddress() const { return ConstantBuffer->GetGPUVirtualAddress(); } diff --git a/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h index d76aea0..c824069 100644 --- a/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h +++ b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h @@ -3,8 +3,8 @@ #include #include #include "Runtime/Renderer/Core/Renderer.h" -#include "Runtime/Renderer/Core/TexturedMesh/Mesh.h" -#include "Runtime/Renderer/Core/TexturedMesh/TexturedMesh.h" +#include "Runtime/Renderer/Core/TexturedMesh/StaticMesh.h" +#include "Runtime/Renderer/Core/TexturedMesh/TexturedStaticMesh.h" namespace krendrr::Runtime::Renderer::Deferred { @@ -23,8 +23,8 @@ namespace krendrr::Runtime::Renderer::Deferred std::shared_ptr RenderApi {}; std::shared_ptr TfExecutor {}; - std::shared_ptr FullscreenQuadMesh {}; - std::shared_ptr SphereMesh {}; + std::shared_ptr FullscreenQuadMesh {}; + std::shared_ptr SphereMesh {}; bool InitBasicMeshes(); struct PrePostRenderData diff --git a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp index c99e55b..e2bc081 100644 --- a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp +++ b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp @@ -4,7 +4,7 @@ #include "Runtime/ModelLoader/Loader.h" #include "Runtime/Renderer/Core/Scene/Scene.h" #include "Runtime/Renderer/Core/Scene/SceneView.h" -#include "Runtime/Renderer/Core/TexturedMesh/Texture.h" +#include "Runtime/Renderer/Core/TexturedMesh/Texture2D.h" #include "nvtx3/nvtx3.hpp" #include "Runtime/RenderApi/Core/ApiCallCheck.h" #include "Runtime/RenderApi/Core/Builders/ConstBufferBuilder.h" @@ -345,7 +345,7 @@ bool DeferredRenderer::GeometryPass(const Core::Scene* Scene, const Core::SceneV ); int DrawIndex = -1; - for (const std::shared_ptr& TexturedMesh : Scene->GetTexturedMeshes()) + for (const std::shared_ptr& TexturedMesh : Scene->GetTexturedMeshes()) { nvtx3::scoped_range MeshIterationRange {"Mesh Iteration"}; @@ -1479,12 +1479,14 @@ bool DeferredRenderer::InitBasicMeshes() 1.f, -1.f, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; - FullscreenQuadMesh = std::make_shared(); - const Core::Mesh::MeshLoadOperation MeshLoad = FullscreenQuadMesh->Load(*RenderApi.get(), *InitCommandList.Get(), RenderApi->ContainerToBytes(QuadMesh)); + auto NewFullscreenQuadMesh = std::make_shared(); + const Core::StaticMesh::MeshLoadOperation MeshLoad = NewFullscreenQuadMesh->Load(*RenderApi.get(), *InitCommandList.Get(), RenderApi->ContainerToBytes(QuadMesh)); if (!MeshLoad.WasSuccessful()) return false; + FullscreenQuadMesh = std::move(NewFullscreenQuadMesh); + CHECKED_S(InitCommandList->Close()); ID3D12CommandList* InitCommandLists[] = {InitCommandList.Get()}; From c9c5467e7b5fcca094adb1810b280c8791d539ab Mon Sep 17 00:00:00 2001 From: Kirill Markin Date: Mon, 6 Oct 2025 16:51:17 +0300 Subject: [PATCH 03/13] Move texture2d and static mesh resources into render api module --- .../DeferredRendering/Source/Application.cpp | 2 +- .../Include/Runtime/ModelLoader/Loader.h | 2 +- Source/Runtime/ModelLoader/Source/Loader.cpp | 16 ++++++++-------- Source/Runtime/RenderApi/Core/CMakeLists.txt | 2 ++ .../RenderApi/Core/Resources}/StaticMesh.h | 8 ++++---- .../RenderApi/Core/Resources}/Texture2D.h | 4 ++-- .../Core/Source/Resources}/StaticMesh.cpp | 12 ++++++------ .../Core/Source/Resources}/Texture2D.cpp | 8 +++----- .../Core/{ => Scene}/Lights/PointLight.h | 0 .../Objects}/TexturedStaticMesh.h | 19 +++++++++++-------- .../Runtime/Renderer/Core/Scene/Scene.h | 1 - .../Source/{ => Scene}/Lights/PointLight.cpp | 2 +- .../Objects}/TexturedStaticMesh.cpp | 10 +++++----- .../Renderer/Core/Source/Scene/Scene.cpp | 5 ++--- .../Renderer/Deferred/DeferredRenderer.h | 8 ++++---- .../Deferred/Source/DeferredRenderer.cpp | 9 +++++---- 16 files changed, 55 insertions(+), 53 deletions(-) rename Source/Runtime/{Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh => RenderApi/Core/Include/Runtime/RenderApi/Core/Resources}/StaticMesh.h (85%) rename Source/Runtime/{Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh => RenderApi/Core/Include/Runtime/RenderApi/Core/Resources}/Texture2D.h (93%) rename Source/Runtime/{Renderer/Core/Source/TexturedMesh => RenderApi/Core/Source/Resources}/StaticMesh.cpp (88%) rename Source/Runtime/{Renderer/Core/Source/TexturedMesh => RenderApi/Core/Source/Resources}/Texture2D.cpp (95%) rename Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/{ => Scene}/Lights/PointLight.h (100%) rename Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/{TexturedMesh => Scene/Objects}/TexturedStaticMesh.h (78%) rename Source/Runtime/Renderer/Core/Source/{ => Scene}/Lights/PointLight.cpp (99%) rename Source/Runtime/Renderer/Core/Source/{TexturedMesh => Scene/Objects}/TexturedStaticMesh.cpp (89%) diff --git a/Source/Examples/DeferredRendering/Source/Application.cpp b/Source/Examples/DeferredRendering/Source/Application.cpp index 784b495..c509219 100644 --- a/Source/Examples/DeferredRendering/Source/Application.cpp +++ b/Source/Examples/DeferredRendering/Source/Application.cpp @@ -7,7 +7,7 @@ #include "Runtime/Application/Core/Window.h" #include "Runtime/ModelLoader/Loader.h" #include "Runtime/RenderApi/Core/RenderApi.h" -#include "Runtime/Renderer/Core/Lights/PointLight.h" +#include "Runtime/Renderer/Core/Scene/Lights/PointLight.h" #include "Runtime/Renderer/Core/Scene/Scene.h" #include "Runtime/TfExecutorBuilder/TfExecutorBuilder.h" diff --git a/Source/Runtime/ModelLoader/Include/Runtime/ModelLoader/Loader.h b/Source/Runtime/ModelLoader/Include/Runtime/ModelLoader/Loader.h index 06ab23a..6cbcb8d 100644 --- a/Source/Runtime/ModelLoader/Include/Runtime/ModelLoader/Loader.h +++ b/Source/Runtime/ModelLoader/Include/Runtime/ModelLoader/Loader.h @@ -3,7 +3,7 @@ #include #include #include "Runtime/RenderApi/Core/RenderApi.h" -#include "Runtime/Renderer/Core/TexturedMesh/TexturedStaticMesh.h" +#include "Runtime/Renderer/Core/Scene/Objects/TexturedStaticMesh.h" #include "taskflow/taskflow.hpp" namespace krendrr::Runtime::ModelLoader diff --git a/Source/Runtime/ModelLoader/Source/Loader.cpp b/Source/Runtime/ModelLoader/Source/Loader.cpp index 3a6b1a4..be30568 100644 --- a/Source/Runtime/ModelLoader/Source/Loader.cpp +++ b/Source/Runtime/ModelLoader/Source/Loader.cpp @@ -8,15 +8,15 @@ #include #include "Runtime/MipMapsGenerator/Generator.h" #include "Runtime/RenderApi/Core/ApiCallCheck.h" -#include "Runtime/Renderer/Core/TexturedMesh/StaticMesh.h" -#include "Runtime/Renderer/Core/TexturedMesh/Texture2D.h" +#include "Runtime/RenderApi/Core/Resources/StaticMesh.h" +#include "Runtime/RenderApi/Core/Resources/Texture2D.h" namespace krendrr::Runtime::ModelLoader { // a bunch of data shared between thread pool jobs struct LoadData { - std::unordered_map> TextureCache {}; + std::unordered_map> TextureCache {}; std::vector TexturesToGenerateMipMaps {}; std::mutex TextureCacheMutex {}; @@ -184,10 +184,10 @@ namespace krendrr::Runtime::ModelLoader // Create Mesh { - std::shared_ptr NewMesh = std::make_shared(); + std::shared_ptr NewMesh = std::make_shared(); NewTexturedMesh->AssignMesh(NewMesh); - Renderer::Core::StaticMesh::MeshLoadOperation MeshLoadOperation = NewMesh->LoadIndexed( + RenderApi::Core::StaticMesh::MeshLoadOperation MeshLoadOperation = NewMesh->LoadIndexed( RenderApi, *NewCommandList.Get(), RenderApi::Core::RenderApi::ContainerToBytes(Vertices), Indices); if (!MeshLoadOperation.WasSuccessful()) @@ -225,7 +225,7 @@ namespace krendrr::Runtime::ModelLoader TexturePath.append("/"); TexturePath.append(RelativeTexturePath.C_Str()); - std::shared_ptr Texture {}; + std::shared_ptr Texture {}; std::unique_lock TextureCacheLock(LoadData.TextureCacheMutex); @@ -238,9 +238,9 @@ namespace krendrr::Runtime::ModelLoader // Since texture loading may take a while, do not keep the mutex ownership TextureCacheLock.unlock(); - Texture = std::make_shared(); + Texture = std::make_shared(); - const Renderer::Core::Texture2D::TextureLoadOperation TextureLoadOperation = Texture->Load(RenderApi, *NewCommandList.Get(), TexturePath); + const RenderApi::Core::Texture2D::TextureLoadOperation TextureLoadOperation = Texture->Load(RenderApi, *NewCommandList.Get(), TexturePath); if (!TextureLoadOperation.WasSuccessful()) { diff --git a/Source/Runtime/RenderApi/Core/CMakeLists.txt b/Source/Runtime/RenderApi/Core/CMakeLists.txt index ef73e48..df6c04f 100644 --- a/Source/Runtime/RenderApi/Core/CMakeLists.txt +++ b/Source/Runtime/RenderApi/Core/CMakeLists.txt @@ -2,4 +2,6 @@ add_krendrr_target(STATIC RenderAPI TARGET_NAME) target_link_libraries(${TARGET_NAME} PUBLIC krendrr::thirdparty::directx12 + krendrr::thirdparty::glm + krendrr::thirdparty::stb_image ) \ No newline at end of file diff --git a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/StaticMesh.h b/Source/Runtime/RenderApi/Core/Include/Runtime/RenderApi/Core/Resources/StaticMesh.h similarity index 85% rename from Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/StaticMesh.h rename to Source/Runtime/RenderApi/Core/Include/Runtime/RenderApi/Core/Resources/StaticMesh.h index aec2619..f471f71 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/StaticMesh.h +++ b/Source/Runtime/RenderApi/Core/Include/Runtime/RenderApi/Core/Resources/StaticMesh.h @@ -5,7 +5,7 @@ #include "Runtime/RenderApi/Core/RenderApi.h" #include "d3dx12/d3dx12.h" -namespace krendrr::Runtime::Renderer::Core +namespace krendrr::Runtime::RenderApi::Core { class StaticMesh { @@ -34,13 +34,13 @@ namespace krendrr::Runtime::Renderer::Core * Creates upload heaps and fills provided command list with copy operations. * Caller need to execute the command list and keep upload buffers alive while copy is not finished. */ - MeshLoadOperation Load(const RenderApi::Core::RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::span& VertexData); + MeshLoadOperation Load(const RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::span& VertexData); /** * Creates upload heaps and fills provided command list with copy operations. * Caller need to execute the command list and keep upload buffers alive while copy is not finished. */ - MeshLoadOperation LoadIndexed(const RenderApi::Core::RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, + MeshLoadOperation LoadIndexed(const RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::span& VertexData, const std::span& IndexData); /** @@ -67,7 +67,7 @@ namespace krendrr::Runtime::Renderer::Core [[nodiscard]] bool CheckLoaded() const; - Microsoft::WRL::ComPtr LoadVertexBuffer(const RenderApi::Core::RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, + Microsoft::WRL::ComPtr LoadVertexBuffer(const RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::span& VertexData); }; } diff --git a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/Texture2D.h b/Source/Runtime/RenderApi/Core/Include/Runtime/RenderApi/Core/Resources/Texture2D.h similarity index 93% rename from Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/Texture2D.h rename to Source/Runtime/RenderApi/Core/Include/Runtime/RenderApi/Core/Resources/Texture2D.h index 2469f2a..ae23c80 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/Texture2D.h +++ b/Source/Runtime/RenderApi/Core/Include/Runtime/RenderApi/Core/Resources/Texture2D.h @@ -6,7 +6,7 @@ #include "glm/vec2.hpp" #include "Runtime/RenderApi/Core/RenderApi.h" -namespace krendrr::Runtime::Renderer::Core +namespace krendrr::Runtime::RenderApi::Core { class Texture2D { @@ -52,7 +52,7 @@ namespace krendrr::Runtime::Renderer::Core * Creates upload heaps and fills provided command list with copy operations. * Caller need to execute the command list and keep upload buffers alive while copy is not finished. */ - TextureLoadOperation Load(const RenderApi::Core::RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, + TextureLoadOperation Load(const RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::string_view& TextureFileName, const TextureLoadParams& Params = TextureLoadParams::Default()); D3D12_CPU_DESCRIPTOR_HANDLE GetTextureHandle() const; diff --git a/Source/Runtime/Renderer/Core/Source/TexturedMesh/StaticMesh.cpp b/Source/Runtime/RenderApi/Core/Source/Resources/StaticMesh.cpp similarity index 88% rename from Source/Runtime/Renderer/Core/Source/TexturedMesh/StaticMesh.cpp rename to Source/Runtime/RenderApi/Core/Source/Resources/StaticMesh.cpp index a3a21fa..37d05d9 100644 --- a/Source/Runtime/Renderer/Core/Source/TexturedMesh/StaticMesh.cpp +++ b/Source/Runtime/RenderApi/Core/Source/Resources/StaticMesh.cpp @@ -1,9 +1,9 @@ -#include "Runtime/Renderer/Core/TexturedMesh/StaticMesh.h" +#include "Runtime/RenderApi/Core/Resources/StaticMesh.h" #include "Runtime/RenderApi/Core/ApiCallCheck.h" -namespace krendrr::Runtime::Renderer::Core +namespace krendrr::Runtime::RenderApi::Core { - StaticMesh::MeshLoadOperation StaticMesh::Load(const RenderApi::Core::RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::span& VertexData) + StaticMesh::MeshLoadOperation StaticMesh::Load(const RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::span& VertexData) { if(IsLoaded()) { @@ -29,7 +29,7 @@ namespace krendrr::Runtime::Renderer::Core }; } - StaticMesh::MeshLoadOperation StaticMesh::LoadIndexed(const RenderApi::Core::RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::span& VertexData, const std::span& IndexData) + StaticMesh::MeshLoadOperation StaticMesh::LoadIndexed(const RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::span& VertexData, const std::span& IndexData) { if(IsLoaded()) { @@ -38,7 +38,7 @@ namespace krendrr::Runtime::Renderer::Core } Microsoft::WRL::ComPtr VertexBufferUpload = LoadVertexBuffer(RenderApi, CommandList, VertexData); - Microsoft::WRL::ComPtr IndexBufferUpload = RenderApi.CreateUploadBufferAndMap(RenderApi::Core::RenderApi::ContainerToBytes(IndexData)); + Microsoft::WRL::ComPtr IndexBufferUpload = RenderApi.CreateUploadBufferAndMap(RenderApi::ContainerToBytes(IndexData)); if (!VertexBufferUpload || !IndexBufferUpload) { // TODO: log error @@ -77,7 +77,7 @@ namespace krendrr::Runtime::Renderer::Core }; } - Microsoft::WRL::ComPtr StaticMesh::LoadVertexBuffer(const RenderApi::Core::RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::span& VertexData) + Microsoft::WRL::ComPtr StaticMesh::LoadVertexBuffer(const RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::span& VertexData) { Microsoft::WRL::ComPtr VertexBufferUpload = RenderApi.CreateUploadBufferAndMap(VertexData); diff --git a/Source/Runtime/Renderer/Core/Source/TexturedMesh/Texture2D.cpp b/Source/Runtime/RenderApi/Core/Source/Resources/Texture2D.cpp similarity index 95% rename from Source/Runtime/Renderer/Core/Source/TexturedMesh/Texture2D.cpp rename to Source/Runtime/RenderApi/Core/Source/Resources/Texture2D.cpp index 147d49d..ae9e942 100644 --- a/Source/Runtime/Renderer/Core/Source/TexturedMesh/Texture2D.cpp +++ b/Source/Runtime/RenderApi/Core/Source/Resources/Texture2D.cpp @@ -1,13 +1,11 @@ -#include "Runtime/Renderer/Core/TexturedMesh/Texture2D.h" -#include +#include "Runtime/RenderApi/Core/Resources/Texture2D.h" #include #include #include #include - #include "Runtime/RenderApi/Core/ApiCallCheck.h" -namespace krendrr::Runtime::Renderer::Core +namespace krendrr::Runtime::RenderApi::Core { bool Texture2D::IsLoaded() const @@ -15,7 +13,7 @@ bool Texture2D::IsLoaded() const return TextureBuffer != nullptr; } -Texture2D::TextureLoadOperation Texture2D::Load(const RenderApi::Core::RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, +Texture2D::TextureLoadOperation Texture2D::Load(const RenderApi& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::string_view& TextureFileName, const TextureLoadParams& Params) { if(IsLoaded()) diff --git a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Lights/PointLight.h b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Lights/PointLight.h similarity index 100% rename from Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Lights/PointLight.h rename to Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Lights/PointLight.h diff --git a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/TexturedStaticMesh.h b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Objects/TexturedStaticMesh.h similarity index 78% rename from Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/TexturedStaticMesh.h rename to Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Objects/TexturedStaticMesh.h index 18ccb82..c1f9039 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/TexturedStaticMesh.h +++ b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Objects/TexturedStaticMesh.h @@ -9,11 +9,14 @@ #include "glm/detail/type_quat.hpp" #include "Runtime/RenderApi/Core/RenderApi.h" -namespace krendrr::Runtime::Renderer::Core +namespace krendrr::Runtime::RenderApi::Core { - class Texture2D; class StaticMesh; + class Texture2D; +} +namespace krendrr::Runtime::Renderer::Core +{ /** * Represents a textured mesh on scene * @@ -25,12 +28,12 @@ namespace krendrr::Runtime::Renderer::Core [[nodiscard]] bool IsValid() const; - void AssignTexture(std::string Name, std::shared_ptr NewTexture); - [[nodiscard]] std::shared_ptr GetTexture(const std::string_view& Name) const; + void AssignTexture(std::string Name, std::shared_ptr NewTexture); + [[nodiscard]] std::shared_ptr GetTexture(const std::string_view& Name) const; [[nodiscard]] bool HasTexture(const std::string_view& Name) const; - void AssignMesh(std::shared_ptr NewMesh); - [[nodiscard]] std::shared_ptr GetMesh() const; + void AssignMesh(std::shared_ptr NewMesh); + [[nodiscard]] std::shared_ptr GetMesh() const; [[nodiscard]] const glm::vec3& GetMeshColor() const; void SetMeshColor(const glm::vec3& NewMeshColor); @@ -59,8 +62,8 @@ namespace krendrr::Runtime::Renderer::Core glm::quat Rotation {}; glm::vec3 Scale {1.f, 1.f, 1.f}; - std::shared_ptr Mesh {}; - std::map, std::less<>> Textures {}; + std::shared_ptr Mesh {}; + std::map, std::less<>> Textures {}; glm::vec3 MeshColor {}; bool bCanCastShadow {true}; diff --git a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Scene.h b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Scene.h index dc7f7a3..585ec47 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Scene.h +++ b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Scene.h @@ -3,7 +3,6 @@ #include #include #include - #include "glm/fwd.hpp" #include "glm/detail/type_quat.hpp" diff --git a/Source/Runtime/Renderer/Core/Source/Lights/PointLight.cpp b/Source/Runtime/Renderer/Core/Source/Scene/Lights/PointLight.cpp similarity index 99% rename from Source/Runtime/Renderer/Core/Source/Lights/PointLight.cpp rename to Source/Runtime/Renderer/Core/Source/Scene/Lights/PointLight.cpp index cd58fa5..59fb3ed 100644 --- a/Source/Runtime/Renderer/Core/Source/Lights/PointLight.cpp +++ b/Source/Runtime/Renderer/Core/Source/Scene/Lights/PointLight.cpp @@ -1,4 +1,4 @@ -#include "Runtime/Renderer/Core/Lights/PointLight.h" +#include "Runtime/Renderer/Core/Scene/Lights/PointLight.h" #include "Runtime/RenderApi/Core/Builders/ConstBufferBuilder.h" namespace krendrr::Runtime::Renderer::Core diff --git a/Source/Runtime/Renderer/Core/Source/TexturedMesh/TexturedStaticMesh.cpp b/Source/Runtime/Renderer/Core/Source/Scene/Objects/TexturedStaticMesh.cpp similarity index 89% rename from Source/Runtime/Renderer/Core/Source/TexturedMesh/TexturedStaticMesh.cpp rename to Source/Runtime/Renderer/Core/Source/Scene/Objects/TexturedStaticMesh.cpp index 295c114..7884911 100644 --- a/Source/Runtime/Renderer/Core/Source/TexturedMesh/TexturedStaticMesh.cpp +++ b/Source/Runtime/Renderer/Core/Source/Scene/Objects/TexturedStaticMesh.cpp @@ -1,4 +1,4 @@ -#include "Runtime/Renderer/Core/TexturedMesh/TexturedStaticMesh.h" +#include "Runtime/Renderer/Core/Scene/Objects/TexturedStaticMesh.h" #include "glm/gtc/quaternion.hpp" #include "Runtime/RenderApi/Core/ApiCallCheck.h" #include "Runtime/RenderApi/Core/Builders/ConstBufferBuilder.h" @@ -10,17 +10,17 @@ namespace krendrr::Runtime::Renderer::Core return Mesh != nullptr; } - void TexturedStaticMesh::AssignMesh(std::shared_ptr NewMesh) + void TexturedStaticMesh::AssignMesh(std::shared_ptr NewMesh) { Mesh = std::move(NewMesh); } - void TexturedStaticMesh::AssignTexture(std::string Name, std::shared_ptr NewTexture) + void TexturedStaticMesh::AssignTexture(std::string Name, std::shared_ptr NewTexture) { Textures.insert_or_assign(std::move(Name), std::move(NewTexture)); } - std::shared_ptr TexturedStaticMesh::GetTexture(const std::string_view& Name) const + std::shared_ptr TexturedStaticMesh::GetTexture(const std::string_view& Name) const { auto Iter = Textures.find(Name); @@ -35,7 +35,7 @@ namespace krendrr::Runtime::Renderer::Core return Textures.contains(Name); } - std::shared_ptr TexturedStaticMesh::GetMesh() const + std::shared_ptr TexturedStaticMesh::GetMesh() const { return Mesh; } diff --git a/Source/Runtime/Renderer/Core/Source/Scene/Scene.cpp b/Source/Runtime/Renderer/Core/Source/Scene/Scene.cpp index 102847f..da11177 100644 --- a/Source/Runtime/Renderer/Core/Source/Scene/Scene.cpp +++ b/Source/Runtime/Renderer/Core/Source/Scene/Scene.cpp @@ -1,7 +1,6 @@ #include "Runtime/Renderer/Core/Scene/Scene.h" - -#include "Runtime/Renderer/Core/Lights/PointLight.h" -#include "Runtime/Renderer/Core/TexturedMesh/TexturedStaticMesh.h" +#include "Runtime/Renderer/Core/Scene/Lights/PointLight.h" +#include "Runtime/Renderer/Core/Scene/Objects/TexturedStaticMesh.h" namespace krendrr::Runtime::Renderer::Core { diff --git a/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h index c824069..23e5803 100644 --- a/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h +++ b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h @@ -3,8 +3,8 @@ #include #include #include "Runtime/Renderer/Core/Renderer.h" -#include "Runtime/Renderer/Core/TexturedMesh/StaticMesh.h" -#include "Runtime/Renderer/Core/TexturedMesh/TexturedStaticMesh.h" +#include "Runtime/RenderApi/Core/Resources/StaticMesh.h" +#include "Runtime/Renderer/Core/Scene/Objects/TexturedStaticMesh.h" namespace krendrr::Runtime::Renderer::Deferred { @@ -23,8 +23,8 @@ namespace krendrr::Runtime::Renderer::Deferred std::shared_ptr RenderApi {}; std::shared_ptr TfExecutor {}; - std::shared_ptr FullscreenQuadMesh {}; - std::shared_ptr SphereMesh {}; + std::shared_ptr FullscreenQuadMesh {}; + std::shared_ptr SphereMesh {}; bool InitBasicMeshes(); struct PrePostRenderData diff --git a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp index e2bc081..730aea7 100644 --- a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp +++ b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp @@ -4,13 +4,13 @@ #include "Runtime/ModelLoader/Loader.h" #include "Runtime/Renderer/Core/Scene/Scene.h" #include "Runtime/Renderer/Core/Scene/SceneView.h" -#include "Runtime/Renderer/Core/TexturedMesh/Texture2D.h" +#include "Runtime/RenderApi/Core/Resources/Texture2D.h" #include "nvtx3/nvtx3.hpp" #include "Runtime/RenderApi/Core/ApiCallCheck.h" #include "Runtime/RenderApi/Core/Builders/ConstBufferBuilder.h" #include "Runtime/RenderApi/Core/Builders/PsoBuilder.h" #include "Runtime/RenderApi/Core/Builders/RootSigBuilder.h" -#include "Runtime/Renderer/Core/Lights/PointLight.h" +#include "Runtime/Renderer/Core/Scene/Lights/PointLight.h" namespace krendrr::Runtime::Renderer::Deferred { @@ -1479,8 +1479,9 @@ bool DeferredRenderer::InitBasicMeshes() 1.f, -1.f, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; - auto NewFullscreenQuadMesh = std::make_shared(); - const Core::StaticMesh::MeshLoadOperation MeshLoad = NewFullscreenQuadMesh->Load(*RenderApi.get(), *InitCommandList.Get(), RenderApi->ContainerToBytes(QuadMesh)); + auto NewFullscreenQuadMesh = std::make_shared(); + const RenderApi::Core::StaticMesh::MeshLoadOperation MeshLoad = NewFullscreenQuadMesh + ->Load(*RenderApi.get(), *InitCommandList.Get(), RenderApi->ContainerToBytes(QuadMesh)); if (!MeshLoad.WasSuccessful()) return false; From 4ebca104c698989211a785634499580fc1345bfe Mon Sep 17 00:00:00 2001 From: Kirill Markin Date: Mon, 6 Oct 2025 18:37:17 +0300 Subject: [PATCH 04/13] Introduce tasking into application tick, allow renderer to form its own task graph inside of render task --- .../SimpleDeferredRendering/Application.h | 5 - .../DeferredRendering/Source/Application.cpp | 112 +++++++++++++----- .../Include/Runtime/Renderer/Core/Renderer.h | 9 +- .../Renderer/Core/Scene/Lights/PointLight.h | 1 - .../Renderer/Deferred/DeferredRenderer.h | 2 +- .../Deferred/Source/DeferredRenderer.cpp | 2 +- .../TfExecutorBuilder/TfExecutorBuilder.h | 5 +- .../TaskFlowEx/Source/TfExecutorBuilder.cpp | 2 +- 8 files changed, 93 insertions(+), 45 deletions(-) diff --git a/Source/Examples/DeferredRendering/Include/Examples/SimpleDeferredRendering/Application.h b/Source/Examples/DeferredRendering/Include/Examples/SimpleDeferredRendering/Application.h index fec7bfe..e8f8053 100644 --- a/Source/Examples/DeferredRendering/Include/Examples/SimpleDeferredRendering/Application.h +++ b/Source/Examples/DeferredRendering/Include/Examples/SimpleDeferredRendering/Application.h @@ -7,11 +7,6 @@ #include "Runtime/Renderer/Core/Scene/SceneView.h" #include "Runtime/Renderer/Deferred/DeferredRenderer.h" -namespace tf -{ - class Executor; -} - namespace krendrr::Runtime::Application::Core { class Window; diff --git a/Source/Examples/DeferredRendering/Source/Application.cpp b/Source/Examples/DeferredRendering/Source/Application.cpp index c509219..c12fdef 100644 --- a/Source/Examples/DeferredRendering/Source/Application.cpp +++ b/Source/Examples/DeferredRendering/Source/Application.cpp @@ -31,8 +31,8 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::Initialize(const R const bool bRenderApiInitResult = RenderApi->Initialize({ .Debug = Runtime::RenderApi::Core::RenderApi::InitParams::Debug::DebugLayerWithGpuBasedValidation, .bEnableShadersDebug = true - //.Debug = Runtime::RenderApi::Core::RenderApi::InitParams::Debug::None, - //.bEnableShadersDebug = false + // .Debug = Runtime::RenderApi::Core::RenderApi::InitParams::Debug::None, + // .bEnableShadersDebug = false }); if (!bRenderApiInitResult) @@ -102,46 +102,96 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::Tick(float DeltaTi static std::size_t FpsDisplayCounter = 0; FpsDisplayCounter++; if (FpsDisplayCounter % 100 == 0) + { + FpsDisplayCounter = 0; std::cout << "Delta: " << DeltaTime << " FPS: " << 1.f / DeltaTime << std::endl; + } } - const glm::ivec2 WindowSize = Window->GetSize(); - Runtime::Application::Core::Window::WindowRenderData RenderData = Window->GetCurrentRenderTargetView(); + Camera.Update(DeltaTime); + + // No sync needed, since all tasks in main task flow access it separately + bool bHasError {}; - const bool bRenderDataSetSuccess = SceneView.SetRenderData( + tf::Taskflow MainTaskFlow {}; + + auto ErrorCheckLambda = [&]() + { + return bHasError ? 1 : 0; + }; + + tf::Task RenderErrorCheckTask = MainTaskFlow.emplace(ErrorCheckLambda) + .name("Render Error Checking Task"); + + tf::Task RenderTickTask = MainTaskFlow.emplace( + [&](tf::Subflow& Subflow) { - RenderData.WindowRenderTarget, - RenderData.Handle, - D3D12_RESOURCE_STATE_PRESENT - }, { - 0, - 0, - WindowSize.x, - WindowSize.y + const glm::ivec2 WindowSize = Window->GetSize(); + const Runtime::Application::Core::Window::WindowRenderData RenderData = Window->GetCurrentRenderTargetView(); + + const bool bRenderDataSetSuccess = SceneView.SetRenderData( + { + RenderData.WindowRenderTarget, + RenderData.Handle, + D3D12_RESOURCE_STATE_PRESENT + }, { + 0, + 0, + WindowSize.x, + WindowSize.y + } + ); + + if (!bRenderDataSetSuccess) + { + bHasError = false; + return; + } + + std::array Views = { + SceneView + }; + + if (!Renderer->Render(Scene.get(), Views, Subflow)) + { + // TODO: add error log + + // remove queued tasks if any + Subflow.graph().clear(); + + bHasError = true; + return; + } } - ); + ).name("Renderer Tick Task"); - if (!bRenderDataSetSuccess) - return false; + tf::Task SwapErrorCheckTask = MainTaskFlow.emplace(ErrorCheckLambda) + .name("Swap Error Checking Task"); - Camera.Update(DeltaTime); + tf::Task SwapTask = MainTaskFlow.emplace( + [&]() + { + if (!Window->Swap()) + { + // TODO: add error log - std::array Views = { - SceneView - }; - if (!Renderer->Render(Scene.get(), Views)) - { - // TODO: add error log - return false; - } + bHasError = true; + } + } + ).name("Window Swap Task"); - if (!Window->Swap()) - { - // TODO: add error log - return false; - } + // dead-end task. can be used for canceling the task flow execution + tf::Task EndTask = MainTaskFlow.emplace([](){}).name("Application Tick End Task"); - return true; + // Allow render tick task to go straight to end task in case of an error + RenderTickTask.precede(RenderErrorCheckTask); + RenderErrorCheckTask.precede(SwapTask, EndTask); + SwapTask.precede(SwapErrorCheckTask); + SwapErrorCheckTask.precede(EndTask); + + TfExecutor->run(MainTaskFlow).wait(); + + return !bHasError; } bool krendrr::Examples::SimpleDeferredRendering::Application::Shutdown() diff --git a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h index 2d8dc26..a059328 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h +++ b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h @@ -6,6 +6,7 @@ namespace tf { class Executor; + class FlowBuilder; } namespace krendrr::Runtime::RenderApi::Core @@ -28,6 +29,8 @@ namespace krendrr::Runtime::Renderer::Core * * Renderer may hold data between render calls, e.g. it can keep multiple * GBuffers between render calls when rendering into multiple scene views at the same time. + * + * */ class Renderer { @@ -35,7 +38,11 @@ namespace krendrr::Runtime::Renderer::Core virtual bool Initialize(std::shared_ptr NewRenderApi, std::shared_ptr NewTfExecutor) = 0; - virtual bool Render(const Scene* Scene, const std::span& SceneViews) = 0; + /** + * Use FlowBuilder to create task graphs (simplified render graph) and run your passes in parallel when needed. + * FlowBuilder tasks are going to be executed right after this call if it has returned true. + */ + virtual bool Render(const Scene* Scene, const std::span& SceneViews, tf::FlowBuilder& FlowBuilder) = 0; virtual bool Shutdown() = 0; diff --git a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Lights/PointLight.h b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Lights/PointLight.h index c94cb4a..e4f6a3f 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Lights/PointLight.h +++ b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Lights/PointLight.h @@ -18,7 +18,6 @@ namespace krendrr::Runtime::Renderer::Core constexpr inline static DXGI_FORMAT DEPTH_STENCIL_FORMAT = DXGI_FORMAT_D24_UNORM_S8_UINT; - [[nodiscard]] const glm::vec3& GetPosition() const; void SetPosition(const glm::vec3& NewPosition); diff --git a/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h index 23e5803..6ad6c75 100644 --- a/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h +++ b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h @@ -14,7 +14,7 @@ namespace krendrr::Runtime::Renderer::Deferred bool Initialize(std::shared_ptr NewRenderApi, std::shared_ptr NewTfExecutor) override; - bool Render(const Core::Scene* Scene, const std::span& SceneViews) override; + bool Render(const Core::Scene* Scene, const std::span& SceneViews, tf::FlowBuilder& FlowBuilder) override; bool Shutdown() override; diff --git a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp index 730aea7..cb9ad03 100644 --- a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp +++ b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp @@ -61,7 +61,7 @@ bool DeferredRenderer::Initialize(std::shared_ptr Ne return true; } -bool DeferredRenderer::Render(const Core::Scene* Scene, const std::span& SceneViews) +bool DeferredRenderer::Render(const Core::Scene* Scene, const std::span& SceneViews, tf::FlowBuilder& FlowBuilder) { if (Scene->GetPointLights().size() > PointLightVolumePassData.MAX_DYNAMIC_POINT_LIGHTS_COUNT) { diff --git a/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TfExecutorBuilder.h b/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TfExecutorBuilder.h index fe4de32..5689b7c 100644 --- a/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TfExecutorBuilder.h +++ b/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TfExecutorBuilder.h @@ -27,10 +27,7 @@ namespace krendrr::Runtime::TaskFlowEx Builder& AttachNvtxObserver(bool bShouldAttach = true); /** - * Sets the amount of workers. Uses std::thread::hardware_concurrency() - 1 by default. - * - * Note: we subtract 1 because we usually have a main thread that pushes top level jobs and then coruns them, - * so it is not part of workers set, but becomes one of them when needed. + * Sets the amount of workers. Uses std::thread::hardware_concurrency() by default. * * If set to 0, uses the default value. */ diff --git a/Source/Runtime/TaskFlowEx/Source/TfExecutorBuilder.cpp b/Source/Runtime/TaskFlowEx/Source/TfExecutorBuilder.cpp index 049424e..c83788e 100644 --- a/Source/Runtime/TaskFlowEx/Source/TfExecutorBuilder.cpp +++ b/Source/Runtime/TaskFlowEx/Source/TfExecutorBuilder.cpp @@ -33,7 +33,7 @@ namespace krendrr::Runtime::TaskFlowEx std::shared_ptr Builder::Build() { std::shared_ptr Executor = std::make_shared( - WorkersCount > 0 ? WorkersCount : std::thread::hardware_concurrency() - 1 + WorkersCount > 0 ? WorkersCount : std::thread::hardware_concurrency() ); if (bIsNvtxObserverAttached) From b090b43b093c322d8598b47a2d7dc3697ed90477 Mon Sep 17 00:00:00 2001 From: Kirill Markin Date: Mon, 6 Oct 2025 19:12:16 +0300 Subject: [PATCH 05/13] use atomic --- .../DeferredRendering/Source/Application.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/Examples/DeferredRendering/Source/Application.cpp b/Source/Examples/DeferredRendering/Source/Application.cpp index c12fdef..161b220 100644 --- a/Source/Examples/DeferredRendering/Source/Application.cpp +++ b/Source/Examples/DeferredRendering/Source/Application.cpp @@ -111,13 +111,13 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::Tick(float DeltaTi Camera.Update(DeltaTime); // No sync needed, since all tasks in main task flow access it separately - bool bHasError {}; + std::atomic_bool bHasError {}; tf::Taskflow MainTaskFlow {}; auto ErrorCheckLambda = [&]() { - return bHasError ? 1 : 0; + return bHasError.load(std::memory_order::relaxed) ? 1 : 0; }; tf::Task RenderErrorCheckTask = MainTaskFlow.emplace(ErrorCheckLambda) @@ -144,7 +144,7 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::Tick(float DeltaTi if (!bRenderDataSetSuccess) { - bHasError = false; + bHasError.store(true, std::memory_order::relaxed); return; } @@ -159,7 +159,7 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::Tick(float DeltaTi // remove queued tasks if any Subflow.graph().clear(); - bHasError = true; + bHasError.store(true, std::memory_order::relaxed); return; } } @@ -175,7 +175,7 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::Tick(float DeltaTi { // TODO: add error log - bHasError = true; + bHasError.store(true, std::memory_order::relaxed); } } ).name("Window Swap Task"); @@ -191,7 +191,7 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::Tick(float DeltaTi TfExecutor->run(MainTaskFlow).wait(); - return !bHasError; + return !bHasError.load(std::memory_order::relaxed); } bool krendrr::Examples::SimpleDeferredRendering::Application::Shutdown() From c321cb0227ccec4aa9a45121b742e589fc87db2c Mon Sep 17 00:00:00 2001 From: Kirill Markin Date: Tue, 7 Oct 2025 15:39:59 +0300 Subject: [PATCH 06/13] add more nvtx ranges in renderer, set names for worker threads --- .../Deferred/Source/DeferredRenderer.cpp | 40 +++++++++++++++---- .../TfExecutorBuilder/TfExecutorBuilder.h | 8 ++++ .../TaskFlowEx/Source/TfExecutorBuilder.cpp | 40 +++++++++++++++++-- 3 files changed, 77 insertions(+), 11 deletions(-) diff --git a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp index cb9ad03..c10b96c 100644 --- a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp +++ b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp @@ -63,6 +63,8 @@ bool DeferredRenderer::Initialize(std::shared_ptr Ne bool DeferredRenderer::Render(const Core::Scene* Scene, const std::span& SceneViews, tf::FlowBuilder& FlowBuilder) { + NVTX3_FUNC_RANGE(); + if (Scene->GetPointLights().size() > PointLightVolumePassData.MAX_DYNAMIC_POINT_LIGHTS_COUNT) { // TODO: add error log @@ -128,7 +130,7 @@ bool DeferredRenderer::Render(const Core::Scene* Scene, const std::spanGetTexturedMeshes()) { @@ -176,7 +178,7 @@ bool DeferredRenderer::UpdateTexturedMeshConstantBuffers(const Core::Scene* Scen bool DeferredRenderer::UpdatePointLightConstantBuffers(const Core::Scene* Scene) { - nvtx3::scoped_range ConstBufUpdateRange {"Update Point Light Constant Buffers"}; + NVTX3_FUNC_RANGE(); for (auto& PointLight : Scene->GetPointLights()) { @@ -271,7 +273,7 @@ bool DeferredRenderer::InitializeGeometryPass() bool DeferredRenderer::GeometryPass(const Core::Scene* Scene, const Core::SceneView& SceneView) { - nvtx3::scoped_range PassRange {"Geometry Pass"}; + NVTX3_FUNC_RANGE(); const unsigned RtvHandleIncrement = RenderApi->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); const unsigned SrvHandleIncrement = RenderApi->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); @@ -514,6 +516,8 @@ bool DeferredRenderer::InitLightPass() bool DeferredRenderer::PrepareLightPassData(const Core::SceneView& SceneView) { + NVTX3_FUNC_RANGE(); + const glm::ivec2 ViewportSize = SceneView.GetViewportSize(); if (LightPassData.Size == SceneView.GetViewportSize()) @@ -595,6 +599,8 @@ bool DeferredRenderer::PrepareLightPassData(const Core::SceneView& SceneView) bool DeferredRenderer::TransitionLightPassFromRenderTargetToReadState() { + NVTX3_FUNC_RANGE(); + CD3DX12_RESOURCE_BARRIER Barrier = CD3DX12_RESOURCE_BARRIER::Transition(LightPassData.ColorTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ); CHECKED_S(LightPassData.RenderTargetToReadTransitionAllocator->Reset()); @@ -612,6 +618,8 @@ bool DeferredRenderer::TransitionLightPassFromRenderTargetToReadState() bool DeferredRenderer::TransitionLightPassFromReadToRenderTargetState() { + NVTX3_FUNC_RANGE(); + CD3DX12_RESOURCE_BARRIER Barrier = CD3DX12_RESOURCE_BARRIER::Transition(LightPassData.ColorTexture.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET); CHECKED_S(LightPassData.TransitionCommandList->Reset(LightPassData.RenderTargetToReadTransitionAllocator.Get(), nullptr)) @@ -696,7 +704,7 @@ bool DeferredRenderer::InitAmbientDirectionalLightPass() bool DeferredRenderer::AmbientDirectionalLightPass(const Core::SceneView& SceneView) { - nvtx3::scoped_range PassRange {"Ambient & Directional Light Pass"}; + NVTX3_FUNC_RANGE(); auto& CommandList = AmbientDirectionalLightPassData.CommandList; auto& CommandAllocator = AmbientDirectionalLightPassData.CommandAllocator; @@ -833,7 +841,7 @@ bool DeferredRenderer::InitPointLightShadowCubeMapPass() bool DeferredRenderer::PointLightShadowCubeMapsPass(const Core::Scene* Scene) { - nvtx3::scoped_range PassRange {"Point Light Shadow Cube Maps Pass"}; + NVTX3_FUNC_RANGE(); auto& CommandAllocator = PointLightShadowCubeMapData.CommandAllocator; auto& CommandList = PointLightShadowCubeMapData.CommandList; @@ -875,6 +883,8 @@ bool DeferredRenderer::PointLightShadowCubeMapsPass(const Core::Scene* Scene) { for(const auto& PointLight : Scene->GetPointLights()) { + nvtx3::scoped_range PointLightLoop{"Point Light Iteration"}; + if (!PointLight->CastsShadows()) continue; @@ -899,6 +909,8 @@ bool DeferredRenderer::PointLightShadowCubeMapsPass(const Core::Scene* Scene) // Render each side of point light for (int i = 0; i < 6; ++i) { + nvtx3::scoped_range PointLightSideLoop{"Point Light Side Iteration"}; + D3D12_CPU_DESCRIPTOR_HANDLE RtvHandle = PointLight->GetShadowCubeMapRtvHandle(i); D3D12_CPU_DESCRIPTOR_HANDLE DsvHandle = PointLight->GetShadowCubeMapDsvHandle(i); CommandList->OMSetRenderTargets(1, &RtvHandle, true, &DsvHandle); @@ -1127,7 +1139,7 @@ bool DeferredRenderer::InitPointLightVolumePass() bool DeferredRenderer::PointLightVolumesPass(const Core::Scene* Scene, const Core::SceneView& SceneView) { - nvtx3::scoped_range PassRange {"Point Light Volumes Pass"}; + NVTX3_FUNC_RANGE(); auto& CommandAllocator = PointLightVolumePassData.CommandAllocator; auto& CommandList = PointLightVolumePassData.CommandList; @@ -1352,7 +1364,7 @@ bool DeferredRenderer::InitPostProcessingPass() bool DeferredRenderer::PostProcessingPass(const Core::SceneView& SceneView) { - nvtx3::scoped_range PassRange {"Post Processing Pass"}; + NVTX3_FUNC_RANGE(); auto& CommandList = PostProcessingPassData.CommandList; auto& CommandAllocator = PostProcessingPassData.CommandAllocator; @@ -1536,6 +1548,8 @@ bool DeferredRenderer::InitPrePostRender() bool DeferredRenderer::PreRender(const Core::Scene* Scene, const Core::SceneView& SceneView) { + NVTX3_FUNC_RANGE(); + CHECKED_S(PrePostRenderData.CommandAllocator->Reset()); CHECKED( @@ -1567,6 +1581,8 @@ bool DeferredRenderer::PreRender(const Core::Scene* Scene, const Core::SceneView bool DeferredRenderer::PostRender(const Core::SceneView& SceneView) { + NVTX3_FUNC_RANGE(); + CHECKED( PrePostRenderData.CommandList->Reset(PrePostRenderData.CommandAllocator.Get(), nullptr), "Can't reset command list" @@ -1589,6 +1605,8 @@ bool DeferredRenderer::PostRender(const Core::SceneView& SceneView) bool DeferredRenderer::WaitDirectQueue() { + NVTX3_FUNC_RANGE(); + CHECKED( RenderApi->GetDirectQueue() ->Signal(FrameFence.Get(), ++FrameFenceValue), @@ -1719,6 +1737,8 @@ bool DeferredRenderer::InitEmptyTexture() bool DeferredRenderer::InitGBufferForView(const Core::SceneView& SceneView) { + NVTX3_FUNC_RANGE(); + const glm::ivec2 ViewportSize = SceneView.GetViewportSize(); if (GBuffer.Size == ViewportSize) @@ -1888,6 +1908,8 @@ bool DeferredRenderer::InitGBufferForView(const Core::SceneView& SceneView) bool DeferredRenderer::TransitionGBufferFromRenderTargetToReadState() { + NVTX3_FUNC_RANGE(); + const std::array Barriers = { CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.DiffuseTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ), CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.WorldPositionTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ), @@ -1912,6 +1934,8 @@ bool DeferredRenderer::TransitionGBufferFromRenderTargetToReadState() bool DeferredRenderer::TransitionGBufferFromReadToRenderTargetState() { + NVTX3_FUNC_RANGE(); + const std::array Barriers = { CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.DiffuseTexture.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET), CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.WorldPositionTexture.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET), diff --git a/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TfExecutorBuilder.h b/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TfExecutorBuilder.h index 5689b7c..1375ef5 100644 --- a/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TfExecutorBuilder.h +++ b/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TfExecutorBuilder.h @@ -26,6 +26,13 @@ namespace krendrr::Runtime::TaskFlowEx */ Builder& AttachNvtxObserver(bool bShouldAttach = true); + /** + * Attaches worker interface that gives all worker threads some human-readable names. + * + * Attached by default. + */ + Builder& AttachWorkerInterface(bool bShouldAttach = true); + /** * Sets the amount of workers. Uses std::thread::hardware_concurrency() by default. * @@ -36,6 +43,7 @@ namespace krendrr::Runtime::TaskFlowEx private: bool bIsNvtxObserverAttached = true; + bool bAttachWorkerInterface = true; unsigned WorkersCount = 0; }; diff --git a/Source/Runtime/TaskFlowEx/Source/TfExecutorBuilder.cpp b/Source/Runtime/TaskFlowEx/Source/TfExecutorBuilder.cpp index c83788e..9c588f1 100644 --- a/Source/Runtime/TaskFlowEx/Source/TfExecutorBuilder.cpp +++ b/Source/Runtime/TaskFlowEx/Source/TfExecutorBuilder.cpp @@ -25,6 +25,29 @@ namespace krendrr::Runtime::TaskFlowEx } }; + struct Worker final : public tf::WorkerInterface + { + void scheduler_prologue(tf::Worker& worker) override + { + constexpr int PrefixSize = 18; + constexpr int PossibleIdSize = 3; + constexpr auto* NamePrefix = L"ThreadPool Worker "; + + std::wstring ThreadName {}; + ThreadName.reserve(PrefixSize + PossibleIdSize); + + ThreadName.append(NamePrefix); + ThreadName.append(std::to_wstring(worker.id())); + + SetThreadDescription(worker.thread().native_handle(), ThreadName.c_str()); + } + + void scheduler_epilogue(tf::Worker& worker, std::exception_ptr ptr) override + { + + } + }; + Builder Builder::Create() { return Builder {}; @@ -32,14 +55,18 @@ namespace krendrr::Runtime::TaskFlowEx std::shared_ptr Builder::Build() { + std::shared_ptr WorkerInterface = nullptr; + + if (bAttachWorkerInterface) + WorkerInterface = std::make_shared(); + std::shared_ptr Executor = std::make_shared( - WorkersCount > 0 ? WorkersCount : std::thread::hardware_concurrency() + WorkersCount > 0 ? WorkersCount : std::thread::hardware_concurrency(), + std::move(WorkerInterface) ); if (bIsNvtxObserverAttached) - { Executor->make_observer(); - } return Executor; } @@ -51,6 +78,13 @@ namespace krendrr::Runtime::TaskFlowEx return *this; } + Builder& Builder::AttachWorkerInterface(bool bShouldAttach) + { + bAttachWorkerInterface = bShouldAttach; + + return *this; + } + Builder& Builder::SetWorkerCount(unsigned NewWorkersCount) { WorkersCount = NewWorkersCount; From 3078435ab0433843f2b2c1e8c82660877a971b33 Mon Sep 17 00:00:00 2001 From: Kirill Markin Date: Wed, 8 Oct 2025 16:18:53 +0300 Subject: [PATCH 07/13] Replace subflow with composible taskflows --- .../SimpleDeferredRendering/Application.h | 2 + .../DeferredRendering/Source/Application.cpp | 126 +++++++++--------- .../Include/Runtime/Renderer/Core/Renderer.h | 13 +- .../Renderer/Deferred/DeferredRenderer.h | 2 +- .../Deferred/Source/DeferredRenderer.cpp | 34 ++++- 5 files changed, 108 insertions(+), 69 deletions(-) diff --git a/Source/Examples/DeferredRendering/Include/Examples/SimpleDeferredRendering/Application.h b/Source/Examples/DeferredRendering/Include/Examples/SimpleDeferredRendering/Application.h index e8f8053..1b4ee75 100644 --- a/Source/Examples/DeferredRendering/Include/Examples/SimpleDeferredRendering/Application.h +++ b/Source/Examples/DeferredRendering/Include/Examples/SimpleDeferredRendering/Application.h @@ -50,6 +50,8 @@ namespace krendrr::Examples::SimpleDeferredRendering bool InitializeSceneViewAndCamera(); + bool FillRenderTaskflow(tf::Taskflow& Taskflow, const std::function& ErrorStop); + }; } diff --git a/Source/Examples/DeferredRendering/Source/Application.cpp b/Source/Examples/DeferredRendering/Source/Application.cpp index 161b220..2dde937 100644 --- a/Source/Examples/DeferredRendering/Source/Application.cpp +++ b/Source/Examples/DeferredRendering/Source/Application.cpp @@ -9,6 +9,7 @@ #include "Runtime/RenderApi/Core/RenderApi.h" #include "Runtime/Renderer/Core/Scene/Lights/PointLight.h" #include "Runtime/Renderer/Core/Scene/Scene.h" +#include "Runtime/TfExecutorBuilder/TaskFailedException.h" #include "Runtime/TfExecutorBuilder/TfExecutorBuilder.h" IMPLEMENT_ENTRY_POINT(krendrr::Examples::SimpleDeferredRendering::Application) @@ -110,63 +111,28 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::Tick(float DeltaTi Camera.Update(DeltaTime); - // No sync needed, since all tasks in main task flow access it separately - std::atomic_bool bHasError {}; - tf::Taskflow MainTaskFlow {}; - auto ErrorCheckLambda = [&]() + std::atomic_bool bWasStoppedOnError {}; + tf::Future TaskflowExecutionFuture {}; + auto StopOnError = [&bWasStoppedOnError, &TaskflowExecutionFuture]() { - return bHasError.load(std::memory_order::relaxed) ? 1 : 0; - }; - - tf::Task RenderErrorCheckTask = MainTaskFlow.emplace(ErrorCheckLambda) - .name("Render Error Checking Task"); - - tf::Task RenderTickTask = MainTaskFlow.emplace( - [&](tf::Subflow& Subflow) + if (TaskflowExecutionFuture.valid()) { - const glm::ivec2 WindowSize = Window->GetSize(); - const Runtime::Application::Core::Window::WindowRenderData RenderData = Window->GetCurrentRenderTargetView(); - - const bool bRenderDataSetSuccess = SceneView.SetRenderData( - { - RenderData.WindowRenderTarget, - RenderData.Handle, - D3D12_RESOURCE_STATE_PRESENT - }, { - 0, - 0, - WindowSize.x, - WindowSize.y - } - ); - - if (!bRenderDataSetSuccess) - { - bHasError.store(true, std::memory_order::relaxed); - return; - } - - std::array Views = { - SceneView - }; - - if (!Renderer->Render(Scene.get(), Views, Subflow)) - { - // TODO: add error log - - // remove queued tasks if any - Subflow.graph().clear(); - - bHasError.store(true, std::memory_order::relaxed); - return; - } + bWasStoppedOnError.store(true, std::memory_order_relaxed); + TaskflowExecutionFuture.cancel(); + } + else + { + // TODO: log error "Trying to cancel taskflow execution when it is not started" } - ).name("Renderer Tick Task"); + }; - tf::Task SwapErrorCheckTask = MainTaskFlow.emplace(ErrorCheckLambda) - .name("Swap Error Checking Task"); + tf::Taskflow RenderTaskFlow {}; + if (!FillRenderTaskflow(RenderTaskFlow, StopOnError)) + return false; + + tf::Task RendererTickTask = MainTaskFlow.composed_of(RenderTaskFlow).name("Renderer Tick Task"); tf::Task SwapTask = MainTaskFlow.emplace( [&]() @@ -175,23 +141,61 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::Tick(float DeltaTi { // TODO: add error log - bHasError.store(true, std::memory_order::relaxed); + throw Runtime::TaskFlowEx::TaskFailedException{}; } } ).name("Window Swap Task"); - // dead-end task. can be used for canceling the task flow execution - tf::Task EndTask = MainTaskFlow.emplace([](){}).name("Application Tick End Task"); - // Allow render tick task to go straight to end task in case of an error - RenderTickTask.precede(RenderErrorCheckTask); - RenderErrorCheckTask.precede(SwapTask, EndTask); - SwapTask.precede(SwapErrorCheckTask); - SwapErrorCheckTask.precede(EndTask); + RendererTickTask.precede(SwapTask); + + try + { + TaskflowExecutionFuture = TfExecutor->run(MainTaskFlow); + TaskflowExecutionFuture.wait(); + } + catch (const Runtime::TaskFlowEx::TaskFailedException&) + { + // TODO: add error log "Application tick failed. Taskflow task failed." + return false; + } + + return true; +} + +bool krendrr::Examples::SimpleDeferredRendering::Application::FillRenderTaskflow(tf::Taskflow& Taskflow, const std::function& ErrorStop) +{ + const glm::ivec2 WindowSize = Window->GetSize(); + const Runtime::Application::Core::Window::WindowRenderData RenderData = Window->GetCurrentRenderTargetView(); + + const bool bRenderDataSetSuccess = SceneView.SetRenderData( + { + RenderData.WindowRenderTarget, + RenderData.Handle, + D3D12_RESOURCE_STATE_PRESENT + }, { + 0, + 0, + WindowSize.x, + WindowSize.y + } + ); + + if (!bRenderDataSetSuccess) + return false; - TfExecutor->run(MainTaskFlow).wait(); + std::array Views = { + SceneView + }; - return !bHasError.load(std::memory_order::relaxed); + if (!Renderer->Render(Scene.get(), Views, Taskflow, ErrorStop)) + { + // TODO: add error log + + return false; + } + + return true; } bool krendrr::Examples::SimpleDeferredRendering::Application::Shutdown() diff --git a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h index a059328..74e0bdf 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h +++ b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h @@ -1,12 +1,13 @@ #pragma once +#include #include #include namespace tf { class Executor; - class FlowBuilder; + class Taskflow; } namespace krendrr::Runtime::RenderApi::Core @@ -29,8 +30,6 @@ namespace krendrr::Runtime::Renderer::Core * * Renderer may hold data between render calls, e.g. it can keep multiple * GBuffers between render calls when rendering into multiple scene views at the same time. - * - * */ class Renderer { @@ -39,10 +38,12 @@ namespace krendrr::Runtime::Renderer::Core virtual bool Initialize(std::shared_ptr NewRenderApi, std::shared_ptr NewTfExecutor) = 0; /** - * Use FlowBuilder to create task graphs (simplified render graph) and run your passes in parallel when needed. - * FlowBuilder tasks are going to be executed right after this call if it has returned true. + * Use Taskflow to create task graphs (simplified render graph) and run your passes in parallel when needed. + * Provided taskflow is usually composed into some high-level taskflow. + * + * ErrorStop can be called from Taskflow tasks to actually request a stop of taskflow execution in case of an error. */ - virtual bool Render(const Scene* Scene, const std::span& SceneViews, tf::FlowBuilder& FlowBuilder) = 0; + virtual bool Render(const Scene* Scene, const std::span& SceneViews, tf::Taskflow& Taskflow, const std::function& ErrorStop) = 0; virtual bool Shutdown() = 0; diff --git a/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h index 6ad6c75..2b4aa5b 100644 --- a/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h +++ b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h @@ -14,7 +14,7 @@ namespace krendrr::Runtime::Renderer::Deferred bool Initialize(std::shared_ptr NewRenderApi, std::shared_ptr NewTfExecutor) override; - bool Render(const Core::Scene* Scene, const std::span& SceneViews, tf::FlowBuilder& FlowBuilder) override; + bool Render(const Core::Scene* Scene, const std::span& SceneViews, tf::Taskflow& Taskflow, const std::function& ErrorStop) override; bool Shutdown() override; diff --git a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp index c10b96c..bb99558 100644 --- a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp +++ b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp @@ -61,7 +61,7 @@ bool DeferredRenderer::Initialize(std::shared_ptr Ne return true; } -bool DeferredRenderer::Render(const Core::Scene* Scene, const std::span& SceneViews, tf::FlowBuilder& FlowBuilder) +bool DeferredRenderer::Render(const Core::Scene* Scene, const std::span& SceneViews, tf::Taskflow& Taskflow, const std::function& ErrorStop) { NVTX3_FUNC_RANGE(); @@ -73,9 +73,15 @@ bool DeferredRenderer::Render(const Core::Scene* Scene, const std::span Date: Wed, 8 Oct 2025 17:30:57 +0300 Subject: [PATCH 08/13] Start refactoring renderer into composable tasking --- .../SimpleDeferredRendering/Application.h | 2 +- .../DeferredRendering/Source/Application.cpp | 31 +--- .../Include/Runtime/Renderer/Core/Renderer.h | 2 +- .../Renderer/Deferred/DeferredRenderer.h | 16 +- .../Deferred/Source/DeferredRenderer.cpp | 140 ++++++++++++------ .../TfExecutorBuilder/TaskFailedException.h | 45 ++++++ 6 files changed, 160 insertions(+), 76 deletions(-) create mode 100644 Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TaskFailedException.h diff --git a/Source/Examples/DeferredRendering/Include/Examples/SimpleDeferredRendering/Application.h b/Source/Examples/DeferredRendering/Include/Examples/SimpleDeferredRendering/Application.h index 1b4ee75..8e9d701 100644 --- a/Source/Examples/DeferredRendering/Include/Examples/SimpleDeferredRendering/Application.h +++ b/Source/Examples/DeferredRendering/Include/Examples/SimpleDeferredRendering/Application.h @@ -50,7 +50,7 @@ namespace krendrr::Examples::SimpleDeferredRendering bool InitializeSceneViewAndCamera(); - bool FillRenderTaskflow(tf::Taskflow& Taskflow, const std::function& ErrorStop); + bool FillRenderTaskflow(tf::Taskflow& Taskflow); }; } diff --git a/Source/Examples/DeferredRendering/Source/Application.cpp b/Source/Examples/DeferredRendering/Source/Application.cpp index 2dde937..9f7d4be 100644 --- a/Source/Examples/DeferredRendering/Source/Application.cpp +++ b/Source/Examples/DeferredRendering/Source/Application.cpp @@ -113,26 +113,13 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::Tick(float DeltaTi tf::Taskflow MainTaskFlow {}; - std::atomic_bool bWasStoppedOnError {}; - tf::Future TaskflowExecutionFuture {}; - auto StopOnError = [&bWasStoppedOnError, &TaskflowExecutionFuture]() - { - if (TaskflowExecutionFuture.valid()) - { - bWasStoppedOnError.store(true, std::memory_order_relaxed); - TaskflowExecutionFuture.cancel(); - } - else - { - // TODO: log error "Trying to cancel taskflow execution when it is not started" - } - }; - tf::Taskflow RenderTaskFlow {}; - if (!FillRenderTaskflow(RenderTaskFlow, StopOnError)) + if (!FillRenderTaskflow(RenderTaskFlow)) return false; - tf::Task RendererTickTask = MainTaskFlow.composed_of(RenderTaskFlow).name("Renderer Tick Task"); + tf::Task RendererTickTask = MainTaskFlow + .composed_of(RenderTaskFlow) + .name("Renderer Tick Task"); tf::Task SwapTask = MainTaskFlow.emplace( [&]() @@ -140,8 +127,7 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::Tick(float DeltaTi if (!Window->Swap()) { // TODO: add error log - - throw Runtime::TaskFlowEx::TaskFailedException{}; + Runtime::TaskFlowEx::CancelCurrentTaskflow(); } } ).name("Window Swap Task"); @@ -151,8 +137,7 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::Tick(float DeltaTi try { - TaskflowExecutionFuture = TfExecutor->run(MainTaskFlow); - TaskflowExecutionFuture.wait(); + TfExecutor->run(MainTaskFlow).wait(); } catch (const Runtime::TaskFlowEx::TaskFailedException&) { @@ -163,7 +148,7 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::Tick(float DeltaTi return true; } -bool krendrr::Examples::SimpleDeferredRendering::Application::FillRenderTaskflow(tf::Taskflow& Taskflow, const std::function& ErrorStop) +bool krendrr::Examples::SimpleDeferredRendering::Application::FillRenderTaskflow(tf::Taskflow& Taskflow) { const glm::ivec2 WindowSize = Window->GetSize(); const Runtime::Application::Core::Window::WindowRenderData RenderData = Window->GetCurrentRenderTargetView(); @@ -188,7 +173,7 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::FillRenderTaskflow SceneView }; - if (!Renderer->Render(Scene.get(), Views, Taskflow, ErrorStop)) + if (!Renderer->Render(Scene.get(), Views, Taskflow)) { // TODO: add error log diff --git a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h index 74e0bdf..a3ca780 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h +++ b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h @@ -43,7 +43,7 @@ namespace krendrr::Runtime::Renderer::Core * * ErrorStop can be called from Taskflow tasks to actually request a stop of taskflow execution in case of an error. */ - virtual bool Render(const Scene* Scene, const std::span& SceneViews, tf::Taskflow& Taskflow, const std::function& ErrorStop) = 0; + virtual bool Render(const Scene* Scene, const std::span& SceneViews, tf::Taskflow& Taskflow) = 0; virtual bool Shutdown() = 0; diff --git a/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h index 2b4aa5b..4eefd06 100644 --- a/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h +++ b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h @@ -5,6 +5,7 @@ #include "Runtime/Renderer/Core/Renderer.h" #include "Runtime/RenderApi/Core/Resources/StaticMesh.h" #include "Runtime/Renderer/Core/Scene/Objects/TexturedStaticMesh.h" +#include "taskflow/core/taskflow.hpp" namespace krendrr::Runtime::Renderer::Deferred { @@ -14,7 +15,7 @@ namespace krendrr::Runtime::Renderer::Deferred bool Initialize(std::shared_ptr NewRenderApi, std::shared_ptr NewTfExecutor) override; - bool Render(const Core::Scene* Scene, const std::span& SceneViews, tf::Taskflow& Taskflow, const std::function& ErrorStop) override; + bool Render(const Core::Scene* Scene, const std::span& SceneViews, tf::Taskflow& Taskflow) override; bool Shutdown() override; @@ -23,6 +24,11 @@ namespace krendrr::Runtime::Renderer::Deferred std::shared_ptr RenderApi {}; std::shared_ptr TfExecutor {}; + std::vector Taskflows {}; + // Next call to this function may invalidate previous return values + tf::Taskflow* AllocateTaskFlow(); + void ClearTaskFlows(); + std::shared_ptr FullscreenQuadMesh {}; std::shared_ptr SphereMesh {}; bool InitBasicMeshes(); @@ -122,9 +128,11 @@ namespace krendrr::Runtime::Renderer::Deferred FrameData FrameData {}; - bool UpdateFrameDataConstantBuffer(const Core::Scene* Scene, const Core::SceneView& SceneView); - bool UpdateTexturedMeshConstantBuffers(const Core::Scene* Scene); - bool UpdatePointLightConstantBuffers(const Core::Scene* Scene); + tf::Taskflow* UpdateFrameDataConstantBuffer(const Core::Scene* Scene, const Core::SceneView& SceneView); + + tf::Taskflow* UpdateTexturedMeshConstantBuffers(const Core::Scene* Scene); + + tf::Taskflow* UpdatePointLightConstantBuffers(const Core::Scene* Scene); struct GeometryPassData { diff --git a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp index bb99558..45e2135 100644 --- a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp +++ b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp @@ -11,6 +11,8 @@ #include "Runtime/RenderApi/Core/Builders/PsoBuilder.h" #include "Runtime/RenderApi/Core/Builders/RootSigBuilder.h" #include "Runtime/Renderer/Core/Scene/Lights/PointLight.h" +#include "Runtime/TfExecutorBuilder/TaskFailedException.h" +#include "taskflow/algorithm/for_each.hpp" namespace krendrr::Runtime::Renderer::Deferred { @@ -61,7 +63,7 @@ bool DeferredRenderer::Initialize(std::shared_ptr Ne return true; } -bool DeferredRenderer::Render(const Core::Scene* Scene, const std::span& SceneViews, tf::Taskflow& Taskflow, const std::function& ErrorStop) +bool DeferredRenderer::Render(const Core::Scene* Scene, const std::span& SceneViews, tf::Taskflow& Taskflow) { NVTX3_FUNC_RANGE(); @@ -71,22 +73,43 @@ bool DeferredRenderer::Render(const Core::Scene* Scene, const std::spanemplace([Scene, SceneView, this]() { - if (!BuildConstantBuffer(*RenderApi, FrameData.ConstantBuffer, FrameData.CpuSrvHeap, L"Frame Data Constant Buffer")) - return false; - } + // Create buffer if not created + if (FrameData.ConstantBuffer == nullptr) + { + if (!BuildConstantBuffer(*RenderApi, FrameData.ConstantBuffer, FrameData.CpuSrvHeap, L"Frame Data Constant Buffer")) + TaskFlowEx::CancelCurrentTaskflow(); + } - // Update buffer - - ConstBuff_Frame* Buffer {}; - CHECKED_S(FrameData.ConstantBuffer->Map(0, nullptr, reinterpret_cast(&Buffer))) - - *Buffer = { - .ViewMatrix = SceneView.GetViewMatrix(), - .ProjectionMatrix = SceneView.GetProjectionMatrix(), - .bHasAmbientLight = Scene->HasAmbientLight(), - .AmbientColor = Scene->GetAmbientLightData().Color, - .AmbientIntensity = Scene->GetAmbientLightData().Intensity, - .DirectionalColor = Scene->GetDirectionalLightData().Color, - .bHasDirectionalLight = Scene->HasDirectionalLight(), - .DirectionalDir = Scene->GetDirectionalLightData().Direction, - .DirectionalIntensity = Scene->GetDirectionalLightData().Intensity, - .CameraPosition = SceneView.GetPosition(), - .ViewportSize = SceneView.GetViewportSize(), - }; + // Update buffer + + ConstBuff_Frame* Buffer {}; + CHECKED_TF_S(FrameData.ConstantBuffer->Map(0, nullptr, reinterpret_cast(&Buffer))) + + *Buffer = { + .ViewMatrix = SceneView.GetViewMatrix(), + .ProjectionMatrix = SceneView.GetProjectionMatrix(), + .bHasAmbientLight = Scene->HasAmbientLight(), + .AmbientColor = Scene->GetAmbientLightData().Color, + .AmbientIntensity = Scene->GetAmbientLightData().Intensity, + .DirectionalColor = Scene->GetDirectionalLightData().Color, + .bHasDirectionalLight = Scene->HasDirectionalLight(), + .DirectionalDir = Scene->GetDirectionalLightData().Direction, + .DirectionalIntensity = Scene->GetDirectionalLightData().Intensity, + .CameraPosition = SceneView.GetPosition(), + .ViewportSize = SceneView.GetViewportSize(), + }; - FrameData.ConstantBuffer->Unmap(0, nullptr); + FrameData.ConstantBuffer->Unmap(0, nullptr); + }); - return true; + return Taskflow; } -bool DeferredRenderer::UpdateTexturedMeshConstantBuffers(const Core::Scene* Scene) +tf::Taskflow* DeferredRenderer::UpdateTexturedMeshConstantBuffers(const Core::Scene* Scene) { NVTX3_FUNC_RANGE(); - for (auto& TexturedMesh : Scene->GetTexturedMeshes()) + auto* Taskflow = AllocateTaskFlow(); + + auto TexturedMeshes = Scene->GetTexturedMeshes(); + Taskflow->for_each(TexturedMeshes.begin(), TexturedMeshes.end(), [&](std::shared_ptr TexturedMesh) { if (!TexturedMesh->UpdateConstantBuffer(*RenderApi)) - return false; - } + TaskFlowEx::CancelCurrentTaskflow(); + }); - return true; + return Taskflow; } -bool DeferredRenderer::UpdatePointLightConstantBuffers(const Core::Scene* Scene) +tf::Taskflow* DeferredRenderer::UpdatePointLightConstantBuffers(const Core::Scene* Scene) { NVTX3_FUNC_RANGE(); - for (auto& PointLight : Scene->GetPointLights()) + auto* Taskflow = AllocateTaskFlow(); + + Taskflow->emplace([Scene, this]() { - if (!PointLight->UpdateConstantBuffer(*RenderApi.get())) - return false; - } + for (auto& PointLight : Scene->GetPointLights()) + { + if (!PointLight->UpdateConstantBuffer(*RenderApi.get())) + TaskFlowEx::CancelCurrentTaskflow(); + } + }); - return true; + return Taskflow; } bool DeferredRenderer::InitializeGeometryPass() @@ -1494,6 +1530,16 @@ bool DeferredRenderer::Shutdown() return WaitDirectQueue(); } +tf::Taskflow* DeferredRenderer::AllocateTaskFlow() +{ + return &Taskflows.emplace_back(); +} + +void DeferredRenderer::ClearTaskFlows() +{ + Taskflows.clear(); +} + bool DeferredRenderer::InitBasicMeshes() { // Load fullscreen Quad diff --git a/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TaskFailedException.h b/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TaskFailedException.h new file mode 100644 index 0000000..9533157 --- /dev/null +++ b/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TaskFailedException.h @@ -0,0 +1,45 @@ +#pragma once + +#include + +namespace krendrr::Runtime::TaskFlowEx +{ + class TaskFailedException : public std::exception + { + public: + [[nodiscard]] const char* what() const override + { + return "Taskflow was cancelled"; + } + }; + + inline void CancelCurrentTaskflow() + { + throw TaskFailedException(); + } +} + +// TODO: add error log +/** + * Checks if api call was successful. If not, logs error and cancels current taskflow + */ +#define CHECKED_TF(ApiCall, ErrorMessage) \ +{ \ +if(FAILED(ApiCall)) \ +{ \ + __debugbreak(); \ + krendrr::Runtime::TaskFlowEx::CancelCurrentTaskflow(); \ +} \ +} \ + +/** + * Checks if api call was successful. If not, cancels current taskflow + */ +#define CHECKED_TF_S(ApiCall) \ +{ \ +if(FAILED(ApiCall)) \ +{ \ + __debugbreak(); \ + krendrr::Runtime::TaskFlowEx::CancelCurrentTaskflow(); \ +} \ +} \ \ No newline at end of file From e809954b004d660b2f38ccdaf540d1b074aa1494 Mon Sep 17 00:00:00 2001 From: Kirill Markin Date: Wed, 8 Oct 2025 18:59:28 +0300 Subject: [PATCH 09/13] High level jobification using subflow tasking --- .../Include/Runtime/Renderer/Core/Renderer.h | 4 +- .../Renderer/Deferred/DeferredRenderer.h | 55 +- .../Deferred/Source/DeferredRenderer.cpp | 1859 ++++++++--------- .../TfExecutorBuilder/TaskFailedException.h | 20 +- 4 files changed, 971 insertions(+), 967 deletions(-) diff --git a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h index a3ca780..8916e74 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h +++ b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h @@ -7,7 +7,7 @@ namespace tf { class Executor; - class Taskflow; + class FlowBuilder; } namespace krendrr::Runtime::RenderApi::Core @@ -43,7 +43,7 @@ namespace krendrr::Runtime::Renderer::Core * * ErrorStop can be called from Taskflow tasks to actually request a stop of taskflow execution in case of an error. */ - virtual bool Render(const Scene* Scene, const std::span& SceneViews, tf::Taskflow& Taskflow) = 0; + virtual bool Render(const Scene* Scene, const std::span& SceneViews, tf::FlowBuilder& FlowBuilder) = 0; virtual bool Shutdown() = 0; diff --git a/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h index 4eefd06..b80c677 100644 --- a/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h +++ b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h @@ -15,7 +15,7 @@ namespace krendrr::Runtime::Renderer::Deferred bool Initialize(std::shared_ptr NewRenderApi, std::shared_ptr NewTfExecutor) override; - bool Render(const Core::Scene* Scene, const std::span& SceneViews, tf::Taskflow& Taskflow) override; + bool Render(const Core::Scene* Scene, const std::span& SceneViews, tf::FlowBuilder& FlowBuilder) override; bool Shutdown() override; @@ -24,11 +24,6 @@ namespace krendrr::Runtime::Renderer::Deferred std::shared_ptr RenderApi {}; std::shared_ptr TfExecutor {}; - std::vector Taskflows {}; - // Next call to this function may invalidate previous return values - tf::Taskflow* AllocateTaskFlow(); - void ClearTaskFlows(); - std::shared_ptr FullscreenQuadMesh {}; std::shared_ptr SphereMesh {}; bool InitBasicMeshes(); @@ -42,12 +37,16 @@ namespace krendrr::Runtime::Renderer::Deferred PrePostRenderData PrePostRenderData {}; bool InitPrePostRender(); - bool PreRender(const Core::Scene* Scene, const Core::SceneView& SceneView); - bool PostRender(const Core::SceneView& SceneView); + + tf::Task PreRender(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder); + + tf::Task PostRender(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder); Microsoft::WRL::ComPtr FrameFence {}; uint64_t FrameFenceValue {}; + tf::Task WaitDirectQueueTask(tf::FlowBuilder& FlowBuilder); + bool WaitDirectQueue(); const std::array& GetCommonStaticSamplers(); @@ -87,9 +86,11 @@ namespace krendrr::Runtime::Renderer::Deferred GBuffer GBuffer {}; // Called every time we need to update GBuffer, so it has same size as scene view - bool InitGBufferForView(const Core::SceneView& SceneView); - bool TransitionGBufferFromRenderTargetToReadState(); - bool TransitionGBufferFromReadToRenderTargetState(); + tf::Task InitGBufferForView(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder); + + tf::Task TransitionGBufferFromRenderTargetToReadState(tf::FlowBuilder& FlowBuilder); + + tf::Task TransitionGBufferFromReadToRenderTargetState(tf::FlowBuilder& FlowBuilder); // Make sure our C++ <-> HLSL types have same sizes static_assert(sizeof(float) == 4); @@ -128,11 +129,11 @@ namespace krendrr::Runtime::Renderer::Deferred FrameData FrameData {}; - tf::Taskflow* UpdateFrameDataConstantBuffer(const Core::Scene* Scene, const Core::SceneView& SceneView); + tf::Task UpdateFrameDataConstantBuffer(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder); - tf::Taskflow* UpdateTexturedMeshConstantBuffers(const Core::Scene* Scene); + tf::Task UpdateTexturedMeshConstantBuffers(const Core::Scene* Scene, tf::FlowBuilder& FlowBuilder); - tf::Taskflow* UpdatePointLightConstantBuffers(const Core::Scene* Scene); + tf::Task UpdatePointLightConstantBuffers(const Core::Scene* Scene, tf::FlowBuilder& FlowBuilder); struct GeometryPassData { @@ -156,7 +157,8 @@ namespace krendrr::Runtime::Renderer::Deferred GeometryPassData GeometryPassData {}; bool InitializeGeometryPass(); - bool GeometryPass(const Core::Scene* Scene, const Core::SceneView& SceneView); + + tf::Task GeometryPass(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder); struct LightPassData { @@ -176,9 +178,12 @@ namespace krendrr::Runtime::Renderer::Deferred LightPassData LightPassData {}; bool InitLightPass(); - bool PrepareLightPassData(const Core::SceneView& SceneView); - bool TransitionLightPassFromRenderTargetToReadState(); - bool TransitionLightPassFromReadToRenderTargetState(); + + tf::Task PrepareLightPassData(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder); + + tf::Task TransitionLightPassFromRenderTargetToReadState(tf::FlowBuilder& FlowBuilder); + + tf::Task TransitionLightPassFromReadToRenderTargetState(tf::FlowBuilder& FlowBuilder); struct AmbientDirectionalLightPassData { @@ -193,7 +198,8 @@ namespace krendrr::Runtime::Renderer::Deferred AmbientDirectionalLightPassData AmbientDirectionalLightPassData {}; bool InitAmbientDirectionalLightPass(); - bool AmbientDirectionalLightPass(const Core::SceneView& SceneView); + + tf::Task AmbientDirectionalLightPass(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder); struct PointLightShadowCubeMapData { @@ -206,7 +212,8 @@ namespace krendrr::Runtime::Renderer::Deferred PointLightShadowCubeMapData PointLightShadowCubeMapData {}; bool InitPointLightShadowCubeMapPass(); - bool PointLightShadowCubeMapsPass(const Core::Scene* Scene); + + tf::Task PointLightShadowCubeMapsPass(const Core::Scene* Scene, tf::FlowBuilder& FlowBuilder); struct PointLightVolumePassData { @@ -227,7 +234,8 @@ namespace krendrr::Runtime::Renderer::Deferred PointLightVolumePassData PointLightVolumePassData{}; bool InitPointLightVolumePass(); - bool PointLightVolumesPass(const Core::Scene* Scene, const Core::SceneView& SceneView); + + tf::Task PointLightVolumesPass(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder); struct PostProcessingPassData { @@ -242,7 +250,10 @@ namespace krendrr::Runtime::Renderer::Deferred PostProcessingPassData PostProcessingPassData {}; bool InitPostProcessingPass(); - bool PostProcessingPass(const Core::SceneView& SceneView); + + tf::Task PostProcessingPass(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder); + + tf::Task PostRenderPasses(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder); }; } diff --git a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp index 45e2135..4247f4d 100644 --- a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp +++ b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp @@ -63,7 +63,7 @@ bool DeferredRenderer::Initialize(std::shared_ptr Ne return true; } -bool DeferredRenderer::Render(const Core::Scene* Scene, const std::span& SceneViews, tf::Taskflow& Taskflow) +bool DeferredRenderer::Render(const Core::Scene* Scene, const std::span& SceneViews, tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); @@ -73,123 +73,80 @@ bool DeferredRenderer::Render(const Core::Scene* Scene, const std::span SceneViewTasks {}; + SceneViewTasks.reserve(SceneViews.size()); for (const Core::SceneView& SceneView : SceneViews) { - auto UpdateFrameDataConstantBufferTask = CreateTask([&, this]() - { - return UpdateFrameDataConstantBuffer(Scene, SceneView); - }).name("UpdateFrameDataConstantBuffer"); - - auto UpdateTexturedMeshConstantBuffersTask = CreateTask([&, this]() - { - return UpdateTexturedMeshConstantBuffers(Scene); - }).name("UpdateTexturedMeshConstantBuffers"); - - auto UpdatePointLightConstantBuffersTask = CreateTask([&, this]() - { - return UpdatePointLightConstantBuffers(Scene); - }).name("UpdatePointLightConstantBuffers"); - - if (bError) + auto SceneViewTask = FlowBuilder.emplace([Scene, SceneView, this](tf::Subflow& Subflow) { - // TODO: log error "Error during taskflow creation in renderer" - return false; - } - - if (!PreRender(Scene, SceneView)) - return false; - - if (!InitGBufferForView(SceneView)) - return false; - - - - - if (!GeometryPass(Scene, SceneView)) - return false; - - - - - - if (!TransitionGBufferFromRenderTargetToReadState()) - return false; - - if (!PrepareLightPassData(SceneView)) - return false; - - - - - if (!AmbientDirectionalLightPass(SceneView)) - return false; - - - - // с самого начала, и до point light volumes pass - if (!PointLightShadowCubeMapsPass(Scene)) - return false; - - if (!PointLightVolumesPass(Scene, SceneView)) - return false; - - - - - - if (!TransitionLightPassFromRenderTargetToReadState()) - return false; - - - - - - if (!PostProcessingPass(SceneView)) - return false; + auto PreRenderTask = Subflow.placeholder() + .succeed( + UpdateFrameDataConstantBuffer(Scene, SceneView, Subflow), + UpdateTexturedMeshConstantBuffers(Scene, Subflow), + UpdatePointLightConstantBuffers(Scene, Subflow), + PreRender(Scene, SceneView, Subflow), + InitGBufferForView(SceneView, Subflow) + .precede( + PrepareLightPassData(SceneView, Subflow) + ) + ); - if (!TransitionLightPassFromReadToRenderTargetState()) - return false; + auto PointLightShadowCubeMapPassTask = PointLightShadowCubeMapsPass(Scene, Subflow) + .succeed( + PreRenderTask + ); - if (!PostRender(SceneView)) - return false; + auto GeometryPassTask = GeometryPass(Scene, SceneView, Subflow) + .succeed( + PreRenderTask + ); - if (!TransitionGBufferFromReadToRenderTargetState()) - return false; + auto GBufferToReadStateTask = TransitionGBufferFromRenderTargetToReadState(Subflow) + .succeed(GeometryPassTask); + auto AmbientDirectionalLightPassTask = AmbientDirectionalLightPass(SceneView, Subflow) + .succeed( + GBufferToReadStateTask, + GeometryPassTask + ); + auto PointLightVolumePass = PointLightVolumesPass(Scene, SceneView, Subflow) + .succeed( + AmbientDirectionalLightPassTask, + GeometryPassTask, + GBufferToReadStateTask, + PointLightShadowCubeMapPassTask + ); + auto PostRenderPassesTask = PostRenderPasses(SceneView, Subflow) + .succeed( + PointLightVolumePass, + AmbientDirectionalLightPassTask + ); + WaitDirectQueueTask(Subflow) + .succeed( + PostRenderPassesTask + ); + }).name("SceneView Iteration Task"); - if (!WaitDirectQueue()) - return false; + SceneViewTasks.emplace_back(SceneViewTask); } + // Make sure all scene views are not rendered in parallel + // since we only have one copy of GBuffer and other resources + FlowBuilder.linearize(SceneViewTasks); + return true; } -tf::Taskflow* DeferredRenderer::UpdateFrameDataConstantBuffer(const Core::Scene* Scene, const Core::SceneView& SceneView) +tf::Task DeferredRenderer::UpdateFrameDataConstantBuffer(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); - auto* Taskflow = AllocateTaskFlow(); - - Taskflow->emplace([Scene, SceneView, this]() + return FlowBuilder.emplace([Scene, SceneView, this]() { // Create buffer if not created if (FrameData.ConstantBuffer == nullptr) @@ -219,42 +176,36 @@ tf::Taskflow* DeferredRenderer::UpdateFrameDataConstantBuffer(const Core::Scene* FrameData.ConstantBuffer->Unmap(0, nullptr); }); - - return Taskflow; } -tf::Taskflow* DeferredRenderer::UpdateTexturedMeshConstantBuffers(const Core::Scene* Scene) +tf::Task DeferredRenderer::UpdateTexturedMeshConstantBuffers(const Core::Scene* Scene, tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); - auto* Taskflow = AllocateTaskFlow(); - auto TexturedMeshes = Scene->GetTexturedMeshes(); - Taskflow->for_each(TexturedMeshes.begin(), TexturedMeshes.end(), [&](std::shared_ptr TexturedMesh) - { - if (!TexturedMesh->UpdateConstantBuffer(*RenderApi)) - TaskFlowEx::CancelCurrentTaskflow(); - }); - return Taskflow; + return FlowBuilder.for_each(TexturedMeshes.begin(), TexturedMeshes.end(), + [&](const auto& TexturedMesh) + { + if (!TexturedMesh->UpdateConstantBuffer(*RenderApi)) + TaskFlowEx::CancelCurrentTaskflow(); + } + ); } -tf::Taskflow* DeferredRenderer::UpdatePointLightConstantBuffers(const Core::Scene* Scene) +tf::Task DeferredRenderer::UpdatePointLightConstantBuffers(const Core::Scene* Scene, tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); - auto* Taskflow = AllocateTaskFlow(); + auto PointLights = Scene->GetPointLights(); - Taskflow->emplace([Scene, this]() - { - for (auto& PointLight : Scene->GetPointLights()) + return FlowBuilder.for_each(PointLights.begin(), PointLights.end(), + [Scene, this](const auto& PointLight) { if (!PointLight->UpdateConstantBuffer(*RenderApi.get())) TaskFlowEx::CancelCurrentTaskflow(); } - }); - - return Taskflow; + ); } bool DeferredRenderer::InitializeGeometryPass() @@ -339,218 +290,219 @@ bool DeferredRenderer::InitializeGeometryPass() return true; } -bool DeferredRenderer::GeometryPass(const Core::Scene* Scene, const Core::SceneView& SceneView) +tf::Task DeferredRenderer::GeometryPass(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); - const unsigned RtvHandleIncrement = RenderApi->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); - const unsigned SrvHandleIncrement = RenderApi->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - - std::array RtvHandles {}; - for (int i = 0; i < GBuffer.TEXTURES_COUNT; ++i) + return FlowBuilder.emplace([Scene, SceneView, this]() { - RtvHandles[i] = CD3DX12_CPU_DESCRIPTOR_HANDLE{GBuffer.CpuRtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), i, RtvHandleIncrement}; - } - - const D3D12_CPU_DESCRIPTOR_HANDLE DsvHandle = GBuffer.CpuDsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); + const unsigned RtvHandleIncrement = RenderApi->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + const unsigned SrvHandleIncrement = RenderApi->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - auto& CommandAllocator = GeometryPassData.DrawCommandAllocator; - auto& CommandList = GeometryPassData.DrawCommandList; + std::array RtvHandles {}; + for (int i = 0; i < GBuffer.TEXTURES_COUNT; ++i) + { + RtvHandles[i] = CD3DX12_CPU_DESCRIPTOR_HANDLE{GBuffer.CpuRtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), i, RtvHandleIncrement}; + } - auto ExecuteCommandList = [this, CommandList]() -> bool - { - CHECKED_S(CommandList->Close()) + const D3D12_CPU_DESCRIPTOR_HANDLE DsvHandle = GBuffer.CpuDsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); - ID3D12CommandList* CommandLists[] = {CommandList.Get()}; + auto& CommandAllocator = GeometryPassData.DrawCommandAllocator; + auto& CommandList = GeometryPassData.DrawCommandList; - RenderApi->GetDirectQueue() - ->ExecuteCommandLists(1, CommandLists); + auto ExecuteCommandList = [this, CommandList]() -> bool + { + CHECKED_S(CommandList->Close()) - return true; - }; + ID3D12CommandList* CommandLists[] = {CommandList.Get()}; - auto ResetCommandList = [this, &CommandAllocator, &CommandList, &SceneView, &RtvHandles, &DsvHandle]() -> bool - { - CHECKED_S(CommandAllocator->Reset()); - CHECKED_S(CommandList->Reset(CommandAllocator.Get(), GeometryPassData.PipelineState.Get())); + RenderApi->GetDirectQueue() + ->ExecuteCommandLists(1, CommandLists); - // Setup pipeline + return true; + }; - CommandList->SetGraphicsRootSignature(GeometryPassData.RootSignature.Get()); - CommandList->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + auto ResetCommandList = [this, &CommandAllocator, &CommandList, &SceneView, &RtvHandles, &DsvHandle]() -> bool + { + CHECKED_S(CommandAllocator->Reset()); + CHECKED_S(CommandList->Reset(CommandAllocator.Get(), GeometryPassData.PipelineState.Get())); - const D3D12_VIEWPORT Viewport = SceneView.GetD3dViewport(); - CommandList->RSSetViewports(1, &Viewport); + // Setup pipeline - static const D3D12_RECT ScissorRect = CD3DX12_RECT(0, 0, LONG_MAX, LONG_MAX); - CommandList->RSSetScissorRects(1, &ScissorRect); + CommandList->SetGraphicsRootSignature(GeometryPassData.RootSignature.Get()); + CommandList->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - CommandList->OMSetRenderTargets( - GBuffer.TEXTURES_COUNT, - RtvHandles.data(), - false, - &DsvHandle - ); + const D3D12_VIEWPORT Viewport = SceneView.GetD3dViewport(); + CommandList->RSSetViewports(1, &Viewport); - CommandList->SetDescriptorHeaps(1, GeometryPassData.GpuDescriptorHeap.GetAddressOf()); + static const D3D12_RECT ScissorRect = CD3DX12_RECT(0, 0, LONG_MAX, LONG_MAX); + CommandList->RSSetScissorRects(1, &ScissorRect); - return true; - }; + CommandList->OMSetRenderTargets( + GBuffer.TEXTURES_COUNT, + RtvHandles.data(), + false, + &DsvHandle + ); - ResetCommandList(); + CommandList->SetDescriptorHeaps(1, GeometryPassData.GpuDescriptorHeap.GetAddressOf()); - for (auto& RtvHandle: RtvHandles) - { - constexpr static FLOAT ClearColor[] = {0.f, 0.f, 0.f, 1.f}; - CommandList->ClearRenderTargetView(RtvHandle, ClearColor, 0, nullptr); - } + return true; + }; - CommandList->ClearDepthStencilView( - GBuffer.CpuDsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, - 1.0f, - 0, - 0, - nullptr - ); + ResetCommandList(); - int DrawIndex = -1; - for (const std::shared_ptr& TexturedMesh : Scene->GetTexturedMeshes()) - { - nvtx3::scoped_range MeshIterationRange {"Mesh Iteration"}; + for (auto& RtvHandle: RtvHandles) + { + constexpr static FLOAT ClearColor[] = {0.f, 0.f, 0.f, 1.f}; + CommandList->ClearRenderTargetView(RtvHandle, ClearColor, 0, nullptr); + } - auto Mesh = TexturedMesh->GetMesh(); + CommandList->ClearDepthStencilView( + GBuffer.CpuDsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), + D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, + 1.0f, + 0, + 0, + nullptr + ); - // Make sure we have enough descriptors to draw this textured mesh + int DrawIndex = -1; + for (const std::shared_ptr& TexturedMesh : Scene->GetTexturedMeshes()) { - if (DrawIndex + 1 == GeometryPassData.PARALLEL_DRAWS_COUNT_ALLOWED) - { - if (!ExecuteCommandList()) - return false; + nvtx3::scoped_range MeshIterationRange {"Mesh Iteration"}; - WaitDirectQueue(); + auto Mesh = TexturedMesh->GetMesh(); - DrawIndex = -1; + // Make sure we have enough descriptors to draw this textured mesh + { + if (DrawIndex + 1 == GeometryPassData.PARALLEL_DRAWS_COUNT_ALLOWED) + { + if (!ExecuteCommandList()) + TaskFlowEx::CancelCurrentTaskflow(); - if (!ResetCommandList()) - return false; - } - DrawIndex += 1; - } + WaitDirectQueue(); - // Setup Mesh - { - D3D12_VERTEX_BUFFER_VIEW VertexBufferView = Mesh->GetVertexBufferView(); - CommandList->IASetVertexBuffers(0, 1, &VertexBufferView); + DrawIndex = -1; - if (Mesh->IsUsingIndices()) - { - D3D12_INDEX_BUFFER_VIEW IndexBufferView = Mesh->GetIndexBufferView(); - CommandList->IASetIndexBuffer(&IndexBufferView); + if (!ResetCommandList()) + TaskFlowEx::CancelCurrentTaskflow(); + } + DrawIndex += 1; } - else + + // Setup Mesh { - CommandList->IASetIndexBuffer(nullptr); - } - } + D3D12_VERTEX_BUFFER_VIEW VertexBufferView = Mesh->GetVertexBufferView(); + CommandList->IASetVertexBuffers(0, 1, &VertexBufferView); - // Prepare SRV descriptor heap - { - D3D12_CPU_DESCRIPTOR_HANDLE SourceHandles[GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT] = { - TexturedMesh->HasTexture(GeometryPassData.DIFFUSE_TEXTURE_NAME) - ? TexturedMesh->GetTexture(GeometryPassData.DIFFUSE_TEXTURE_NAME)->GetTextureHandle() - : CpuEmptyTextureHeap->GetCPUDescriptorHandleForHeapStart(), - - TexturedMesh->HasTexture(GeometryPassData.METALLIC_TEXTURE_NAME) - ? TexturedMesh->GetTexture(GeometryPassData.METALLIC_TEXTURE_NAME)->GetTextureHandle() - : CpuEmptyTextureHeap->GetCPUDescriptorHandleForHeapStart(), - - TexturedMesh->HasTexture(GeometryPassData.ROUGHNESS_TEXTURE_NAME) - ? TexturedMesh->GetTexture(GeometryPassData.ROUGHNESS_TEXTURE_NAME)->GetTextureHandle() - : CpuEmptyTextureHeap->GetCPUDescriptorHandleForHeapStart(), - - TexturedMesh->HasTexture(GeometryPassData.NORMAL_TEXTURE_NAME) - ? TexturedMesh->GetTexture(GeometryPassData.NORMAL_TEXTURE_NAME)->GetTextureHandle() - : CpuEmptyTextureHeap->GetCPUDescriptorHandleForHeapStart(), - - TexturedMesh->HasTexture(GeometryPassData.EMISSIVE_TEXTURE_NAME) - ? TexturedMesh->GetTexture(GeometryPassData.EMISSIVE_TEXTURE_NAME)->GetTextureHandle() - : CpuEmptyTextureHeap->GetCPUDescriptorHandleForHeapStart(), - }; + if (Mesh->IsUsingIndices()) + { + D3D12_INDEX_BUFFER_VIEW IndexBufferView = Mesh->GetIndexBufferView(); + CommandList->IASetIndexBuffer(&IndexBufferView); + } + else + { + CommandList->IASetIndexBuffer(nullptr); + } + } - D3D12_CPU_DESCRIPTOR_HANDLE DestinationHandles[GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT] = {}; - for (int i = 0; i < GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT; ++i) + // Prepare SRV descriptor heap { - DestinationHandles[i] = CD3DX12_CPU_DESCRIPTOR_HANDLE { - GeometryPassData.GpuDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - DrawIndex * static_cast(GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT) + i, - SrvHandleIncrement + D3D12_CPU_DESCRIPTOR_HANDLE SourceHandles[GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT] = { + TexturedMesh->HasTexture(GeometryPassData.DIFFUSE_TEXTURE_NAME) + ? TexturedMesh->GetTexture(GeometryPassData.DIFFUSE_TEXTURE_NAME)->GetTextureHandle() + : CpuEmptyTextureHeap->GetCPUDescriptorHandleForHeapStart(), + + TexturedMesh->HasTexture(GeometryPassData.METALLIC_TEXTURE_NAME) + ? TexturedMesh->GetTexture(GeometryPassData.METALLIC_TEXTURE_NAME)->GetTextureHandle() + : CpuEmptyTextureHeap->GetCPUDescriptorHandleForHeapStart(), + + TexturedMesh->HasTexture(GeometryPassData.ROUGHNESS_TEXTURE_NAME) + ? TexturedMesh->GetTexture(GeometryPassData.ROUGHNESS_TEXTURE_NAME)->GetTextureHandle() + : CpuEmptyTextureHeap->GetCPUDescriptorHandleForHeapStart(), + + TexturedMesh->HasTexture(GeometryPassData.NORMAL_TEXTURE_NAME) + ? TexturedMesh->GetTexture(GeometryPassData.NORMAL_TEXTURE_NAME)->GetTextureHandle() + : CpuEmptyTextureHeap->GetCPUDescriptorHandleForHeapStart(), + + TexturedMesh->HasTexture(GeometryPassData.EMISSIVE_TEXTURE_NAME) + ? TexturedMesh->GetTexture(GeometryPassData.EMISSIVE_TEXTURE_NAME)->GetTextureHandle() + : CpuEmptyTextureHeap->GetCPUDescriptorHandleForHeapStart(), }; - } - - UINT RangeSize[GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT] = { - 1, - 1, - 1, - 1, - 1 - }; - RenderApi->GetDevice() - ->CopyDescriptors( - GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT, - DestinationHandles, - RangeSize, - GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT, - SourceHandles, - RangeSize, - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV - ); - } + D3D12_CPU_DESCRIPTOR_HANDLE DestinationHandles[GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT] = {}; + for (int i = 0; i < GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT; ++i) + { + DestinationHandles[i] = CD3DX12_CPU_DESCRIPTOR_HANDLE { + GeometryPassData.GpuDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), + DrawIndex * static_cast(GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT) + i, + SrvHandleIncrement + }; + } - // Set root signature parameters - { - const CD3DX12_GPU_DESCRIPTOR_HANDLE TableHandle { - GeometryPassData.GpuDescriptorHeap->GetGPUDescriptorHandleForHeapStart(), - DrawIndex * static_cast(GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT), - SrvHandleIncrement - }; + UINT RangeSize[GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT] = { + 1, + 1, + 1, + 1, + 1 + }; - CommandList->SetGraphicsRootDescriptorTable(0, TableHandle); - CommandList->SetGraphicsRootConstantBufferView(1, FrameData.ConstantBuffer->GetGPUVirtualAddress()); - CommandList->SetGraphicsRootConstantBufferView(2, TexturedMesh->GetConstantBufferGpuAddress()); - } + RenderApi->GetDevice() + ->CopyDescriptors( + GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT, + DestinationHandles, + RangeSize, + GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT, + SourceHandles, + RangeSize, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV + ); + } - // Draw - { - const std::int32_t PrimitivesCount = Mesh->GetPrimitivesCount(); - if (Mesh->IsUsingIndices()) + // Set root signature parameters { - CommandList->DrawIndexedInstanced( - PrimitivesCount, - 1, - 0, - 0, - 0 - ); + const CD3DX12_GPU_DESCRIPTOR_HANDLE TableHandle { + GeometryPassData.GpuDescriptorHeap->GetGPUDescriptorHandleForHeapStart(), + DrawIndex * static_cast(GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT), + SrvHandleIncrement + }; + + CommandList->SetGraphicsRootDescriptorTable(0, TableHandle); + CommandList->SetGraphicsRootConstantBufferView(1, FrameData.ConstantBuffer->GetGPUVirtualAddress()); + CommandList->SetGraphicsRootConstantBufferView(2, TexturedMesh->GetConstantBufferGpuAddress()); } - else + + // Draw { - CommandList->DrawInstanced( - PrimitivesCount, - 1, - 0, - 0 - ); + const std::int32_t PrimitivesCount = Mesh->GetPrimitivesCount(); + if (Mesh->IsUsingIndices()) + { + CommandList->DrawIndexedInstanced( + PrimitivesCount, + 1, + 0, + 0, + 0 + ); + } + else + { + CommandList->DrawInstanced( + PrimitivesCount, + 1, + 0, + 0 + ); + } } } - } - - if (DrawIndex >= 0) - if (!ExecuteCommandList()) - return false; - return true; + if (DrawIndex >= 0) + if (!ExecuteCommandList()) + TaskFlowEx::CancelCurrentTaskflow(); + }); } bool DeferredRenderer::InitLightPass() @@ -582,124 +534,131 @@ bool DeferredRenderer::InitLightPass() return true; } -bool DeferredRenderer::PrepareLightPassData(const Core::SceneView& SceneView) +tf::Task DeferredRenderer::PrepareLightPassData(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); - const glm::ivec2 ViewportSize = SceneView.GetViewportSize(); + return FlowBuilder.emplace([SceneView, this]() + { + const glm::ivec2 ViewportSize = SceneView.GetViewportSize(); - if (LightPassData.Size == SceneView.GetViewportSize()) - return true; + if (LightPassData.Size == SceneView.GetViewportSize()) + return; - LightPassData.Size = ViewportSize; + LightPassData.Size = ViewportSize; - // Create or resize color texture - { - const CD3DX12_HEAP_PROPERTIES HeapProperties {D3D12_HEAP_TYPE_DEFAULT}; - const CD3DX12_RESOURCE_DESC ResourceDesc = CD3DX12_RESOURCE_DESC::Tex2D( - LightPassData.COLOR_TEXTURE_FORMAT, - ViewportSize.x, - ViewportSize.y, - 1, - 1, - 1, - 0, - D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET - ); + // Create or resize color texture + { + const CD3DX12_HEAP_PROPERTIES HeapProperties {D3D12_HEAP_TYPE_DEFAULT}; + const CD3DX12_RESOURCE_DESC ResourceDesc = CD3DX12_RESOURCE_DESC::Tex2D( + LightPassData.COLOR_TEXTURE_FORMAT, + ViewportSize.x, + ViewportSize.y, + 1, + 1, + 1, + 0, + D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET + ); - const D3D12_CLEAR_VALUE ClearValue = { - .Format = LightPassData.COLOR_TEXTURE_FORMAT, - .Color = { - 0.f, 0.f, 0.f, 1.f - } - }; + const D3D12_CLEAR_VALUE ClearValue = { + .Format = LightPassData.COLOR_TEXTURE_FORMAT, + .Color = { + 0.f, 0.f, 0.f, 1.f + } + }; - CHECKED( - RenderApi->GetDevice() - ->CreateCommittedResource( - &HeapProperties, - D3D12_HEAP_FLAG_NONE, - &ResourceDesc, - D3D12_RESOURCE_STATE_RENDER_TARGET, - &ClearValue, - IID_PPV_ARGS(&LightPassData.ColorTexture) - ), - "Can't create light pass color texture" - ) - } + CHECKED_TF( + RenderApi->GetDevice() + ->CreateCommittedResource( + &HeapProperties, + D3D12_HEAP_FLAG_NONE, + &ResourceDesc, + D3D12_RESOURCE_STATE_RENDER_TARGET, + &ClearValue, + IID_PPV_ARGS(&LightPassData.ColorTexture) + ), + "Can't create light pass color texture" + ) + } - // Create RTV heap and handle - { - D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = { - .Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV, - .NumDescriptors = 1, - }; + // Create RTV heap and handle + { + D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = { + .Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV, + .NumDescriptors = 1, + }; + + CHECKED_TF( + RenderApi->GetDevice() + ->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&LightPassData.CpuRtvHeap)), + "Failed to create cpu rtv descriptor heap" + ) - CHECKED( RenderApi->GetDevice() - ->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&LightPassData.CpuRtvHeap)), - "Failed to create cpu rtv descriptor heap" - ) + ->CreateRenderTargetView(LightPassData.ColorTexture.Get(), nullptr, LightPassData.CpuRtvHeap->GetCPUDescriptorHandleForHeapStart()); + } - RenderApi->GetDevice() - ->CreateRenderTargetView(LightPassData.ColorTexture.Get(), nullptr, LightPassData.CpuRtvHeap->GetCPUDescriptorHandleForHeapStart()); - } + // Create SRV heap and handle + { + D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = { + .Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + .NumDescriptors = 1, + }; - // Create SRV heap and handle - { - D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = { - .Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - .NumDescriptors = 1, - }; + CHECKED_TF( + RenderApi->GetDevice() + ->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&LightPassData.CpuSrvHeap)), + "Failed to create cpu srv descriptor heap" + ) - CHECKED( RenderApi->GetDevice() - ->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&LightPassData.CpuSrvHeap)), - "Failed to create cpu srv descriptor heap" - ) - - RenderApi->GetDevice() - ->CreateShaderResourceView(LightPassData.ColorTexture.Get(), nullptr, LightPassData.CpuSrvHeap->GetCPUDescriptorHandleForHeapStart()); - } - - return true; + ->CreateShaderResourceView(LightPassData.ColorTexture.Get(), nullptr, LightPassData.CpuSrvHeap->GetCPUDescriptorHandleForHeapStart()); + } + }); } -bool DeferredRenderer::TransitionLightPassFromRenderTargetToReadState() +tf::Task DeferredRenderer::TransitionLightPassFromRenderTargetToReadState(tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); - CD3DX12_RESOURCE_BARRIER Barrier = CD3DX12_RESOURCE_BARRIER::Transition(LightPassData.ColorTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ); - - CHECKED_S(LightPassData.RenderTargetToReadTransitionAllocator->Reset()); - CHECKED_S(LightPassData.TransitionCommandList->Reset(LightPassData.RenderTargetToReadTransitionAllocator.Get(), nullptr)) + return FlowBuilder.emplace([this]() + { + CD3DX12_RESOURCE_BARRIER Barrier = CD3DX12_RESOURCE_BARRIER::Transition(LightPassData.ColorTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ); - LightPassData.TransitionCommandList->ResourceBarrier(1, &Barrier); - CHECKED_S(LightPassData.TransitionCommandList->Close()); + CHECKED_TF_S(LightPassData.RenderTargetToReadTransitionAllocator->Reset()) + CHECKED_TF_S(LightPassData.TransitionCommandList->Reset(LightPassData.RenderTargetToReadTransitionAllocator.Get(), nullptr)) - ID3D12CommandList* CommandLists[] = {LightPassData.TransitionCommandList.Get()}; - RenderApi->GetDirectQueue() - ->ExecuteCommandLists(1, CommandLists); + LightPassData.TransitionCommandList->ResourceBarrier(1, &Barrier); + CHECKED_TF_S(LightPassData.TransitionCommandList->Close()) - return true; + ID3D12CommandList* CommandLists[] = {LightPassData.TransitionCommandList.Get()}; + RenderApi->GetDirectQueue() + ->ExecuteCommandLists(1, CommandLists); + }); } -bool DeferredRenderer::TransitionLightPassFromReadToRenderTargetState() +tf::Task DeferredRenderer::TransitionLightPassFromReadToRenderTargetState(tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); - CD3DX12_RESOURCE_BARRIER Barrier = CD3DX12_RESOURCE_BARRIER::Transition(LightPassData.ColorTexture.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET); + return FlowBuilder.emplace([this]() + { + CD3DX12_RESOURCE_BARRIER Barrier = CD3DX12_RESOURCE_BARRIER::Transition( + LightPassData.ColorTexture.Get(), + D3D12_RESOURCE_STATE_GENERIC_READ, + D3D12_RESOURCE_STATE_RENDER_TARGET + ); - CHECKED_S(LightPassData.TransitionCommandList->Reset(LightPassData.RenderTargetToReadTransitionAllocator.Get(), nullptr)) + CHECKED_TF_S(LightPassData.TransitionCommandList->Reset(LightPassData.RenderTargetToReadTransitionAllocator.Get(), nullptr)) - LightPassData.TransitionCommandList->ResourceBarrier(1, &Barrier); - CHECKED_S(LightPassData.TransitionCommandList->Close()); + LightPassData.TransitionCommandList->ResourceBarrier(1, &Barrier); + CHECKED_TF_S(LightPassData.TransitionCommandList->Close()) - ID3D12CommandList* CommandLists[] = {LightPassData.TransitionCommandList.Get()}; - RenderApi->GetDirectQueue() - ->ExecuteCommandLists(1, CommandLists); - - return true; + ID3D12CommandList* CommandLists[] = {LightPassData.TransitionCommandList.Get()}; + RenderApi->GetDirectQueue() + ->ExecuteCommandLists(1, CommandLists); + }); } bool DeferredRenderer::InitAmbientDirectionalLightPass() @@ -770,85 +729,86 @@ bool DeferredRenderer::InitAmbientDirectionalLightPass() return true; } -bool DeferredRenderer::AmbientDirectionalLightPass(const Core::SceneView& SceneView) +tf::Task DeferredRenderer::AmbientDirectionalLightPass(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); - auto& CommandList = AmbientDirectionalLightPassData.CommandList; - auto& CommandAllocator = AmbientDirectionalLightPassData.CommandAllocator; - - CHECKED_S(CommandAllocator->Reset()); - CHECKED_S(CommandList->Reset(CommandAllocator.Get(), AmbientDirectionalLightPassData.PipelineState.Get())); - - // Copy GBuffer descriptors + return FlowBuilder.emplace([SceneView, this]() { - RenderApi->GetDevice() - ->CopyDescriptorsSimple( - GBuffer.TEXTURES_COUNT, - AmbientDirectionalLightPassData.GpuDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - GBuffer.CpuSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV - ); - } + auto& CommandList = AmbientDirectionalLightPassData.CommandList; + auto& CommandAllocator = AmbientDirectionalLightPassData.CommandAllocator; - // Setup Render target - { - constexpr static FLOAT ClearColor[4] = {0.f, 0.f, 0.f, 1.f}; - CommandList->ClearRenderTargetView(LightPassData.CpuRtvHeap->GetCPUDescriptorHandleForHeapStart(), ClearColor, 0, nullptr); + CHECKED_TF_S(CommandAllocator->Reset()) + CHECKED_TF_S(CommandList->Reset(CommandAllocator.Get(), AmbientDirectionalLightPassData.PipelineState.Get())) - const D3D12_CPU_DESCRIPTOR_HANDLE RtvHandle = LightPassData.CpuRtvHeap->GetCPUDescriptorHandleForHeapStart(); - CommandList->OMSetRenderTargets(1, &RtvHandle, true, nullptr); + // Copy GBuffer descriptors + { + RenderApi->GetDevice() + ->CopyDescriptorsSimple( + GBuffer.TEXTURES_COUNT, + AmbientDirectionalLightPassData.GpuDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), + GBuffer.CpuSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV + ); + } - D3D12_VIEWPORT Viewport = SceneView.GetD3dViewport(); - CommandList->RSSetViewports(1, &Viewport); + // Setup Render target + { + constexpr static FLOAT ClearColor[4] = {0.f, 0.f, 0.f, 1.f}; + CommandList->ClearRenderTargetView(LightPassData.CpuRtvHeap->GetCPUDescriptorHandleForHeapStart(), ClearColor, 0, nullptr); - static const D3D12_RECT ScissorRect = CD3DX12_RECT(0, 0, LONG_MAX, LONG_MAX); - CommandList->RSSetScissorRects(1, &ScissorRect); - } + const D3D12_CPU_DESCRIPTOR_HANDLE RtvHandle = LightPassData.CpuRtvHeap->GetCPUDescriptorHandleForHeapStart(); + CommandList->OMSetRenderTargets(1, &RtvHandle, true, nullptr); - // Setup Root Params - { - CommandList->SetGraphicsRootSignature(AmbientDirectionalLightPassData.RootSignature.Get()); + D3D12_VIEWPORT Viewport = SceneView.GetD3dViewport(); + CommandList->RSSetViewports(1, &Viewport); - CommandList->SetDescriptorHeaps(1, AmbientDirectionalLightPassData.GpuDescriptorHeap.GetAddressOf()); - CommandList->SetGraphicsRootDescriptorTable(0, AmbientDirectionalLightPassData.GpuDescriptorHeap->GetGPUDescriptorHandleForHeapStart()); + static const D3D12_RECT ScissorRect = CD3DX12_RECT(0, 0, LONG_MAX, LONG_MAX); + CommandList->RSSetScissorRects(1, &ScissorRect); + } - CommandList->SetGraphicsRootConstantBufferView(1, FrameData.ConstantBuffer->GetGPUVirtualAddress()); - } + // Setup Root Params + { + CommandList->SetGraphicsRootSignature(AmbientDirectionalLightPassData.RootSignature.Get()); - // Setup fullscreen quad mesh - { - const D3D12_VERTEX_BUFFER_VIEW VertexBufferView = FullscreenQuadMesh->GetVertexBufferView(); - CommandList->IASetVertexBuffers(0, 1, &VertexBufferView); + CommandList->SetDescriptorHeaps(1, AmbientDirectionalLightPassData.GpuDescriptorHeap.GetAddressOf()); + CommandList->SetGraphicsRootDescriptorTable(0, AmbientDirectionalLightPassData.GpuDescriptorHeap->GetGPUDescriptorHandleForHeapStart()); - if (FullscreenQuadMesh->IsUsingIndices()) - { - const D3D12_INDEX_BUFFER_VIEW IndexBufferView = FullscreenQuadMesh->GetIndexBufferView(); - CommandList->IASetIndexBuffer(&IndexBufferView); + CommandList->SetGraphicsRootConstantBufferView(1, FrameData.ConstantBuffer->GetGPUVirtualAddress()); } - CommandList->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - } - - // Draw - { - if (FullscreenQuadMesh->IsUsingIndices()) + // Setup fullscreen quad mesh { - CommandList->DrawIndexedInstanced(FullscreenQuadMesh->GetPrimitivesCount(), 1, 0, 0, 0); + const D3D12_VERTEX_BUFFER_VIEW VertexBufferView = FullscreenQuadMesh->GetVertexBufferView(); + CommandList->IASetVertexBuffers(0, 1, &VertexBufferView); + + if (FullscreenQuadMesh->IsUsingIndices()) + { + const D3D12_INDEX_BUFFER_VIEW IndexBufferView = FullscreenQuadMesh->GetIndexBufferView(); + CommandList->IASetIndexBuffer(&IndexBufferView); + } + + CommandList->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); } - else + + // Draw { - CommandList->DrawInstanced(FullscreenQuadMesh->GetPrimitivesCount(), 1, 0, 0); + if (FullscreenQuadMesh->IsUsingIndices()) + { + CommandList->DrawIndexedInstanced(FullscreenQuadMesh->GetPrimitivesCount(), 1, 0, 0, 0); + } + else + { + CommandList->DrawInstanced(FullscreenQuadMesh->GetPrimitivesCount(), 1, 0, 0); + } } - } - CHECKED_S(CommandList->Close()); + CHECKED_TF_S(CommandList->Close()) - ID3D12CommandList* CommandLists[] = {CommandList.Get()}; - RenderApi->GetDirectQueue() - ->ExecuteCommandLists(1, CommandLists); - - return true; + ID3D12CommandList* CommandLists[] = {CommandList.Get()}; + RenderApi->GetDirectQueue() + ->ExecuteCommandLists(1, CommandLists); + }); } bool DeferredRenderer::InitPointLightShadowCubeMapPass() @@ -907,147 +867,148 @@ bool DeferredRenderer::InitPointLightShadowCubeMapPass() return true; } -bool DeferredRenderer::PointLightShadowCubeMapsPass(const Core::Scene* Scene) +tf::Task DeferredRenderer::PointLightShadowCubeMapsPass(const Core::Scene* Scene, tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); - auto& CommandAllocator = PointLightShadowCubeMapData.CommandAllocator; - auto& CommandList = PointLightShadowCubeMapData.CommandList; + return FlowBuilder.emplace([Scene, this]() + { + auto& CommandAllocator = PointLightShadowCubeMapData.CommandAllocator; + auto& CommandList = PointLightShadowCubeMapData.CommandList; - CHECKED_S(CommandAllocator->Reset()); - CHECKED_S(CommandList->Reset(CommandAllocator.Get(), PointLightShadowCubeMapData.PipelineState.Get())); + CHECKED_TF_S(CommandAllocator->Reset()) + CHECKED_TF_S(CommandList->Reset(CommandAllocator.Get(), PointLightShadowCubeMapData.PipelineState.Get())) - // Transition to present state - { - for(const auto& PointLight : Scene->GetPointLights()) + // Transition to present state { - if (!PointLight->CastsShadows()) - continue; + for(const auto& PointLight : Scene->GetPointLights()) + { + if (!PointLight->CastsShadows()) + continue; - PointLight->TransitionShadowCubeMapFromReadToRenderTarget(CommandList.Get()); + PointLight->TransitionShadowCubeMapFromReadToRenderTarget(CommandList.Get()); + } } - } - // Prepare command list for rendering - { - CommandList->SetGraphicsRootSignature(PointLightShadowCubeMapData.RootSignature.Get()); - CommandList->SetGraphicsRootConstantBufferView(0, FrameData.ConstantBuffer->GetGPUVirtualAddress()); - - const D3D12_VIEWPORT Viewport = CD3DX12_VIEWPORT( - 0.f, - 0.f, - Core::PointLight::SHADOW_MAP_SIZE, - Core::PointLight::SHADOW_MAP_SIZE - ); - CommandList->RSSetViewports(1, &Viewport); + // Prepare command list for rendering + { + CommandList->SetGraphicsRootSignature(PointLightShadowCubeMapData.RootSignature.Get()); + CommandList->SetGraphicsRootConstantBufferView(0, FrameData.ConstantBuffer->GetGPUVirtualAddress()); + + const D3D12_VIEWPORT Viewport = CD3DX12_VIEWPORT( + 0.f, + 0.f, + Core::PointLight::SHADOW_MAP_SIZE, + Core::PointLight::SHADOW_MAP_SIZE + ); + CommandList->RSSetViewports(1, &Viewport); - const CD3DX12_RECT ScissorRect = CD3DX12_RECT(0, 0, LONG_MAX, LONG_MAX); - CommandList->RSSetScissorRects(1, &ScissorRect); + const CD3DX12_RECT ScissorRect = CD3DX12_RECT(0, 0, LONG_MAX, LONG_MAX); + CommandList->RSSetScissorRects(1, &ScissorRect); - CommandList->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - } + CommandList->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + } - // Render shadow maps - { - for(const auto& PointLight : Scene->GetPointLights()) + // Render shadow maps { - nvtx3::scoped_range PointLightLoop{"Point Light Iteration"}; - - if (!PointLight->CastsShadows()) - continue; - - CommandList->SetGraphicsRootConstantBufferView(1, PointLight->GetConstantBufferGpuHandle()); + for(const auto& PointLight : Scene->GetPointLights()) + { + nvtx3::scoped_range PointLightLoop{"Point Light Iteration"}; - glm::mat4 ProjectionMatrix = glm::perspective( - glm::radians(90.f), - 1.0f, - 1.0f, - PointLight->GetShadowFarDistance() - ); + if (!PointLight->CastsShadows()) + continue; - const std::array ShadowViewMatrices = { - glm::lookAt(PointLight->GetPosition(), PointLight->GetPosition() + glm::vec3{1, 0, 0}, {0, 1, 0}), - glm::lookAt(PointLight->GetPosition(), PointLight->GetPosition() + glm::vec3{-1, 0, 0}, {0, 1, 0}), - glm::lookAt(PointLight->GetPosition(), PointLight->GetPosition() + glm::vec3{0, 1, 0}, {0, 0, -1}), - glm::lookAt(PointLight->GetPosition(), PointLight->GetPosition() + glm::vec3{0, -1, 0}, {0, 0, 1}), - glm::lookAt(PointLight->GetPosition(), PointLight->GetPosition() + glm::vec3{0, 0, 1}, {0, 1, 0}), - glm::lookAt(PointLight->GetPosition(), PointLight->GetPosition() + glm::vec3{0, 0, -1}, {0, 1, 0}), - }; + CommandList->SetGraphicsRootConstantBufferView(1, PointLight->GetConstantBufferGpuHandle()); - // Render each side of point light - for (int i = 0; i < 6; ++i) - { - nvtx3::scoped_range PointLightSideLoop{"Point Light Side Iteration"}; + glm::mat4 ProjectionMatrix = glm::perspective( + glm::radians(90.f), + 1.0f, + 1.0f, + PointLight->GetShadowFarDistance() + ); - D3D12_CPU_DESCRIPTOR_HANDLE RtvHandle = PointLight->GetShadowCubeMapRtvHandle(i); - D3D12_CPU_DESCRIPTOR_HANDLE DsvHandle = PointLight->GetShadowCubeMapDsvHandle(i); - CommandList->OMSetRenderTargets(1, &RtvHandle, true, &DsvHandle); + const std::array ShadowViewMatrices = { + glm::lookAt(PointLight->GetPosition(), PointLight->GetPosition() + glm::vec3{1, 0, 0}, {0, 1, 0}), + glm::lookAt(PointLight->GetPosition(), PointLight->GetPosition() + glm::vec3{-1, 0, 0}, {0, 1, 0}), + glm::lookAt(PointLight->GetPosition(), PointLight->GetPosition() + glm::vec3{0, 1, 0}, {0, 0, -1}), + glm::lookAt(PointLight->GetPosition(), PointLight->GetPosition() + glm::vec3{0, -1, 0}, {0, 0, 1}), + glm::lookAt(PointLight->GetPosition(), PointLight->GetPosition() + glm::vec3{0, 0, 1}, {0, 1, 0}), + glm::lookAt(PointLight->GetPosition(), PointLight->GetPosition() + glm::vec3{0, 0, -1}, {0, 1, 0}), + }; - FLOAT ClearColor[4] = {1.f, 1.f, 1.f, 1.f}; - CommandList->ClearRenderTargetView(RtvHandle, ClearColor, 0, nullptr); + // Render each side of point light + for (int i = 0; i < 6; ++i) + { + nvtx3::scoped_range PointLightSideLoop{"Point Light Side Iteration"}; - CommandList->ClearDepthStencilView(DsvHandle, D3D12_CLEAR_FLAG_DEPTH, 1.f, 0, 0, nullptr); + D3D12_CPU_DESCRIPTOR_HANDLE RtvHandle = PointLight->GetShadowCubeMapRtvHandle(i); + D3D12_CPU_DESCRIPTOR_HANDLE DsvHandle = PointLight->GetShadowCubeMapDsvHandle(i); + CommandList->OMSetRenderTargets(1, &RtvHandle, true, &DsvHandle); - glm::mat4 ViewProjectionMatrix = ProjectionMatrix * ShadowViewMatrices[i]; + FLOAT ClearColor[4] = {1.f, 1.f, 1.f, 1.f}; + CommandList->ClearRenderTargetView(RtvHandle, ClearColor, 0, nullptr); - CommandList->SetGraphicsRoot32BitConstants(3, 16, &ViewProjectionMatrix[0][0], 0); + CommandList->ClearDepthStencilView(DsvHandle, D3D12_CLEAR_FLAG_DEPTH, 1.f, 0, 0, nullptr); - for (const auto& TexturedMesh : Scene->GetTexturedMeshes()) - { - auto Mesh = TexturedMesh->GetMesh(); + glm::mat4 ViewProjectionMatrix = ProjectionMatrix * ShadowViewMatrices[i]; - CommandList->SetGraphicsRootConstantBufferView(2, TexturedMesh->GetConstantBufferGpuAddress()); + CommandList->SetGraphicsRoot32BitConstants(3, 16, &ViewProjectionMatrix[0][0], 0); - // Set up mesh + for (const auto& TexturedMesh : Scene->GetTexturedMeshes()) { - D3D12_VERTEX_BUFFER_VIEW VertexBufferView = Mesh->GetVertexBufferView(); - CommandList->IASetVertexBuffers(0, 1, &VertexBufferView); + auto Mesh = TexturedMesh->GetMesh(); - if (Mesh->IsUsingIndices()) - { - D3D12_INDEX_BUFFER_VIEW IndexBufferView = Mesh->GetIndexBufferView(); - CommandList->IASetIndexBuffer(&IndexBufferView); - } - else - { - CommandList->IASetIndexBuffer(nullptr); - } - } + CommandList->SetGraphicsRootConstantBufferView(2, TexturedMesh->GetConstantBufferGpuAddress()); - // Draw - { - if (Mesh->IsUsingIndices()) + // Set up mesh { - CommandList->DrawIndexedInstanced(Mesh->GetPrimitivesCount(), 1, 0, 0, 0); + D3D12_VERTEX_BUFFER_VIEW VertexBufferView = Mesh->GetVertexBufferView(); + CommandList->IASetVertexBuffers(0, 1, &VertexBufferView); + + if (Mesh->IsUsingIndices()) + { + D3D12_INDEX_BUFFER_VIEW IndexBufferView = Mesh->GetIndexBufferView(); + CommandList->IASetIndexBuffer(&IndexBufferView); + } + else + { + CommandList->IASetIndexBuffer(nullptr); + } } - else + + // Draw { - CommandList->DrawInstanced(Mesh->GetPrimitivesCount(), 1, 0, 0); + if (Mesh->IsUsingIndices()) + { + CommandList->DrawIndexedInstanced(Mesh->GetPrimitivesCount(), 1, 0, 0, 0); + } + else + { + CommandList->DrawInstanced(Mesh->GetPrimitivesCount(), 1, 0, 0); + } } } } } } - } - // Transition to back read state - { - for(const auto& PointLight : Scene->GetPointLights()) + // Transition to back read state { - if (!PointLight->CastsShadows()) - continue; + for(const auto& PointLight : Scene->GetPointLights()) + { + if (!PointLight->CastsShadows()) + continue; - PointLight->TransitionShadowCubeMapFromRenderTargetToRead(CommandList.Get()); + PointLight->TransitionShadowCubeMapFromRenderTargetToRead(CommandList.Get()); + } } - } - CHECKED_S(CommandList->Close()); + CHECKED_TF_S(CommandList->Close()) - ID3D12CommandList* CommandLists[] = {CommandList.Get()}; - RenderApi->GetDirectQueue() - ->ExecuteCommandLists(1, CommandLists); - - return true; + ID3D12CommandList* CommandLists[] = {CommandList.Get()}; + RenderApi->GetDirectQueue() + ->ExecuteCommandLists(1, CommandLists); + }); } bool DeferredRenderer::InitPointLightVolumePass() @@ -1205,161 +1166,162 @@ bool DeferredRenderer::InitPointLightVolumePass() return true; } -bool DeferredRenderer::PointLightVolumesPass(const Core::Scene* Scene, const Core::SceneView& SceneView) +tf::Task DeferredRenderer::PointLightVolumesPass(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); - auto& CommandAllocator = PointLightVolumePassData.CommandAllocator; - auto& CommandList = PointLightVolumePassData.CommandList; - - CHECKED_S(CommandAllocator->Reset()); - CHECKED_S(CommandList->Reset(CommandAllocator.Get(), PointLightVolumePassData.StencilPipelineState.Get())); - - // Fill GBuffer descriptors - { - RenderApi->GetDevice() - ->CopyDescriptorsSimple( - GBuffer.TEXTURES_COUNT, - PointLightVolumePassData.GpuDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - GBuffer.CpuSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV - ); - } - - // Prepare point light depth stencil buffers + return FlowBuilder.emplace([Scene, SceneView, this]() { - CD3DX12_RESOURCE_BARRIER ResourceBarrier = CD3DX12_RESOURCE_BARRIER::Transition( - GBuffer.DepthStencilTexture.Get(), - D3D12_RESOURCE_STATE_DEPTH_WRITE, - D3D12_RESOURCE_STATE_COPY_SOURCE - ); + auto& CommandAllocator = PointLightVolumePassData.CommandAllocator; + auto& CommandList = PointLightVolumePassData.CommandList; - CommandList->ResourceBarrier(1, &ResourceBarrier); + CHECKED_TF_S(CommandAllocator->Reset()) + CHECKED_TF_S(CommandList->Reset(CommandAllocator.Get(), PointLightVolumePassData.StencilPipelineState.Get())) - for (const auto& PointLight : Scene->GetPointLights()) + // Fill GBuffer descriptors { - PointLight->PrepareDepthStencilForVolumeRendering( - *RenderApi, - SceneView.GetViewportSize(), - CommandList.Get(), - GBuffer.DepthStencilTexture.Get() - ); + RenderApi->GetDevice() + ->CopyDescriptorsSimple( + GBuffer.TEXTURES_COUNT, + PointLightVolumePassData.GpuDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), + GBuffer.CpuSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV + ); } - ResourceBarrier = CD3DX12_RESOURCE_BARRIER::Transition( - GBuffer.DepthStencilTexture.Get(), - D3D12_RESOURCE_STATE_COPY_SOURCE, - D3D12_RESOURCE_STATE_DEPTH_WRITE - ); - - CommandList->ResourceBarrier(1, &ResourceBarrier); - } + // Prepare point light depth stencil buffers + { + CD3DX12_RESOURCE_BARRIER ResourceBarrier = CD3DX12_RESOURCE_BARRIER::Transition( + GBuffer.DepthStencilTexture.Get(), + D3D12_RESOURCE_STATE_DEPTH_WRITE, + D3D12_RESOURCE_STATE_COPY_SOURCE + ); - // Set up command list - { - CommandList->SetGraphicsRootSignature(PointLightVolumePassData.RootSignature.Get()); - CommandList->SetDescriptorHeaps(1, PointLightVolumePassData.GpuDescriptorHeap.GetAddressOf()); + CommandList->ResourceBarrier(1, &ResourceBarrier); - CommandList->SetGraphicsRootDescriptorTable(0, PointLightVolumePassData.GpuDescriptorHeap->GetGPUDescriptorHandleForHeapStart()); - CommandList->SetGraphicsRootConstantBufferView(1, FrameData.ConstantBuffer->GetGPUVirtualAddress()); + for (const auto& PointLight : Scene->GetPointLights()) + { + PointLight->PrepareDepthStencilForVolumeRendering( + *RenderApi, + SceneView.GetViewportSize(), + CommandList.Get(), + GBuffer.DepthStencilTexture.Get() + ); + } - D3D12_VERTEX_BUFFER_VIEW VertexBufferView = SphereMesh->GetVertexBufferView(); - CommandList->IASetVertexBuffers(0, 1, &VertexBufferView); + ResourceBarrier = CD3DX12_RESOURCE_BARRIER::Transition( + GBuffer.DepthStencilTexture.Get(), + D3D12_RESOURCE_STATE_COPY_SOURCE, + D3D12_RESOURCE_STATE_DEPTH_WRITE + ); - if (SphereMesh->IsUsingIndices()) - { - D3D12_INDEX_BUFFER_VIEW IndexBufferView = SphereMesh->GetIndexBufferView(); - CommandList->IASetIndexBuffer(&IndexBufferView); + CommandList->ResourceBarrier(1, &ResourceBarrier); } - CommandList->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - - D3D12_VIEWPORT Viewport = SceneView.GetD3dViewport(); - CommandList->RSSetViewports(1, &Viewport); - - D3D12_RECT Scissors = D3D12_RECT(0, 0, LONG_MAX, LONG_MAX); - CommandList->RSSetScissorRects(1, &Scissors); - } - - // Fill stencil buffers - { - for (const auto& PointLight : Scene->GetPointLights()) + // Set up command list { - CommandList->SetGraphicsRootConstantBufferView(2, PointLight->GetConstantBufferGpuHandle()); + CommandList->SetGraphicsRootSignature(PointLightVolumePassData.RootSignature.Get()); + CommandList->SetDescriptorHeaps(1, PointLightVolumePassData.GpuDescriptorHeap.GetAddressOf()); - D3D12_CPU_DESCRIPTOR_HANDLE DsvHandle = PointLight->GetDepthStencilVolumeDsvHandle(); - CommandList->OMSetRenderTargets(0, nullptr, false, &DsvHandle); + CommandList->SetGraphicsRootDescriptorTable(0, PointLightVolumePassData.GpuDescriptorHeap->GetGPUDescriptorHandleForHeapStart()); + CommandList->SetGraphicsRootConstantBufferView(1, FrameData.ConstantBuffer->GetGPUVirtualAddress()); + + D3D12_VERTEX_BUFFER_VIEW VertexBufferView = SphereMesh->GetVertexBufferView(); + CommandList->IASetVertexBuffers(0, 1, &VertexBufferView); if (SphereMesh->IsUsingIndices()) { - CommandList->DrawIndexedInstanced(SphereMesh->GetPrimitivesCount(), 1, 0, 0, 0); + D3D12_INDEX_BUFFER_VIEW IndexBufferView = SphereMesh->GetIndexBufferView(); + CommandList->IASetIndexBuffer(&IndexBufferView); } - else + + CommandList->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + D3D12_VIEWPORT Viewport = SceneView.GetD3dViewport(); + CommandList->RSSetViewports(1, &Viewport); + + D3D12_RECT Scissors = D3D12_RECT(0, 0, LONG_MAX, LONG_MAX); + CommandList->RSSetScissorRects(1, &Scissors); + } + + // Fill stencil buffers + { + for (const auto& PointLight : Scene->GetPointLights()) { - CommandList->DrawInstanced(SphereMesh->GetPrimitivesCount(), 1, 0, 0); + CommandList->SetGraphicsRootConstantBufferView(2, PointLight->GetConstantBufferGpuHandle()); + + D3D12_CPU_DESCRIPTOR_HANDLE DsvHandle = PointLight->GetDepthStencilVolumeDsvHandle(); + CommandList->OMSetRenderTargets(0, nullptr, false, &DsvHandle); + + if (SphereMesh->IsUsingIndices()) + { + CommandList->DrawIndexedInstanced(SphereMesh->GetPrimitivesCount(), 1, 0, 0, 0); + } + else + { + CommandList->DrawInstanced(SphereMesh->GetPrimitivesCount(), 1, 0, 0); + } } } - } - CommandList->SetPipelineState(PointLightVolumePassData.ColorPipelineState.Get()); - CommandList->OMSetStencilRef(1); - - // Draw color based on stencil buffers - { - int PointLightIndex = 0; + CommandList->SetPipelineState(PointLightVolumePassData.ColorPipelineState.Get()); + CommandList->OMSetStencilRef(1); - for (const auto& PointLight : Scene->GetPointLights()) + // Draw color based on stencil buffers { - CommandList->SetGraphicsRootConstantBufferView(2, PointLight->GetConstantBufferGpuHandle()); + int PointLightIndex = 0; - const unsigned SrvIncrement = RenderApi->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + for (const auto& PointLight : Scene->GetPointLights()) + { + CommandList->SetGraphicsRootConstantBufferView(2, PointLight->GetConstantBufferGpuHandle()); - CD3DX12_CPU_DESCRIPTOR_HANDLE CpuShadowCubeMapSrvHandle { - PointLightVolumePassData.GpuDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - static_cast(GBuffer.TEXTURES_COUNT) + PointLightIndex, - SrvIncrement - }; + const unsigned SrvIncrement = RenderApi->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - RenderApi->GetDevice() - ->CopyDescriptorsSimple( - 1, - CpuShadowCubeMapSrvHandle, - PointLight->GetShadowCubeMapSrvHandle(), - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV - ); + CD3DX12_CPU_DESCRIPTOR_HANDLE CpuShadowCubeMapSrvHandle { + PointLightVolumePassData.GpuDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), + static_cast(GBuffer.TEXTURES_COUNT) + PointLightIndex, + SrvIncrement + }; - CD3DX12_GPU_DESCRIPTOR_HANDLE GpuShadowCubeMapSrvHandle { - PointLightVolumePassData.GpuDescriptorHeap->GetGPUDescriptorHandleForHeapStart(), - static_cast(GBuffer.TEXTURES_COUNT) + PointLightIndex, - SrvIncrement - }; + RenderApi->GetDevice() + ->CopyDescriptorsSimple( + 1, + CpuShadowCubeMapSrvHandle, + PointLight->GetShadowCubeMapSrvHandle(), + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV + ); + + CD3DX12_GPU_DESCRIPTOR_HANDLE GpuShadowCubeMapSrvHandle { + PointLightVolumePassData.GpuDescriptorHeap->GetGPUDescriptorHandleForHeapStart(), + static_cast(GBuffer.TEXTURES_COUNT) + PointLightIndex, + SrvIncrement + }; - CommandList->SetGraphicsRootDescriptorTable(3, GpuShadowCubeMapSrvHandle); + CommandList->SetGraphicsRootDescriptorTable(3, GpuShadowCubeMapSrvHandle); - D3D12_CPU_DESCRIPTOR_HANDLE RtvHandle = LightPassData.CpuRtvHeap->GetCPUDescriptorHandleForHeapStart(); - D3D12_CPU_DESCRIPTOR_HANDLE DsvHandle = PointLight->GetDepthStencilVolumeDsvHandle(); - CommandList->OMSetRenderTargets(1, &RtvHandle, true, &DsvHandle); + D3D12_CPU_DESCRIPTOR_HANDLE RtvHandle = LightPassData.CpuRtvHeap->GetCPUDescriptorHandleForHeapStart(); + D3D12_CPU_DESCRIPTOR_HANDLE DsvHandle = PointLight->GetDepthStencilVolumeDsvHandle(); + CommandList->OMSetRenderTargets(1, &RtvHandle, true, &DsvHandle); - if (SphereMesh->IsUsingIndices()) - { - CommandList->DrawIndexedInstanced(SphereMesh->GetPrimitivesCount(), 1, 0, 0, 0); - } - else - { - CommandList->DrawInstanced(SphereMesh->GetPrimitivesCount(), 1, 0, 0); - } + if (SphereMesh->IsUsingIndices()) + { + CommandList->DrawIndexedInstanced(SphereMesh->GetPrimitivesCount(), 1, 0, 0, 0); + } + else + { + CommandList->DrawInstanced(SphereMesh->GetPrimitivesCount(), 1, 0, 0); + } - ++PointLightIndex; + ++PointLightIndex; + } } - } - CHECKED_S(CommandList->Close()) + CHECKED_TF_S(CommandList->Close()) - ID3D12CommandList* CommandLists[] = {CommandList.Get()}; - RenderApi->GetDirectQueue() - ->ExecuteCommandLists(1, CommandLists); - - return true; + ID3D12CommandList* CommandLists[] = {CommandList.Get()}; + RenderApi->GetDirectQueue() + ->ExecuteCommandLists(1, CommandLists); + }); } bool DeferredRenderer::InitPostProcessingPass() @@ -1430,114 +1392,119 @@ bool DeferredRenderer::InitPostProcessingPass() return true; } -bool DeferredRenderer::PostProcessingPass(const Core::SceneView& SceneView) +tf::Task DeferredRenderer::PostProcessingPass(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); - auto& CommandList = PostProcessingPassData.CommandList; - auto& CommandAllocator = PostProcessingPassData.CommandAllocator; - - CHECKED_S(CommandAllocator->Reset()); - CHECKED_S(CommandList->Reset(CommandAllocator.Get(), PostProcessingPassData.PipelineState.Get())); - - // Copy GBuffer descriptors + return FlowBuilder.emplace([SceneView, this]() { - RenderApi->GetDevice() - ->CopyDescriptorsSimple( - GBuffer.TEXTURES_COUNT, - PostProcessingPassData.GpuDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - GBuffer.CpuSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV - ); + auto& CommandList = PostProcessingPassData.CommandList; + auto& CommandAllocator = PostProcessingPassData.CommandAllocator; - RenderApi->GetDevice() - ->CopyDescriptorsSimple( - 1, - CD3DX12_CPU_DESCRIPTOR_HANDLE - { - PostProcessingPassData.GpuDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), + CHECKED_TF_S(CommandAllocator->Reset()) + CHECKED_TF_S(CommandList->Reset(CommandAllocator.Get(), PostProcessingPassData.PipelineState.Get())) + + // Copy GBuffer descriptors + { + RenderApi->GetDevice() + ->CopyDescriptorsSimple( GBuffer.TEXTURES_COUNT, - RenderApi->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) - }, - LightPassData.CpuSrvHeap->GetCPUDescriptorHandleForHeapStart(), - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV - ); - } + PostProcessingPassData.GpuDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), + GBuffer.CpuSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV + ); - // Setup Render target - { - const D3D12_CPU_DESCRIPTOR_HANDLE RtvHandle = SceneView.GetRenderTargetHandle(); + RenderApi->GetDevice() + ->CopyDescriptorsSimple( + 1, + CD3DX12_CPU_DESCRIPTOR_HANDLE + { + PostProcessingPassData.GpuDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), + GBuffer.TEXTURES_COUNT, + RenderApi->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) + }, + LightPassData.CpuSrvHeap->GetCPUDescriptorHandleForHeapStart(), + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV + ); + } - constexpr static FLOAT ClearColor[4] = {0.f, 0.f, 0.f, 1.f}; - CommandList->ClearRenderTargetView(RtvHandle, ClearColor, 0, nullptr); + // Setup Render target + { + const D3D12_CPU_DESCRIPTOR_HANDLE RtvHandle = SceneView.GetRenderTargetHandle(); - CommandList->OMSetRenderTargets(1, &RtvHandle, true, nullptr); + constexpr static FLOAT ClearColor[4] = {0.f, 0.f, 0.f, 1.f}; + CommandList->ClearRenderTargetView(RtvHandle, ClearColor, 0, nullptr); - D3D12_VIEWPORT Viewport = SceneView.GetD3dViewport(); - CommandList->RSSetViewports(1, &Viewport); + CommandList->OMSetRenderTargets(1, &RtvHandle, true, nullptr); - static const D3D12_RECT ScissorRect = CD3DX12_RECT(0, 0, LONG_MAX, LONG_MAX); - CommandList->RSSetScissorRects(1, &ScissorRect); - } + D3D12_VIEWPORT Viewport = SceneView.GetD3dViewport(); + CommandList->RSSetViewports(1, &Viewport); - // Setup Root Params - { - CommandList->SetGraphicsRootSignature(PostProcessingPassData.RootSignature.Get()); + static const D3D12_RECT ScissorRect = CD3DX12_RECT(0, 0, LONG_MAX, LONG_MAX); + CommandList->RSSetScissorRects(1, &ScissorRect); + } - CommandList->SetDescriptorHeaps(1, PostProcessingPassData.GpuDescriptorHeap.GetAddressOf()); - CommandList->SetGraphicsRootDescriptorTable(0, PostProcessingPassData.GpuDescriptorHeap->GetGPUDescriptorHandleForHeapStart()); + // Setup Root Params + { + CommandList->SetGraphicsRootSignature(PostProcessingPassData.RootSignature.Get()); - CommandList->SetGraphicsRootConstantBufferView(1, FrameData.ConstantBuffer->GetGPUVirtualAddress()); - } + CommandList->SetDescriptorHeaps(1, PostProcessingPassData.GpuDescriptorHeap.GetAddressOf()); + CommandList->SetGraphicsRootDescriptorTable(0, PostProcessingPassData.GpuDescriptorHeap->GetGPUDescriptorHandleForHeapStart()); - // Setup fullscreen quad mesh - { - const D3D12_VERTEX_BUFFER_VIEW VertexBufferView = FullscreenQuadMesh->GetVertexBufferView(); - CommandList->IASetVertexBuffers(0, 1, &VertexBufferView); + CommandList->SetGraphicsRootConstantBufferView(1, FrameData.ConstantBuffer->GetGPUVirtualAddress()); + } - if (FullscreenQuadMesh->IsUsingIndices()) + // Setup fullscreen quad mesh { - const D3D12_INDEX_BUFFER_VIEW IndexBufferView = FullscreenQuadMesh->GetIndexBufferView(); - CommandList->IASetIndexBuffer(&IndexBufferView); - } + const D3D12_VERTEX_BUFFER_VIEW VertexBufferView = FullscreenQuadMesh->GetVertexBufferView(); + CommandList->IASetVertexBuffers(0, 1, &VertexBufferView); - CommandList->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - } + if (FullscreenQuadMesh->IsUsingIndices()) + { + const D3D12_INDEX_BUFFER_VIEW IndexBufferView = FullscreenQuadMesh->GetIndexBufferView(); + CommandList->IASetIndexBuffer(&IndexBufferView); + } - // Draw - { - if (FullscreenQuadMesh->IsUsingIndices()) - { - CommandList->DrawIndexedInstanced(FullscreenQuadMesh->GetPrimitivesCount(), 1, 0, 0, 0); + CommandList->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); } - else + + // Draw { - CommandList->DrawInstanced(FullscreenQuadMesh->GetPrimitivesCount(), 1, 0, 0); + if (FullscreenQuadMesh->IsUsingIndices()) + { + CommandList->DrawIndexedInstanced(FullscreenQuadMesh->GetPrimitivesCount(), 1, 0, 0, 0); + } + else + { + CommandList->DrawInstanced(FullscreenQuadMesh->GetPrimitivesCount(), 1, 0, 0); + } } - } - - CHECKED_S(CommandList->Close()); - ID3D12CommandList* CommandLists[] = {CommandList.Get()}; - RenderApi->GetDirectQueue() - ->ExecuteCommandLists(1, CommandLists); - - return true; -} + CHECKED_TF_S(CommandList->Close()) -bool DeferredRenderer::Shutdown() -{ - return WaitDirectQueue(); + ID3D12CommandList* CommandLists[] = {CommandList.Get()}; + RenderApi->GetDirectQueue() + ->ExecuteCommandLists(1, CommandLists); + }); } -tf::Taskflow* DeferredRenderer::AllocateTaskFlow() +tf::Task DeferredRenderer::PostRenderPasses(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - return &Taskflows.emplace_back(); + return FlowBuilder.emplace([SceneView, this](tf::Subflow& Subflow) + { + Subflow.linearize({ + TransitionLightPassFromRenderTargetToReadState(Subflow), + PostProcessingPass(SceneView, Subflow), + TransitionLightPassFromReadToRenderTargetState(Subflow), + PostRender(SceneView, Subflow), + TransitionGBufferFromReadToRenderTargetState(Subflow) + }); + }); } -void DeferredRenderer::ClearTaskFlows() +bool DeferredRenderer::Shutdown() { - Taskflows.clear(); + return WaitDirectQueue(); } bool DeferredRenderer::InitBasicMeshes() @@ -1624,61 +1591,84 @@ bool DeferredRenderer::InitPrePostRender() return true; } -bool DeferredRenderer::PreRender(const Core::Scene* Scene, const Core::SceneView& SceneView) +tf::Task DeferredRenderer::PreRender(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); - CHECKED_S(PrePostRenderData.CommandAllocator->Reset()); - - CHECKED( - PrePostRenderData.CommandList->Reset(PrePostRenderData.CommandAllocator.Get(), nullptr), - "Can't reset command list" - ) + return FlowBuilder.emplace([Scene, SceneView, this]() + { + CHECKED_TF_S(PrePostRenderData.CommandAllocator->Reset()); - SceneView.TransitionIntoRenderTargetState(PrePostRenderData.CommandList.Get()); + CHECKED_TF( + PrePostRenderData.CommandList->Reset(PrePostRenderData.CommandAllocator.Get(), nullptr), + "Can't reset command list" + ) - CHECKED( - PrePostRenderData.CommandList->Close(), - "Failed to close command list" - ) + SceneView.TransitionIntoRenderTargetState(PrePostRenderData.CommandList.Get()); - ID3D12CommandList* CommandLists[] = {PrePostRenderData.CommandList.Get()}; + CHECKED_TF( + PrePostRenderData.CommandList->Close(), + "Failed to close command list" + ) - RenderApi->GetDirectQueue() - ->ExecuteCommandLists(1, CommandLists); + ID3D12CommandList* CommandLists[] = {PrePostRenderData.CommandList.Get()}; - // Initialize Point Lights for shadow mapping if enabled - for (const auto& PointLight : Scene->GetPointLights()) - { - if (!PointLight->HasShadowResources()) - PointLight->CreateShadowCubeMapResource(*RenderApi); - } + RenderApi->GetDirectQueue() + ->ExecuteCommandLists(1, CommandLists); - return true; + // Initialize Point Lights for shadow mapping if enabled + for (const auto& PointLight : Scene->GetPointLights()) + { + if (!PointLight->HasShadowResources()) + PointLight->CreateShadowCubeMapResource(*RenderApi); + } + }); } -bool DeferredRenderer::PostRender(const Core::SceneView& SceneView) +tf::Task DeferredRenderer::PostRender(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); - CHECKED( - PrePostRenderData.CommandList->Reset(PrePostRenderData.CommandAllocator.Get(), nullptr), - "Can't reset command list" - ) + return FlowBuilder.emplace([SceneView, this]() + { + CHECKED_TF( + PrePostRenderData.CommandList->Reset(PrePostRenderData.CommandAllocator.Get(), nullptr), + "Can't reset command list" + ) - SceneView.TransitionIntoOriginalState(PrePostRenderData.CommandList.Get()); + SceneView.TransitionIntoOriginalState(PrePostRenderData.CommandList.Get()); - CHECKED( - PrePostRenderData.CommandList->Close(), - "Failed to close command list" - ) + CHECKED_TF( + PrePostRenderData.CommandList->Close(), + "Failed to close command list" + ) - ID3D12CommandList* CommandLists[] = {PrePostRenderData.CommandList.Get()}; + ID3D12CommandList* CommandLists[] = {PrePostRenderData.CommandList.Get()}; - RenderApi->GetDirectQueue() - ->ExecuteCommandLists(1, CommandLists); + RenderApi->GetDirectQueue() + ->ExecuteCommandLists(1, CommandLists); + }); +} - return true; +tf::Task DeferredRenderer::WaitDirectQueueTask(tf::FlowBuilder& FlowBuilder) +{ + NVTX3_FUNC_RANGE(); + + return FlowBuilder.emplace([this](tf::Subflow& Subflow) + { + const uint64_t ExpectedValue = ++FrameFenceValue; + + CHECKED_TF( + RenderApi->GetDirectQueue() + ->Signal(FrameFence.Get(), ExpectedValue), + "Failed to signal Fence" + ) + + Subflow.executor().corun_until([this, ExpectedValue]() + { + return FrameFence->GetCompletedValue() >= ExpectedValue; + }); + }); } bool DeferredRenderer::WaitDirectQueue() @@ -1813,227 +1803,230 @@ bool DeferredRenderer::InitEmptyTexture() return WaitDirectQueue(); } -bool DeferredRenderer::InitGBufferForView(const Core::SceneView& SceneView) +tf::Task DeferredRenderer::InitGBufferForView(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); - const glm::ivec2 ViewportSize = SceneView.GetViewportSize(); - - if (GBuffer.Size == ViewportSize) - return true; - - // Allocate textures - - auto CreateTextureBuffer = [&](Microsoft::WRL::ComPtr& TextureBuffer, DXGI_FORMAT Format, const std::wstring_view& Name, bool bIsDepth = false) -> bool + return FlowBuilder.emplace([SceneView, this]() { - D3D12_HEAP_PROPERTIES HeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); - D3D12_RESOURCE_DESC ResourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(Format, ViewportSize.x, ViewportSize.y, 1, 1); + const glm::ivec2 ViewportSize = SceneView.GetViewportSize(); - D3D12_CLEAR_VALUE ClearValue = {}; - ClearValue.Format = Format; + if (GBuffer.Size == ViewportSize) + return; - D3D12_RESOURCE_STATES State = D3D12_RESOURCE_STATE_RENDER_TARGET; + // Allocate textures - if (bIsDepth) + auto CreateTextureBuffer = [&](Microsoft::WRL::ComPtr& TextureBuffer, DXGI_FORMAT Format, const std::wstring_view& Name, bool bIsDepth = false) -> bool { - ResourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; - ClearValue.DepthStencil.Depth = 1.0f; - ClearValue.DepthStencil.Stencil = 0; - State = D3D12_RESOURCE_STATE_DEPTH_WRITE; - } - else - { - ResourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; - ClearValue.Color[0] = 0.f; - ClearValue.Color[1] = 0.f; - ClearValue.Color[2] = 0.f; - ClearValue.Color[3] = 1.f; - } + D3D12_HEAP_PROPERTIES HeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + D3D12_RESOURCE_DESC ResourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(Format, ViewportSize.x, ViewportSize.y, 1, 1); - CHECKED( - RenderApi->GetDevice() - ->CreateCommittedResource( - &HeapProperties, - D3D12_HEAP_FLAG_NONE, - &ResourceDesc, - State, - &ClearValue, - IID_PPV_ARGS(&TextureBuffer) - ), - "Can't create texture for gbuffer" - ) + D3D12_CLEAR_VALUE ClearValue = {}; + ClearValue.Format = Format; - TextureBuffer->SetName(Name.data()); + D3D12_RESOURCE_STATES State = D3D12_RESOURCE_STATE_RENDER_TARGET; - return true; - }; + if (bIsDepth) + { + ResourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + ClearValue.DepthStencil.Depth = 1.0f; + ClearValue.DepthStencil.Stencil = 0; + State = D3D12_RESOURCE_STATE_DEPTH_WRITE; + } + else + { + ResourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + ClearValue.Color[0] = 0.f; + ClearValue.Color[1] = 0.f; + ClearValue.Color[2] = 0.f; + ClearValue.Color[3] = 1.f; + } - const bool bError = !CreateTextureBuffer(GBuffer.DiffuseTexture, DXGI_FORMAT_R8G8B8A8_UNORM, L"GBuffer Diffuse") - || !CreateTextureBuffer(GBuffer.WorldPositionTexture, DXGI_FORMAT_R32G32B32A32_FLOAT, L"GBuffer World Position") - || !CreateTextureBuffer(GBuffer.WorldNormalTexture, DXGI_FORMAT_R32G32B32A32_FLOAT, L"GBuffer World Normal") - || !CreateTextureBuffer(GBuffer.MetallicTexture, DXGI_FORMAT_R8G8B8A8_UNORM, L"GBuffer Metallic") - || !CreateTextureBuffer(GBuffer.RoughnessTexture, DXGI_FORMAT_R8G8B8A8_UNORM, L"GBuffer Roughness") - || !CreateTextureBuffer(GBuffer.EmissiveTexture, DXGI_FORMAT_R8G8B8A8_UNORM, L"GBuffer Emissive") - || !CreateTextureBuffer(GBuffer.DepthStencilTexture, DXGI_FORMAT_D24_UNORM_S8_UINT, L"GBuffer DepthStencil", true); + CHECKED( + RenderApi->GetDevice() + ->CreateCommittedResource( + &HeapProperties, + D3D12_HEAP_FLAG_NONE, + &ResourceDesc, + State, + &ClearValue, + IID_PPV_ARGS(&TextureBuffer) + ), + "Can't create texture for gbuffer" + ) + + TextureBuffer->SetName(Name.data()); + + return true; + }; - if (bError) - return false; + const bool bError = !CreateTextureBuffer(GBuffer.DiffuseTexture, DXGI_FORMAT_R8G8B8A8_UNORM, L"GBuffer Diffuse") + || !CreateTextureBuffer(GBuffer.WorldPositionTexture, DXGI_FORMAT_R32G32B32A32_FLOAT, L"GBuffer World Position") + || !CreateTextureBuffer(GBuffer.WorldNormalTexture, DXGI_FORMAT_R32G32B32A32_FLOAT, L"GBuffer World Normal") + || !CreateTextureBuffer(GBuffer.MetallicTexture, DXGI_FORMAT_R8G8B8A8_UNORM, L"GBuffer Metallic") + || !CreateTextureBuffer(GBuffer.RoughnessTexture, DXGI_FORMAT_R8G8B8A8_UNORM, L"GBuffer Roughness") + || !CreateTextureBuffer(GBuffer.EmissiveTexture, DXGI_FORMAT_R8G8B8A8_UNORM, L"GBuffer Emissive") + || !CreateTextureBuffer(GBuffer.DepthStencilTexture, DXGI_FORMAT_D24_UNORM_S8_UINT, L"GBuffer DepthStencil", true); - const std::array Textures { - std::addressof(GBuffer.DiffuseTexture), - std::addressof(GBuffer.WorldPositionTexture), - std::addressof(GBuffer.WorldNormalTexture), - std::addressof(GBuffer.MetallicTexture), - std::addressof(GBuffer.RoughnessTexture), - std::addressof(GBuffer.EmissiveTexture) - }; + if (bError) + TaskFlowEx::CancelCurrentTaskflow(); - // Create RTV descriptors - { - D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = { - .Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV, - .NumDescriptors = 6, - .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE + const std::array Textures { + std::addressof(GBuffer.DiffuseTexture), + std::addressof(GBuffer.WorldPositionTexture), + std::addressof(GBuffer.WorldNormalTexture), + std::addressof(GBuffer.MetallicTexture), + std::addressof(GBuffer.RoughnessTexture), + std::addressof(GBuffer.EmissiveTexture) }; - CHECKED( - RenderApi->GetDevice() - ->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&GBuffer.CpuRtvDescriptorHeap)), - "Can't create cpu rtv descriptor heap for gbuffer" - ) - - CD3DX12_CPU_DESCRIPTOR_HANDLE Handle {GBuffer.CpuRtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()}; - const unsigned IncrementSize = RenderApi->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); - for (const auto & Texture: Textures) + // Create RTV descriptors { - RenderApi->GetDevice() - ->CreateRenderTargetView(Texture->Get(), nullptr, Handle); - - Handle.Offset(1, IncrementSize); - } - } - - // Create SRV descriptors - { - D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = { - .Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - .NumDescriptors = GBuffer.TEXTURES_COUNT, - }; + D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = { + .Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV, + .NumDescriptors = 6, + .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE + }; - CHECKED( - RenderApi->GetDevice() - ->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&GBuffer.CpuSrvDescriptorHeap)), - "Can't create cpu srv descriptor heap for gbuffer" - ) + CHECKED_TF( + RenderApi->GetDevice() + ->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&GBuffer.CpuRtvDescriptorHeap)), + "Can't create cpu rtv descriptor heap for gbuffer" + ) - CD3DX12_CPU_DESCRIPTOR_HANDLE Handle {GBuffer.CpuSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()}; - const unsigned IncrementSize = RenderApi->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - for (const auto & Texture: Textures) - { - RenderApi->GetDevice() - ->CreateShaderResourceView(Texture->Get(), nullptr, Handle); + CD3DX12_CPU_DESCRIPTOR_HANDLE Handle {GBuffer.CpuRtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()}; + const unsigned IncrementSize = RenderApi->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + for (const auto & Texture: Textures) + { + RenderApi->GetDevice() + ->CreateRenderTargetView(Texture->Get(), nullptr, Handle); - Handle.Offset(1, IncrementSize); + Handle.Offset(1, IncrementSize); + } } - } - // Create DSV descriptor - { - D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = { - .Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV, - .NumDescriptors = 1, - .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE - }; + // Create SRV descriptors + { + D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = { + .Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + .NumDescriptors = GBuffer.TEXTURES_COUNT, + }; - CHECKED( - RenderApi->GetDevice() - ->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&GBuffer.CpuDsvDescriptorHeap)), - "Can't create cpu dsv descriptor heap for gbuffer" - ) + CHECKED_TF( + RenderApi->GetDevice() + ->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&GBuffer.CpuSrvDescriptorHeap)), + "Can't create cpu srv descriptor heap for gbuffer" + ) - CD3DX12_CPU_DESCRIPTOR_HANDLE Handle {GBuffer.CpuDsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()}; - RenderApi->GetDevice()->CreateDepthStencilView(GBuffer.DepthStencilTexture.Get(), nullptr, Handle); - } + CD3DX12_CPU_DESCRIPTOR_HANDLE Handle {GBuffer.CpuSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()}; + const unsigned IncrementSize = RenderApi->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + for (const auto & Texture: Textures) + { + RenderApi->GetDevice() + ->CreateShaderResourceView(Texture->Get(), nullptr, Handle); - // Create command list for barrier transitions - { - CHECKED( - RenderApi->GetDevice() - ->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&GBuffer.PresentToReadTransitionAllocator)), - "Failed to create command allocator" - ) + Handle.Offset(1, IncrementSize); + } + } - CHECKED( - RenderApi->GetDevice() - ->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&GBuffer.ReadToPresentTransitionAllocator)), - "Failed to create command allocator" - ) + // Create DSV descriptor + { + D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = { + .Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV, + .NumDescriptors = 1, + .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE + }; - CHECKED( - RenderApi->GetDevice() - ->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, - GBuffer.PresentToReadTransitionAllocator.Get(), nullptr, IID_PPV_ARGS(&GBuffer.TransitionCommandList)), - "Failed to create command list" - ) + CHECKED_TF( + RenderApi->GetDevice() + ->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&GBuffer.CpuDsvDescriptorHeap)), + "Can't create cpu dsv descriptor heap for gbuffer" + ) - CHECKED_S(GBuffer.TransitionCommandList->Close()); - } + CD3DX12_CPU_DESCRIPTOR_HANDLE Handle {GBuffer.CpuDsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart()}; + RenderApi->GetDevice()->CreateDepthStencilView(GBuffer.DepthStencilTexture.Get(), nullptr, Handle); + } - GBuffer.Size = ViewportSize; + // Create command list for barrier transitions + { + CHECKED_TF( + RenderApi->GetDevice() + ->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&GBuffer.PresentToReadTransitionAllocator)), + "Failed to create command allocator" + ) + + CHECKED_TF( + RenderApi->GetDevice() + ->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&GBuffer.ReadToPresentTransitionAllocator)), + "Failed to create command allocator" + ) + + CHECKED_TF( + RenderApi->GetDevice() + ->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, + GBuffer.PresentToReadTransitionAllocator.Get(), nullptr, IID_PPV_ARGS(&GBuffer.TransitionCommandList)), + "Failed to create command list" + ) + + CHECKED_TF_S(GBuffer.TransitionCommandList->Close()); + } - return true; + GBuffer.Size = ViewportSize; + }); } -bool DeferredRenderer::TransitionGBufferFromRenderTargetToReadState() +tf::Task DeferredRenderer::TransitionGBufferFromRenderTargetToReadState(tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); - const std::array Barriers = { - CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.DiffuseTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ), - CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.WorldPositionTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ), - CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.WorldNormalTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ), - CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.MetallicTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ), - CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.RoughnessTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ), - CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.EmissiveTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ), - }; - - CHECKED_S(GBuffer.PresentToReadTransitionAllocator->Reset()); - CHECKED_S(GBuffer.TransitionCommandList->Reset(GBuffer.PresentToReadTransitionAllocator.Get(), nullptr)) + return FlowBuilder.emplace([this]() + { + const std::array Barriers = { + CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.DiffuseTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ), + CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.WorldPositionTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ), + CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.WorldNormalTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ), + CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.MetallicTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ), + CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.RoughnessTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ), + CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.EmissiveTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ), + }; - GBuffer.TransitionCommandList->ResourceBarrier(std::size(Barriers), Barriers.data()); - CHECKED_S(GBuffer.TransitionCommandList->Close()); + CHECKED_TF_S(GBuffer.PresentToReadTransitionAllocator->Reset()) + CHECKED_TF_S(GBuffer.TransitionCommandList->Reset(GBuffer.PresentToReadTransitionAllocator.Get(), nullptr)) - ID3D12CommandList* CommandLists[] = {GBuffer.TransitionCommandList.Get()}; - RenderApi->GetDirectQueue() - ->ExecuteCommandLists(1, CommandLists); + GBuffer.TransitionCommandList->ResourceBarrier(std::size(Barriers), Barriers.data()); + CHECKED_TF_S(GBuffer.TransitionCommandList->Close()); - return true; + ID3D12CommandList* CommandLists[] = {GBuffer.TransitionCommandList.Get()}; + RenderApi->GetDirectQueue() + ->ExecuteCommandLists(1, CommandLists); + }); } -bool DeferredRenderer::TransitionGBufferFromReadToRenderTargetState() +tf::Task DeferredRenderer::TransitionGBufferFromReadToRenderTargetState(tf::FlowBuilder& FlowBuilder) { NVTX3_FUNC_RANGE(); - const std::array Barriers = { - CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.DiffuseTexture.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET), - CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.WorldPositionTexture.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET), - CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.WorldNormalTexture.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET), - CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.MetallicTexture.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET), - CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.RoughnessTexture.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET), - CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.EmissiveTexture.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET), - }; - - CHECKED_S(GBuffer.ReadToPresentTransitionAllocator->Reset()); - CHECKED_S(GBuffer.TransitionCommandList->Reset(GBuffer.ReadToPresentTransitionAllocator.Get(), nullptr)) + return FlowBuilder.emplace([this]() + { + const std::array Barriers = { + CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.DiffuseTexture.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET), + CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.WorldPositionTexture.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET), + CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.WorldNormalTexture.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET), + CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.MetallicTexture.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET), + CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.RoughnessTexture.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET), + CD3DX12_RESOURCE_BARRIER::Transition(GBuffer.EmissiveTexture.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET), + }; - GBuffer.TransitionCommandList->ResourceBarrier(std::size(Barriers), Barriers.data()); - CHECKED_S(GBuffer.TransitionCommandList->Close()); + CHECKED_TF_S(GBuffer.ReadToPresentTransitionAllocator->Reset()) + CHECKED_TF_S(GBuffer.TransitionCommandList->Reset(GBuffer.ReadToPresentTransitionAllocator.Get(), nullptr)) - ID3D12CommandList* CommandLists[] = {GBuffer.TransitionCommandList.Get()}; - RenderApi->GetDirectQueue() - ->ExecuteCommandLists(1, CommandLists); + GBuffer.TransitionCommandList->ResourceBarrier(std::size(Barriers), Barriers.data()); + CHECKED_TF_S(GBuffer.TransitionCommandList->Close()) - return true; + ID3D12CommandList* CommandLists[] = {GBuffer.TransitionCommandList.Get()}; + RenderApi->GetDirectQueue() + ->ExecuteCommandLists(1, CommandLists); + }); } } diff --git a/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TaskFailedException.h b/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TaskFailedException.h index 9533157..59412bf 100644 --- a/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TaskFailedException.h +++ b/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TaskFailedException.h @@ -25,11 +25,11 @@ namespace krendrr::Runtime::TaskFlowEx */ #define CHECKED_TF(ApiCall, ErrorMessage) \ { \ -if(FAILED(ApiCall)) \ -{ \ - __debugbreak(); \ - krendrr::Runtime::TaskFlowEx::CancelCurrentTaskflow(); \ -} \ + if(FAILED(ApiCall)) \ + { \ + __debugbreak(); \ + krendrr::Runtime::TaskFlowEx::CancelCurrentTaskflow(); \ + } \ } \ /** @@ -37,9 +37,9 @@ if(FAILED(ApiCall)) \ */ #define CHECKED_TF_S(ApiCall) \ { \ -if(FAILED(ApiCall)) \ -{ \ - __debugbreak(); \ - krendrr::Runtime::TaskFlowEx::CancelCurrentTaskflow(); \ -} \ + if(FAILED(ApiCall)) \ + { \ + __debugbreak(); \ + krendrr::Runtime::TaskFlowEx::CancelCurrentTaskflow(); \ + } \ } \ \ No newline at end of file From a1beaf9d2877c0c5dc3ed423825b0e83297b77e0 Mon Sep 17 00:00:00 2001 From: Kirill Markin Date: Wed, 8 Oct 2025 19:03:24 +0300 Subject: [PATCH 10/13] Add names to tasks to see them in profiler --- .../Deferred/Source/DeferredRenderer.cpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp index 4247f4d..4ed7af6 100644 --- a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp +++ b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp @@ -175,7 +175,7 @@ tf::Task DeferredRenderer::UpdateFrameDataConstantBuffer(const Core::Scene* Scen }; FrameData.ConstantBuffer->Unmap(0, nullptr); - }); + }).name("UpdateFrameDataConstantBuffer Task"); } tf::Task DeferredRenderer::UpdateTexturedMeshConstantBuffers(const Core::Scene* Scene, tf::FlowBuilder& FlowBuilder) @@ -190,7 +190,7 @@ tf::Task DeferredRenderer::UpdateTexturedMeshConstantBuffers(const Core::Scene* if (!TexturedMesh->UpdateConstantBuffer(*RenderApi)) TaskFlowEx::CancelCurrentTaskflow(); } - ); + ).name("UpdateTexturedMeshConstantBuffers Task"); } tf::Task DeferredRenderer::UpdatePointLightConstantBuffers(const Core::Scene* Scene, tf::FlowBuilder& FlowBuilder) @@ -200,12 +200,12 @@ tf::Task DeferredRenderer::UpdatePointLightConstantBuffers(const Core::Scene* Sc auto PointLights = Scene->GetPointLights(); return FlowBuilder.for_each(PointLights.begin(), PointLights.end(), - [Scene, this](const auto& PointLight) + [this](const auto& PointLight) { if (!PointLight->UpdateConstantBuffer(*RenderApi.get())) TaskFlowEx::CancelCurrentTaskflow(); } - ); + ).name("UpdatePointLightConstantBuffers Task"); } bool DeferredRenderer::InitializeGeometryPass() @@ -502,7 +502,7 @@ tf::Task DeferredRenderer::GeometryPass(const Core::Scene* Scene, const Core::Sc if (DrawIndex >= 0) if (!ExecuteCommandList()) TaskFlowEx::CancelCurrentTaskflow(); - }); + }).name("GeometryPass Task"); } bool DeferredRenderer::InitLightPass() @@ -615,7 +615,7 @@ tf::Task DeferredRenderer::PrepareLightPassData(const Core::SceneView& SceneView RenderApi->GetDevice() ->CreateShaderResourceView(LightPassData.ColorTexture.Get(), nullptr, LightPassData.CpuSrvHeap->GetCPUDescriptorHandleForHeapStart()); } - }); + }).name("PrepareLightPassData Task"); } tf::Task DeferredRenderer::TransitionLightPassFromRenderTargetToReadState(tf::FlowBuilder& FlowBuilder) @@ -808,7 +808,7 @@ tf::Task DeferredRenderer::AmbientDirectionalLightPass(const Core::SceneView& Sc ID3D12CommandList* CommandLists[] = {CommandList.Get()}; RenderApi->GetDirectQueue() ->ExecuteCommandLists(1, CommandLists); - }); + }).name("AmbientDirectionalLightPass Task"); } bool DeferredRenderer::InitPointLightShadowCubeMapPass() @@ -1008,7 +1008,7 @@ tf::Task DeferredRenderer::PointLightShadowCubeMapsPass(const Core::Scene* Scene ID3D12CommandList* CommandLists[] = {CommandList.Get()}; RenderApi->GetDirectQueue() ->ExecuteCommandLists(1, CommandLists); - }); + }).name("PointLightShadowCubeMapsPass Task"); } bool DeferredRenderer::InitPointLightVolumePass() @@ -1321,7 +1321,7 @@ tf::Task DeferredRenderer::PointLightVolumesPass(const Core::Scene* Scene, const ID3D12CommandList* CommandLists[] = {CommandList.Get()}; RenderApi->GetDirectQueue() ->ExecuteCommandLists(1, CommandLists); - }); + }).name("PointLightVolumesPass Task"); } bool DeferredRenderer::InitPostProcessingPass() @@ -1499,7 +1499,7 @@ tf::Task DeferredRenderer::PostRenderPasses(const Core::SceneView& SceneView, tf PostRender(SceneView, Subflow), TransitionGBufferFromReadToRenderTargetState(Subflow) }); - }); + }).name("PostRenderPasses Task"); } bool DeferredRenderer::Shutdown() @@ -1622,7 +1622,7 @@ tf::Task DeferredRenderer::PreRender(const Core::Scene* Scene, const Core::Scene if (!PointLight->HasShadowResources()) PointLight->CreateShadowCubeMapResource(*RenderApi); } - }); + }).name("PreRender Task"); } tf::Task DeferredRenderer::PostRender(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) @@ -1668,7 +1668,7 @@ tf::Task DeferredRenderer::WaitDirectQueueTask(tf::FlowBuilder& FlowBuilder) { return FrameFence->GetCompletedValue() >= ExpectedValue; }); - }); + }).name("WaitDirectQueue Task"); } bool DeferredRenderer::WaitDirectQueue() @@ -1972,7 +1972,7 @@ tf::Task DeferredRenderer::InitGBufferForView(const Core::SceneView& SceneView, } GBuffer.Size = ViewportSize; - }); + }).name("InitGBufferForView Task"); } tf::Task DeferredRenderer::TransitionGBufferFromRenderTargetToReadState(tf::FlowBuilder& FlowBuilder) @@ -1999,7 +1999,7 @@ tf::Task DeferredRenderer::TransitionGBufferFromRenderTargetToReadState(tf::Flow ID3D12CommandList* CommandLists[] = {GBuffer.TransitionCommandList.Get()}; RenderApi->GetDirectQueue() ->ExecuteCommandLists(1, CommandLists); - }); + }).name("TransitionGBufferFromRenderTargetToReadState Task"); } tf::Task DeferredRenderer::TransitionGBufferFromReadToRenderTargetState(tf::FlowBuilder& FlowBuilder) From 7dbd195714e033dbcce4764f02c47128a20e3243 Mon Sep 17 00:00:00 2001 From: Kirill Markin Date: Wed, 8 Oct 2025 19:19:47 +0300 Subject: [PATCH 11/13] Make second light dynamic on sponza --- Source/Examples/DeferredRendering/Source/Application.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Examples/DeferredRendering/Source/Application.cpp b/Source/Examples/DeferredRendering/Source/Application.cpp index 9f7d4be..055f1a1 100644 --- a/Source/Examples/DeferredRendering/Source/Application.cpp +++ b/Source/Examples/DeferredRendering/Source/Application.cpp @@ -230,8 +230,7 @@ void krendrr::Examples::SimpleDeferredRendering::Application::SetupSponzaScene() auto PointLight1 = Scene->SpawnPointLight(); PointLight1->SetPosition({1000, 250, 0}); - PointLight1->SetColor({1.f, 0.3f, 0.3f}); - PointLight1->SetCastsShadows(false); + PointLight1->SetColor({1.f, 1.f, 1.f}); auto PointLight2 = Scene->SpawnPointLight(); PointLight2->SetPosition({-1100, 250, 0}); From d3e4dd57d8bf4a3bc53a4a96eca417287a471811 Mon Sep 17 00:00:00 2001 From: Kirill Markin Date: Wed, 8 Oct 2025 21:25:03 +0300 Subject: [PATCH 12/13] Adjust descriptor heap size dynamically for geometry pass --- .../Renderer/Deferred/DeferredRenderer.h | 2 +- .../Deferred/Source/DeferredRenderer.cpp | 107 +++++------------- 2 files changed, 30 insertions(+), 79 deletions(-) diff --git a/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h index b80c677..c9217dd 100644 --- a/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h +++ b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h @@ -148,11 +148,11 @@ namespace krendrr::Runtime::Renderer::Deferred Microsoft::WRL::ComPtr RootSignature {}; Microsoft::WRL::ComPtr PipelineState {}; - constexpr inline static unsigned PARALLEL_DRAWS_COUNT_ALLOWED = 1000; Microsoft::WRL::ComPtr DrawCommandAllocator {}; Microsoft::WRL::ComPtr DrawCommandList {}; Microsoft::WRL::ComPtr GpuDescriptorHeap {}; + unsigned CurrentGpuDescriptorSize {}; }; GeometryPassData GeometryPassData {}; diff --git a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp index 4ed7af6..cea4675 100644 --- a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp +++ b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp @@ -65,8 +65,6 @@ bool DeferredRenderer::Initialize(std::shared_ptr Ne bool DeferredRenderer::Render(const Core::Scene* Scene, const std::span& SceneViews, tf::FlowBuilder& FlowBuilder) { - NVTX3_FUNC_RANGE(); - if (Scene->GetPointLights().size() > PointLightVolumePassData.MAX_DYNAMIC_POINT_LIGHTS_COUNT) { // TODO: add error log @@ -144,8 +142,6 @@ bool DeferredRenderer::Render(const Core::Scene* Scene, const std::spanGetTexturedMeshes(); return FlowBuilder.for_each(TexturedMeshes.begin(), TexturedMeshes.end(), @@ -195,8 +189,6 @@ tf::Task DeferredRenderer::UpdateTexturedMeshConstantBuffers(const Core::Scene* tf::Task DeferredRenderer::UpdatePointLightConstantBuffers(const Core::Scene* Scene, tf::FlowBuilder& FlowBuilder) { - NVTX3_FUNC_RANGE(); - auto PointLights = Scene->GetPointLights(); return FlowBuilder.for_each(PointLights.begin(), PointLights.end(), @@ -254,21 +246,6 @@ bool DeferredRenderer::InitializeGeometryPass() if (!GeometryPassData.PipelineState) return false; - // Create GPU srv heap for textured mesh texture handles - { - D3D12_DESCRIPTOR_HEAP_DESC HeapDesc { - .Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - .NumDescriptors = GeometryPassData.PARALLEL_DRAWS_COUNT_ALLOWED * GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT, - .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE - }; - - CHECKED( - RenderApi->GetDevice() - ->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&GeometryPassData.GpuDescriptorHeap)), - "Can't create descriptor heap" - ) - } - // Create command list { CHECKED( @@ -292,10 +269,28 @@ bool DeferredRenderer::InitializeGeometryPass() tf::Task DeferredRenderer::GeometryPass(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - NVTX3_FUNC_RANGE(); - return FlowBuilder.emplace([Scene, SceneView, this]() { + const unsigned SrvDescriptorsCount = static_cast(Scene->GetTexturedMeshes().size()) * GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT; + + // Make sure we have a descriptor heap with enough size + if (GeometryPassData.CurrentGpuDescriptorSize == 0 || GeometryPassData.CurrentGpuDescriptorSize < SrvDescriptorsCount) + { + D3D12_DESCRIPTOR_HEAP_DESC HeapDesc { + .Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + .NumDescriptors = SrvDescriptorsCount, + .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE + }; + + CHECKED_TF( + RenderApi->GetDevice() + ->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&GeometryPassData.GpuDescriptorHeap)), + "Can't create descriptor heap" + ) + + GeometryPassData.CurrentGpuDescriptorSize = SrvDescriptorsCount; + } + const unsigned RtvHandleIncrement = RenderApi->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); const unsigned SrvHandleIncrement = RenderApi->GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); @@ -312,7 +307,7 @@ tf::Task DeferredRenderer::GeometryPass(const Core::Scene* Scene, const Core::Sc auto ExecuteCommandList = [this, CommandList]() -> bool { - CHECKED_S(CommandList->Close()) + CHECKED_TF_S(CommandList->Close()) ID3D12CommandList* CommandLists[] = {CommandList.Get()}; @@ -324,8 +319,8 @@ tf::Task DeferredRenderer::GeometryPass(const Core::Scene* Scene, const Core::Sc auto ResetCommandList = [this, &CommandAllocator, &CommandList, &SceneView, &RtvHandles, &DsvHandle]() -> bool { - CHECKED_S(CommandAllocator->Reset()); - CHECKED_S(CommandList->Reset(CommandAllocator.Get(), GeometryPassData.PipelineState.Get())); + CHECKED_TF_S(CommandAllocator->Reset()); + CHECKED_TF_S(CommandList->Reset(CommandAllocator.Get(), GeometryPassData.PipelineState.Get())); // Setup pipeline @@ -367,30 +362,14 @@ tf::Task DeferredRenderer::GeometryPass(const Core::Scene* Scene, const Core::Sc nullptr ); - int DrawIndex = -1; - for (const std::shared_ptr& TexturedMesh : Scene->GetTexturedMeshes()) + auto TexturedMeshes = Scene->GetTexturedMeshes(); + for (int DrawIndex = 0; DrawIndex < TexturedMeshes.size(); ++DrawIndex) { + const std::shared_ptr& TexturedMesh = TexturedMeshes[DrawIndex]; nvtx3::scoped_range MeshIterationRange {"Mesh Iteration"}; auto Mesh = TexturedMesh->GetMesh(); - // Make sure we have enough descriptors to draw this textured mesh - { - if (DrawIndex + 1 == GeometryPassData.PARALLEL_DRAWS_COUNT_ALLOWED) - { - if (!ExecuteCommandList()) - TaskFlowEx::CancelCurrentTaskflow(); - - WaitDirectQueue(); - - DrawIndex = -1; - - if (!ResetCommandList()) - TaskFlowEx::CancelCurrentTaskflow(); - } - DrawIndex += 1; - } - // Setup Mesh { D3D12_VERTEX_BUFFER_VIEW VertexBufferView = Mesh->GetVertexBufferView(); @@ -499,9 +478,9 @@ tf::Task DeferredRenderer::GeometryPass(const Core::Scene* Scene, const Core::Sc } } - if (DrawIndex >= 0) - if (!ExecuteCommandList()) - TaskFlowEx::CancelCurrentTaskflow(); + if (!ExecuteCommandList()) + TaskFlowEx::CancelCurrentTaskflow(); + }).name("GeometryPass Task"); } @@ -536,8 +515,6 @@ bool DeferredRenderer::InitLightPass() tf::Task DeferredRenderer::PrepareLightPassData(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - NVTX3_FUNC_RANGE(); - return FlowBuilder.emplace([SceneView, this]() { const glm::ivec2 ViewportSize = SceneView.GetViewportSize(); @@ -620,8 +597,6 @@ tf::Task DeferredRenderer::PrepareLightPassData(const Core::SceneView& SceneView tf::Task DeferredRenderer::TransitionLightPassFromRenderTargetToReadState(tf::FlowBuilder& FlowBuilder) { - NVTX3_FUNC_RANGE(); - return FlowBuilder.emplace([this]() { CD3DX12_RESOURCE_BARRIER Barrier = CD3DX12_RESOURCE_BARRIER::Transition(LightPassData.ColorTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ); @@ -640,8 +615,6 @@ tf::Task DeferredRenderer::TransitionLightPassFromRenderTargetToReadState(tf::Fl tf::Task DeferredRenderer::TransitionLightPassFromReadToRenderTargetState(tf::FlowBuilder& FlowBuilder) { - NVTX3_FUNC_RANGE(); - return FlowBuilder.emplace([this]() { CD3DX12_RESOURCE_BARRIER Barrier = CD3DX12_RESOURCE_BARRIER::Transition( @@ -731,8 +704,6 @@ bool DeferredRenderer::InitAmbientDirectionalLightPass() tf::Task DeferredRenderer::AmbientDirectionalLightPass(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - NVTX3_FUNC_RANGE(); - return FlowBuilder.emplace([SceneView, this]() { auto& CommandList = AmbientDirectionalLightPassData.CommandList; @@ -869,8 +840,6 @@ bool DeferredRenderer::InitPointLightShadowCubeMapPass() tf::Task DeferredRenderer::PointLightShadowCubeMapsPass(const Core::Scene* Scene, tf::FlowBuilder& FlowBuilder) { - NVTX3_FUNC_RANGE(); - return FlowBuilder.emplace([Scene, this]() { auto& CommandAllocator = PointLightShadowCubeMapData.CommandAllocator; @@ -1168,8 +1137,6 @@ bool DeferredRenderer::InitPointLightVolumePass() tf::Task DeferredRenderer::PointLightVolumesPass(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - NVTX3_FUNC_RANGE(); - return FlowBuilder.emplace([Scene, SceneView, this]() { auto& CommandAllocator = PointLightVolumePassData.CommandAllocator; @@ -1394,8 +1361,6 @@ bool DeferredRenderer::InitPostProcessingPass() tf::Task DeferredRenderer::PostProcessingPass(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - NVTX3_FUNC_RANGE(); - return FlowBuilder.emplace([SceneView, this]() { auto& CommandList = PostProcessingPassData.CommandList; @@ -1593,8 +1558,6 @@ bool DeferredRenderer::InitPrePostRender() tf::Task DeferredRenderer::PreRender(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - NVTX3_FUNC_RANGE(); - return FlowBuilder.emplace([Scene, SceneView, this]() { CHECKED_TF_S(PrePostRenderData.CommandAllocator->Reset()); @@ -1627,8 +1590,6 @@ tf::Task DeferredRenderer::PreRender(const Core::Scene* Scene, const Core::Scene tf::Task DeferredRenderer::PostRender(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - NVTX3_FUNC_RANGE(); - return FlowBuilder.emplace([SceneView, this]() { CHECKED_TF( @@ -1652,8 +1613,6 @@ tf::Task DeferredRenderer::PostRender(const Core::SceneView& SceneView, tf::Flow tf::Task DeferredRenderer::WaitDirectQueueTask(tf::FlowBuilder& FlowBuilder) { - NVTX3_FUNC_RANGE(); - return FlowBuilder.emplace([this](tf::Subflow& Subflow) { const uint64_t ExpectedValue = ++FrameFenceValue; @@ -1673,8 +1632,6 @@ tf::Task DeferredRenderer::WaitDirectQueueTask(tf::FlowBuilder& FlowBuilder) bool DeferredRenderer::WaitDirectQueue() { - NVTX3_FUNC_RANGE(); - CHECKED( RenderApi->GetDirectQueue() ->Signal(FrameFence.Get(), ++FrameFenceValue), @@ -1805,8 +1762,6 @@ bool DeferredRenderer::InitEmptyTexture() tf::Task DeferredRenderer::InitGBufferForView(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - NVTX3_FUNC_RANGE(); - return FlowBuilder.emplace([SceneView, this]() { const glm::ivec2 ViewportSize = SceneView.GetViewportSize(); @@ -1977,8 +1932,6 @@ tf::Task DeferredRenderer::InitGBufferForView(const Core::SceneView& SceneView, tf::Task DeferredRenderer::TransitionGBufferFromRenderTargetToReadState(tf::FlowBuilder& FlowBuilder) { - NVTX3_FUNC_RANGE(); - return FlowBuilder.emplace([this]() { const std::array Barriers = { @@ -2004,8 +1957,6 @@ tf::Task DeferredRenderer::TransitionGBufferFromRenderTargetToReadState(tf::Flow tf::Task DeferredRenderer::TransitionGBufferFromReadToRenderTargetState(tf::FlowBuilder& FlowBuilder) { - NVTX3_FUNC_RANGE(); - return FlowBuilder.emplace([this]() { const std::array Barriers = { From ef3e166071d1979859d1d335e583b6e2026c1cad Mon Sep 17 00:00:00 2001 From: Kirill Markin Date: Wed, 8 Oct 2025 21:27:47 +0300 Subject: [PATCH 13/13] remove redurant line break --- .../Core/Include/Runtime/RenderApi/Core/ApiCallCheck.h | 8 ++++---- .../Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp | 4 ++-- .../Runtime/TfExecutorBuilder/TaskFailedException.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/Runtime/RenderApi/Core/Include/Runtime/RenderApi/Core/ApiCallCheck.h b/Source/Runtime/RenderApi/Core/Include/Runtime/RenderApi/Core/ApiCallCheck.h index a28b2d6..f6a8dd6 100644 --- a/Source/Runtime/RenderApi/Core/Include/Runtime/RenderApi/Core/ApiCallCheck.h +++ b/Source/Runtime/RenderApi/Core/Include/Runtime/RenderApi/Core/ApiCallCheck.h @@ -13,7 +13,7 @@ __debugbreak(); \ return {}; \ } \ -} \ +} /** * Checks if api call was successful. returns false or default value if false @@ -25,7 +25,7 @@ __debugbreak(); \ return {}; \ } \ -} \ +} // TODO: add error log /** @@ -38,7 +38,7 @@ __debugbreak(); \ return; \ } \ -} \ +} /** * Checks if api call was successful. Returns if not @@ -50,4 +50,4 @@ __debugbreak(); \ return; \ } \ -} \ +} diff --git a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp index cea4675..f10bf7a 100644 --- a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp +++ b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp @@ -319,8 +319,8 @@ tf::Task DeferredRenderer::GeometryPass(const Core::Scene* Scene, const Core::Sc auto ResetCommandList = [this, &CommandAllocator, &CommandList, &SceneView, &RtvHandles, &DsvHandle]() -> bool { - CHECKED_TF_S(CommandAllocator->Reset()); - CHECKED_TF_S(CommandList->Reset(CommandAllocator.Get(), GeometryPassData.PipelineState.Get())); + CHECKED_TF_S(CommandAllocator->Reset()) + CHECKED_TF_S(CommandList->Reset(CommandAllocator.Get(), GeometryPassData.PipelineState.Get())) // Setup pipeline diff --git a/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TaskFailedException.h b/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TaskFailedException.h index 59412bf..ae7a969 100644 --- a/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TaskFailedException.h +++ b/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TaskFailedException.h @@ -30,7 +30,7 @@ namespace krendrr::Runtime::TaskFlowEx __debugbreak(); \ krendrr::Runtime::TaskFlowEx::CancelCurrentTaskflow(); \ } \ -} \ +} /** * Checks if api call was successful. If not, cancels current taskflow @@ -42,4 +42,4 @@ namespace krendrr::Runtime::TaskFlowEx __debugbreak(); \ krendrr::Runtime::TaskFlowEx::CancelCurrentTaskflow(); \ } \ -} \ \ No newline at end of file +} \ No newline at end of file