Graphics: Add RenderTexture class
This commit is contained in:
parent
4f08d0b3c1
commit
aaf3d97954
|
|
@ -1 +1 @@
|
||||||
4
|
5
|
||||||
|
|
|
||||||
|
|
@ -1037,7 +1037,7 @@ int main(int argc, char* argv[])
|
||||||
builder.Draw(3);
|
builder.Draw(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
graph.AddBackbufferOutput(toneMappingOutput);
|
graph.MarkAsFinalOutput(toneMappingOutput);
|
||||||
|
|
||||||
return graph.Bake();
|
return graph.Bake();
|
||||||
}();
|
}();
|
||||||
|
|
@ -1180,7 +1180,9 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
currentFrame = &frame;
|
currentFrame = &frame;
|
||||||
|
|
||||||
if (bakedGraph.Resize(frame))
|
std::array<Nz::Vector2ui, 1> sizes = { currentFrame->GetSize() };
|
||||||
|
|
||||||
|
if (bakedGraph.Resize(frame, sizes))
|
||||||
{
|
{
|
||||||
frame.PushForRelease(std::move(gbufferShaderBinding));
|
frame.PushForRelease(std::move(gbufferShaderBinding));
|
||||||
|
|
||||||
|
|
@ -1512,7 +1514,7 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
bakedGraph.Execute(frame);
|
bakedGraph.Execute(frame);
|
||||||
|
|
||||||
const Nz::RenderTarget* windowRT = &windowSwapchain;
|
const Nz::WindowSwapchain* windowRT = &windowSwapchain;
|
||||||
frame.Execute([&](Nz::CommandBufferBuilder& builder)
|
frame.Execute([&](Nz::CommandBufferBuilder& builder)
|
||||||
{
|
{
|
||||||
Nz::Recti windowRenderRect(0, 0, window.GetSize().x, window.GetSize().y);
|
Nz::Recti windowRenderRect(0, 0, window.GetSize().x, window.GetSize().y);
|
||||||
|
|
|
||||||
|
|
@ -412,6 +412,81 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Nz::TextureInfo screenTextureInfo = {
|
||||||
|
.pixelFormat = Nz::PixelFormat::RGBA8,
|
||||||
|
.type = Nz::ImageType::E2D,
|
||||||
|
.levelCount = 1,
|
||||||
|
.height = 360,
|
||||||
|
.width = 480
|
||||||
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<Nz::Texture> screenTexture = device->InstantiateTexture(screenTextureInfo);
|
||||||
|
|
||||||
|
Nz::RenderTexture renderTexture(screenTexture);
|
||||||
|
|
||||||
|
entt::handle tvCameraEntity = world.CreateEntity();
|
||||||
|
{
|
||||||
|
auto& cameraNode = tvCameraEntity.emplace<Nz::NodeComponent>();
|
||||||
|
cameraNode.SetParentJoint(bobEntity, "Head");
|
||||||
|
cameraNode.SetRotation(Nz::EulerAnglesf(-30.f, 180.f, 0.f));
|
||||||
|
//cameraNode.SetParent(playerCamera);
|
||||||
|
|
||||||
|
auto& cameraComponent = tvCameraEntity.emplace<Nz::CameraComponent>(&renderTexture);
|
||||||
|
cameraComponent.UpdateZNear(0.2f);
|
||||||
|
cameraComponent.UpdateZFar(1000.f);
|
||||||
|
cameraComponent.UpdateRenderMask(1);
|
||||||
|
cameraComponent.UpdateClearColor(Nz::Color(0.f, 0.f, 0.f));
|
||||||
|
cameraComponent.UpdateRenderOrder(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
entt::handle tvEntity = world.CreateEntity();
|
||||||
|
{
|
||||||
|
Nz::MeshParams tvMeshParams;
|
||||||
|
tvMeshParams.vertexScale = Nz::Vector3f(0.01f);
|
||||||
|
|
||||||
|
std::shared_ptr<Nz::Mesh> tvMesh = fs.Load<Nz::Mesh>("assets/retro_tv_lowpoly_4k_textures/scene.gltf", tvMeshParams);
|
||||||
|
if (!tvMesh)
|
||||||
|
{
|
||||||
|
NazaraError("failed to load tv mesh");
|
||||||
|
return __LINE__;
|
||||||
|
}
|
||||||
|
|
||||||
|
tvMesh->RemoveSubMesh(1); // looks like this submesh has issues loading
|
||||||
|
|
||||||
|
// Screen UVs are upside down (model made for OpenGL?)
|
||||||
|
{
|
||||||
|
// Reverse them
|
||||||
|
Nz::VertexMapper vertexMapper(*tvMesh->GetSubMesh(1));
|
||||||
|
Nz::SparsePtr<Nz::Vector2f> uv = vertexMapper.GetComponentPtr<Nz::Vector2f>(Nz::VertexComponent::TexCoord);
|
||||||
|
for (Nz::UInt32 i = 0; i < vertexMapper.GetVertexCount(); ++i)
|
||||||
|
uv[i].y = 1.f - uv[i].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Nz::GraphicalMesh> tvGfxMesh = Nz::GraphicalMesh::BuildFromMesh(*tvMesh);
|
||||||
|
std::shared_ptr<Nz::Model> tvModel = std::make_shared<Nz::Model>(std::move(tvGfxMesh));
|
||||||
|
|
||||||
|
Nz::TextureParams srgbTexParams;
|
||||||
|
srgbTexParams.loadFormat = Nz::PixelFormat::RGBA8_SRGB;
|
||||||
|
|
||||||
|
std::shared_ptr<Nz::MaterialInstance> tvMat = Nz::MaterialInstance::Instantiate(Nz::MaterialType::PhysicallyBased);
|
||||||
|
tvMat->SetTextureProperty("BaseColorMap", fs.Load<Nz::Texture>("assets/retro_tv_lowpoly_4k_textures/textures/old_tv_baseColor.jpeg", srgbTexParams));
|
||||||
|
tvMat->SetTextureProperty("NormalMap", fs.Load<Nz::Texture>("assets/retro_tv_lowpoly_4k_textures/textures/old_tv_normal.png"));
|
||||||
|
|
||||||
|
tvModel->SetMaterial(0, tvMat);
|
||||||
|
|
||||||
|
std::shared_ptr<Nz::MaterialInstance> screenMat = Nz::MaterialInstance::Instantiate(Nz::MaterialType::PhysicallyBased);
|
||||||
|
screenMat->SetTextureProperty("BaseColorMap", screenTexture);
|
||||||
|
|
||||||
|
tvModel->SetMaterial(1, screenMat);
|
||||||
|
|
||||||
|
auto& tvNode = tvEntity.emplace<Nz::NodeComponent>();
|
||||||
|
tvNode.SetPosition(Nz::Vector3f(-2.586f, 0.5f, 0.892f));
|
||||||
|
|
||||||
|
auto& tvGfx = tvEntity.emplace<Nz::GraphicsComponent>();
|
||||||
|
tvGfx.AttachRenderable(tvModel);
|
||||||
|
}
|
||||||
|
|
||||||
Nz::MillisecondClock fpsClock, updateClock;
|
Nz::MillisecondClock fpsClock, updateClock;
|
||||||
float incr = 0.f;
|
float incr = 0.f;
|
||||||
unsigned int currentFrame = 0;
|
unsigned int currentFrame = 0;
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@
|
||||||
#include <Nazara/Core/ObjectLibrary.hpp>
|
#include <Nazara/Core/ObjectLibrary.hpp>
|
||||||
#include <Nazara/Core/ObjectRef.hpp>
|
#include <Nazara/Core/ObjectRef.hpp>
|
||||||
#include <Nazara/Core/OwnedMemoryStream.hpp>
|
#include <Nazara/Core/OwnedMemoryStream.hpp>
|
||||||
|
#include <Nazara/Core/ParameterFile.hpp>
|
||||||
#include <Nazara/Core/ParameterList.hpp>
|
#include <Nazara/Core/ParameterList.hpp>
|
||||||
#include <Nazara/Core/Plugin.hpp>
|
#include <Nazara/Core/Plugin.hpp>
|
||||||
#include <Nazara/Core/PluginInterface.hpp>
|
#include <Nazara/Core/PluginInterface.hpp>
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
#include <Nazara/Graphics/DebugDrawPipelinePass.hpp>
|
#include <Nazara/Graphics/DebugDrawPipelinePass.hpp>
|
||||||
#include <Nazara/Graphics/DepthPipelinePass.hpp>
|
#include <Nazara/Graphics/DepthPipelinePass.hpp>
|
||||||
#include <Nazara/Graphics/DirectionalLight.hpp>
|
#include <Nazara/Graphics/DirectionalLight.hpp>
|
||||||
|
#include <Nazara/Graphics/DirectionalLightShadowData.hpp>
|
||||||
#include <Nazara/Graphics/ElementRenderer.hpp>
|
#include <Nazara/Graphics/ElementRenderer.hpp>
|
||||||
#include <Nazara/Graphics/ElementRendererRegistry.hpp>
|
#include <Nazara/Graphics/ElementRendererRegistry.hpp>
|
||||||
#include <Nazara/Graphics/Enums.hpp>
|
#include <Nazara/Graphics/Enums.hpp>
|
||||||
|
|
@ -48,6 +49,7 @@
|
||||||
#include <Nazara/Graphics/FramePassAttachment.hpp>
|
#include <Nazara/Graphics/FramePassAttachment.hpp>
|
||||||
#include <Nazara/Graphics/FramePipeline.hpp>
|
#include <Nazara/Graphics/FramePipeline.hpp>
|
||||||
#include <Nazara/Graphics/FramePipelinePass.hpp>
|
#include <Nazara/Graphics/FramePipelinePass.hpp>
|
||||||
|
#include <Nazara/Graphics/FramePipelinePassRegistry.hpp>
|
||||||
#include <Nazara/Graphics/GraphicalMesh.hpp>
|
#include <Nazara/Graphics/GraphicalMesh.hpp>
|
||||||
#include <Nazara/Graphics/Graphics.hpp>
|
#include <Nazara/Graphics/Graphics.hpp>
|
||||||
#include <Nazara/Graphics/GuillotineTextureAtlas.hpp>
|
#include <Nazara/Graphics/GuillotineTextureAtlas.hpp>
|
||||||
|
|
@ -62,9 +64,13 @@
|
||||||
#include <Nazara/Graphics/MaterialPipeline.hpp>
|
#include <Nazara/Graphics/MaterialPipeline.hpp>
|
||||||
#include <Nazara/Graphics/MaterialSettings.hpp>
|
#include <Nazara/Graphics/MaterialSettings.hpp>
|
||||||
#include <Nazara/Graphics/Model.hpp>
|
#include <Nazara/Graphics/Model.hpp>
|
||||||
|
#include <Nazara/Graphics/PipelinePassList.hpp>
|
||||||
|
#include <Nazara/Graphics/PipelineViewer.hpp>
|
||||||
#include <Nazara/Graphics/PointLight.hpp>
|
#include <Nazara/Graphics/PointLight.hpp>
|
||||||
#include <Nazara/Graphics/PointLightShadowData.hpp>
|
#include <Nazara/Graphics/PointLightShadowData.hpp>
|
||||||
|
#include <Nazara/Graphics/PostProcessPipelinePass.hpp>
|
||||||
#include <Nazara/Graphics/PredefinedMaterials.hpp>
|
#include <Nazara/Graphics/PredefinedMaterials.hpp>
|
||||||
|
#include <Nazara/Graphics/PredefinedShaderStructBuilder.hpp>
|
||||||
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
|
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
|
||||||
#include <Nazara/Graphics/RenderBufferPool.hpp>
|
#include <Nazara/Graphics/RenderBufferPool.hpp>
|
||||||
#include <Nazara/Graphics/RenderElement.hpp>
|
#include <Nazara/Graphics/RenderElement.hpp>
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ namespace Nz
|
||||||
const std::shared_ptr<Texture>& GetAttachmentTexture(std::size_t attachmentIndex) const;
|
const std::shared_ptr<Texture>& GetAttachmentTexture(std::size_t attachmentIndex) const;
|
||||||
const std::shared_ptr<RenderPass>& GetRenderPass(std::size_t passIndex) const;
|
const std::shared_ptr<RenderPass>& GetRenderPass(std::size_t passIndex) const;
|
||||||
|
|
||||||
bool Resize(RenderFrame& renderFrame);
|
bool Resize(RenderFrame& renderFrame, std::span<Vector2ui> viewerTargetSizes);
|
||||||
|
|
||||||
BakedFrameGraph& operator=(const BakedFrameGraph&) = delete;
|
BakedFrameGraph& operator=(const BakedFrameGraph&) = delete;
|
||||||
BakedFrameGraph& operator=(BakedFrameGraph&&) noexcept = default;
|
BakedFrameGraph& operator=(BakedFrameGraph&&) noexcept = default;
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ namespace Nz
|
||||||
inline float GetZFar() const;
|
inline float GetZFar() const;
|
||||||
inline float GetZNear() const;
|
inline float GetZNear() const;
|
||||||
|
|
||||||
std::size_t RegisterPasses(const std::vector<std::unique_ptr<FramePipelinePass>>& passes, FrameGraph& frameGraph, const FunctionRef<void(std::size_t passIndex, FramePass& framePass, FramePipelinePassFlags flags)>& passCallback = nullptr) const override;
|
std::size_t RegisterPasses(const std::vector<std::unique_ptr<FramePipelinePass>>& passes, FrameGraph& frameGraph, std::optional<unsigned int> viewerIndex, const FunctionRef<void(std::size_t passIndex, FramePass& framePass, FramePipelinePassFlags flags)>& passCallback = nullptr) const override;
|
||||||
|
|
||||||
inline void UpdateClearColor(Color color);
|
inline void UpdateClearColor(Color color);
|
||||||
inline void UpdateFOV(DegreeAnglef fov);
|
inline void UpdateFOV(DegreeAnglef fov);
|
||||||
|
|
|
||||||
|
|
@ -38,11 +38,12 @@ namespace Nz
|
||||||
inline std::size_t AddAttachmentCube(FramePassAttachment attachment);
|
inline std::size_t AddAttachmentCube(FramePassAttachment attachment);
|
||||||
inline std::size_t AddAttachmentCubeFace(std::size_t attachmentId, CubemapFace face);
|
inline std::size_t AddAttachmentCubeFace(std::size_t attachmentId, CubemapFace face);
|
||||||
inline std::size_t AddAttachmentProxy(std::string name, std::size_t attachmentId);
|
inline std::size_t AddAttachmentProxy(std::string name, std::size_t attachmentId);
|
||||||
inline void AddBackbufferOutput(std::size_t backbufferOutput);
|
|
||||||
inline FramePass& AddPass(std::string name);
|
inline FramePass& AddPass(std::string name);
|
||||||
|
|
||||||
BakedFrameGraph Bake();
|
BakedFrameGraph Bake();
|
||||||
|
|
||||||
|
inline void MarkAsFinalOutput(std::size_t attachmentIndex);
|
||||||
|
|
||||||
FrameGraph& operator=(const FrameGraph&) = delete;
|
FrameGraph& operator=(const FrameGraph&) = delete;
|
||||||
FrameGraph& operator=(FrameGraph&&) noexcept = default;
|
FrameGraph& operator=(FrameGraph&&) noexcept = default;
|
||||||
|
|
||||||
|
|
@ -138,7 +139,7 @@ namespace Nz
|
||||||
|
|
||||||
using AttachmentType = std::variant<FramePassAttachment, AttachmentProxy, AttachmentArray, AttachmentCube, AttachmentLayer>;
|
using AttachmentType = std::variant<FramePassAttachment, AttachmentProxy, AttachmentArray, AttachmentCube, AttachmentLayer>;
|
||||||
|
|
||||||
std::vector<std::size_t> m_backbufferOutputs;
|
std::vector<std::size_t> m_finalOutputs;
|
||||||
std::vector<FramePass> m_framePasses;
|
std::vector<FramePass> m_framePasses;
|
||||||
std::vector<AttachmentType> m_attachments;
|
std::vector<AttachmentType> m_attachments;
|
||||||
WorkData m_pending;
|
WorkData m_pending;
|
||||||
|
|
|
||||||
|
|
@ -78,16 +78,16 @@ namespace Nz
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void FrameGraph::AddBackbufferOutput(std::size_t backbufferOutput)
|
|
||||||
{
|
|
||||||
m_backbufferOutputs.push_back(backbufferOutput);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FramePass& FrameGraph::AddPass(std::string name)
|
inline FramePass& FrameGraph::AddPass(std::string name)
|
||||||
{
|
{
|
||||||
std::size_t id = m_framePasses.size();
|
std::size_t id = m_framePasses.size();
|
||||||
return m_framePasses.emplace_back(*this, id, std::move(name));
|
return m_framePasses.emplace_back(*this, id, std::move(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void FrameGraph::MarkAsFinalOutput(std::size_t attachmentIndex)
|
||||||
|
{
|
||||||
|
m_finalOutputs.push_back(attachmentIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Nazara/Graphics/DebugOff.hpp>
|
#include <Nazara/Graphics/DebugOff.hpp>
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,11 @@ namespace Nz
|
||||||
PixelFormat format;
|
PixelFormat format;
|
||||||
FramePassAttachmentSize size;
|
FramePassAttachmentSize size;
|
||||||
TextureUsageFlags usage;
|
TextureUsageFlags usage;
|
||||||
|
bool canReuse;
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
unsigned int layerCount;
|
unsigned int layerCount;
|
||||||
|
unsigned int viewerIndex;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,8 +90,8 @@ namespace Nz
|
||||||
|
|
||||||
struct Input
|
struct Input
|
||||||
{
|
{
|
||||||
std::size_t attachmentId;
|
|
||||||
std::optional<TextureLayout> assumedLayout;
|
std::optional<TextureLayout> assumedLayout;
|
||||||
|
std::size_t attachmentId;
|
||||||
bool doesRead = true;
|
bool doesRead = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,17 +18,19 @@ namespace Nz
|
||||||
enum class FramePassAttachmentSize
|
enum class FramePassAttachmentSize
|
||||||
{
|
{
|
||||||
Fixed,
|
Fixed,
|
||||||
SwapchainFactor
|
SwapchainFactor,
|
||||||
|
ViewerTargetFactor,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FramePassAttachment
|
struct FramePassAttachment
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
PixelFormat format;
|
PixelFormat format;
|
||||||
TextureUsage additionalUsage = TextureUsage::TransferSource;
|
TextureUsageFlags additionalUsages;
|
||||||
FramePassAttachmentSize size = FramePassAttachmentSize::SwapchainFactor;
|
FramePassAttachmentSize size = FramePassAttachmentSize::ViewerTargetFactor;
|
||||||
unsigned int width = 100'000;
|
unsigned int width = 100'000;
|
||||||
unsigned int height = 100'000;
|
unsigned int height = 100'000;
|
||||||
|
unsigned int viewerIndex = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ namespace Nz
|
||||||
|
|
||||||
inline void EnablePassFlags(std::size_t passIndex, FramePipelinePassFlags flags);
|
inline void EnablePassFlags(std::size_t passIndex, FramePipelinePassFlags flags);
|
||||||
|
|
||||||
std::size_t RegisterPasses(const std::vector<std::unique_ptr<FramePipelinePass>>& passes, FrameGraph& frameGraph, const FunctionRef<void(std::size_t passIndex, FramePass& framePass, FramePipelinePassFlags flags)>& passCallback = nullptr) const;
|
std::size_t RegisterPasses(const std::vector<std::unique_ptr<FramePipelinePass>>& passes, FrameGraph& frameGraph, std::optional<unsigned int> viewerIndex, const FunctionRef<void(std::size_t passIndex, FramePass& framePass, FramePipelinePassFlags flags)>& passCallback = nullptr) const;
|
||||||
|
|
||||||
inline void SetFinalOutput(std::size_t attachmentIndex);
|
inline void SetFinalOutput(std::size_t attachmentIndex);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Nz
|
||||||
|
|
||||||
virtual std::vector<std::unique_ptr<FramePipelinePass>> BuildPasses(FramePipelinePass::PassData& passData) const = 0;
|
virtual std::vector<std::unique_ptr<FramePipelinePass>> BuildPasses(FramePipelinePass::PassData& passData) const = 0;
|
||||||
|
|
||||||
virtual std::size_t RegisterPasses(const std::vector<std::unique_ptr<FramePipelinePass>>& passes, FrameGraph& frameGraph, const FunctionRef<void(std::size_t passIndex, FramePass& framePass, FramePipelinePassFlags flags)>& passCallback = nullptr) const = 0;
|
virtual std::size_t RegisterPasses(const std::vector<std::unique_ptr<FramePipelinePass>>& passes, FrameGraph& frameGraph, std::optional<unsigned int> viewerIndex, const FunctionRef<void(std::size_t passIndex, FramePass& framePass, FramePipelinePassFlags flags)>& passCallback = nullptr) const = 0;
|
||||||
|
|
||||||
PipelineViewer& operator=(const PipelineViewer&) = delete;
|
PipelineViewer& operator=(const PipelineViewer&) = delete;
|
||||||
PipelineViewer& operator=(PipelineViewer&&) = delete;
|
PipelineViewer& operator=(PipelineViewer&&) = delete;
|
||||||
|
|
|
||||||
|
|
@ -270,4 +270,3 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Nazara/OpenGLRenderer/DebugOff.hpp>
|
#include <Nazara/OpenGLRenderer/DebugOff.hpp>
|
||||||
#include "OpenGLCommandBuffer.hpp"
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@
|
||||||
#include <Nazara/Renderer/RenderPipelineLayout.hpp>
|
#include <Nazara/Renderer/RenderPipelineLayout.hpp>
|
||||||
#include <Nazara/Renderer/RenderStates.hpp>
|
#include <Nazara/Renderer/RenderStates.hpp>
|
||||||
#include <Nazara/Renderer/RenderTarget.hpp>
|
#include <Nazara/Renderer/RenderTarget.hpp>
|
||||||
|
#include <Nazara/Renderer/RenderTexture.hpp>
|
||||||
#include <Nazara/Renderer/ShaderBinding.hpp>
|
#include <Nazara/Renderer/ShaderBinding.hpp>
|
||||||
#include <Nazara/Renderer/ShaderModule.hpp>
|
#include <Nazara/Renderer/ShaderModule.hpp>
|
||||||
#include <Nazara/Renderer/Swapchain.hpp>
|
#include <Nazara/Renderer/Swapchain.hpp>
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,6 @@ namespace Nz
|
||||||
|
|
||||||
virtual void BlitTexture(RenderFrame& renderFrame, CommandBufferBuilder& builder, const Texture& texture) const = 0;
|
virtual void BlitTexture(RenderFrame& renderFrame, CommandBufferBuilder& builder, const Texture& texture) const = 0;
|
||||||
|
|
||||||
virtual const Framebuffer& GetFramebuffer(std::size_t i) const = 0;
|
|
||||||
virtual std::size_t GetFramebufferCount() const = 0;
|
|
||||||
virtual const RenderPass& GetRenderPass() const = 0;
|
|
||||||
virtual const Vector2ui& GetSize() const = 0;
|
virtual const Vector2ui& GetSize() const = 0;
|
||||||
|
|
||||||
NazaraSignal(OnRenderTargetRelease, const RenderTarget* /*renderTarget*/);
|
NazaraSignal(OnRenderTargetRelease, const RenderTarget* /*renderTarget*/);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||||
|
// This file is part of the "Nazara Engine - Renderer module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_RENDERER_RENDERTEXTURE_HPP
|
||||||
|
#define NAZARA_RENDERER_RENDERTEXTURE_HPP
|
||||||
|
|
||||||
|
#include <NazaraUtils/Prerequisites.hpp>
|
||||||
|
#include <Nazara/Renderer/Config.hpp>
|
||||||
|
#include <Nazara/Renderer/Enums.hpp>
|
||||||
|
#include <Nazara/Renderer/RenderTarget.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
class Texture;
|
||||||
|
|
||||||
|
class NAZARA_RENDERER_API RenderTexture : public RenderTarget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline RenderTexture(std::shared_ptr<Texture> targetTexture);
|
||||||
|
inline RenderTexture(std::shared_ptr<Texture> targetTexture, PipelineStage targetPipelineStage, MemoryAccessFlags targetMemoryFlags, TextureLayout targetLayout);
|
||||||
|
RenderTexture(const RenderTexture&) = delete;
|
||||||
|
RenderTexture(RenderTexture&&) = delete;
|
||||||
|
~RenderTexture() = default;
|
||||||
|
|
||||||
|
void BlitTexture(RenderFrame& renderFrame, CommandBufferBuilder& builder, const Texture& texture) const override;
|
||||||
|
|
||||||
|
const Vector2ui& GetSize() const override;
|
||||||
|
|
||||||
|
RenderTexture& operator=(const RenderTexture&) = delete;
|
||||||
|
RenderTexture& operator=(RenderTexture&&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Texture> m_targetTexture;
|
||||||
|
MemoryAccessFlags m_targetMemoryFlags;
|
||||||
|
PipelineStage m_targetPipelineStage;
|
||||||
|
TextureLayout m_targetLayout;
|
||||||
|
Vector2ui m_textureSize;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Renderer/RenderTexture.inl>
|
||||||
|
|
||||||
|
#endif // NAZARA_RENDERER_RENDERTEXTURE_HPP
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||||
|
// This file is part of the "Nazara Engine - Renderer module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Renderer/RenderTexture.hpp>
|
||||||
|
#include <Nazara/Renderer/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
inline RenderTexture::RenderTexture(std::shared_ptr<Texture> targetTexture) :
|
||||||
|
RenderTexture(std::move(targetTexture), PipelineStage::FragmentShader, MemoryAccess::ColorRead, TextureLayout::ColorInput)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Renderer/DebugOff.hpp>
|
||||||
|
|
@ -33,7 +33,10 @@ namespace Nz
|
||||||
|
|
||||||
virtual std::shared_ptr<CommandPool> CreateCommandPool(QueueType queueType) = 0;
|
virtual std::shared_ptr<CommandPool> CreateCommandPool(QueueType queueType) = 0;
|
||||||
|
|
||||||
|
virtual const Framebuffer& GetFramebuffer(std::size_t i) const = 0;
|
||||||
|
virtual std::size_t GetFramebufferCount() const = 0;
|
||||||
virtual PresentMode GetPresentMode() const = 0;
|
virtual PresentMode GetPresentMode() const = 0;
|
||||||
|
virtual const RenderPass& GetRenderPass() const = 0;
|
||||||
virtual PresentModeFlags GetSupportedPresentModes() const = 0;
|
virtual PresentModeFlags GetSupportedPresentModes() const = 0;
|
||||||
|
|
||||||
virtual void NotifyResize(const Vector2ui& newSize) = 0;
|
virtual void NotifyResize(const Vector2ui& newSize) = 0;
|
||||||
|
|
|
||||||
|
|
@ -108,4 +108,3 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Nazara/Renderer/DebugOff.hpp>
|
#include <Nazara/Renderer/DebugOff.hpp>
|
||||||
#include "TransientResources.hpp"
|
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,9 @@ namespace Nz
|
||||||
|
|
||||||
inline void EnableRenderOnlyIfFocused(bool enable = true);
|
inline void EnableRenderOnlyIfFocused(bool enable = true);
|
||||||
|
|
||||||
const Framebuffer& GetFramebuffer(std::size_t i) const override;
|
inline const Framebuffer& GetFramebuffer(std::size_t i) const;
|
||||||
std::size_t GetFramebufferCount() const override;
|
inline std::size_t GetFramebufferCount() const;
|
||||||
const RenderPass& GetRenderPass() const override;
|
inline const RenderPass& GetRenderPass() const;
|
||||||
const Vector2ui& GetSize() const override;
|
const Vector2ui& GetSize() const override;
|
||||||
inline Swapchain& GetSwapchain();
|
inline Swapchain& GetSwapchain();
|
||||||
inline const Swapchain& GetSwapchain() const;
|
inline const Swapchain& GetSwapchain() const;
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,24 @@ namespace Nz
|
||||||
m_renderOnlyIfFocused = enable;
|
m_renderOnlyIfFocused = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const Framebuffer& WindowSwapchain::GetFramebuffer(std::size_t i) const
|
||||||
|
{
|
||||||
|
assert(m_swapchain);
|
||||||
|
return m_swapchain->GetFramebuffer(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::size_t WindowSwapchain::GetFramebufferCount() const
|
||||||
|
{
|
||||||
|
assert(m_swapchain);
|
||||||
|
return m_swapchain->GetFramebufferCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const RenderPass& WindowSwapchain::GetRenderPass() const
|
||||||
|
{
|
||||||
|
assert(m_swapchain);
|
||||||
|
return m_swapchain->GetRenderPass();
|
||||||
|
}
|
||||||
|
|
||||||
inline Swapchain& WindowSwapchain::GetSwapchain()
|
inline Swapchain& WindowSwapchain::GetSwapchain()
|
||||||
{
|
{
|
||||||
return *m_swapchain;
|
return *m_swapchain;
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,13 @@ namespace Nz
|
||||||
texDimensions.y *= textureData.height;
|
texDimensions.y *= textureData.height;
|
||||||
texDimensions /= 100'000;
|
texDimensions /= 100'000;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FramePassAttachmentSize::ViewerTargetFactor:
|
||||||
|
texDimensions = viewerTargetSizes[textureData.viewerIndex];
|
||||||
|
texDimensions.x *= textureData.width;
|
||||||
|
texDimensions.y *= textureData.height;
|
||||||
|
texDimensions /= 100'000;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return texDimensions;
|
return texDimensions;
|
||||||
|
|
|
||||||
|
|
@ -55,10 +55,10 @@ namespace Nz
|
||||||
return m_viewport;
|
return m_viewport;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t Camera::RegisterPasses(const std::vector<std::unique_ptr<FramePipelinePass>>& passes, FrameGraph& frameGraph, const FunctionRef<void(std::size_t passIndex, FramePass& framePass, FramePipelinePassFlags flags)>& passCallback) const
|
std::size_t Camera::RegisterPasses(const std::vector<std::unique_ptr<FramePipelinePass>>& passes, FrameGraph& frameGraph, std::optional<unsigned int> viewerIndex, const FunctionRef<void(std::size_t passIndex, FramePass& framePass, FramePipelinePassFlags flags)>& passCallback) const
|
||||||
{
|
{
|
||||||
assert(m_framePipelinePasses);
|
assert(m_framePipelinePasses);
|
||||||
return m_framePipelinePasses->RegisterPasses(passes, frameGraph, passCallback);
|
return m_framePipelinePasses->RegisterPasses(passes, frameGraph, viewerIndex, passCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::UpdateTarget(const RenderTarget* renderTarget)
|
void Camera::UpdateTarget(const RenderTarget* renderTarget)
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include <Nazara/Renderer/RenderTarget.hpp>
|
#include <Nazara/Renderer/RenderTarget.hpp>
|
||||||
#include <Nazara/Renderer/UploadPool.hpp>
|
#include <Nazara/Renderer/UploadPool.hpp>
|
||||||
#include <NazaraUtils/StackArray.hpp>
|
#include <NazaraUtils/StackArray.hpp>
|
||||||
|
#include <NazaraUtils/StackVector.hpp>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <Nazara/Graphics/Debug.hpp>
|
#include <Nazara/Graphics/Debug.hpp>
|
||||||
|
|
||||||
|
|
@ -368,16 +369,26 @@ namespace Nz
|
||||||
}
|
}
|
||||||
m_removedWorldInstances.Clear();
|
m_removedWorldInstances.Clear();
|
||||||
|
|
||||||
|
StackVector<Vector2ui> viewerSizes = NazaraStackVector(Vector2ui, m_viewerPool.size());
|
||||||
|
for (auto& viewerData : m_viewerPool)
|
||||||
|
{
|
||||||
|
if (viewerData.pendingDestruction)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Recti viewport = viewerData.viewer->GetViewport();
|
||||||
|
viewerSizes.emplace_back(Vector2i(viewport.width, viewport.height));
|
||||||
|
}
|
||||||
|
|
||||||
bool frameGraphInvalidated;
|
bool frameGraphInvalidated;
|
||||||
if (m_rebuildFrameGraph)
|
if (m_rebuildFrameGraph)
|
||||||
{
|
{
|
||||||
renderFrame.PushForRelease(std::move(m_bakedFrameGraph));
|
renderFrame.PushForRelease(std::move(m_bakedFrameGraph));
|
||||||
m_bakedFrameGraph = BuildFrameGraph(renderFrame);
|
m_bakedFrameGraph = BuildFrameGraph(renderFrame);
|
||||||
m_bakedFrameGraph.Resize(renderFrame);
|
m_bakedFrameGraph.Resize(renderFrame, viewerSizes);
|
||||||
frameGraphInvalidated = true;
|
frameGraphInvalidated = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
frameGraphInvalidated = m_bakedFrameGraph.Resize(renderFrame);
|
frameGraphInvalidated = m_bakedFrameGraph.Resize(renderFrame, viewerSizes);
|
||||||
|
|
||||||
// Find active lights (i.e. visible in any frustum)
|
// Find active lights (i.e. visible in any frustum)
|
||||||
m_activeLights.Clear();
|
m_activeLights.Clear();
|
||||||
|
|
@ -658,6 +669,7 @@ namespace Nz
|
||||||
lightData->shadowData->RegisterToFrameGraph(frameGraph, nullptr);
|
lightData->shadowData->RegisterToFrameGraph(frameGraph, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int viewerIndex = 0;
|
||||||
for (auto& viewerData : m_viewerPool)
|
for (auto& viewerData : m_viewerPool)
|
||||||
{
|
{
|
||||||
if (viewerData.pendingDestruction)
|
if (viewerData.pendingDestruction)
|
||||||
|
|
@ -684,7 +696,7 @@ namespace Nz
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
viewerData.finalColorAttachment = viewerData.viewer->RegisterPasses(viewerData.passes, frameGraph, framePassCallback);
|
viewerData.finalColorAttachment = viewerData.viewer->RegisterPasses(viewerData.passes, frameGraph, viewerIndex++, framePassCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
using ViewerPair = std::pair<const RenderTarget*, const ViewerData*>;
|
using ViewerPair = std::pair<const RenderTarget*, const ViewerData*>;
|
||||||
|
|
@ -760,14 +772,14 @@ namespace Nz
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
frameGraph.AddBackbufferOutput(renderTargetData.finalAttachment);
|
frameGraph.MarkAsFinalOutput(renderTargetData.finalAttachment);
|
||||||
}
|
}
|
||||||
else if (targetViewers.size() == 1)
|
else if (targetViewers.size() == 1)
|
||||||
{
|
{
|
||||||
// Single viewer on that target
|
// Single viewer on that target
|
||||||
const auto& viewer = *targetViewers.front();
|
const auto& viewer = *targetViewers.front();
|
||||||
|
|
||||||
frameGraph.AddBackbufferOutput(viewer.finalColorAttachment);
|
frameGraph.MarkAsFinalOutput(viewer.finalColorAttachment);
|
||||||
renderTargetData.finalAttachment = viewer.finalColorAttachment;
|
renderTargetData.finalAttachment = viewer.finalColorAttachment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Nz
|
||||||
|
|
||||||
BakedFrameGraph FrameGraph::Bake()
|
BakedFrameGraph FrameGraph::Bake()
|
||||||
{
|
{
|
||||||
if (m_backbufferOutputs.empty())
|
if (m_finalOutputs.empty())
|
||||||
throw std::runtime_error("no backbuffer output has been set");
|
throw std::runtime_error("no backbuffer output has been set");
|
||||||
|
|
||||||
m_pending.attachmentReadList.clear();
|
m_pending.attachmentReadList.clear();
|
||||||
|
|
@ -45,7 +45,7 @@ namespace Nz
|
||||||
|
|
||||||
BuildReadWriteList();
|
BuildReadWriteList();
|
||||||
|
|
||||||
for (std::size_t output : m_backbufferOutputs)
|
for (std::size_t output : m_finalOutputs)
|
||||||
{
|
{
|
||||||
auto it = m_pending.attachmentWriteList.find(output);
|
auto it = m_pending.attachmentWriteList.find(output);
|
||||||
if (it == m_pending.attachmentWriteList.end())
|
if (it == m_pending.attachmentWriteList.end())
|
||||||
|
|
@ -101,10 +101,7 @@ namespace Nz
|
||||||
// Add depth-stencil clear values
|
// Add depth-stencil clear values
|
||||||
if (const auto& depthStencilClear = framePass.GetDepthStencilClear())
|
if (const auto& depthStencilClear = framePass.GetDepthStencilClear())
|
||||||
{
|
{
|
||||||
std::size_t depthClearIndex = colorOutputs.size();
|
auto& dsClearValues = bakedPass.outputClearDepthStencil.emplace();
|
||||||
bakedPass.outputClearValues.resize(depthClearIndex + 1);
|
|
||||||
|
|
||||||
auto& dsClearValues = bakedPass.outputClearValues[depthClearIndex];
|
|
||||||
dsClearValues.depth = depthStencilClear->depth;
|
dsClearValues.depth = depthStencilClear->depth;
|
||||||
dsClearValues.stencil = depthStencilClear->stencil;
|
dsClearValues.stencil = depthStencilClear->stencil;
|
||||||
}
|
}
|
||||||
|
|
@ -261,36 +258,42 @@ namespace Nz
|
||||||
if (std::holds_alternative<FramePassAttachment>(attachmentData))
|
if (std::holds_alternative<FramePassAttachment>(attachmentData))
|
||||||
{
|
{
|
||||||
std::size_t textureId = Retrieve(m_pending.attachmentToTextures, attachmentId);
|
std::size_t textureId = Retrieve(m_pending.attachmentToTextures, attachmentId);
|
||||||
|
if (m_pending.textures[textureId].canReuse)
|
||||||
assert(std::find(m_pending.texture2DPool.begin(), m_pending.texture2DPool.end(), textureId) == m_pending.texture2DPool.end());
|
{
|
||||||
m_pending.texture2DPool.push_back(textureId);
|
assert(std::find(m_pending.texture2DPool.begin(), m_pending.texture2DPool.end(), textureId) == m_pending.texture2DPool.end());
|
||||||
|
m_pending.texture2DPool.push_back(textureId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (std::holds_alternative<AttachmentArray>(attachmentData))
|
else if (std::holds_alternative<AttachmentArray>(attachmentData))
|
||||||
{
|
{
|
||||||
std::size_t textureId = Retrieve(m_pending.attachmentToTextures, attachmentId);
|
std::size_t textureId = Retrieve(m_pending.attachmentToTextures, attachmentId);
|
||||||
|
if (m_pending.textures[textureId].canReuse)
|
||||||
assert(std::find(m_pending.textureCubePool.begin(), m_pending.textureCubePool.end(), textureId) == m_pending.textureCubePool.end());
|
{
|
||||||
m_pending.texture2DArrayPool.push_back(textureId);
|
assert(std::find(m_pending.textureCubePool.begin(), m_pending.textureCubePool.end(), textureId) == m_pending.textureCubePool.end());
|
||||||
|
m_pending.texture2DArrayPool.push_back(textureId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (std::holds_alternative<AttachmentCube>(attachmentData))
|
else if (std::holds_alternative<AttachmentCube>(attachmentData))
|
||||||
{
|
{
|
||||||
std::size_t textureId = Retrieve(m_pending.attachmentToTextures, attachmentId);
|
std::size_t textureId = Retrieve(m_pending.attachmentToTextures, attachmentId);
|
||||||
|
if (m_pending.textures[textureId].canReuse)
|
||||||
assert(std::find(m_pending.textureCubePool.begin(), m_pending.textureCubePool.end(), textureId) == m_pending.textureCubePool.end());
|
{
|
||||||
m_pending.textureCubePool.push_back(textureId);
|
assert(std::find(m_pending.textureCubePool.begin(), m_pending.textureCubePool.end(), textureId) == m_pending.textureCubePool.end());
|
||||||
|
m_pending.textureCubePool.push_back(textureId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add TextureUsage::ShaderSampling to backbuffer output
|
// Add TextureUsage::ShaderSampling and TextureUsage::TransferSource to final outputs
|
||||||
for (std::size_t output : m_backbufferOutputs)
|
for (std::size_t output : m_finalOutputs)
|
||||||
{
|
{
|
||||||
auto it = m_pending.attachmentToTextures.find(output);
|
auto it = m_pending.attachmentToTextures.find(output);
|
||||||
assert(it != m_pending.attachmentToTextures.end());
|
assert(it != m_pending.attachmentToTextures.end());
|
||||||
|
|
||||||
auto& backbufferTexture = m_pending.textures[it->second];
|
auto& finalTexture = m_pending.textures[it->second];
|
||||||
backbufferTexture.usage |= TextureUsage::ShaderSampling;
|
finalTexture.usage |= TextureUsage::ShaderSampling | TextureUsage::TransferSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply texture view usage to their parents
|
// Apply texture view usage to their parents
|
||||||
|
|
@ -1015,6 +1018,9 @@ namespace Nz
|
||||||
data.size != attachmentData.size)
|
data.size != attachmentData.size)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (data.size == FramePassAttachmentSize::ViewerTargetFactor && data.viewerIndex != attachmentData.viewerIndex)
|
||||||
|
continue;
|
||||||
|
|
||||||
m_pending.texture2DPool.erase(it);
|
m_pending.texture2DPool.erase(it);
|
||||||
m_pending.attachmentToTextures.emplace(attachmentIndex, textureId);
|
m_pending.attachmentToTextures.emplace(attachmentIndex, textureId);
|
||||||
|
|
||||||
|
|
@ -1035,7 +1041,19 @@ namespace Nz
|
||||||
data.height = attachmentData.height;
|
data.height = attachmentData.height;
|
||||||
data.size = attachmentData.size;
|
data.size = attachmentData.size;
|
||||||
data.layerCount = 1;
|
data.layerCount = 1;
|
||||||
data.usage = attachmentData.additionalUsage;
|
data.usage = attachmentData.additionalUsages;
|
||||||
|
data.viewerIndex = attachmentData.viewerIndex;
|
||||||
|
data.canReuse = true;
|
||||||
|
|
||||||
|
// Final outputs cannot be reused
|
||||||
|
for (std::size_t outputAttachmentIndex : m_finalOutputs)
|
||||||
|
{
|
||||||
|
if (attachmentIndex == outputAttachmentIndex)
|
||||||
|
{
|
||||||
|
data.canReuse = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return textureId;
|
return textureId;
|
||||||
}
|
}
|
||||||
|
|
@ -1058,6 +1076,9 @@ namespace Nz
|
||||||
data.layerCount != attachmentData.layerCount)
|
data.layerCount != attachmentData.layerCount)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (data.size == FramePassAttachmentSize::ViewerTargetFactor && data.viewerIndex != attachmentData.viewerIndex)
|
||||||
|
continue;
|
||||||
|
|
||||||
m_pending.texture2DArrayPool.erase(it);
|
m_pending.texture2DArrayPool.erase(it);
|
||||||
m_pending.attachmentToTextures.emplace(attachmentIndex, textureId);
|
m_pending.attachmentToTextures.emplace(attachmentIndex, textureId);
|
||||||
|
|
||||||
|
|
@ -1078,7 +1099,19 @@ namespace Nz
|
||||||
data.height = attachmentData.height;
|
data.height = attachmentData.height;
|
||||||
data.size = attachmentData.size;
|
data.size = attachmentData.size;
|
||||||
data.layerCount = attachmentData.layerCount;
|
data.layerCount = attachmentData.layerCount;
|
||||||
data.usage = attachmentData.additionalUsage;
|
data.usage = attachmentData.additionalUsages;
|
||||||
|
data.viewerIndex = attachmentData.viewerIndex;
|
||||||
|
data.canReuse = true;
|
||||||
|
|
||||||
|
// Final outputs cannot be reused
|
||||||
|
for (std::size_t outputAttachmentIndex : m_finalOutputs)
|
||||||
|
{
|
||||||
|
if (attachmentIndex == outputAttachmentIndex)
|
||||||
|
{
|
||||||
|
data.canReuse = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return textureId;
|
return textureId;
|
||||||
}
|
}
|
||||||
|
|
@ -1100,6 +1133,9 @@ namespace Nz
|
||||||
data.size != attachmentData.size)
|
data.size != attachmentData.size)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (data.size == FramePassAttachmentSize::ViewerTargetFactor && data.viewerIndex != attachmentData.viewerIndex)
|
||||||
|
continue;
|
||||||
|
|
||||||
m_pending.textureCubePool.erase(it);
|
m_pending.textureCubePool.erase(it);
|
||||||
m_pending.attachmentToTextures.emplace(attachmentIndex, textureId);
|
m_pending.attachmentToTextures.emplace(attachmentIndex, textureId);
|
||||||
|
|
||||||
|
|
@ -1120,7 +1156,19 @@ namespace Nz
|
||||||
data.height = attachmentData.height;
|
data.height = attachmentData.height;
|
||||||
data.size = attachmentData.size;
|
data.size = attachmentData.size;
|
||||||
data.layerCount = 1;
|
data.layerCount = 1;
|
||||||
data.usage = attachmentData.additionalUsage;
|
data.usage = attachmentData.additionalUsages;
|
||||||
|
data.viewerIndex = attachmentData.viewerIndex;
|
||||||
|
data.canReuse = true;
|
||||||
|
|
||||||
|
// Final outputs cannot be reused
|
||||||
|
for (std::size_t outputAttachmentIndex : m_finalOutputs)
|
||||||
|
{
|
||||||
|
if (attachmentIndex == outputAttachmentIndex)
|
||||||
|
{
|
||||||
|
data.canReuse = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return textureId;
|
return textureId;
|
||||||
}
|
}
|
||||||
|
|
@ -1147,6 +1195,7 @@ namespace Nz
|
||||||
parentTextureId,
|
parentTextureId,
|
||||||
texLayer.layerIndex
|
texLayer.layerIndex
|
||||||
};
|
};
|
||||||
|
data.viewerIndex = parentTexture.viewerIndex;
|
||||||
|
|
||||||
return textureId;
|
return textureId;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace Nz
|
||||||
return passes;
|
return passes;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t PipelinePassList::RegisterPasses(const std::vector<std::unique_ptr<FramePipelinePass>>& passes, FrameGraph& frameGraph, const FunctionRef<void(std::size_t passIndex, FramePass& framePass, FramePipelinePassFlags flags)>& passCallback) const
|
std::size_t PipelinePassList::RegisterPasses(const std::vector<std::unique_ptr<FramePipelinePass>>& passes, FrameGraph& frameGraph, std::optional<unsigned int> viewerIndex, const FunctionRef<void(std::size_t passIndex, FramePass& framePass, FramePipelinePassFlags flags)>& passCallback) const
|
||||||
{
|
{
|
||||||
NazaraAssert(m_passes.size() == passes.size(), "pass vector size doesn't match passlist size");
|
NazaraAssert(m_passes.size() == passes.size(), "pass vector size doesn't match passlist size");
|
||||||
|
|
||||||
|
|
@ -47,7 +47,19 @@ namespace Nz
|
||||||
{
|
{
|
||||||
using T = std::decay_t<decltype(arg)>;
|
using T = std::decay_t<decltype(arg)>;
|
||||||
if constexpr (std::is_same_v<T, FramePassAttachment>)
|
if constexpr (std::is_same_v<T, FramePassAttachment>)
|
||||||
return frameGraph.AddAttachment(arg);
|
{
|
||||||
|
if (arg.size == FramePassAttachmentSize::ViewerTargetFactor)
|
||||||
|
{
|
||||||
|
if (!viewerIndex)
|
||||||
|
throw std::runtime_error(Format("no viewer index but attachment {} depends on viewer target size", arg.name));
|
||||||
|
|
||||||
|
FramePassAttachment attachment = arg;
|
||||||
|
attachment.viewerIndex = *viewerIndex;
|
||||||
|
return frameGraph.AddAttachment(attachment);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return frameGraph.AddAttachment(arg);
|
||||||
|
}
|
||||||
else if constexpr (std::is_same_v<T, AttachmentProxy>)
|
else if constexpr (std::is_same_v<T, AttachmentProxy>)
|
||||||
return frameGraph.AddAttachmentProxy(arg.name, GetAttachmentIndex(arg.attachmentIndex));
|
return frameGraph.AddAttachmentProxy(arg.name, GetAttachmentIndex(arg.attachmentIndex));
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||||
|
// This file is part of the "Nazara Engine - Renderer module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/Renderer/RenderTexture.hpp>
|
||||||
|
#include <Nazara/Renderer/CommandBufferBuilder.hpp>
|
||||||
|
#include <Nazara/Renderer/Texture.hpp>
|
||||||
|
#include <Nazara/Renderer/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
RenderTexture::RenderTexture(std::shared_ptr<Texture> texture, PipelineStage targetPipelineStage, MemoryAccessFlags targetMemoryFlags, TextureLayout targetLayout) :
|
||||||
|
m_targetTexture(std::move(texture)),
|
||||||
|
m_targetMemoryFlags(targetMemoryFlags),
|
||||||
|
m_targetPipelineStage(targetPipelineStage),
|
||||||
|
m_targetLayout(targetLayout),
|
||||||
|
m_textureSize(Vector2ui(m_targetTexture->GetSize()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTexture::BlitTexture(RenderFrame& /*renderFrame*/, CommandBufferBuilder& builder, const Texture& texture) const
|
||||||
|
{
|
||||||
|
Vector3ui textureSize = texture.GetSize();
|
||||||
|
Vector3ui targetTextureSize = m_targetTexture->GetSize();
|
||||||
|
|
||||||
|
builder.BeginDebugRegion("Blit to texture", Color::Blue());
|
||||||
|
{
|
||||||
|
builder.TextureBarrier(PipelineStage::ColorOutput, PipelineStage::Transfer, MemoryAccess::ColorWrite, MemoryAccess::TransferRead, TextureLayout::ColorOutput, TextureLayout::TransferSource, texture);
|
||||||
|
builder.TextureBarrier(PipelineStage::TopOfPipe, PipelineStage::Transfer, {}, MemoryAccess::TransferWrite, TextureLayout::Undefined, TextureLayout::TransferDestination, *m_targetTexture);
|
||||||
|
|
||||||
|
Boxui fromBox(0, 0, 0, textureSize.x, textureSize.y, 1);
|
||||||
|
Boxui toBox(0, 0, 0, targetTextureSize.x, targetTextureSize.y, 1);
|
||||||
|
|
||||||
|
builder.BlitTexture(texture, fromBox, TextureLayout::TransferSource, *m_targetTexture, toBox, TextureLayout::TransferDestination, SamplerFilter::Linear);
|
||||||
|
|
||||||
|
builder.TextureBarrier(PipelineStage::Transfer, m_targetPipelineStage, MemoryAccess::TransferWrite, m_targetMemoryFlags, TextureLayout::TransferDestination, m_targetLayout, *m_targetTexture);
|
||||||
|
}
|
||||||
|
builder.EndDebugRegion();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vector2ui& RenderTexture::GetSize() const
|
||||||
|
{
|
||||||
|
return m_textureSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,21 +30,6 @@ namespace Nz
|
||||||
ConnectSignals();
|
ConnectSignals();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Framebuffer& WindowSwapchain::GetFramebuffer(std::size_t i) const
|
|
||||||
{
|
|
||||||
return m_swapchain->GetFramebuffer(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t WindowSwapchain::GetFramebufferCount() const
|
|
||||||
{
|
|
||||||
return m_swapchain->GetFramebufferCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
const RenderPass& WindowSwapchain::GetRenderPass() const
|
|
||||||
{
|
|
||||||
return m_swapchain->GetRenderPass();
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector2ui& WindowSwapchain::GetSize() const
|
const Vector2ui& WindowSwapchain::GetSize() const
|
||||||
{
|
{
|
||||||
return (m_swapchain) ? m_swapchain->GetSize() : m_window->GetSize();
|
return (m_swapchain) ? m_swapchain->GetSize() : m_window->GetSize();
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,7 @@ int main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Nz::RenderTarget* windowRT = &windowSwapchain;
|
const Nz::WindowSwapchain* windowRT = &windowSwapchain;
|
||||||
frame.Execute([&](Nz::CommandBufferBuilder& builder)
|
frame.Execute([&](Nz::CommandBufferBuilder& builder)
|
||||||
{
|
{
|
||||||
builder.BeginDebugRegion("Compute part", Nz::Color::Blue());
|
builder.BeginDebugRegion("Compute part", Nz::Color::Blue());
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,7 @@ int main()
|
||||||
|
|
||||||
debugDrawer.Prepare(frame);
|
debugDrawer.Prepare(frame);
|
||||||
|
|
||||||
const Nz::RenderTarget& windowRT = windowSwapchain.GetSwapchain();
|
const Nz::WindowSwapchain* windowRT = &windowSwapchain;
|
||||||
frame.Execute([&](Nz::CommandBufferBuilder& builder)
|
frame.Execute([&](Nz::CommandBufferBuilder& builder)
|
||||||
{
|
{
|
||||||
windowSize = window.GetSize();
|
windowSize = window.GetSize();
|
||||||
|
|
@ -368,7 +368,7 @@ int main()
|
||||||
|
|
||||||
builder.BeginDebugRegion("Main window rendering", Nz::Color::Green());
|
builder.BeginDebugRegion("Main window rendering", Nz::Color::Green());
|
||||||
{
|
{
|
||||||
builder.BeginRenderPass(windowRT.GetFramebuffer(frame.GetFramebufferIndex()), windowRT.GetRenderPass(), renderRect, { clearValues[0], clearValues[1] });
|
builder.BeginRenderPass(windowRT->GetFramebuffer(frame.GetFramebufferIndex()), windowRT->GetRenderPass(), renderRect, { clearValues[0], clearValues[1] });
|
||||||
{
|
{
|
||||||
builder.BindIndexBuffer(*renderBufferIB, Nz::IndexType::U16);
|
builder.BindIndexBuffer(*renderBufferIB, Nz::IndexType::U16);
|
||||||
builder.BindRenderPipeline(*pipeline);
|
builder.BindRenderPipeline(*pipeline);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue