diff --git a/examples/PhysicallyBasedRendering/main.cpp b/examples/PhysicallyBasedRendering/main.cpp index 0b0f17aa0..fa1c6cb53 100644 --- a/examples/PhysicallyBasedRendering/main.cpp +++ b/examples/PhysicallyBasedRendering/main.cpp @@ -62,7 +62,6 @@ int main(int argc, char* argv[]) Nz::Vector2ui windowSize = window.GetSize(); Nz::Camera camera(&windowSwapchain); - camera.EnableFramePipelinePasses(Nz::FramePipelineExtraPass::GammaCorrection); //camera.UpdateClearColor(Nz::Color::Gray); Nz::ViewerInstance& viewerInstance = camera.GetViewerInstance(); @@ -77,7 +76,7 @@ int main(int argc, char* argv[]) Nz::ElementRendererRegistry elementRegistry; Nz::ForwardFramePipeline framePipeline(elementRegistry); - [[maybe_unused]] std::size_t cameraIndex = framePipeline.RegisterViewer(&camera, 0, Nz::FramePipelineAllExtraPasses); + [[maybe_unused]] std::size_t cameraIndex = framePipeline.RegisterViewer(&camera, 0); std::size_t worldInstanceIndex1 = framePipeline.RegisterWorldInstance(modelInstance); framePipeline.RegisterRenderable(worldInstanceIndex1, Nz::FramePipeline::NoSkeletonInstance, &model, 0xFFFFFFFF, scissorBox); diff --git a/examples/PhysicsPlayground/main.cpp b/examples/PhysicsPlayground/main.cpp index 550071186..82f04c2a4 100644 --- a/examples/PhysicsPlayground/main.cpp +++ b/examples/PhysicsPlayground/main.cpp @@ -351,7 +351,6 @@ int main(int argc, char* argv[]) auto& cameraComponent = cameraEntity.emplace(&windowSwapchain, Nz::ProjectionType::Perspective); cameraComponent.UpdateFOV(70.f); cameraComponent.UpdateClearColor(Nz::Color::sRGBToLinear(Nz::Color(0.46f, 0.48f, 0.84f, 1.f))); - cameraComponent.EnableFramePipelinePasses(Nz::FramePipelineExtraPass::GammaCorrection); } auto UpdateCamera = [&] diff --git a/include/Nazara/Graphics/Camera.hpp b/include/Nazara/Graphics/Camera.hpp index 3ba03e89a..4b0590a76 100644 --- a/include/Nazara/Graphics/Camera.hpp +++ b/include/Nazara/Graphics/Camera.hpp @@ -8,32 +8,31 @@ #define NAZARA_GRAPHICS_CAMERA_HPP #include -#include #include +#include #include #include #include #include -#include -#include namespace Nz { - class NAZARA_GRAPHICS_API Camera : public AbstractViewer + class PipelinePassList; + + class NAZARA_GRAPHICS_API Camera : public PipelineViewer { public: - inline Camera(const RenderTarget* renderTarget, ProjectionType projectionType = ProjectionType::Perspective); + inline Camera(const RenderTarget* renderTarget, std::shared_ptr pipelinePasses, ProjectionType projectionType = ProjectionType::Perspective); + Camera(const RenderTarget* renderTarget, ProjectionType projectionType = ProjectionType::Perspective); inline Camera(const Camera& camera); inline Camera(Camera&& camera) noexcept; ~Camera() = default; - inline void DisableFramePipelinePasses(FramePipelineExtraPassFlags framePipelineExtraPassFlags); - inline void EnableFramePipelinePasses(FramePipelineExtraPassFlags framePipelineExtraPassFlags); + std::vector> BuildPasses(FramePipelinePass::PassData& passData) const override; inline float GetAspectRatio() const; const Color& GetClearColor() const override; inline DegreeAnglef GetFOV() const; - inline FramePipelineExtraPassFlags GetFramePipelineExtraPassFlags() const; inline ProjectionType GetProjectionType() const; UInt32 GetRenderMask() const override; inline Int32 GetRenderOrder() const; @@ -46,9 +45,10 @@ namespace Nz inline float GetZFar() const; inline float GetZNear() const; + std::size_t RegisterPasses(const std::vector>& passes, FrameGraph& frameGraph) const override; + inline void UpdateClearColor(Color color); inline void UpdateFOV(DegreeAnglef fov); - inline void UpdateFramePipelinePasses(FramePipelineExtraPassFlags framePipelineExtraFlags); inline void UpdateProjectionType(ProjectionType projectionType); inline void UpdateRenderMask(UInt32 renderMask); inline void UpdateRenderOrder(Int32 renderOrder); @@ -70,10 +70,10 @@ namespace Nz NazaraSlot(RenderTarget, OnRenderTargetRelease, m_onRenderTargetRelease); NazaraSlot(RenderTarget, OnRenderTargetSizeChange, m_onRenderTargetSizeChange); + std::shared_ptr m_framePipelinePasses; const RenderTarget* m_renderTarget; Color m_clearColor; DegreeAnglef m_fov; - FramePipelineExtraPassFlags m_framePipelineExtraPassFlags; Int32 m_renderOrder; ProjectionType m_projectionType; Rectf m_targetRegion; diff --git a/include/Nazara/Graphics/Camera.inl b/include/Nazara/Graphics/Camera.inl index fe747811b..18263b0b6 100644 --- a/include/Nazara/Graphics/Camera.inl +++ b/include/Nazara/Graphics/Camera.inl @@ -7,11 +7,11 @@ namespace Nz { - inline Camera::Camera(const RenderTarget* renderTarget, ProjectionType projectionType) : + inline Camera::Camera(const RenderTarget* renderTarget, std::shared_ptr pipelinePasses, ProjectionType projectionType) : + m_framePipelinePasses(std::move(pipelinePasses)), m_renderTarget(nullptr), m_clearColor(Color::Black()), m_fov(90.f), - m_framePipelineExtraPassFlags(FramePipelineExtraPass::DebugDraw), m_renderOrder(0), m_projectionType(projectionType), m_targetRegion(0.f, 0.f, 1.f, 1.f), @@ -21,17 +21,14 @@ namespace Nz m_zFar((projectionType == ProjectionType::Perspective) ? 1000.f : 1.f), m_zNear((projectionType == ProjectionType::Perspective) ? 1.f : -1.f) { - if (projectionType == ProjectionType::Perspective) - m_framePipelineExtraPassFlags |= FramePipelineExtraPass::DepthPrepass; - UpdateTarget(renderTarget); } inline Camera::Camera(const Camera& camera) : + m_framePipelinePasses(camera.m_framePipelinePasses), m_renderTarget(nullptr), m_clearColor(camera.m_clearColor), m_fov(camera.m_fov), - m_framePipelineExtraPassFlags(camera.m_framePipelineExtraPassFlags), m_renderOrder(camera.m_renderOrder), m_projectionType(camera.m_projectionType), m_targetRegion(camera.m_targetRegion), @@ -46,10 +43,10 @@ namespace Nz } inline Camera::Camera(Camera&& camera) noexcept : + m_framePipelinePasses(std::move(camera.m_framePipelinePasses)), m_renderTarget(nullptr), m_clearColor(camera.m_clearColor), m_fov(camera.m_fov), - m_framePipelineExtraPassFlags(camera.m_framePipelineExtraPassFlags), m_renderOrder(camera.m_renderOrder), m_projectionType(camera.m_projectionType), m_targetRegion(camera.m_targetRegion), @@ -63,16 +60,6 @@ namespace Nz UpdateTarget(camera.m_renderTarget); } - inline void Camera::DisableFramePipelinePasses(FramePipelineExtraPassFlags framePipelineExtraPassFlags) - { - m_framePipelineExtraPassFlags &= ~framePipelineExtraPassFlags; - } - - inline void Camera::EnableFramePipelinePasses(FramePipelineExtraPassFlags framePipelineExtraPassFlags) - { - m_framePipelineExtraPassFlags |= framePipelineExtraPassFlags; - } - inline float Camera::GetAspectRatio() const { return m_aspectRatio; @@ -83,11 +70,6 @@ namespace Nz return m_fov; } - inline FramePipelineExtraPassFlags Camera::GetFramePipelineExtraPassFlags() const - { - return m_framePipelineExtraPassFlags; - } - inline ProjectionType Camera::GetProjectionType() const { return m_projectionType; @@ -129,11 +111,6 @@ namespace Nz UpdateProjectionMatrix(); } - inline void Camera::UpdateFramePipelinePasses(FramePipelineExtraPassFlags framePipelineExtraFlags) - { - m_framePipelineExtraPassFlags = framePipelineExtraFlags; - } - inline void Camera::UpdateZFar(float zFar) { m_zFar = zFar; @@ -150,7 +127,7 @@ namespace Nz inline Camera& Camera::operator=(const Camera& camera) { - m_framePipelineExtraPassFlags = camera.m_framePipelineExtraPassFlags; + m_framePipelinePasses = camera.m_framePipelinePasses; m_fov = camera.m_fov; m_projectionType = camera.m_projectionType; m_targetRegion = camera.m_targetRegion; @@ -167,7 +144,7 @@ namespace Nz inline Camera& Camera::operator=(Camera&& camera) noexcept { - m_framePipelineExtraPassFlags = camera.m_framePipelineExtraPassFlags; + m_framePipelinePasses = std::move(camera.m_framePipelinePasses); m_fov = camera.m_fov; m_projectionType = camera.m_projectionType; m_targetRegion = camera.m_targetRegion; @@ -281,4 +258,3 @@ namespace Nz } #include -#include "Camera.hpp" diff --git a/include/Nazara/Graphics/DebugDrawPipelinePass.hpp b/include/Nazara/Graphics/DebugDrawPipelinePass.hpp index 790a145a0..a25aac0eb 100644 --- a/include/Nazara/Graphics/DebugDrawPipelinePass.hpp +++ b/include/Nazara/Graphics/DebugDrawPipelinePass.hpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace Nz { @@ -17,24 +18,26 @@ namespace Nz class FrameGraph; class FramePass; class FramePipeline; + class ParameterList; class RenderFrame; class NAZARA_GRAPHICS_API DebugDrawPipelinePass : public FramePipelinePass { public: - DebugDrawPipelinePass(FramePipeline& owner, AbstractViewer* viewer); + DebugDrawPipelinePass(PassData& passData, std::string passName, const ParameterList& parameters = {}); DebugDrawPipelinePass(const DebugDrawPipelinePass&) = delete; DebugDrawPipelinePass(DebugDrawPipelinePass&&) = delete; ~DebugDrawPipelinePass() = default; - void Prepare(RenderFrame& renderFrame); + void Prepare(FrameData& frameData) override; - FramePass& RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t inputColorBufferIndex, std::size_t outputColorBufferIndex); + FramePass& RegisterToFrameGraph(FrameGraph& frameGraph, const PassInputOuputs& inputOuputs) override; DebugDrawPipelinePass& operator=(const DebugDrawPipelinePass&) = delete; DebugDrawPipelinePass& operator=(DebugDrawPipelinePass&&) = delete; private: + std::string m_passName; AbstractViewer* m_viewer; FramePipeline& m_pipeline; }; diff --git a/include/Nazara/Graphics/DebugDrawPipelinePass.inl b/include/Nazara/Graphics/DebugDrawPipelinePass.inl index c172f3461..5b564aa3d 100644 --- a/include/Nazara/Graphics/DebugDrawPipelinePass.inl +++ b/include/Nazara/Graphics/DebugDrawPipelinePass.inl @@ -6,6 +6,13 @@ namespace Nz { + inline DebugDrawPipelinePass::DebugDrawPipelinePass(PassData& passData, std::string passName, const ParameterList& /*parameters*/) : + FramePipelinePass({}), + m_passName(std::move(passName)), + m_viewer(passData.viewer), + m_pipeline(passData.pipeline) + { + } } #include diff --git a/include/Nazara/Graphics/DepthPipelinePass.hpp b/include/Nazara/Graphics/DepthPipelinePass.hpp index 5886f50f2..dd9e6cca0 100644 --- a/include/Nazara/Graphics/DepthPipelinePass.hpp +++ b/include/Nazara/Graphics/DepthPipelinePass.hpp @@ -30,24 +30,28 @@ namespace Nz class NAZARA_GRAPHICS_API DepthPipelinePass : public FramePipelinePass { public: - DepthPipelinePass(FramePipeline& owner, ElementRendererRegistry& elementRegistry, AbstractViewer* viewer, std::size_t passIndex, std::string passName); + inline DepthPipelinePass(PassData& passData, std::string passName, const ParameterList& parameters); + inline DepthPipelinePass(PassData& passData, std::string passName, std::size_t materialPassIndex); DepthPipelinePass(const DepthPipelinePass&) = delete; DepthPipelinePass(DepthPipelinePass&&) = delete; ~DepthPipelinePass() = default; inline void InvalidateCommandBuffers(); - inline void InvalidateElements(); + void InvalidateElements() override; - void Prepare(RenderFrame& renderFrame, const Frustumf& frustum, const std::vector& visibleRenderables, std::size_t visibilityHash); + void Prepare(FrameData& frameData) override; - void RegisterMaterialInstance(const MaterialInstance& materialInstance); - FramePass& RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t outputAttachment); + void RegisterMaterialInstance(const MaterialInstance& materialInstance) override; - void UnregisterMaterialInstance(const MaterialInstance& materialInstance); + FramePass& RegisterToFrameGraph(FrameGraph& frameGraph, const PassInputOuputs& inputOuputs) override; + + void UnregisterMaterialInstance(const MaterialInstance& materialInstance) override; DepthPipelinePass& operator=(const DepthPipelinePass&) = delete; DepthPipelinePass& operator=(DepthPipelinePass&&) = delete; + static std::size_t GetMaterialPassIndex(const ParameterList& parameters); + private: struct MaterialPassEntry { diff --git a/include/Nazara/Graphics/DepthPipelinePass.inl b/include/Nazara/Graphics/DepthPipelinePass.inl index 230724055..b0f4ddc9f 100644 --- a/include/Nazara/Graphics/DepthPipelinePass.inl +++ b/include/Nazara/Graphics/DepthPipelinePass.inl @@ -6,6 +6,24 @@ namespace Nz { + inline DepthPipelinePass::DepthPipelinePass(PassData& passData, std::string passName, const ParameterList& parameters) : + DepthPipelinePass(passData, std::move(passName), GetMaterialPassIndex(parameters)) + { + } + + inline DepthPipelinePass::DepthPipelinePass(PassData& passData, std::string passName, std::size_t materialPassIndex) : + FramePipelinePass(FramePipelineNotification::ElementInvalidation | FramePipelineNotification::MaterialInstanceRegistration), + m_passIndex(materialPassIndex), + m_lastVisibilityHash(0), + m_passName(std::move(passName)), + m_viewer(passData.viewer), + m_elementRegistry(passData.elementRegistry), + m_pipeline(passData.pipeline), + m_rebuildCommandBuffer(false), + m_rebuildElements(false) + { + } + inline void DepthPipelinePass::InvalidateCommandBuffers() { m_rebuildCommandBuffer = true; diff --git a/include/Nazara/Graphics/Enums.hpp b/include/Nazara/Graphics/Enums.hpp index 3995d9962..66970f2fe 100644 --- a/include/Nazara/Graphics/Enums.hpp +++ b/include/Nazara/Graphics/Enums.hpp @@ -41,25 +41,22 @@ namespace Nz Volume }; - enum class FramePipelineExtraPass + enum class FramePipelineNotification { - DebugDraw, - DepthPrepass, - GammaCorrection, + ElementInvalidation, + MaterialInstanceRegistration, - Max = GammaCorrection + Max = MaterialInstanceRegistration }; template<> - struct EnumAsFlags + struct EnumAsFlags { - static constexpr FramePipelineExtraPass max = FramePipelineExtraPass::Max; + static constexpr FramePipelineNotification max = FramePipelineNotification::Max; }; - using FramePipelineExtraPassFlags = Flags; + using FramePipelineNotificationFlags = Flags; - constexpr FramePipelineExtraPassFlags FramePipelineAllExtraPasses = FramePipelineExtraPass::DebugDraw | FramePipelineExtraPass::DepthPrepass | FramePipelineExtraPass::GammaCorrection; - enum class MaterialPropertyType { Bool, diff --git a/include/Nazara/Graphics/ForwardFramePipeline.hpp b/include/Nazara/Graphics/ForwardFramePipeline.hpp index 719b80c5d..b2be1470f 100644 --- a/include/Nazara/Graphics/ForwardFramePipeline.hpp +++ b/include/Nazara/Graphics/ForwardFramePipeline.hpp @@ -55,7 +55,7 @@ namespace Nz std::size_t RegisterLight(const Light* light, UInt32 renderMask) override; std::size_t RegisterRenderable(std::size_t worldInstanceIndex, std::size_t skeletonInstanceIndex, const InstancedRenderable* instancedRenderable, UInt32 renderMask, const Recti& scissorBox) override; std::size_t RegisterSkeleton(SkeletonInstancePtr skeletonInstance) override; - std::size_t RegisterViewer(AbstractViewer* viewerInstance, Int32 renderOrder, FramePipelineExtraPassFlags passFlags) override; + std::size_t RegisterViewer(PipelineViewer* viewerInstance, Int32 renderOrder) override; std::size_t RegisterWorldInstance(WorldInstancePtr worldInstance) override; const Light* RetrieveLight(std::size_t lightIndex) const override; @@ -140,14 +140,8 @@ namespace Nz }; std::size_t finalColorAttachment; - std::size_t forwardColorAttachment; - std::size_t debugColorAttachment; - std::size_t depthStencilAttachment; - std::unique_ptr depthPrepass; - std::unique_ptr forwardPass; - std::unique_ptr debugDrawPass; - std::unique_ptr gammaCorrectionPass; - AbstractViewer* viewer; + std::vector> passes; + PipelineViewer* viewer; Int32 renderOrder = 0; RenderQueueRegistry forwardRegistry; RenderQueue forwardRenderQueue; diff --git a/include/Nazara/Graphics/ForwardPipelinePass.hpp b/include/Nazara/Graphics/ForwardPipelinePass.hpp index 89e3e4730..14d3043c1 100644 --- a/include/Nazara/Graphics/ForwardPipelinePass.hpp +++ b/include/Nazara/Graphics/ForwardPipelinePass.hpp @@ -34,20 +34,21 @@ namespace Nz class NAZARA_GRAPHICS_API ForwardPipelinePass : public FramePipelinePass, TransferInterface { public: - ForwardPipelinePass(FramePipeline& owner, ElementRendererRegistry& elementRegistry, AbstractViewer* viewer); + ForwardPipelinePass(PassData& passData, std::string passName, const ParameterList& parameters = {}); ForwardPipelinePass(const ForwardPipelinePass&) = delete; ForwardPipelinePass(ForwardPipelinePass&&) = delete; ~ForwardPipelinePass() = default; inline void InvalidateCommandBuffers(); - inline void InvalidateElements(); + void InvalidateElements() override; - void Prepare(RenderFrame& renderFrame, const Frustumf& frustum, const std::vector& visibleRenderables, const Bitset& visibleLights, std::size_t visibilityHash); + void Prepare(FrameData& frameData) override; - void RegisterMaterialInstance(const MaterialInstance& material); - FramePass& RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t colorBufferIndex, std::size_t depthBufferIndex, bool hasDepthPrepass); + void RegisterMaterialInstance(const MaterialInstance& material) override; - void UnregisterMaterialInstance(const MaterialInstance& material); + FramePass& RegisterToFrameGraph(FrameGraph& frameGraph, const PassInputOuputs& inputOuputs) override; + + void UnregisterMaterialInstance(const MaterialInstance& material) override; ForwardPipelinePass& operator=(const ForwardPipelinePass&) = delete; ForwardPipelinePass& operator=(ForwardPipelinePass&&) = delete; @@ -79,6 +80,7 @@ namespace Nz std::size_t m_forwardPassIndex; std::size_t m_lastVisibilityHash; std::shared_ptr m_lightDataBuffer; + std::string m_passName; std::vector> m_elementRendererData; std::vector m_renderElements; std::unordered_map m_materialInstances; diff --git a/include/Nazara/Graphics/FramePipeline.hpp b/include/Nazara/Graphics/FramePipeline.hpp index ceeac1d5e..d56c6e4d5 100644 --- a/include/Nazara/Graphics/FramePipeline.hpp +++ b/include/Nazara/Graphics/FramePipeline.hpp @@ -20,11 +20,11 @@ namespace Nz { - class AbstractViewer; class InstancedRenderable; class Light; class LightShadowData; class MaterialInstance; + class PipelineViewer; class RenderFrame; class NAZARA_GRAPHICS_API FramePipeline @@ -47,7 +47,7 @@ namespace Nz virtual std::size_t RegisterLight(const Light* light, UInt32 renderMask) = 0; virtual std::size_t RegisterRenderable(std::size_t worldInstanceIndex, std::size_t skeletonInstanceIndex, const InstancedRenderable* instancedRenderable, UInt32 renderMask, const Recti& scissorBox) = 0; virtual std::size_t RegisterSkeleton(SkeletonInstancePtr skeletonInstance) = 0; - virtual std::size_t RegisterViewer(AbstractViewer* viewerInstance, Int32 renderOrder, FramePipelineExtraPassFlags passFlags) = 0; + virtual std::size_t RegisterViewer(PipelineViewer* viewerInstance, Int32 renderOrder) = 0; virtual std::size_t RegisterWorldInstance(WorldInstancePtr worldInstance) = 0; virtual const Light* RetrieveLight(std::size_t lightIndex) const = 0; diff --git a/include/Nazara/Graphics/FramePipelinePass.hpp b/include/Nazara/Graphics/FramePipelinePass.hpp index 90e6d0eb1..7ea286034 100644 --- a/include/Nazara/Graphics/FramePipelinePass.hpp +++ b/include/Nazara/Graphics/FramePipelinePass.hpp @@ -9,25 +9,80 @@ #include #include +#include +#include #include +#include +#include namespace Nz { + class AbstractViewer; + class ElementRendererRegistry; + class FrameGraph; + class FramePass; + class FramePipeline; class InstancedRenderable; + class MaterialInstance; + class RenderFrame; class SkeletonInstance; class WorldInstance; class NAZARA_GRAPHICS_API FramePipelinePass { public: - FramePipelinePass() = default; + struct FrameData; + struct PassData; + struct PassInputOuputs; + struct VisibleRenderable; + + inline FramePipelinePass(FramePipelineNotificationFlags notificationFlags); FramePipelinePass(const FramePipelinePass&) = delete; FramePipelinePass(FramePipelinePass&&) = delete; virtual ~FramePipelinePass(); + virtual void InvalidateElements(); + + virtual void Prepare(FrameData& frameData) = 0; + + virtual void RegisterMaterialInstance(const MaterialInstance& materialInstance); + + virtual FramePass& RegisterToFrameGraph(FrameGraph& frameGraph, const PassInputOuputs& inputOuputs) = 0; + + inline bool ShouldNotify(FramePipelineNotification notification) const; + + virtual void UnregisterMaterialInstance(const MaterialInstance& materialInstance); + FramePipelinePass& operator=(const FramePipelinePass&) = delete; FramePipelinePass& operator=(FramePipelinePass&&) = delete; + struct FrameData + { + const Bitset* visibleLights; + const Frustumf& frustum; + RenderFrame& renderFrame; + const std::vector& visibleRenderables; + std::size_t visibilityHash; + }; + + struct PassData + { + AbstractViewer* viewer; + ElementRendererRegistry& elementRegistry; + FramePipeline& pipeline; + }; + + struct PassInputOuputs + { + // TODO: Add Nz::View / Nz::Span + const std::size_t* inputAttachments; + const std::size_t* outputAttachments; + std::size_t depthStencilInput = InvalidAttachmentIndex; + std::size_t depthStencilOutput = InvalidAttachmentIndex; + std::size_t inputCount = 0; + std::size_t outputCount = 0; + }; + struct VisibleRenderable { const InstancedRenderable* instancedRenderable; @@ -35,6 +90,11 @@ namespace Nz const WorldInstance* worldInstance; Recti scissorBox; }; + + static constexpr std::size_t InvalidAttachmentIndex = std::numeric_limits::max(); + + private: + FramePipelineNotificationFlags m_notificationFlags; }; } diff --git a/include/Nazara/Graphics/FramePipelinePass.inl b/include/Nazara/Graphics/FramePipelinePass.inl index c172f3461..f131c0a45 100644 --- a/include/Nazara/Graphics/FramePipelinePass.inl +++ b/include/Nazara/Graphics/FramePipelinePass.inl @@ -6,6 +6,15 @@ namespace Nz { + inline FramePipelinePass::FramePipelinePass(FramePipelineNotificationFlags notificationFlags) : + m_notificationFlags(notificationFlags) + { + } + + inline bool FramePipelinePass::ShouldNotify(FramePipelineNotification notification) const + { + return m_notificationFlags.Test(notification); + } } #include diff --git a/include/Nazara/Graphics/FramePipelinePassRegistry.hpp b/include/Nazara/Graphics/FramePipelinePassRegistry.hpp new file mode 100644 index 000000000..066407347 --- /dev/null +++ b/include/Nazara/Graphics/FramePipelinePassRegistry.hpp @@ -0,0 +1,52 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_GRAPHICS_FRAMEPIPELINEPASSREGISTRY_HPP +#define NAZARA_GRAPHICS_FRAMEPIPELINEPASSREGISTRY_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class ParameterList; + + class FramePipelinePassRegistry + { + public: + using Factory = std::function(FramePipelinePass::PassData& passData, std::string passName, const ParameterList& parameters)>; + + FramePipelinePassRegistry() = default; + FramePipelinePassRegistry(const FramePipelinePassRegistry&) = default; + FramePipelinePassRegistry(FramePipelinePassRegistry&&) = default; + ~FramePipelinePassRegistry() = default; + + inline std::unique_ptr BuildPass(std::size_t passIndex, FramePipelinePass::PassData& passData, std::string passName, const ParameterList& parameters) const; + + inline std::size_t GetPassIndex(std::string_view passName) const; + + template std::size_t RegisterPass(std::string passName); + inline std::size_t RegisterPass(std::string passName, Factory factory); + + FramePipelinePassRegistry& operator=(const FramePipelinePassRegistry&) = default; + FramePipelinePassRegistry& operator=(FramePipelinePassRegistry&&) = default; + + private: + std::list m_passNames; //< in order to allow std::string_view as a key in C++17 (keep std::string stable as well because of SSO) + std::unordered_map m_passIndex; + std::vector m_passFactories; + }; +} + +#include + +#endif // NAZARA_GRAPHICS_FRAMEPIPELINEPASSREGISTRY_HPP diff --git a/include/Nazara/Graphics/FramePipelinePassRegistry.inl b/include/Nazara/Graphics/FramePipelinePassRegistry.inl new file mode 100644 index 000000000..cce610dfe --- /dev/null +++ b/include/Nazara/Graphics/FramePipelinePassRegistry.inl @@ -0,0 +1,49 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + inline std::unique_ptr FramePipelinePassRegistry::BuildPass(std::size_t passIndex, FramePipelinePass::PassData& passData, std::string passName, const ParameterList& parameters) const + { + assert(passIndex < m_passFactories.size()); + return m_passFactories[passIndex](passData, passName, parameters); + } + + inline std::size_t FramePipelinePassRegistry::GetPassIndex(std::string_view passName) const + { + auto it = m_passIndex.find(passName); + if (it == m_passIndex.end()) + throw std::runtime_error("pass " + std::string(passName) + " must be registered before being used"); + + return it->second; + } + + template + std::size_t FramePipelinePassRegistry::RegisterPass(std::string passName) + { + return RegisterPass(std::move(passName), [](FramePipelinePass::PassData& passData, std::string passName, const ParameterList& parameters) -> std::unique_ptr + { + return std::make_unique(passData, std::move(passName), parameters); + }); + } + + inline std::size_t FramePipelinePassRegistry::RegisterPass(std::string passName, Factory factory) + { + if (m_passIndex.find(passName) != m_passIndex.end()) + throw std::runtime_error("pass " + passName + " is already registered"); + + m_passNames.push_back(std::move(passName)); + + std::size_t passIndex = m_passIndex.size(); + m_passIndex.emplace(m_passNames.back(), passIndex); + m_passFactories.emplace_back(std::move(factory)); + + return passIndex; + } +} + +#include diff --git a/include/Nazara/Graphics/Graphics.hpp b/include/Nazara/Graphics/Graphics.hpp index c6150f591..9ad9c39e4 100644 --- a/include/Nazara/Graphics/Graphics.hpp +++ b/include/Nazara/Graphics/Graphics.hpp @@ -9,9 +9,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -43,7 +45,10 @@ namespace Nz inline const std::shared_ptr& GetBlitPipeline(bool transparent) const; inline const std::shared_ptr& GetBlitPipelineLayout() const; inline const DefaultMaterials& GetDefaultMaterials() const; + inline const std::shared_ptr& GetDefaultPipelinePasses() const; inline const DefaultTextures& GetDefaultTextures() const; + inline FramePipelinePassRegistry& GetFramePipelinePassRegistry(); + inline const FramePipelinePassRegistry& GetFramePipelinePassRegistry() const; inline MaterialPassRegistry& GetMaterialPassRegistry(); inline const MaterialPassRegistry& GetMaterialPassRegistry() const; inline MaterialInstanceLoader& GetMaterialInstanceLoader(); @@ -88,21 +93,25 @@ namespace Nz private: void BuildBlitPipeline(); void BuildDefaultMaterials(); + void BuildDefaultPipelinePasses(); void BuildDefaultTextures(); template void RegisterEmbedShaderModule(const UInt8(&content)[N]); void RegisterMaterialPasses(); + void RegisterPipelinePasses(); void RegisterShaderModules(); void SelectDepthStencilFormats(); std::optional m_renderPassCache; std::optional m_samplerCache; std::shared_ptr m_shaderModuleResolver; + std::shared_ptr m_defaultPipelinePasses; std::shared_ptr m_renderDevice; std::shared_ptr m_blitPipeline; std::shared_ptr m_blitPipelineTransparent; std::shared_ptr m_blitPipelineLayout; DefaultMaterials m_defaultMaterials; DefaultTextures m_defaultTextures; + FramePipelinePassRegistry m_pipelinePassRegistry; MaterialInstanceLoader m_materialInstanceLoader; MaterialLoader m_materialLoader; MaterialPassRegistry m_materialPassRegistry; diff --git a/include/Nazara/Graphics/Graphics.inl b/include/Nazara/Graphics/Graphics.inl index 27d7ba802..be53f3601 100644 --- a/include/Nazara/Graphics/Graphics.inl +++ b/include/Nazara/Graphics/Graphics.inl @@ -21,11 +21,26 @@ namespace Nz return m_defaultMaterials; } + inline const std::shared_ptr& Graphics::GetDefaultPipelinePasses() const + { + return m_defaultPipelinePasses; + } + inline auto Graphics::GetDefaultTextures() const -> const DefaultTextures& { return m_defaultTextures; } + inline FramePipelinePassRegistry& Graphics::GetFramePipelinePassRegistry() + { + return m_pipelinePassRegistry; + } + + inline const FramePipelinePassRegistry& Graphics::GetFramePipelinePassRegistry() const + { + return m_pipelinePassRegistry; + } + inline MaterialPassRegistry& Graphics::GetMaterialPassRegistry() { return m_materialPassRegistry; diff --git a/include/Nazara/Graphics/LightShadowData.hpp b/include/Nazara/Graphics/LightShadowData.hpp index 246242c11..c656764a1 100644 --- a/include/Nazara/Graphics/LightShadowData.hpp +++ b/include/Nazara/Graphics/LightShadowData.hpp @@ -30,7 +30,7 @@ namespace Nz inline bool IsPerViewer() const; - virtual void PrepareRendering(RenderFrame& renderFrame, const AbstractViewer* viewer) = 0; + virtual void PrepareRendering(RenderFrame& renderFrame, [[maybe_unused]] const AbstractViewer* viewer) = 0; virtual void RegisterMaterialInstance(const MaterialInstance& matInstance) = 0; virtual void RegisterPassInputs(FramePass& pass, const AbstractViewer* viewer) = 0; diff --git a/include/Nazara/Graphics/PipelinePassList.hpp b/include/Nazara/Graphics/PipelinePassList.hpp new file mode 100644 index 000000000..af8d24b4c --- /dev/null +++ b/include/Nazara/Graphics/PipelinePassList.hpp @@ -0,0 +1,72 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_GRAPHICS_PIPELINEPASSLIST_HPP +#define NAZARA_GRAPHICS_PIPELINEPASSLIST_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class FrameGraph; + + class NAZARA_GRAPHICS_API PipelinePassList + { + public: + PipelinePassList() = default; + PipelinePassList(const PipelinePassList&) = delete; + PipelinePassList(PipelinePassList&&) = delete; + ~PipelinePassList() = default; + + inline std::size_t AddAttachment(FramePassAttachment attachment); + inline std::size_t AddPass(std::string name, std::size_t implIndex, ParameterList parameterList = {}); + + std::vector> BuildPasses(FramePipelinePass::PassData& passData) const; + + std::size_t RegisterPasses(const std::vector>& passes, FrameGraph& frameGraph) const; + + inline void SetFinalOutput(std::size_t attachmentIndex); + inline void SetPassInput(std::size_t passIndex, std::size_t inputIndex, std::size_t attachmentIndex); + inline void SetPassOutput(std::size_t passIndex, std::size_t outputIndex, std::size_t attachmentIndex); + inline void SetPassDepthStencilInput(std::size_t passIndex, std::size_t attachmentIndex); + inline void SetPassDepthStencilOutput(std::size_t passIndex, std::size_t attachmentIndex); + + PipelinePassList& operator=(const PipelinePassList&) = delete; + PipelinePassList& operator=(PipelinePassList&&) = delete; + + static constexpr std::size_t MaxPassAttachment = 8; + + private: + static constexpr std::size_t NoAttachment = std::numeric_limits::max(); + + struct Pass + { + FixedVector inputs; + FixedVector outputs; + std::size_t depthStencilInput = NoAttachment; + std::size_t depthStencilOutput = NoAttachment; + std::size_t implIndex; + std::string name; + ParameterList parameterList; + }; + + std::size_t m_finalOutputAttachment; + std::vector m_attachments; + std::vector m_passes; + }; +} + +#include + +#endif // NAZARA_GRAPHICS_PIPELINEPASSLIST_HPP diff --git a/include/Nazara/Graphics/PipelinePassList.inl b/include/Nazara/Graphics/PipelinePassList.inl new file mode 100644 index 000000000..8af962078 --- /dev/null +++ b/include/Nazara/Graphics/PipelinePassList.inl @@ -0,0 +1,73 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + inline std::size_t PipelinePassList::AddAttachment(FramePassAttachment attachment) + { + std::size_t index = m_attachments.size(); + m_attachments.emplace_back(std::move(attachment)); + + return index; + } + + inline std::size_t PipelinePassList::AddPass(std::string name, std::size_t implIndex, ParameterList parameterList) + { + std::size_t index = m_passes.size(); + auto& pass = m_passes.emplace_back(); + pass.name = std::move(name); + pass.implIndex = implIndex; + pass.parameterList = std::move(parameterList); + + return index; + } + + inline void PipelinePassList::SetFinalOutput(std::size_t attachmentIndex) + { + m_finalOutputAttachment = attachmentIndex; + } + + inline void PipelinePassList::SetPassInput(std::size_t passIndex, std::size_t inputIndex, std::size_t attachmentIndex) + { + assert(passIndex < m_passes.size()); + auto& pass = m_passes[passIndex]; + assert(inputIndex < MaxPassAttachment); + + if (inputIndex >= pass.inputs.size()) + pass.inputs.resize(inputIndex + 1, NoAttachment); + + pass.inputs[inputIndex] = attachmentIndex; + } + + inline void PipelinePassList::SetPassOutput(std::size_t passIndex, std::size_t outputIndex, std::size_t attachmentIndex) + { + assert(passIndex < m_passes.size()); + auto& pass = m_passes[passIndex]; + assert(outputIndex < MaxPassAttachment); + + if (outputIndex >= pass.outputs.size()) + pass.outputs.resize(outputIndex + 1, NoAttachment); + + pass.outputs[outputIndex] = attachmentIndex; + } + + inline void PipelinePassList::SetPassDepthStencilInput(std::size_t passIndex, std::size_t attachmentIndex) + { + assert(passIndex < m_passes.size()); + auto& pass = m_passes[passIndex]; + pass.depthStencilInput = attachmentIndex; + } + + inline void PipelinePassList::SetPassDepthStencilOutput(std::size_t passIndex, std::size_t attachmentIndex) + { + assert(passIndex < m_passes.size()); + auto& pass = m_passes[passIndex]; + pass.depthStencilOutput = attachmentIndex; + } +} + +#include diff --git a/include/Nazara/Graphics/PipelineViewer.hpp b/include/Nazara/Graphics/PipelineViewer.hpp new file mode 100644 index 000000000..f74bc5bbf --- /dev/null +++ b/include/Nazara/Graphics/PipelineViewer.hpp @@ -0,0 +1,36 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_GRAPHICS_PIPELINEVIEWER_HPP +#define NAZARA_GRAPHICS_PIPELINEVIEWER_HPP + +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_GRAPHICS_API PipelineViewer : public AbstractViewer + { + public: + PipelineViewer() = default; + PipelineViewer(const PipelineViewer&) = delete; + PipelineViewer(PipelineViewer&&) = delete; + ~PipelineViewer() = default; + + virtual std::vector> BuildPasses(FramePipelinePass::PassData& passData) const = 0; + + virtual std::size_t RegisterPasses(const std::vector>& passes, FrameGraph& frameGraph) const = 0; + + PipelineViewer& operator=(const PipelineViewer&) = delete; + PipelineViewer& operator=(PipelineViewer&&) = delete; + }; +} + +#include + +#endif // NAZARA_GRAPHICS_PIPELINEVIEWER_HPP diff --git a/include/Nazara/Graphics/PipelineViewer.inl b/include/Nazara/Graphics/PipelineViewer.inl new file mode 100644 index 000000000..c172f3461 --- /dev/null +++ b/include/Nazara/Graphics/PipelineViewer.inl @@ -0,0 +1,11 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include + +namespace Nz +{ +} + +#include diff --git a/include/Nazara/Graphics/PostProcessPipelinePass.hpp b/include/Nazara/Graphics/PostProcessPipelinePass.hpp index b27ddedfb..1d3a6f455 100644 --- a/include/Nazara/Graphics/PostProcessPipelinePass.hpp +++ b/include/Nazara/Graphics/PostProcessPipelinePass.hpp @@ -17,6 +17,7 @@ namespace Nz class FrameGraph; class FramePass; class FramePipeline; + class ParameterList; class RenderFrame; class RenderPipeline; class ShaderBinding; @@ -24,18 +25,21 @@ namespace Nz class NAZARA_GRAPHICS_API PostProcessPipelinePass : public FramePipelinePass { public: - PostProcessPipelinePass(FramePipeline& owner, std::string passName, std::string shaderName); + PostProcessPipelinePass(PassData& passData, std::string passName, const ParameterList& parameters); + PostProcessPipelinePass(PassData& passData, std::string passName, std::string shaderName); PostProcessPipelinePass(const PostProcessPipelinePass&) = delete; PostProcessPipelinePass(PostProcessPipelinePass&&) = delete; ~PostProcessPipelinePass() = default; - void Prepare(RenderFrame& renderFrame); + void Prepare(FrameData& frameData) override; - FramePass& RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t inputColorBufferIndex, std::size_t outputColorBufferIndex); + FramePass& RegisterToFrameGraph(FrameGraph& frameGraph, const PassInputOuputs& inputOuputs) override; PostProcessPipelinePass& operator=(const PostProcessPipelinePass&) = delete; PostProcessPipelinePass& operator=(PostProcessPipelinePass&&) = delete; + static std::string GetShaderName(const ParameterList& parameters); + private: void BuildPipeline(); diff --git a/include/Nazara/Graphics/PostProcessPipelinePass.inl b/include/Nazara/Graphics/PostProcessPipelinePass.inl index c172f3461..67c5832ac 100644 --- a/include/Nazara/Graphics/PostProcessPipelinePass.inl +++ b/include/Nazara/Graphics/PostProcessPipelinePass.inl @@ -6,6 +6,10 @@ namespace Nz { + inline PostProcessPipelinePass::PostProcessPipelinePass(PassData& passData, std::string passName, const ParameterList& parameters) : + PostProcessPipelinePass(passData, std::move(passName), GetShaderName(parameters)) + { + } } #include diff --git a/include/Nazara/Graphics/SpotLightShadowData.hpp b/include/Nazara/Graphics/SpotLightShadowData.hpp index 582714473..1cb7ceb33 100644 --- a/include/Nazara/Graphics/SpotLightShadowData.hpp +++ b/include/Nazara/Graphics/SpotLightShadowData.hpp @@ -28,7 +28,7 @@ namespace Nz inline const ViewerInstance& GetViewerInstance() const; - void PrepareRendering(RenderFrame& renderFrame, const AbstractViewer* viewer) override; + void PrepareRendering(RenderFrame& renderFrame, [[maybe_unused]] const AbstractViewer* viewer) override; void RegisterMaterialInstance(const MaterialInstance& matInstance) override; void RegisterPassInputs(FramePass& pass, const AbstractViewer* viewer) override; diff --git a/src/Nazara/Graphics/Camera.cpp b/src/Nazara/Graphics/Camera.cpp index 4266ce813..056c77c8f 100644 --- a/src/Nazara/Graphics/Camera.cpp +++ b/src/Nazara/Graphics/Camera.cpp @@ -3,11 +3,25 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include +#include +#include #include #include namespace Nz { + Camera::Camera(const RenderTarget* renderTarget, ProjectionType projectionType) : + Camera(renderTarget, Graphics::Instance()->GetDefaultPipelinePasses(), projectionType) + { + } + + std::vector> Camera::BuildPasses(FramePipelinePass::PassData& passData) const + { + assert(m_framePipelinePasses); + return m_framePipelinePasses->BuildPasses(passData); + } + const Color& Camera::GetClearColor() const { return m_clearColor; @@ -41,6 +55,12 @@ namespace Nz return m_viewport; } + std::size_t Camera::RegisterPasses(const std::vector>& passes, FrameGraph& frameGraph) const + { + assert(m_framePipelinePasses); + return m_framePipelinePasses->RegisterPasses(passes, frameGraph); + } + void Camera::UpdateTarget(const RenderTarget* renderTarget) { m_onRenderTargetRelease.Disconnect(); diff --git a/src/Nazara/Graphics/DebugDrawPipelinePass.cpp b/src/Nazara/Graphics/DebugDrawPipelinePass.cpp index ec06f27a1..f9dc471ea 100644 --- a/src/Nazara/Graphics/DebugDrawPipelinePass.cpp +++ b/src/Nazara/Graphics/DebugDrawPipelinePass.cpp @@ -8,31 +8,36 @@ #include #include #include -#include #include namespace Nz { - DebugDrawPipelinePass::DebugDrawPipelinePass(FramePipeline& owner, AbstractViewer* viewer) : - m_viewer(viewer), - m_pipeline(owner) - { - } - - void DebugDrawPipelinePass::Prepare(RenderFrame& renderFrame) + void DebugDrawPipelinePass::Prepare(FrameData& frameData) { DebugDrawer& debugDrawer = m_pipeline.GetDebugDrawer(); debugDrawer.SetViewerData(m_viewer->GetViewerInstance().GetViewProjMatrix()); - debugDrawer.Prepare(renderFrame); + debugDrawer.Prepare(frameData.renderFrame); } - FramePass& DebugDrawPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t inputColorBufferIndex, std::size_t outputColorBufferIndex) + FramePass& DebugDrawPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, const PassInputOuputs& inputOuputs) { - FramePass& debugDrawPass = frameGraph.AddPass("Debug draw pass"); - debugDrawPass.AddInput(inputColorBufferIndex); - debugDrawPass.AddOutput(outputColorBufferIndex); + if (inputOuputs.inputCount != 1) + throw std::runtime_error("one input expected"); - debugDrawPass.SetExecutionCallback([&]() + if (inputOuputs.outputCount != 1) + throw std::runtime_error("one output expected"); + + FramePass& debugDrawPass = frameGraph.AddPass("Debug draw pass"); + debugDrawPass.AddInput(inputOuputs.inputAttachments[0]); + debugDrawPass.AddOutput(inputOuputs.outputAttachments[0]); + + if (inputOuputs.depthStencilInput != InvalidAttachmentIndex) + debugDrawPass.SetDepthStencilInput(inputOuputs.depthStencilInput); + + if (inputOuputs.depthStencilOutput != InvalidAttachmentIndex) + debugDrawPass.SetDepthStencilOutput(inputOuputs.depthStencilInput); + + debugDrawPass.SetExecutionCallback([&] { return FramePassExecution::UpdateAndExecute; }); diff --git a/src/Nazara/Graphics/DepthPipelinePass.cpp b/src/Nazara/Graphics/DepthPipelinePass.cpp index 6ec77af8a..84a457b6e 100644 --- a/src/Nazara/Graphics/DepthPipelinePass.cpp +++ b/src/Nazara/Graphics/DepthPipelinePass.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -15,26 +16,14 @@ namespace Nz { - DepthPipelinePass::DepthPipelinePass(FramePipeline& owner, ElementRendererRegistry& elementRegistry, AbstractViewer* viewer, std::size_t passIndex, std::string passName) : - m_passIndex(passIndex), - m_lastVisibilityHash(0), - m_passName(std::move(passName)), - m_viewer(viewer), - m_elementRegistry(elementRegistry), - m_pipeline(owner), - m_rebuildCommandBuffer(false), - m_rebuildElements(false) + void DepthPipelinePass::Prepare(FrameData& frameData) { - } - - void DepthPipelinePass::Prepare(RenderFrame& renderFrame, const Frustumf& frustum, const std::vector& visibleRenderables, std::size_t visibilityHash) - { - if (m_lastVisibilityHash != visibilityHash || m_rebuildElements) //< FIXME + if (m_lastVisibilityHash != frameData.visibilityHash || m_rebuildElements) //< FIXME { - renderFrame.PushForRelease(std::move(m_renderElements)); + frameData.renderFrame.PushForRelease(std::move(m_renderElements)); m_renderElements.clear(); - for (const auto& renderableData : visibleRenderables) + for (const auto& renderableData : frameData.visibleRenderables) { InstancedRenderable::ElementData elementData{ &renderableData.scissorBox, @@ -56,14 +45,14 @@ namespace Nz m_renderQueueRegistry.Finalize(); - m_lastVisibilityHash = visibilityHash; + m_lastVisibilityHash = frameData.visibilityHash; m_rebuildElements = true; } // TODO: Don't sort every frame if no material pass requires distance sorting m_renderQueue.Sort([&](const RenderElement* element) { - return element->ComputeSortingScore(frustum, m_renderQueueRegistry); + return element->ComputeSortingScore(frameData.frustum, m_renderQueueRegistry); }); if (m_rebuildElements) @@ -78,7 +67,7 @@ namespace Nz m_elementRendererData[elementType] = elementRenderer.InstanciateData(); } - elementRenderer.Reset(*m_elementRendererData[elementType], renderFrame); + elementRenderer.Reset(*m_elementRendererData[elementType], frameData.renderFrame); }); const auto& viewerInstance = m_viewer->GetViewerInstance(); @@ -89,12 +78,12 @@ namespace Nz { ElementRenderer& elementRenderer = m_elementRegistry.GetElementRenderer(elementType); - elementRenderer.Prepare(viewerInstance, *m_elementRendererData[elementType], renderFrame, elementCount, elements, SparsePtr(&defaultRenderStates, 0)); + elementRenderer.Prepare(viewerInstance, *m_elementRendererData[elementType], frameData.renderFrame, elementCount, elements, SparsePtr(&defaultRenderStates, 0)); }); m_elementRegistry.ForEachElementRenderer([&](std::size_t elementType, ElementRenderer& elementRenderer) { - elementRenderer.PrepareEnd(renderFrame, *m_elementRendererData[elementType]); + elementRenderer.PrepareEnd(frameData.renderFrame, *m_elementRendererData[elementType]); }); m_rebuildCommandBuffer = true; @@ -128,13 +117,25 @@ namespace Nz it->second.usedCount++; } - FramePass& DepthPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t outputAttachment) + FramePass& DepthPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, const PassInputOuputs& inputOuputs) { + if (inputOuputs.inputCount > 0) + throw std::runtime_error("no input expected"); + + if (inputOuputs.outputCount > 0) + throw std::runtime_error("no output expected"); + + if (inputOuputs.depthStencilInput != InvalidAttachmentIndex) + throw std::runtime_error("no depth-stencil input expected"); + + if (inputOuputs.depthStencilOutput == InvalidAttachmentIndex) + throw std::runtime_error("expected depth-stencil output"); + FramePass& depthPrepass = frameGraph.AddPass(m_passName); - depthPrepass.SetDepthStencilOutput(outputAttachment); + depthPrepass.SetDepthStencilOutput(inputOuputs.depthStencilOutput); depthPrepass.SetDepthStencilClear(1.f, 0); - depthPrepass.SetExecutionCallback([&]() + depthPrepass.SetExecutionCallback([&] { return (m_rebuildCommandBuffer) ? FramePassExecution::UpdateAndExecute : FramePassExecution::Execute; }); @@ -169,4 +170,24 @@ namespace Nz m_materialInstances.erase(it); } } + + std::size_t DepthPipelinePass::GetMaterialPassIndex(const ParameterList& parameters) + { + Result passIndexResult = parameters.GetIntegerParameter("MatPassIndex"); + if (passIndexResult.IsOk()) + return passIndexResult.GetValue(); + // TODO: Log error if key is present but not of the right + + Result passResult = parameters.GetStringViewParameter("MatPass"); + if (passIndexResult.IsOk()) + { + auto& materialPassRegistry = Graphics::Instance()->GetMaterialPassRegistry(); + + std::string_view passName = passResult.GetValue(); + return materialPassRegistry.GetPassIndex(passName); + } + // TODO: Log error if key is present but not of the right + + throw std::runtime_error("DepthPipelinePass expect either MatPass or MatPassIndex parameter"); + } } diff --git a/src/Nazara/Graphics/DirectionalLightShadowData.cpp b/src/Nazara/Graphics/DirectionalLightShadowData.cpp index c28d98b1d..36aebd5bc 100644 --- a/src/Nazara/Graphics/DirectionalLightShadowData.cpp +++ b/src/Nazara/Graphics/DirectionalLightShadowData.cpp @@ -118,7 +118,15 @@ namespace Nz std::size_t visibilityHash = 5U; const auto& visibleRenderables = m_pipeline.FrustumCull(lightFrustum, 0xFFFFFFFF, visibilityHash); - cascade.depthPass->Prepare(renderFrame, lightFrustum, visibleRenderables, visibilityHash); + FramePipelinePass::FrameData passData = { + nullptr, + frustum, + renderFrame, + visibleRenderables, + visibilityHash + }; + + cascade.depthPass->Prepare(passData); } } @@ -233,7 +241,11 @@ namespace Nz CascadeData& cascade = viewerData.cascades[i]; cascade.attachmentIndex = frameGraph.AddAttachmentArrayLayer(viewerData.textureArrayAttachmentIndex, i); - cascade.depthPass->RegisterToFrameGraph(frameGraph, cascade.attachmentIndex); + + FramePipelinePass::PassInputOuputs passInputOuputs; + passInputOuputs.depthStencilOutput = cascade.attachmentIndex; + + cascade.depthPass->RegisterToFrameGraph(frameGraph, passInputOuputs); } } @@ -254,7 +266,13 @@ namespace Nz shadowViewer.UpdateRenderMask(0xFFFFFFFF); shadowViewer.UpdateViewport(Recti(0, 0, SafeCast(shadowMapSize), SafeCast(shadowMapSize))); - cascade.depthPass.emplace(m_pipeline, m_elementRegistry, &shadowViewer, shadowPassIndex, Format("Cascade #{}", cascadeIndex++)); + FramePipelinePass::PassData passData = { + &shadowViewer, + m_elementRegistry, + m_pipeline + }; + + cascade.depthPass.emplace(passData, Format("Cascade #{}", cascadeIndex++), shadowPassIndex); } m_pipeline.ForEachRegisteredMaterialInstance([&](const MaterialInstance& matInstance) diff --git a/src/Nazara/Graphics/ForwardFramePipeline.cpp b/src/Nazara/Graphics/ForwardFramePipeline.cpp index 90e061247..e10f0b628 100644 --- a/src/Nazara/Graphics/ForwardFramePipeline.cpp +++ b/src/Nazara/Graphics/ForwardFramePipeline.cpp @@ -3,11 +3,11 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include #include #include #include #include +#include #include #include #include @@ -110,16 +110,6 @@ namespace Nz lightData->onLightInvalidated.Connect(lightData->light->OnLightDataInvalided, [=](Light*) { //TODO: Switch lights to storage buffers so they can all be part of GPU memory - for (auto& viewerData : m_viewerPool) - { - if (viewerData.pendingDestruction) - continue; - - UInt32 viewerRenderMask = viewerData.viewer->GetRenderMask(); - - if (viewerRenderMask & renderMask) - viewerData.forwardPass->InvalidateElements(); - } }); lightData->onLightShadowCastingChanged.Connect(lightData->light->OnLightShadowCastingChanged, [=](Light* light, bool isCastingShadows) @@ -194,10 +184,11 @@ namespace Nz if (viewerRenderMask & renderMask) { - if (viewerData.depthPrepass) - viewerData.depthPrepass->InvalidateElements(); - - viewerData.forwardPass->InvalidateElements(); + for (auto& passPtr : viewerData.passes) + { + if (passPtr->ShouldNotify(FramePipelineNotification::ElementInvalidation)) + passPtr->InvalidateElements(); + } } } }); @@ -213,10 +204,11 @@ namespace Nz if (viewerData.pendingDestruction) continue; - if (viewerData.depthPrepass) - viewerData.depthPrepass->RegisterMaterialInstance(*newMaterial); - - viewerData.forwardPass->RegisterMaterialInstance(*newMaterial); + for (auto& passPtr : viewerData.passes) + { + if (passPtr->ShouldNotify(FramePipelineNotification::MaterialInstanceRegistration)) + passPtr->RegisterMaterialInstance(*newMaterial); + } } } @@ -230,10 +222,11 @@ namespace Nz if (viewerData.pendingDestruction) continue; - if (viewerData.depthPrepass) - viewerData.depthPrepass->UnregisterMaterialInstance(*prevMaterial); - - viewerData.forwardPass->UnregisterMaterialInstance(*prevMaterial); + for (auto& passPtr : viewerData.passes) + { + if (passPtr->ShouldNotify(FramePipelineNotification::MaterialInstanceRegistration)) + passPtr->UnregisterMaterialInstance(*prevMaterial); + } } } }); @@ -250,10 +243,11 @@ namespace Nz if (viewerData.pendingDestruction) continue; - if (viewerData.depthPrepass) - viewerData.depthPrepass->RegisterMaterialInstance(*mat); - - viewerData.forwardPass->RegisterMaterialInstance(*mat); + for (auto& passPtr : viewerData.passes) + { + if (passPtr->ShouldNotify(FramePipelineNotification::MaterialInstanceRegistration)) + passPtr->RegisterMaterialInstance(*mat); + } } } } @@ -275,28 +269,24 @@ namespace Nz return skeletonInstanceIndex; } - std::size_t ForwardFramePipeline::RegisterViewer(AbstractViewer* viewerInstance, Int32 renderOrder, FramePipelineExtraPassFlags passFlags) + std::size_t ForwardFramePipeline::RegisterViewer(PipelineViewer* viewerInstance, Int32 renderOrder) { - std::size_t depthPassIndex = Graphics::Instance()->GetMaterialPassRegistry().GetPassIndex("DepthPass"); - std::size_t viewerIndex; auto& viewerData = *m_viewerPool.Allocate(viewerIndex); viewerData.renderOrder = renderOrder; - viewerData.forwardPass = std::make_unique(*this, m_elementRegistry, viewerInstance); viewerData.viewer = viewerInstance; viewerData.onTransferRequired.Connect(viewerInstance->GetViewerInstance().OnTransferRequired, [this](TransferInterface* transferInterface) { m_transferSet.insert(transferInterface); }); - if (passFlags.Test(FramePipelineExtraPass::DebugDraw)) - viewerData.debugDrawPass = std::make_unique(*this, viewerInstance); + FramePipelinePass::PassData passData = { + viewerInstance, + m_elementRegistry, + *this + }; - if (passFlags.Test(FramePipelineExtraPass::DepthPrepass)) - viewerData.depthPrepass = std::make_unique(*this, m_elementRegistry, viewerInstance, depthPassIndex, "Depth pre-pass"); - - if (passFlags.Test(FramePipelineExtraPass::GammaCorrection)) - viewerData.gammaCorrectionPass = std::make_unique(*this, "Gamma correction", "PostProcess.GammaCorrection"); + viewerData.passes = viewerInstance->BuildPasses(passData); m_transferSet.insert(&viewerInstance->GetViewerInstance()); @@ -446,16 +436,16 @@ namespace Nz std::size_t visibilityHash = 5; const auto& visibleRenderables = FrustumCull(viewerData.frame.frustum, renderMask, visibilityHash); - if (viewerData.depthPrepass) - viewerData.depthPrepass->Prepare(renderFrame, viewerData.frame.frustum, visibleRenderables, visibilityHash); + FramePipelinePass::FrameData passData = { + &viewerData.frame.visibleLights, + viewerData.frame.frustum, + renderFrame, + visibleRenderables, + visibilityHash + }; - viewerData.forwardPass->Prepare(renderFrame, viewerData.frame.frustum, visibleRenderables, viewerData.frame.visibleLights, visibilityHash); - - if (viewerData.gammaCorrectionPass) - viewerData.gammaCorrectionPass->Prepare(renderFrame); - - if (viewerData.debugDrawPass) - viewerData.debugDrawPass->Prepare(renderFrame); + for (auto& passPtr : viewerData.passes) + passPtr->Prepare(passData); } if (frameGraphInvalidated) @@ -587,10 +577,11 @@ namespace Nz if (viewerData.pendingDestruction) continue; - if (viewerData.depthPrepass) - viewerData.depthPrepass->UnregisterMaterialInstance(*material); - - viewerData.forwardPass->UnregisterMaterialInstance(*material); + for (auto& passPtr : viewerData.passes) + { + if (passPtr->ShouldNotify(FramePipelineNotification::MaterialInstanceRegistration)) + passPtr->UnregisterMaterialInstance(*material); + } } } @@ -654,10 +645,11 @@ namespace Nz if (viewerRenderMask & renderableData->renderMask) { - if (viewerData.depthPrepass) - viewerData.depthPrepass->InvalidateElements(); - - viewerData.forwardPass->InvalidateElements(); + for (auto& passPtr : viewerData.passes) + { + if (passPtr->ShouldNotify(FramePipelineNotification::ElementInvalidation)) + passPtr->InvalidateElements(); + } } } } @@ -677,10 +669,11 @@ namespace Nz if (viewerRenderMask & renderableData->renderMask) { - if (viewerData.depthPrepass) - viewerData.depthPrepass->InvalidateElements(); - - viewerData.forwardPass->InvalidateElements(); + for (auto& passPtr : viewerData.passes) + { + if (passPtr->ShouldNotify(FramePipelineNotification::ElementInvalidation)) + passPtr->InvalidateElements(); + } } } } @@ -720,46 +713,7 @@ namespace Nz lightData->shadowData->RegisterToFrameGraph(frameGraph, viewerData.viewer); } - viewerData.forwardColorAttachment = frameGraph.AddAttachment({ - "Forward output", - PixelFormat::RGBA8 - }); - - viewerData.depthStencilAttachment = frameGraph.AddAttachment({ - "Depth-stencil buffer", - Graphics::Instance()->GetPreferredDepthStencilFormat() - }); - - if (viewerData.depthPrepass) - viewerData.depthPrepass->RegisterToFrameGraph(frameGraph, viewerData.depthStencilAttachment); - - FramePass& forwardPass = viewerData.forwardPass->RegisterToFrameGraph(frameGraph, viewerData.forwardColorAttachment, viewerData.depthStencilAttachment, viewerData.depthPrepass != nullptr); - for (std::size_t i : m_shadowCastingLights.IterBits()) - { - LightData* lightData = m_lightPool.RetrieveFromIndex(i); - if ((renderMask & lightData->renderMask) != 0) - lightData->shadowData->RegisterPassInputs(forwardPass, (lightData->shadowData->IsPerViewer()) ? viewerData.viewer : nullptr); - } - - viewerData.finalColorAttachment = viewerData.forwardColorAttachment; - - if (viewerData.gammaCorrectionPass) - { - std::size_t postGammaColorAttachment = frameGraph.AddAttachment({ - "Gamma-corrected output", - PixelFormat::RGBA8 - }); - - viewerData.gammaCorrectionPass->RegisterToFrameGraph(frameGraph, viewerData.finalColorAttachment, postGammaColorAttachment); - viewerData.finalColorAttachment = postGammaColorAttachment; - } - - if (viewerData.debugDrawPass) - { - viewerData.debugColorAttachment = frameGraph.AddAttachmentProxy("Debug draw output", viewerData.finalColorAttachment); - viewerData.debugDrawPass->RegisterToFrameGraph(frameGraph, viewerData.finalColorAttachment, viewerData.debugColorAttachment); - viewerData.finalColorAttachment = viewerData.debugColorAttachment; - } + viewerData.finalColorAttachment = viewerData.viewer->RegisterPasses(viewerData.passes, frameGraph); } using ViewerPair = std::pair; diff --git a/src/Nazara/Graphics/ForwardPipelinePass.cpp b/src/Nazara/Graphics/ForwardPipelinePass.cpp index 274936464..0abcb48a8 100644 --- a/src/Nazara/Graphics/ForwardPipelinePass.cpp +++ b/src/Nazara/Graphics/ForwardPipelinePass.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -12,9 +13,8 @@ #include #include #include -#include #include -#include +#include #include #include #include @@ -23,11 +23,13 @@ namespace Nz { - ForwardPipelinePass::ForwardPipelinePass(FramePipeline& owner, ElementRendererRegistry& elementRegistry, AbstractViewer* viewer) : + ForwardPipelinePass::ForwardPipelinePass(PassData& passData, std::string passName, const ParameterList& /*parameters*/) : + FramePipelinePass(FramePipelineNotification::ElementInvalidation | FramePipelineNotification::MaterialInstanceRegistration), m_lastVisibilityHash(0), - m_viewer(viewer), - m_elementRegistry(elementRegistry), - m_pipeline(owner), + m_passName(std::move(passName)), + m_viewer(passData.viewer), + m_elementRegistry(passData.elementRegistry), + m_pipeline(passData.pipeline), m_pendingLightUploadAllocation(nullptr), m_rebuildCommandBuffer(false), m_rebuildElements(false) @@ -42,14 +44,16 @@ namespace Nz m_renderState.lightData = RenderBufferView(m_lightDataBuffer.get()); } - void ForwardPipelinePass::Prepare(RenderFrame& renderFrame, const Frustumf& frustum, const std::vector& visibleRenderables, const Bitset& visibleLights, std::size_t visibilityHash) + void ForwardPipelinePass::Prepare(FrameData& frameData) { - if (m_lastVisibilityHash != visibilityHash || m_rebuildElements) //< FIXME + NazaraAssert(frameData.visibleLights, "visible lights must be valid"); + + if (m_lastVisibilityHash != frameData.visibilityHash || m_rebuildElements) //< FIXME { - renderFrame.PushForRelease(std::move(m_renderElements)); + frameData.renderFrame.PushForRelease(std::move(m_renderElements)); m_renderElements.clear(); - for (const auto& renderableData : visibleRenderables) + for (const auto& renderableData : frameData.visibleRenderables) { InstancedRenderable::ElementData elementData{ &renderableData.scissorBox, @@ -71,17 +75,17 @@ namespace Nz m_renderQueueRegistry.Finalize(); - m_lastVisibilityHash = visibilityHash; + m_lastVisibilityHash = frameData.visibilityHash; InvalidateElements(); } // TODO: Don't sort every frame if no material pass requires distance sorting m_renderQueue.Sort([&](const RenderElement* element) { - return element->ComputeSortingScore(frustum, m_renderQueueRegistry); + return element->ComputeSortingScore(frameData.frustum, m_renderQueueRegistry); }); - PrepareLights(renderFrame, frustum, visibleLights); + PrepareLights(frameData.renderFrame, frameData.frustum, *frameData.visibleLights); if (m_rebuildElements) { @@ -93,7 +97,7 @@ namespace Nz if (!m_elementRendererData[elementType]) m_elementRendererData[elementType] = elementRenderer.InstanciateData(); - elementRenderer.Reset(*m_elementRendererData[elementType], renderFrame); + elementRenderer.Reset(*m_elementRendererData[elementType], frameData.renderFrame); }); const auto& viewerInstance = m_viewer->GetViewerInstance(); @@ -101,12 +105,12 @@ namespace Nz m_elementRegistry.ProcessRenderQueue(m_renderQueue, [&](std::size_t elementType, const Pointer* elements, std::size_t elementCount) { ElementRenderer& elementRenderer = m_elementRegistry.GetElementRenderer(elementType); - elementRenderer.Prepare(viewerInstance, *m_elementRendererData[elementType], renderFrame, elementCount, elements, SparsePtr(&m_renderState, 0)); + elementRenderer.Prepare(viewerInstance, *m_elementRendererData[elementType], frameData.renderFrame, elementCount, elements, SparsePtr(&m_renderState, 0)); }); m_elementRegistry.ForEachElementRenderer([&](std::size_t elementType, ElementRenderer& elementRenderer) { - elementRenderer.PrepareEnd(renderFrame, *m_elementRendererData[elementType]); + elementRenderer.PrepareEnd(frameData.renderFrame, *m_elementRendererData[elementType]); }); m_rebuildCommandBuffer = true; @@ -140,14 +144,23 @@ namespace Nz it->second.usedCount++; } - FramePass& ForwardPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t colorBufferIndex, std::size_t depthBufferIndex, bool hasDepthPrepass) + FramePass& ForwardPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, const PassInputOuputs& inputOuputs) { - FramePass& forwardPass = frameGraph.AddPass("Forward pass"); - forwardPass.AddOutput(colorBufferIndex); - if (hasDepthPrepass) - forwardPass.SetDepthStencilInput(depthBufferIndex); + if (inputOuputs.inputCount > 0) + throw std::runtime_error("no input expected"); - forwardPass.SetDepthStencilOutput(depthBufferIndex); + if (inputOuputs.outputCount != 1) + throw std::runtime_error("one output expected"); + + if (inputOuputs.depthStencilOutput == InvalidAttachmentIndex) + throw std::runtime_error("expected depth-stencil output"); + + FramePass& forwardPass = frameGraph.AddPass(m_passName); + forwardPass.AddOutput(inputOuputs.outputAttachments[0]); + if (inputOuputs.depthStencilInput != FramePipelinePass::InvalidAttachmentIndex) + forwardPass.SetDepthStencilInput(inputOuputs.depthStencilInput); + + forwardPass.SetDepthStencilOutput(inputOuputs.depthStencilOutput); forwardPass.SetClearColor(0, m_viewer->GetClearColor()); forwardPass.SetDepthStencilClear(1.f, 0); @@ -188,7 +201,7 @@ namespace Nz } } - void ForwardPipelinePass::OnTransfer(RenderFrame& renderFrame, CommandBufferBuilder& builder) + void ForwardPipelinePass::OnTransfer(RenderFrame& /*renderFrame*/, CommandBufferBuilder& builder) { assert(m_pendingLightUploadAllocation); builder.CopyBuffer(*m_pendingLightUploadAllocation, RenderBufferView(m_lightDataBuffer.get())); diff --git a/src/Nazara/Graphics/FramePipelinePass.cpp b/src/Nazara/Graphics/FramePipelinePass.cpp index a1772f1f4..c1bca3b1f 100644 --- a/src/Nazara/Graphics/FramePipelinePass.cpp +++ b/src/Nazara/Graphics/FramePipelinePass.cpp @@ -8,4 +8,16 @@ namespace Nz { FramePipelinePass::~FramePipelinePass() = default; + + void FramePipelinePass::InvalidateElements() + { + } + + void FramePipelinePass::RegisterMaterialInstance(const MaterialInstance& materialInstance) + { + } + + void FramePipelinePass::UnregisterMaterialInstance(const MaterialInstance& materialInstance) + { + } } diff --git a/src/Nazara/Graphics/Graphics.cpp b/src/Nazara/Graphics/Graphics.cpp index cdbe79850..d65a75b06 100644 --- a/src/Nazara/Graphics/Graphics.cpp +++ b/src/Nazara/Graphics/Graphics.cpp @@ -5,9 +5,13 @@ #include #include #include +#include +#include #include #include #include +#include +#include #include #include #include @@ -148,6 +152,8 @@ namespace Nz MaterialPipeline::Initialize(); BuildDefaultMaterials(); + RegisterPipelinePasses(); + BuildDefaultPipelinePasses(); Font::SetDefaultAtlas(std::make_shared(*m_renderDevice)); @@ -364,6 +370,43 @@ namespace Nz } } + void Graphics::BuildDefaultPipelinePasses() + { + m_defaultPipelinePasses = std::make_shared(); + + // Forward pass + std::size_t forwardColorOutput = m_defaultPipelinePasses->AddAttachment({ + "Forward output", + PixelFormat::RGBA16F + }); + + std::size_t forwardDepthOutput = m_defaultPipelinePasses->AddAttachment({ + "Depth-stencil buffer", + m_preferredDepthStencilFormat + }); + + std::size_t forwardPass = m_defaultPipelinePasses->AddPass("ForwardPass", m_pipelinePassRegistry.GetPassIndex("Forward")); + + m_defaultPipelinePasses->SetPassOutput(forwardPass, 0, forwardColorOutput); + m_defaultPipelinePasses->SetPassDepthStencilOutput(forwardPass, forwardDepthOutput); + + // Gamma correction + std::size_t gammaCorrectionOutput = m_defaultPipelinePasses->AddAttachment({ + "Gamma-corrected output", + PixelFormat::RGBA8 + }); + + ParameterList gammaCorrectionParameters; + gammaCorrectionParameters.SetParameter("Shader", "PostProcess.GammaCorrection"); + + std::size_t gammaCorrectionPass = m_defaultPipelinePasses->AddPass("Gamma correction", m_pipelinePassRegistry.GetPassIndex("PostProcess"), gammaCorrectionParameters); + + m_defaultPipelinePasses->SetPassInput(gammaCorrectionPass, 0, forwardColorOutput); + m_defaultPipelinePasses->SetPassOutput(gammaCorrectionPass, 0, gammaCorrectionOutput); + + m_defaultPipelinePasses->SetFinalOutput(gammaCorrectionOutput); + } + void Graphics::BuildDefaultTextures() { // Depth textures (white but with a depth format) @@ -419,6 +462,12 @@ namespace Nz m_materialPassRegistry.RegisterPass("DistanceShadowPass"); } + void Graphics::RegisterPipelinePasses() + { + m_pipelinePassRegistry.RegisterPass("Depth"); + m_pipelinePassRegistry.RegisterPass("Forward"); + m_pipelinePassRegistry.RegisterPass("PostProcess"); + } void Graphics::RegisterShaderModules() { m_shaderModuleResolver = std::make_shared(); diff --git a/src/Nazara/Graphics/PipelinePassList.cpp b/src/Nazara/Graphics/PipelinePassList.cpp new file mode 100644 index 000000000..564ecc1b5 --- /dev/null +++ b/src/Nazara/Graphics/PipelinePassList.cpp @@ -0,0 +1,67 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + std::vector> PipelinePassList::BuildPasses(FramePipelinePass::PassData& passData) const + { + auto& passRegistry = Graphics::Instance()->GetFramePipelinePassRegistry(); + + std::vector> passes; + for (const Pass& pass : m_passes) + passes.emplace_back(passRegistry.BuildPass(pass.implIndex, passData, pass.name, pass.parameterList)); + + return passes; + } + + std::size_t PipelinePassList::RegisterPasses(const std::vector>& passes, FrameGraph& frameGraph) const + { + NazaraAssert(m_passes.size() == passes.size(), "pass vector size doesn't match passlist size"); + + StackArray attachmentIndices = NazaraStackArrayNoInit(std::size_t, m_attachments.size()); + for (std::size_t i = 0; i < m_attachments.size(); ++i) + attachmentIndices[i] = frameGraph.AddAttachment(m_attachments[i]); + + auto GetAttachmentIndex = [&](std::size_t attachmentIndex) + { + if (attachmentIndex == NoAttachment) + return NoAttachment; + + assert(attachmentIndex < m_attachments.size()); + return attachmentIndices[attachmentIndex]; + }; + + for (std::size_t i = 0; i < passes.size(); ++i) + { + const Pass& passData = m_passes[i]; + + std::array inputs; + for (std::size_t j = 0; j < passData.inputs.size(); ++j) + inputs[j] = GetAttachmentIndex(passData.inputs[j]); + + std::array outputs; + for (std::size_t j = 0; j < passData.outputs.size(); ++j) + outputs[j] = GetAttachmentIndex(passData.outputs[j]); + + FramePipelinePass::PassInputOuputs passInputOuputs; + passInputOuputs.depthStencilInput = GetAttachmentIndex(passData.depthStencilInput); + passInputOuputs.depthStencilOutput = GetAttachmentIndex(passData.depthStencilOutput); + passInputOuputs.inputAttachments = inputs.data(); + passInputOuputs.inputCount = passData.inputs.size(); + passInputOuputs.outputAttachments = outputs.data(); + passInputOuputs.outputCount = passData.outputs.size(); + + passes[i]->RegisterToFrameGraph(frameGraph, passInputOuputs); + } + + return GetAttachmentIndex(m_finalOutputAttachment); + } +} diff --git a/src/Nazara/Graphics/PointLightShadowData.cpp b/src/Nazara/Graphics/PointLightShadowData.cpp index b1f84ce30..076011ff1 100644 --- a/src/Nazara/Graphics/PointLightShadowData.cpp +++ b/src/Nazara/Graphics/PointLightShadowData.cpp @@ -83,7 +83,13 @@ namespace Nz m_pipeline.QueueTransfer(&viewerInstance); - m_directions[i].depthPass.emplace(m_pipeline, elementRegistry, &viewer, shadowPassIndex, std::string(s_dirNames[i])); + FramePipelinePass::PassData passData = { + &viewer, + elementRegistry, + m_pipeline + }; + + m_directions[i].depthPass.emplace(passData, std::string(s_dirNames[i]), shadowPassIndex); } m_pipeline.ForEachRegisteredMaterialInstance([this](const MaterialInstance& matInstance) @@ -106,7 +112,15 @@ namespace Nz std::size_t visibilityHash = 5U; const auto& visibleRenderables = m_pipeline.FrustumCull(frustum, 0xFFFFFFFF, visibilityHash); - direction.depthPass->Prepare(renderFrame, frustum, visibleRenderables, visibilityHash); + FramePipelinePass::FrameData passData = { + nullptr, + frustum, + renderFrame, + visibleRenderables, + visibilityHash + }; + + direction.depthPass->Prepare(passData); } } @@ -144,7 +158,11 @@ namespace Nz { DirectionData& direction = m_directions[i]; direction.attachmentIndex = frameGraph.AddAttachmentCubeFace(m_cubeAttachmentIndex, static_cast(i)); - direction.depthPass->RegisterToFrameGraph(frameGraph, direction.attachmentIndex); + + FramePipelinePass::PassInputOuputs passInputOuputs; + passInputOuputs.depthStencilOutput = direction.attachmentIndex; + + direction.depthPass->RegisterToFrameGraph(frameGraph, passInputOuputs); } } diff --git a/src/Nazara/Graphics/PostProcessPipelinePass.cpp b/src/Nazara/Graphics/PostProcessPipelinePass.cpp index ca774fc43..cf8a6dc5e 100644 --- a/src/Nazara/Graphics/PostProcessPipelinePass.cpp +++ b/src/Nazara/Graphics/PostProcessPipelinePass.cpp @@ -11,10 +11,11 @@ namespace Nz { - PostProcessPipelinePass::PostProcessPipelinePass(FramePipeline& owner, std::string passName, std::string shaderName) : + PostProcessPipelinePass::PostProcessPipelinePass(PassData& passData, std::string passName, std::string shaderName) : + FramePipelinePass({}), m_passName(std::move(passName)), m_shader(nzsl::ShaderStageType::Fragment | nzsl::ShaderStageType::Vertex, std::move(shaderName)), - m_pipeline(owner) + m_pipeline(passData.pipeline) { RenderPipelineLayoutInfo layoutInfo; layoutInfo.bindings.assign({ @@ -37,25 +38,39 @@ namespace Nz BuildPipeline(); } - void PostProcessPipelinePass::Prepare(RenderFrame& renderFrame) + void PostProcessPipelinePass::Prepare(FrameData& frameData) { if (m_nextRenderPipeline) { if (m_renderPipeline) - renderFrame.PushForRelease(std::move(m_renderPipeline)); + frameData.renderFrame.PushForRelease(std::move(m_renderPipeline)); m_renderPipeline = std::move(m_nextRenderPipeline); m_rebuildFramePass = true; } } - FramePass& PostProcessPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t inputColorBufferIndex, std::size_t outputColorBufferIndex) + FramePass& PostProcessPipelinePass::RegisterToFrameGraph(FrameGraph& frameGraph, const PassInputOuputs& inputOuputs) { + if (inputOuputs.inputCount != 1) + throw std::runtime_error("one input expected"); + + if (inputOuputs.outputCount != 1) + throw std::runtime_error("one output expected"); + + if (inputOuputs.depthStencilInput != InvalidAttachmentIndex) + throw std::runtime_error("unexpected depth-stencil output"); + + if (inputOuputs.depthStencilOutput != InvalidAttachmentIndex) + throw std::runtime_error("unexpected depth-stencil output"); + + std::size_t inputColorBufferIndex = inputOuputs.inputAttachments[0]; + FramePass& postProcess = frameGraph.AddPass(m_passName); postProcess.AddInput(inputColorBufferIndex); - postProcess.AddOutput(outputColorBufferIndex); + postProcess.AddOutput(inputOuputs.outputAttachments[0]); - postProcess.SetExecutionCallback([&]() + postProcess.SetExecutionCallback([&] { return (m_rebuildFramePass) ? FramePassExecution::UpdateAndExecute : FramePassExecution::Execute; }); @@ -94,6 +109,16 @@ namespace Nz return postProcess; } + std::string PostProcessPipelinePass::GetShaderName(const ParameterList& parameters) + { + Result shaderResult = parameters.GetStringParameter("Shader"); + if (shaderResult.IsOk()) + return std::move(shaderResult).GetValue(); + // TODO: Log error if key is present but not of the right + + throw std::runtime_error("PostProcessPipelinePass expect a Shader parameter"); + } + void PostProcessPipelinePass::BuildPipeline() { std::shared_ptr renderDevice = Graphics::Instance()->GetRenderDevice(); diff --git a/src/Nazara/Graphics/SpotLightShadowData.cpp b/src/Nazara/Graphics/SpotLightShadowData.cpp index 2d9c1a7f6..4442298b9 100644 --- a/src/Nazara/Graphics/SpotLightShadowData.cpp +++ b/src/Nazara/Graphics/SpotLightShadowData.cpp @@ -48,7 +48,13 @@ namespace Nz std::size_t shadowPassIndex = Graphics::Instance()->GetMaterialPassRegistry().GetPassIndex("ShadowPass"); - m_depthPass.emplace(m_pipeline, elementRegistry, &m_viewer, shadowPassIndex, "Spotlight shadow mapping"); + FramePipelinePass::PassData passData = { + &m_viewer, + elementRegistry, + m_pipeline + }; + + m_depthPass.emplace(passData, "Spotlight shadow mapping", shadowPassIndex); m_pipeline.ForEachRegisteredMaterialInstance([this](const MaterialInstance& matInstance) { m_depthPass->RegisterMaterialInstance(matInstance); @@ -66,7 +72,15 @@ namespace Nz std::size_t visibilityHash = 5U; const auto& visibleRenderables = m_pipeline.FrustumCull(frustum, 0xFFFFFFFF, visibilityHash); - m_depthPass->Prepare(renderFrame, frustum, visibleRenderables, visibilityHash); + FramePipelinePass::FrameData passData = { + nullptr, + frustum, + renderFrame, + visibleRenderables, + visibilityHash + }; + + m_depthPass->Prepare(passData); } void SpotLightShadowData::RegisterMaterialInstance(const MaterialInstance& matInstance) @@ -94,7 +108,10 @@ namespace Nz shadowMapSize, shadowMapSize, }); - m_depthPass->RegisterToFrameGraph(frameGraph, m_attachmentIndex); + FramePipelinePass::PassInputOuputs passInputOuputs; + passInputOuputs.depthStencilOutput = m_attachmentIndex; + + m_depthPass->RegisterToFrameGraph(frameGraph, passInputOuputs); } const Texture* SpotLightShadowData::RetrieveLightShadowmap(const BakedFrameGraph& bakedGraph, const AbstractViewer* /*viewer*/) const diff --git a/src/Nazara/Graphics/Systems/RenderSystem.cpp b/src/Nazara/Graphics/Systems/RenderSystem.cpp index 54e521725..3028f50f9 100644 --- a/src/Nazara/Graphics/Systems/RenderSystem.cpp +++ b/src/Nazara/Graphics/Systems/RenderSystem.cpp @@ -344,7 +344,7 @@ namespace Nz CameraEntity* cameraEntity = m_cameraEntityPool.Allocate(poolIndex); cameraEntity->poolIndex = poolIndex; cameraEntity->entity = entity; - cameraEntity->viewerIndex = m_pipeline->RegisterViewer(&entityCamera, entityCamera.GetRenderOrder(), entityCamera.GetFramePipelineExtraPassFlags()); + cameraEntity->viewerIndex = m_pipeline->RegisterViewer(&entityCamera, entityCamera.GetRenderOrder()); cameraEntity->onNodeInvalidation.Connect(entityNode.OnNodeInvalidation, [this, cameraEntity](const Node* /*node*/) { m_invalidatedCameraNode.insert(cameraEntity); diff --git a/src/Nazara/Renderer/DebugDrawer.cpp b/src/Nazara/Renderer/DebugDrawer.cpp index 00d1ad0f9..9a5bf46db 100644 --- a/src/Nazara/Renderer/DebugDrawer.cpp +++ b/src/Nazara/Renderer/DebugDrawer.cpp @@ -53,7 +53,7 @@ namespace Nz pipelineInfo.pipelineLayout = m_renderPipelineLayout; pipelineInfo.shaderModules.push_back(std::move(debugDrawShader)); pipelineInfo.depthBuffer = true; - pipelineInfo.depthWrite = false; + pipelineInfo.depthWrite = true; pipelineInfo.blending = true; pipelineInfo.blend.srcColor = BlendFunc::SrcAlpha; diff --git a/tests/GraphicsTest/main.cpp b/tests/GraphicsTest/main.cpp index 40f6e0ef6..228c21bdc 100644 --- a/tests/GraphicsTest/main.cpp +++ b/tests/GraphicsTest/main.cpp @@ -94,7 +94,7 @@ int main() Nz::ElementRendererRegistry elementRegistry; Nz::ForwardFramePipeline framePipeline(elementRegistry); - [[maybe_unused]] std::size_t cameraIndex = framePipeline.RegisterViewer(&camera, 0, Nz::FramePipelineAllExtraPasses); + [[maybe_unused]] std::size_t cameraIndex = framePipeline.RegisterViewer(&camera, 0); std::size_t worldInstanceIndex1 = framePipeline.RegisterWorldInstance(modelInstance); std::size_t worldInstanceIndex2 = framePipeline.RegisterWorldInstance(modelInstance2); framePipeline.RegisterRenderable(worldInstanceIndex1, Nz::FramePipeline::NoSkeletonInstance, &model, 0xFFFFFFFF, scissorBox);