diff --git a/Source/Examples/DeferredRendering/Include/Examples/SimpleDeferredRendering/Application.h b/Source/Examples/DeferredRendering/Include/Examples/SimpleDeferredRendering/Application.h index fec7bfe..8e9d701 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; @@ -55,6 +50,8 @@ namespace krendrr::Examples::SimpleDeferredRendering bool InitializeSceneViewAndCamera(); + bool FillRenderTaskflow(tf::Taskflow& Taskflow); + }; } diff --git a/Source/Examples/DeferredRendering/Source/Application.cpp b/Source/Examples/DeferredRendering/Source/Application.cpp index a4ddea4..055f1a1 100644 --- a/Source/Examples/DeferredRendering/Source/Application.cpp +++ b/Source/Examples/DeferredRendering/Source/Application.cpp @@ -7,8 +7,9 @@ #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/TaskFailedException.h" #include "Runtime/TfExecutorBuilder/TfExecutorBuilder.h" IMPLEMENT_ENTRY_POINT(krendrr::Examples::SimpleDeferredRendering::Application) @@ -31,8 +32,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) @@ -86,7 +87,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; @@ -102,11 +103,55 @@ 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; + } } + Camera.Update(DeltaTime); + + tf::Taskflow MainTaskFlow {}; + + tf::Taskflow RenderTaskFlow {}; + if (!FillRenderTaskflow(RenderTaskFlow)) + return false; + + tf::Task RendererTickTask = MainTaskFlow + .composed_of(RenderTaskFlow) + .name("Renderer Tick Task"); + + tf::Task SwapTask = MainTaskFlow.emplace( + [&]() + { + if (!Window->Swap()) + { + // TODO: add error log + Runtime::TaskFlowEx::CancelCurrentTaskflow(); + } + } + ).name("Window Swap Task"); + + // Allow render tick task to go straight to end task in case of an error + RendererTickTask.precede(SwapTask); + + try + { + TfExecutor->run(MainTaskFlow).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 glm::ivec2 WindowSize = Window->GetSize(); - Runtime::Application::Core::Window::WindowRenderData RenderData = Window->GetCurrentRenderTargetView(); + const Runtime::Application::Core::Window::WindowRenderData RenderData = Window->GetCurrentRenderTargetView(); const bool bRenderDataSetSuccess = SceneView.SetRenderData( { @@ -124,20 +169,14 @@ bool krendrr::Examples::SimpleDeferredRendering::Application::Tick(float DeltaTi if (!bRenderDataSetSuccess) return false; - Camera.Update(DeltaTime); - std::array Views = { SceneView }; - if (!Renderer->Render(Views)) - { - // TODO: add error log - return false; - } - if (!Window->Swap()) + if (!Renderer->Render(Scene.get(), Views, Taskflow)) { // TODO: add error log + return false; } @@ -191,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}); diff --git a/Source/Runtime/ModelLoader/Include/Runtime/ModelLoader/Loader.h b/Source/Runtime/ModelLoader/Include/Runtime/ModelLoader/Loader.h index a922b43..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/TexturedMesh.h" +#include "Runtime/Renderer/Core/Scene/Objects/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..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/Mesh.h" -#include "Runtime/Renderer/Core/TexturedMesh/Texture.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 {}; @@ -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( + RenderApi::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 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/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/Core/Include/Runtime/Renderer/Core/TexturedMesh/Mesh.h b/Source/Runtime/RenderApi/Core/Include/Runtime/RenderApi/Core/Resources/StaticMesh.h similarity index 74% rename from Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/Mesh.h rename to Source/Runtime/RenderApi/Core/Include/Runtime/RenderApi/Core/Resources/StaticMesh.h index 9e06876..f471f71 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/Mesh.h +++ b/Source/Runtime/RenderApi/Core/Include/Runtime/RenderApi/Core/Resources/StaticMesh.h @@ -5,18 +5,18 @@ #include "Runtime/RenderApi/Core/RenderApi.h" #include "d3dx12/d3dx12.h" -namespace krendrr::Runtime::Renderer::Core +namespace krendrr::Runtime::RenderApi::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 { @@ -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/Texture.h b/Source/Runtime/RenderApi/Core/Include/Runtime/RenderApi/Core/Resources/Texture2D.h similarity index 80% rename from Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/Texture.h rename to Source/Runtime/RenderApi/Core/Include/Runtime/RenderApi/Core/Resources/Texture2D.h index b74541f..ae23c80 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/Texture.h +++ b/Source/Runtime/RenderApi/Core/Include/Runtime/RenderApi/Core/Resources/Texture2D.h @@ -3,22 +3,21 @@ #include #include #include - #include "glm/vec2.hpp" #include "Runtime/RenderApi/Core/RenderApi.h" -namespace krendrr::Runtime::Renderer::Core +namespace krendrr::Runtime::RenderApi::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 { @@ -53,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/Mesh.cpp b/Source/Runtime/RenderApi/Core/Source/Resources/StaticMesh.cpp similarity index 79% rename from Source/Runtime/Renderer/Core/Source/TexturedMesh/Mesh.cpp rename to Source/Runtime/RenderApi/Core/Source/Resources/StaticMesh.cpp index 3f4d995..37d05d9 100644 --- a/Source/Runtime/Renderer/Core/Source/TexturedMesh/Mesh.cpp +++ b/Source/Runtime/RenderApi/Core/Source/Resources/StaticMesh.cpp @@ -1,9 +1,9 @@ -#include "Runtime/Renderer/Core/TexturedMesh/Mesh.h" +#include "Runtime/RenderApi/Core/Resources/StaticMesh.h" #include "Runtime/RenderApi/Core/ApiCallCheck.h" -namespace krendrr::Runtime::Renderer::Core +namespace krendrr::Runtime::RenderApi::Core { - Mesh::MeshLoadOperation Mesh::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 }; } - 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& 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 Mesh::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); @@ -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/RenderApi/Core/Source/Resources/Texture2D.cpp similarity index 88% rename from Source/Runtime/Renderer/Core/Source/TexturedMesh/Texture.cpp rename to Source/Runtime/RenderApi/Core/Source/Resources/Texture2D.cpp index 64bf9b2..ae9e942 100644 --- a/Source/Runtime/Renderer/Core/Source/TexturedMesh/Texture.cpp +++ b/Source/Runtime/RenderApi/Core/Source/Resources/Texture2D.cpp @@ -1,21 +1,19 @@ -#include "Runtime/Renderer/Core/TexturedMesh/Texture.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 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& RenderApi, ID3D12GraphicsCommandList& CommandList, const std::string_view& TextureFileName, const TextureLoadParams& Params) { if(IsLoaded()) @@ -155,7 +153,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 +161,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/Include/Runtime/Renderer/Core/Renderer.h b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h index 3bc40e7..8916e74 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h +++ b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Renderer.h @@ -1,11 +1,13 @@ #pragma once +#include #include #include namespace tf { class Executor; + class FlowBuilder; } namespace krendrr::Runtime::RenderApi::Core @@ -19,22 +21,29 @@ 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; + /** + * 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 Shutdown() = 0; 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 99% 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 index c94cb4a..e4f6a3f 100644 --- 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 @@ -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/Core/Include/Runtime/Renderer/Core/TexturedMesh/TexturedMesh.h b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Objects/TexturedStaticMesh.h similarity index 75% rename from Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/TexturedMesh.h rename to Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Objects/TexturedStaticMesh.h index 585f6f4..c1f9039 100644 --- a/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/TexturedMesh/TexturedMesh.h +++ b/Source/Runtime/Renderer/Core/Include/Runtime/Renderer/Core/Scene/Objects/TexturedStaticMesh.h @@ -9,28 +9,31 @@ #include "glm/detail/type_quat.hpp" #include "Runtime/RenderApi/Core/RenderApi.h" -namespace krendrr::Runtime::Renderer::Core +namespace krendrr::Runtime::RenderApi::Core { - class Texture; - class Mesh; + class StaticMesh; + class Texture2D; +} +namespace krendrr::Runtime::Renderer::Core +{ /** * 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 +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 5bede42..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" @@ -14,16 +13,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 +53,7 @@ namespace krendrr::Runtime::Renderer::Core private: - std::vector> TexturedMeshes {}; + std::vector> TexturedMeshes {}; std::vector> PointLights {}; 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/TexturedMesh.cpp b/Source/Runtime/Renderer/Core/Source/Scene/Objects/TexturedStaticMesh.cpp similarity index 59% rename from Source/Runtime/Renderer/Core/Source/TexturedMesh/TexturedMesh.cpp rename to Source/Runtime/Renderer/Core/Source/Scene/Objects/TexturedStaticMesh.cpp index f1ebb39..7884911 100644 --- a/Source/Runtime/Renderer/Core/Source/TexturedMesh/TexturedMesh.cpp +++ b/Source/Runtime/Renderer/Core/Source/Scene/Objects/TexturedStaticMesh.cpp @@ -1,26 +1,26 @@ -#include "Runtime/Renderer/Core/TexturedMesh/TexturedMesh.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" 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/Core/Source/Scene/Scene.cpp b/Source/Runtime/Renderer/Core/Source/Scene/Scene.cpp index 8a071b5..da11177 100644 --- a/Source/Runtime/Renderer/Core/Source/Scene/Scene.cpp +++ b/Source/Runtime/Renderer/Core/Source/Scene/Scene.cpp @@ -1,13 +1,12 @@ #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/Scene/Lights/PointLight.h" +#include "Runtime/Renderer/Core/Scene/Objects/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 +15,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 +31,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 +46,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/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h b/Source/Runtime/Renderer/Deferred/Include/Runtime/Renderer/Deferred/DeferredRenderer.h index 1fb89ab..c9217dd 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,9 @@ #include #include #include "Runtime/Renderer/Core/Renderer.h" -#include "Runtime/Renderer/Core/TexturedMesh/Mesh.h" -#include "Runtime/Renderer/Core/TexturedMesh/TexturedMesh.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 { @@ -12,21 +13,19 @@ 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, tf::FlowBuilder& FlowBuilder) override; bool Shutdown() override; private: std::shared_ptr RenderApi {}; - std::shared_ptr Scene {}; - std::shared_ptr TfExecutor {}; - std::shared_ptr FullscreenQuadMesh {}; - std::shared_ptr SphereMesh {}; + std::shared_ptr FullscreenQuadMesh {}; + std::shared_ptr SphereMesh {}; bool InitBasicMeshes(); struct PrePostRenderData @@ -38,12 +37,16 @@ namespace krendrr::Runtime::Renderer::Deferred PrePostRenderData PrePostRenderData {}; bool InitPrePostRender(); - bool PreRender(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(); @@ -83,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); @@ -124,9 +129,11 @@ namespace krendrr::Runtime::Renderer::Deferred FrameData FrameData {}; - bool UpdateFrameDataConstantBuffer(const Core::SceneView& SceneView); - bool UpdateTexturedMeshConstantBuffers(); - bool UpdatePointLightConstantBuffers(); + tf::Task UpdateFrameDataConstantBuffer(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder); + + tf::Task UpdateTexturedMeshConstantBuffers(const Core::Scene* Scene, tf::FlowBuilder& FlowBuilder); + + tf::Task UpdatePointLightConstantBuffers(const Core::Scene* Scene, tf::FlowBuilder& FlowBuilder); struct GeometryPassData { @@ -141,16 +148,17 @@ 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 {}; bool InitializeGeometryPass(); - bool GeometryPass(const Core::SceneView& SceneView); + + tf::Task GeometryPass(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder); struct LightPassData { @@ -170,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 { @@ -187,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 { @@ -200,7 +212,8 @@ namespace krendrr::Runtime::Renderer::Deferred PointLightShadowCubeMapData PointLightShadowCubeMapData {}; bool InitPointLightShadowCubeMapPass(); - bool PointLightShadowCubeMapsPass(); + + tf::Task PointLightShadowCubeMapsPass(const Core::Scene* Scene, tf::FlowBuilder& FlowBuilder); struct PointLightVolumePassData { @@ -221,7 +234,8 @@ namespace krendrr::Runtime::Renderer::Deferred PointLightVolumePassData PointLightVolumePassData{}; bool InitPointLightVolumePass(); - bool PointLightVolumesPass(const Core::SceneView& SceneView); + + tf::Task PointLightVolumesPass(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder); struct PostProcessingPassData { @@ -236,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 7c0f0ae..f10bf7a 100644 --- a/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp +++ b/Source/Runtime/Renderer/Deferred/Source/DeferredRenderer.cpp @@ -4,24 +4,24 @@ #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/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" +#include "Runtime/TfExecutorBuilder/TaskFailedException.h" +#include "taskflow/algorithm/for_each.hpp" 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 +63,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, tf::FlowBuilder& FlowBuilder) { if (Scene->GetPointLights().size() > PointLightVolumePassData.MAX_DYNAMIC_POINT_LIGHTS_COUNT) { @@ -71,122 +71,133 @@ bool DeferredRenderer::Render(const std::span& SceneViews) return false; } + std::vector SceneViewTasks {}; + SceneViewTasks.reserve(SceneViews.size()); + for (const Core::SceneView& SceneView : SceneViews) { - if (!UpdateFrameDataConstantBuffer(SceneView)) - return false; - - if (!UpdateTexturedMeshConstantBuffers()) - return false; - - if (!UpdatePointLightConstantBuffers()) - return false; - - if (!PreRender(SceneView)) - return false; - - if (!InitGBufferForView(SceneView)) - return false; - - if (!GeometryPass(SceneView)) - return false; - - if (!TransitionGBufferFromRenderTargetToReadState()) - return false; - - if (!PrepareLightPassData(SceneView)) - return false; + auto SceneViewTask = FlowBuilder.emplace([Scene, SceneView, this](tf::Subflow& Subflow) + { + 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 (!AmbientDirectionalLightPass(SceneView)) - return false; + auto PointLightShadowCubeMapPassTask = PointLightShadowCubeMapsPass(Scene, Subflow) + .succeed( + PreRenderTask + ); - if (!PointLightShadowCubeMapsPass()) - return false; + auto GeometryPassTask = GeometryPass(Scene, SceneView, Subflow) + .succeed( + PreRenderTask + ); - if (!PointLightVolumesPass(SceneView)) - return false; + auto GBufferToReadStateTask = TransitionGBufferFromRenderTargetToReadState(Subflow) + .succeed(GeometryPassTask); - if (!TransitionLightPassFromRenderTargetToReadState()) - return false; + auto AmbientDirectionalLightPassTask = AmbientDirectionalLightPass(SceneView, Subflow) + .succeed( + GBufferToReadStateTask, + GeometryPassTask + ); - if (!PostProcessingPass(SceneView)) - return false; + auto PointLightVolumePass = PointLightVolumesPass(Scene, SceneView, Subflow) + .succeed( + AmbientDirectionalLightPassTask, + GeometryPassTask, + GBufferToReadStateTask, + PointLightShadowCubeMapPassTask + ); - if (!TransitionLightPassFromReadToRenderTargetState()) - return false; + auto PostRenderPassesTask = PostRenderPasses(SceneView, Subflow) + .succeed( + PointLightVolumePass, + AmbientDirectionalLightPassTask + ); - if (!PostRender(SceneView)) - return false; + WaitDirectQueueTask(Subflow) + .succeed( + PostRenderPassesTask + ); - if (!TransitionGBufferFromReadToRenderTargetState()) - return false; + }).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; } -bool DeferredRenderer::UpdateFrameDataConstantBuffer(const Core::SceneView& SceneView) +tf::Task DeferredRenderer::UpdateFrameDataConstantBuffer(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - nvtx3::scoped_range ConstBufUpdateRange {"Update Frame Data Constant Buffer"}; - - // Create buffer if not created - if (FrameData.ConstantBuffer == nullptr) + return FlowBuilder.emplace([Scene, SceneView, this]() { - if (!BuildConstantBuffer(*RenderApi, FrameData.ConstantBuffer, FrameData.CpuSrvHeap, L"Frame Data Constant Buffer")) - return false; - } - - // 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(), - }; + // Create buffer if not created + if (FrameData.ConstantBuffer == nullptr) + { + if (!BuildConstantBuffer(*RenderApi, FrameData.ConstantBuffer, FrameData.CpuSrvHeap, L"Frame Data Constant Buffer")) + TaskFlowEx::CancelCurrentTaskflow(); + } - FrameData.ConstantBuffer->Unmap(0, nullptr); + // 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(), + }; - return true; + FrameData.ConstantBuffer->Unmap(0, nullptr); + }).name("UpdateFrameDataConstantBuffer Task"); } -bool DeferredRenderer::UpdateTexturedMeshConstantBuffers() +tf::Task DeferredRenderer::UpdateTexturedMeshConstantBuffers(const Core::Scene* Scene, tf::FlowBuilder& FlowBuilder) { - nvtx3::scoped_range ConstBufUpdateRange {"Update Textured Mesh Constant Buffers"}; + auto TexturedMeshes = Scene->GetTexturedMeshes(); - for (auto& TexturedMesh : Scene->GetTexturedMeshes()) - { - if (!TexturedMesh->UpdateConstantBuffer(*RenderApi)) - return false; - } - - return true; + return FlowBuilder.for_each(TexturedMeshes.begin(), TexturedMeshes.end(), + [&](const auto& TexturedMesh) + { + if (!TexturedMesh->UpdateConstantBuffer(*RenderApi)) + TaskFlowEx::CancelCurrentTaskflow(); + } + ).name("UpdateTexturedMeshConstantBuffers Task"); } -bool DeferredRenderer::UpdatePointLightConstantBuffers() +tf::Task DeferredRenderer::UpdatePointLightConstantBuffers(const Core::Scene* Scene, tf::FlowBuilder& FlowBuilder) { - nvtx3::scoped_range ConstBufUpdateRange {"Update Point Light Constant Buffers"}; - - for (auto& PointLight : Scene->GetPointLights()) - { - if (!PointLight->UpdateConstantBuffer(*RenderApi.get())) - return false; - } + auto PointLights = Scene->GetPointLights(); - return true; + return FlowBuilder.for_each(PointLights.begin(), PointLights.end(), + [this](const auto& PointLight) + { + if (!PointLight->UpdateConstantBuffer(*RenderApi.get())) + TaskFlowEx::CancelCurrentTaskflow(); + } + ).name("UpdatePointLightConstantBuffers Task"); } bool DeferredRenderer::InitializeGeometryPass() @@ -235,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( @@ -271,218 +267,221 @@ bool DeferredRenderer::InitializeGeometryPass() return true; } -bool DeferredRenderer::GeometryPass(const Core::SceneView& SceneView) +tf::Task DeferredRenderer::GeometryPass(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - nvtx3::scoped_range PassRange {"Geometry Pass"}; - - 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(); - - auto& CommandAllocator = GeometryPassData.DrawCommandAllocator; - auto& CommandList = GeometryPassData.DrawCommandList; + const unsigned SrvDescriptorsCount = static_cast(Scene->GetTexturedMeshes().size()) * GeometryPassData.TEXTURED_MESH_TEXTURES_COUNT; - auto ExecuteCommandList = [this, CommandList]() -> bool - { - CHECKED_S(CommandList->Close()) + // 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 + }; - ID3D12CommandList* CommandLists[] = {CommandList.Get()}; + CHECKED_TF( + RenderApi->GetDevice() + ->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&GeometryPassData.GpuDescriptorHeap)), + "Can't create descriptor heap" + ) - RenderApi->GetDirectQueue() - ->ExecuteCommandLists(1, CommandLists); + GeometryPassData.CurrentGpuDescriptorSize = SrvDescriptorsCount; + } - return true; - }; + 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 ResetCommandList = [this, &CommandAllocator, &CommandList, &SceneView, &RtvHandles, &DsvHandle]() -> bool - { - CHECKED_S(CommandAllocator->Reset()); - CHECKED_S(CommandList->Reset(CommandAllocator.Get(), GeometryPassData.PipelineState.Get())); + std::array RtvHandles {}; + for (int i = 0; i < GBuffer.TEXTURES_COUNT; ++i) + { + RtvHandles[i] = CD3DX12_CPU_DESCRIPTOR_HANDLE{GBuffer.CpuRtvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), i, RtvHandleIncrement}; + } - // Setup pipeline + const D3D12_CPU_DESCRIPTOR_HANDLE DsvHandle = GBuffer.CpuDsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); - CommandList->SetGraphicsRootSignature(GeometryPassData.RootSignature.Get()); - CommandList->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + auto& CommandAllocator = GeometryPassData.DrawCommandAllocator; + auto& CommandList = GeometryPassData.DrawCommandList; - const D3D12_VIEWPORT Viewport = SceneView.GetD3dViewport(); - CommandList->RSSetViewports(1, &Viewport); + auto ExecuteCommandList = [this, CommandList]() -> bool + { + CHECKED_TF_S(CommandList->Close()) - static const D3D12_RECT ScissorRect = CD3DX12_RECT(0, 0, LONG_MAX, LONG_MAX); - CommandList->RSSetScissorRects(1, &ScissorRect); + ID3D12CommandList* CommandLists[] = {CommandList.Get()}; - CommandList->OMSetRenderTargets( - GBuffer.TEXTURES_COUNT, - RtvHandles.data(), - false, - &DsvHandle - ); + RenderApi->GetDirectQueue() + ->ExecuteCommandLists(1, CommandLists); - CommandList->SetDescriptorHeaps(1, GeometryPassData.GpuDescriptorHeap.GetAddressOf()); + return true; + }; - return true; - }; + auto ResetCommandList = [this, &CommandAllocator, &CommandList, &SceneView, &RtvHandles, &DsvHandle]() -> bool + { + CHECKED_TF_S(CommandAllocator->Reset()) + CHECKED_TF_S(CommandList->Reset(CommandAllocator.Get(), GeometryPassData.PipelineState.Get())) - ResetCommandList(); + // Setup pipeline - for (auto& RtvHandle: RtvHandles) - { - constexpr static FLOAT ClearColor[] = {0.f, 0.f, 0.f, 1.f}; - CommandList->ClearRenderTargetView(RtvHandle, ClearColor, 0, nullptr); - } + CommandList->SetGraphicsRootSignature(GeometryPassData.RootSignature.Get()); + CommandList->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - CommandList->ClearDepthStencilView( - GBuffer.CpuDsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, - 1.0f, - 0, - 0, - nullptr - ); + const D3D12_VIEWPORT Viewport = SceneView.GetD3dViewport(); + CommandList->RSSetViewports(1, &Viewport); - int DrawIndex = -1; - for (const std::shared_ptr& TexturedMesh : Scene->GetTexturedMeshes()) - { - nvtx3::scoped_range MeshIterationRange {"Mesh Iteration"}; + static const D3D12_RECT ScissorRect = CD3DX12_RECT(0, 0, LONG_MAX, LONG_MAX); + CommandList->RSSetScissorRects(1, &ScissorRect); - auto Mesh = TexturedMesh->GetMesh(); + CommandList->OMSetRenderTargets( + GBuffer.TEXTURES_COUNT, + RtvHandles.data(), + false, + &DsvHandle + ); - // Make sure we have enough descriptors to draw this textured mesh - { - if (DrawIndex + 1 == GeometryPassData.PARALLEL_DRAWS_COUNT_ALLOWED) - { - if (!ExecuteCommandList()) - return false; + CommandList->SetDescriptorHeaps(1, GeometryPassData.GpuDescriptorHeap.GetAddressOf()); - WaitDirectQueue(); + return true; + }; - DrawIndex = -1; + ResetCommandList(); - if (!ResetCommandList()) - return false; - } - DrawIndex += 1; + for (auto& RtvHandle: RtvHandles) + { + constexpr static FLOAT ClearColor[] = {0.f, 0.f, 0.f, 1.f}; + CommandList->ClearRenderTargetView(RtvHandle, ClearColor, 0, nullptr); } - // Setup Mesh + CommandList->ClearDepthStencilView( + GBuffer.CpuDsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), + D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, + 1.0f, + 0, + 0, + nullptr + ); + + auto TexturedMeshes = Scene->GetTexturedMeshes(); + for (int DrawIndex = 0; DrawIndex < TexturedMeshes.size(); ++DrawIndex) { - D3D12_VERTEX_BUFFER_VIEW VertexBufferView = Mesh->GetVertexBufferView(); - CommandList->IASetVertexBuffers(0, 1, &VertexBufferView); + const std::shared_ptr& TexturedMesh = TexturedMeshes[DrawIndex]; + nvtx3::scoped_range MeshIterationRange {"Mesh Iteration"}; - if (Mesh->IsUsingIndices()) - { - D3D12_INDEX_BUFFER_VIEW IndexBufferView = Mesh->GetIndexBufferView(); - CommandList->IASetIndexBuffer(&IndexBufferView); - } - else + auto Mesh = TexturedMesh->GetMesh(); + + // 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; + TaskFlowEx::CancelCurrentTaskflow(); - return true; + }).name("GeometryPass Task"); } bool DeferredRenderer::InitLightPass() @@ -514,118 +513,125 @@ bool DeferredRenderer::InitLightPass() return true; } -bool DeferredRenderer::PrepareLightPassData(const Core::SceneView& SceneView) +tf::Task DeferredRenderer::PrepareLightPassData(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - 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()); + } + }).name("PrepareLightPassData Task"); } -bool DeferredRenderer::TransitionLightPassFromRenderTargetToReadState() +tf::Task DeferredRenderer::TransitionLightPassFromRenderTargetToReadState(tf::FlowBuilder& FlowBuilder) { - CD3DX12_RESOURCE_BARRIER Barrier = CD3DX12_RESOURCE_BARRIER::Transition(LightPassData.ColorTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ); + 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); - CHECKED_S(LightPassData.RenderTargetToReadTransitionAllocator->Reset()); - CHECKED_S(LightPassData.TransitionCommandList->Reset(LightPassData.RenderTargetToReadTransitionAllocator.Get(), nullptr)) + CHECKED_TF_S(LightPassData.RenderTargetToReadTransitionAllocator->Reset()) + 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::TransitionLightPassFromReadToRenderTargetState() +tf::Task DeferredRenderer::TransitionLightPassFromReadToRenderTargetState(tf::FlowBuilder& FlowBuilder) { - 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)) + 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 + ); - LightPassData.TransitionCommandList->ResourceBarrier(1, &Barrier); - CHECKED_S(LightPassData.TransitionCommandList->Close()); + 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::InitAmbientDirectionalLightPass() @@ -696,85 +702,84 @@ bool DeferredRenderer::InitAmbientDirectionalLightPass() return true; } -bool DeferredRenderer::AmbientDirectionalLightPass(const Core::SceneView& SceneView) +tf::Task DeferredRenderer::AmbientDirectionalLightPass(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - nvtx3::scoped_range PassRange {"Ambient & Directional Light Pass"}; - - 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); + }).name("AmbientDirectionalLightPass Task"); } bool DeferredRenderer::InitPointLightShadowCubeMapPass() @@ -833,143 +838,146 @@ bool DeferredRenderer::InitPointLightShadowCubeMapPass() return true; } -bool DeferredRenderer::PointLightShadowCubeMapsPass() +tf::Task DeferredRenderer::PointLightShadowCubeMapsPass(const Core::Scene* Scene, tf::FlowBuilder& FlowBuilder) { - nvtx3::scoped_range PassRange {"Point Light Shadow Cube Maps Pass"}; - - 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 { - if (!PointLight->CastsShadows()) - continue; + for(const auto& PointLight : Scene->GetPointLights()) + { + nvtx3::scoped_range PointLightLoop{"Point Light Iteration"}; - CommandList->SetGraphicsRootConstantBufferView(1, PointLight->GetConstantBufferGpuHandle()); + if (!PointLight->CastsShadows()) + continue; - glm::mat4 ProjectionMatrix = glm::perspective( - glm::radians(90.f), - 1.0f, - 1.0f, - PointLight->GetShadowFarDistance() - ); + CommandList->SetGraphicsRootConstantBufferView(1, PointLight->GetConstantBufferGpuHandle()); - 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}), - }; + glm::mat4 ProjectionMatrix = glm::perspective( + glm::radians(90.f), + 1.0f, + 1.0f, + PointLight->GetShadowFarDistance() + ); - // Render each side of point light - for (int i = 0; i < 6; ++i) - { - 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); + }).name("PointLightShadowCubeMapsPass Task"); } bool DeferredRenderer::InitPointLightVolumePass() @@ -1127,161 +1135,160 @@ bool DeferredRenderer::InitPointLightVolumePass() return true; } -bool DeferredRenderer::PointLightVolumesPass(const Core::SceneView& SceneView) +tf::Task DeferredRenderer::PointLightVolumesPass(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - nvtx3::scoped_range PassRange {"Point Light Volumes Pass"}; - - auto& CommandAllocator = PointLightVolumePassData.CommandAllocator; - auto& CommandList = PointLightVolumePassData.CommandList; - - CHECKED_S(CommandAllocator->Reset()); - CHECKED_S(CommandList->Reset(CommandAllocator.Get(), PointLightVolumePassData.StencilPipelineState.Get())); - - // Fill GBuffer descriptors + return FlowBuilder.emplace([Scene, SceneView, this]() { - RenderApi->GetDevice() - ->CopyDescriptorsSimple( - GBuffer.TEXTURES_COUNT, - PointLightVolumePassData.GpuDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - GBuffer.CpuSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV - ); - } + auto& CommandAllocator = PointLightVolumePassData.CommandAllocator; + auto& CommandList = PointLightVolumePassData.CommandList; - // 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 - ); + CHECKED_TF_S(CommandAllocator->Reset()) + CHECKED_TF_S(CommandList->Reset(CommandAllocator.Get(), PointLightVolumePassData.StencilPipelineState.Get())) - CommandList->ResourceBarrier(1, &ResourceBarrier); - - 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 - ); + // 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 + ); - CommandList->ResourceBarrier(1, &ResourceBarrier); - } + CommandList->ResourceBarrier(1, &ResourceBarrier); - // Set up command list - { - CommandList->SetGraphicsRootSignature(PointLightVolumePassData.RootSignature.Get()); - CommandList->SetDescriptorHeaps(1, PointLightVolumePassData.GpuDescriptorHeap.GetAddressOf()); - - 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()); + + CommandList->SetGraphicsRootDescriptorTable(0, PointLightVolumePassData.GpuDescriptorHeap->GetGPUDescriptorHandleForHeapStart()); + CommandList->SetGraphicsRootConstantBufferView(1, FrameData.ConstantBuffer->GetGPUVirtualAddress()); - D3D12_CPU_DESCRIPTOR_HANDLE DsvHandle = PointLight->GetDepthStencilVolumeDsvHandle(); - CommandList->OMSetRenderTargets(0, nullptr, false, &DsvHandle); + 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); + CommandList->SetPipelineState(PointLightVolumePassData.ColorPipelineState.Get()); + CommandList->OMSetStencilRef(1); - // Draw color based on stencil buffers - { - int PointLightIndex = 0; - - 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()) - - ID3D12CommandList* CommandLists[] = {CommandList.Get()}; - RenderApi->GetDirectQueue() - ->ExecuteCommandLists(1, CommandLists); + CHECKED_TF_S(CommandList->Close()) - return true; + ID3D12CommandList* CommandLists[] = {CommandList.Get()}; + RenderApi->GetDirectQueue() + ->ExecuteCommandLists(1, CommandLists); + }).name("PointLightVolumesPass Task"); } bool DeferredRenderer::InitPostProcessingPass() @@ -1352,99 +1359,112 @@ bool DeferredRenderer::InitPostProcessingPass() return true; } -bool DeferredRenderer::PostProcessingPass(const Core::SceneView& SceneView) +tf::Task DeferredRenderer::PostProcessingPass(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - nvtx3::scoped_range PassRange {"Post Processing Pass"}; - - 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()); + CHECKED_TF_S(CommandList->Close()) - ID3D12CommandList* CommandLists[] = {CommandList.Get()}; - RenderApi->GetDirectQueue() - ->ExecuteCommandLists(1, CommandLists); + ID3D12CommandList* CommandLists[] = {CommandList.Get()}; + RenderApi->GetDirectQueue() + ->ExecuteCommandLists(1, CommandLists); + }); +} - return true; +tf::Task DeferredRenderer::PostRenderPasses(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) +{ + return FlowBuilder.emplace([SceneView, this](tf::Subflow& Subflow) + { + Subflow.linearize({ + TransitionLightPassFromRenderTargetToReadState(Subflow), + PostProcessingPass(SceneView, Subflow), + TransitionLightPassFromReadToRenderTargetState(Subflow), + PostRender(SceneView, Subflow), + TransitionGBufferFromReadToRenderTargetState(Subflow) + }); + }).name("PostRenderPasses Task"); } bool DeferredRenderer::Shutdown() @@ -1481,12 +1501,15 @@ 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 RenderApi::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()}; @@ -1533,57 +1556,78 @@ bool DeferredRenderer::InitPrePostRender() return true; } -bool DeferredRenderer::PreRender(const Core::SceneView& SceneView) +tf::Task DeferredRenderer::PreRender(const Core::Scene* Scene, const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - 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); + } + }).name("PreRender Task"); } -bool DeferredRenderer::PostRender(const Core::SceneView& SceneView) +tf::Task DeferredRenderer::PostRender(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - 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) +{ + 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; + }); + }).name("WaitDirectQueue Task"); } bool DeferredRenderer::WaitDirectQueue() @@ -1716,221 +1760,224 @@ bool DeferredRenderer::InitEmptyTexture() return WaitDirectQueue(); } -bool DeferredRenderer::InitGBufferForView(const Core::SceneView& SceneView) +tf::Task DeferredRenderer::InitGBufferForView(const Core::SceneView& SceneView, tf::FlowBuilder& FlowBuilder) { - 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) - { - ResourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; - ClearValue.DepthStencil.Depth = 1.0f; - ClearValue.DepthStencil.Stencil = 0; - State = D3D12_RESOURCE_STATE_DEPTH_WRITE; - } - else + auto CreateTextureBuffer = [&](Microsoft::WRL::ComPtr& TextureBuffer, DXGI_FORMAT Format, const std::wstring_view& Name, bool bIsDepth = false) -> bool { - 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; - } - - 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; - }; + 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 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); + D3D12_CLEAR_VALUE ClearValue = {}; + ClearValue.Format = Format; - if (bError) - return false; + D3D12_RESOURCE_STATES State = D3D12_RESOURCE_STATE_RENDER_TARGET; - 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 (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; + } - // Create RTV descriptors - { - D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = { - .Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV, - .NumDescriptors = 6, - .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE + 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; }; - CHECKED( - RenderApi->GetDevice() - ->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&GBuffer.CpuRtvDescriptorHeap)), - "Can't create cpu rtv descriptor heap for gbuffer" - ) + 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); + + if (bError) + TaskFlowEx::CancelCurrentTaskflow(); + + 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) + }; - 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; + }).name("InitGBufferForView Task"); } -bool DeferredRenderer::TransitionGBufferFromRenderTargetToReadState() +tf::Task DeferredRenderer::TransitionGBufferFromRenderTargetToReadState(tf::FlowBuilder& FlowBuilder) { - 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); + }).name("TransitionGBufferFromRenderTargetToReadState Task"); } -bool DeferredRenderer::TransitionGBufferFromReadToRenderTargetState() +tf::Task DeferredRenderer::TransitionGBufferFromReadToRenderTargetState(tf::FlowBuilder& FlowBuilder) { - 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 new file mode 100644 index 0000000..ae7a969 --- /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 diff --git a/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TfExecutorBuilder.h b/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TfExecutorBuilder.h index fe4de32..1375ef5 100644 --- a/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TfExecutorBuilder.h +++ b/Source/Runtime/TaskFlowEx/Include/Runtime/TfExecutorBuilder/TfExecutorBuilder.h @@ -27,10 +27,14 @@ namespace krendrr::Runtime::TaskFlowEx Builder& AttachNvtxObserver(bool bShouldAttach = true); /** - * Sets the amount of workers. Uses std::thread::hardware_concurrency() - 1 by default. + * Attaches worker interface that gives all worker threads some human-readable names. * - * 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. + * Attached by default. + */ + Builder& AttachWorkerInterface(bool bShouldAttach = true); + + /** + * Sets the amount of workers. Uses std::thread::hardware_concurrency() by default. * * If set to 0, uses the default value. */ @@ -39,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 049424e..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() - 1 + 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;