Graphics: Rework RenderTargets

- RenderTarget have been moved to the Graphics module and are now lightweight objects between the target of rendering (swapchain or texture)
- RenderTexture no longer require a blit between the framegraph texture and the target texture (the target texture is now directly rendered onto using a new feature of the framegraph)
- ForwardFramePipeline viewers are now properly ordered by render order
This commit is contained in:
SirLynix
2023-11-20 23:00:06 +01:00
parent d06f9bda89
commit 938ba09d45
41 changed files with 445 additions and 254 deletions

View File

@@ -3,8 +3,8 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/AbstractViewer.hpp>
#include <Nazara/Graphics/RenderTarget.hpp>
#include <Nazara/Graphics/ViewerInstance.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz

View File

@@ -11,8 +11,8 @@
namespace Nz
{
Camera::Camera(const RenderTarget* renderTarget, ProjectionType projectionType) :
Camera(renderTarget, Graphics::Instance()->GetDefaultPipelinePasses(), projectionType)
Camera::Camera(std::shared_ptr<const RenderTarget> renderTarget, ProjectionType projectionType) :
Camera(std::move(renderTarget), Graphics::Instance()->GetDefaultPipelinePasses(), projectionType)
{
}
@@ -61,12 +61,12 @@ namespace Nz
return m_framePipelinePasses->RegisterPasses(passes, frameGraph, viewerIndex, passCallback);
}
void Camera::UpdateTarget(const RenderTarget* renderTarget)
void Camera::UpdateTarget(std::shared_ptr<const RenderTarget> renderTarget)
{
m_onRenderTargetRelease.Disconnect();
m_onRenderTargetSizeChange.Disconnect();
m_renderTarget = renderTarget;
m_renderTarget = std::move(renderTarget);
if (m_renderTarget)
{
m_onRenderTargetRelease.Connect(m_renderTarget->OnRenderTargetRelease, [this](const RenderTarget*)

View File

@@ -11,6 +11,7 @@
#include <Nazara/Graphics/PointLight.hpp>
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
#include <Nazara/Graphics/RenderElement.hpp>
#include <Nazara/Graphics/RenderTarget.hpp>
#include <Nazara/Graphics/SpotLight.hpp>
#include <Nazara/Graphics/ViewerInstance.hpp>
#include <Nazara/Graphics/WorldInstance.hpp>
@@ -19,7 +20,6 @@
#include <Nazara/Renderer/CommandBufferBuilder.hpp>
#include <Nazara/Renderer/Framebuffer.hpp>
#include <Nazara/Renderer/RenderFrame.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Renderer/UploadPool.hpp>
#include <NazaraUtils/StackArray.hpp>
#include <NazaraUtils/StackVector.hpp>
@@ -383,7 +383,7 @@ namespace Nz
if (m_rebuildFrameGraph)
{
renderFrame.PushForRelease(std::move(m_bakedFrameGraph));
m_bakedFrameGraph = BuildFrameGraph(renderFrame);
m_bakedFrameGraph = BuildFrameGraph();
m_bakedFrameGraph.Resize(renderFrame, viewerSizes);
frameGraphInvalidated = true;
}
@@ -509,10 +509,11 @@ namespace Nz
{
const RenderTarget& renderTarget = *renderTargetPtr;
const auto& data = renderTargetData;
renderTarget.OnRenderEnd(renderFrame, m_bakedFrameGraph, data.finalAttachment);
renderFrame.Execute([&](CommandBufferBuilder& builder)
{
const std::shared_ptr<Texture>& sourceTexture = m_bakedFrameGraph.GetAttachmentTexture(data.finalAttachment);
renderTarget.BlitTexture(renderFrame, builder, *sourceTexture);
}, QueueType::Graphics);
}
@@ -658,7 +659,7 @@ namespace Nz
}
}
BakedFrameGraph ForwardFramePipeline::BuildFrameGraph(RenderFrame& renderFrame)
BakedFrameGraph ForwardFramePipeline::BuildFrameGraph()
{
FrameGraph frameGraph;
@@ -669,37 +670,7 @@ namespace Nz
lightData->shadowData->RegisterToFrameGraph(frameGraph, nullptr);
}
unsigned int viewerIndex = 0;
for (auto& viewerData : m_viewerPool)
{
if (viewerData.pendingDestruction)
continue;
UInt32 renderMask = viewerData.viewer->GetRenderMask();
for (std::size_t i : m_shadowCastingLights.IterBits())
{
LightData* lightData = m_lightPool.RetrieveFromIndex(i);
if (lightData->shadowData->IsPerViewer() && (renderMask & lightData->renderMask) != 0)
lightData->shadowData->RegisterToFrameGraph(frameGraph, viewerData.viewer);
}
auto framePassCallback = [this, &viewerData, renderMask](std::size_t /*passIndex*/, FramePass& framePass, FramePipelinePassFlags flags)
{
if (flags.Test(FramePipelinePassFlag::LightShadowing))
{
for (std::size_t i : m_shadowCastingLights.IterBits())
{
LightData* lightData = m_lightPool.RetrieveFromIndex(i);
if ((renderMask & lightData->renderMask) != 0)
lightData->shadowData->RegisterPassInputs(framePass, (lightData->shadowData->IsPerViewer()) ? viewerData.viewer : nullptr);
}
}
};
viewerData.finalColorAttachment = viewerData.viewer->RegisterPasses(viewerData.passes, frameGraph, viewerIndex++, framePassCallback);
}
using ViewerPair = std::pair<const RenderTarget*, const ViewerData*>;
using ViewerPair = std::pair<const RenderTarget*, ViewerData*>;
StackArray<ViewerPair> viewers = NazaraStackArray(ViewerPair, m_viewerPool.size());
auto viewerIt = viewers.begin();
@@ -718,9 +689,62 @@ namespace Nz
return lhs.second->renderOrder < rhs.second->renderOrder;
});
StackVector<std::size_t> dependenciesColorAttachments = NazaraStackVector(std::size_t, viewers.size());
m_renderTargets.clear();
for (auto&& [renderTarget, viewerData] : viewers)
unsigned int viewerIndex = 0;
for (auto it = viewers.begin(), prevIt = it; it != viewers.end(); ++it)
{
auto&& [renderTarget, viewerData] = *it;
UInt32 renderMask = viewerData->viewer->GetRenderMask();
for (std::size_t i : m_shadowCastingLights.IterBits())
{
LightData* lightData = m_lightPool.RetrieveFromIndex(i);
if (lightData->shadowData->IsPerViewer() && (renderMask & lightData->renderMask) != 0)
lightData->shadowData->RegisterToFrameGraph(frameGraph, viewerData->viewer);
}
// Keep track of previous dependencies attachments (from viewers having a smaller render order)
Int32 renderOrder = viewerData->renderOrder;
for (auto it2 = prevIt; prevIt != it; ++prevIt)
{
ViewerData* prevViewerData = prevIt->second;
Int32 prevRenderOrder = prevViewerData->renderOrder;
if (prevRenderOrder >= renderOrder)
break;
dependenciesColorAttachments.push_back(prevViewerData->finalColorAttachment);
prevIt = it2;
}
auto framePassCallback = [&, viewerData, renderMask](std::size_t /*passIndex*/, FramePass& framePass, FramePipelinePassFlags flags)
{
// Inject previous final attachments as inputs for all passes, to force framegraph to order viewers passes relative to each other
// TODO: Allow the user to define which pass of viewer A uses viewer B rendering
for (std::size_t finalAttachment : dependenciesColorAttachments)
{
std::size_t inputIndex = framePass.AddInput(finalAttachment);
// Disable ReadInput to prevent the framegraph from transitionning the texture layout (for now it's handled externally)
// (however if we manage to get rid of the texture blit from RenderTexture by making the framegraph use the external texture directly, this would be necessary)
framePass.SetReadInput(inputIndex, false);
}
if (flags.Test(FramePipelinePassFlag::LightShadowing))
{
for (std::size_t i : m_shadowCastingLights.IterBits())
{
LightData* lightData = m_lightPool.RetrieveFromIndex(i);
if ((renderMask & lightData->renderMask) != 0)
lightData->shadowData->RegisterPassInputs(framePass, (lightData->shadowData->IsPerViewer()) ? viewerData->viewer : nullptr);
}
}
};
viewerData->finalColorAttachment = viewerData->viewer->RegisterPasses(viewerData->passes, frameGraph, viewerIndex++, framePassCallback);
// Group viewers by render targets
auto& renderTargetData = m_renderTargets[renderTarget];
renderTargetData.viewers.push_back(viewerData);
}
@@ -772,15 +796,15 @@ namespace Nz
}
});
frameGraph.MarkAsFinalOutput(renderTargetData.finalAttachment);
renderTarget->OnBuildGraph(frameGraph, renderTargetData.finalAttachment);
}
else if (targetViewers.size() == 1)
{
// Single viewer on that target
const auto& viewer = *targetViewers.front();
frameGraph.MarkAsFinalOutput(viewer.finalColorAttachment);
renderTargetData.finalAttachment = viewer.finalColorAttachment;
renderTarget->OnBuildGraph(frameGraph, renderTargetData.finalAttachment);
}
}

View File

@@ -28,7 +28,7 @@ namespace Nz
BakedFrameGraph FrameGraph::Bake()
{
if (m_finalOutputs.empty())
if (m_backbufferOutputs.empty())
throw std::runtime_error("no backbuffer output has been set");
m_pending.attachmentReadList.clear();
@@ -45,7 +45,7 @@ namespace Nz
BuildReadWriteList();
for (std::size_t output : m_finalOutputs)
for (std::size_t output : m_backbufferOutputs)
{
auto it = m_pending.attachmentWriteList.find(output);
if (it == m_pending.attachmentWriteList.end())
@@ -123,6 +123,7 @@ namespace Nz
{
auto& bakedTexture = bakedTextures.emplace_back();
static_cast<FrameGraphTextureData&>(bakedTexture) = std::move(texture);
bakedTexture.texture = bakedTexture.externalTexture;
}
return BakedFrameGraph(std::move(bakedPasses), std::move(bakedTextures), std::move(m_pending.attachmentToTextures), std::move(m_pending.passIdToPhysicalPassIndex));
@@ -290,7 +291,7 @@ namespace Nz
}
// Add TextureUsage::ShaderSampling and TextureUsage::TransferSource to final outputs
for (std::size_t output : m_finalOutputs)
for (std::size_t output : m_backbufferOutputs)
{
auto it = m_pending.attachmentToTextures.find(output);
assert(it != m_pending.attachmentToTextures.end());
@@ -1000,6 +1001,54 @@ namespace Nz
if (auto it = m_pending.attachmentToTextures.find(attachmentIndex); it != m_pending.attachmentToTextures.end())
return it->second;
auto InsertTexture = [this](ImageType imageType, std::size_t attachmentIndex, const FramePassAttachment& attachmentData, std::size_t& textureId) -> FrameGraphTextureData&
{
textureId = m_pending.textures.size();
m_pending.attachmentToTextures.emplace(attachmentIndex, textureId);
FrameGraphTextureData& data = m_pending.textures.emplace_back();
data.type = imageType;
data.name = attachmentData.name;
data.format = attachmentData.format;
data.width = attachmentData.width;
data.height = attachmentData.height;
data.size = attachmentData.size;
data.layerCount = 1;
data.usage = attachmentData.additionalUsages;
data.viewerIndex = attachmentData.viewerIndex;
data.canReuse = true;
return data;
};
auto CheckExternalTexture = [this](std::size_t attachmentIndex, FrameGraphTextureData& data)
{
// Check if texture
if (auto externalIt = m_externalTextures.find(attachmentIndex); externalIt != m_externalTextures.end())
{
if (data.viewData)
throw std::runtime_error("texture views cannot be bound to external textures");
data.externalTexture = externalIt->second;
data.canReuse = false;
data.size = FramePassAttachmentSize::Fixed;
const TextureInfo& textureInfo = data.externalTexture->GetTextureInfo();
data.width = textureInfo.width;
data.height = textureInfo.height;
// Check that texture settings match
if (textureInfo.type != data.type)
throw std::runtime_error("external texture type doesn't match attachment type");
if (textureInfo.layerCount != data.layerCount)
throw std::runtime_error("external texture layer count doesn't match attachment type");
if (textureInfo.pixelFormat != data.format)
throw std::runtime_error("external texture format doesn't match attachment type");
}
};
return std::visit([&](auto&& arg) -> std::size_t
{
using T = std::decay_t<decltype(arg)>;
@@ -1033,23 +1082,14 @@ namespace Nz
return textureId;
}
std::size_t textureId = m_pending.textures.size();
m_pending.attachmentToTextures.emplace(attachmentIndex, textureId);
FrameGraphTextureData& data = m_pending.textures.emplace_back();
data.type = ImageType::E2D;
data.name = attachmentData.name;
data.format = attachmentData.format;
data.width = attachmentData.width;
data.height = attachmentData.height;
data.size = attachmentData.size;
std::size_t textureId;
FrameGraphTextureData& data = InsertTexture(ImageType::E2D, attachmentIndex, attachmentData, textureId);
data.layerCount = 1;
data.usage = attachmentData.additionalUsages;
data.viewerIndex = attachmentData.viewerIndex;
data.canReuse = true;
CheckExternalTexture(attachmentIndex, data);
// Final outputs cannot be reused
for (std::size_t outputAttachmentIndex : m_finalOutputs)
for (std::size_t outputAttachmentIndex : m_backbufferOutputs)
{
if (attachmentIndex == outputAttachmentIndex)
{
@@ -1091,23 +1131,14 @@ namespace Nz
return textureId;
}
std::size_t textureId = m_pending.textures.size();
m_pending.attachmentToTextures.emplace(attachmentIndex, textureId);
FrameGraphTextureData& data = m_pending.textures.emplace_back();
data.type = ImageType::E2D_Array;
data.name = attachmentData.name;
data.format = attachmentData.format;
data.width = attachmentData.width;
data.height = attachmentData.height;
data.size = attachmentData.size;
std::size_t textureId;
FrameGraphTextureData& data = InsertTexture(ImageType::E2D_Array, attachmentIndex, attachmentData, textureId);
data.layerCount = attachmentData.layerCount;
data.usage = attachmentData.additionalUsages;
data.viewerIndex = attachmentData.viewerIndex;
data.canReuse = true;
CheckExternalTexture(attachmentIndex, data);
// Final outputs cannot be reused
for (std::size_t outputAttachmentIndex : m_finalOutputs)
for (std::size_t outputAttachmentIndex : m_backbufferOutputs)
{
if (attachmentIndex == outputAttachmentIndex)
{
@@ -1148,23 +1179,14 @@ namespace Nz
return textureId;
}
std::size_t textureId = m_pending.textures.size();
m_pending.attachmentToTextures.emplace(attachmentIndex, textureId);
FrameGraphTextureData& data = m_pending.textures.emplace_back();
data.type = ImageType::Cubemap;
data.name = attachmentData.name;
data.format = attachmentData.format;
data.width = attachmentData.width;
data.height = attachmentData.height;
data.size = attachmentData.size;
std::size_t textureId;
FrameGraphTextureData& data = InsertTexture(ImageType::Cubemap, attachmentIndex, attachmentData, textureId);
data.layerCount = 1;
data.usage = attachmentData.additionalUsages;
data.viewerIndex = attachmentData.viewerIndex;
data.canReuse = true;
CheckExternalTexture(attachmentIndex, data);
// Final outputs cannot be reused
for (std::size_t outputAttachmentIndex : m_finalOutputs)
for (std::size_t outputAttachmentIndex : m_backbufferOutputs)
{
if (attachmentIndex == outputAttachmentIndex)
{
@@ -1200,6 +1222,8 @@ namespace Nz
};
data.viewerIndex = parentTexture.viewerIndex;
CheckExternalTexture(attachmentIndex, data);
return textureId;
}
else if constexpr (std::is_same_v<T, AttachmentProxy>)
@@ -1209,6 +1233,9 @@ namespace Nz
std::size_t textureId = RegisterTexture(proxy.attachmentId);
m_pending.attachmentToTextures.emplace(attachmentIndex, textureId);
if (m_externalTextures.contains(proxy.attachmentId))
throw std::runtime_error("proxy attachments cannot be bound to external textures");
return textureId;
}
else

View File

@@ -1,9 +1,9 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Renderer module"
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Renderer/Debug.hpp>
#include <Nazara/Graphics/RenderTarget.hpp>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{

View File

@@ -0,0 +1,35 @@
// 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 <Nazara/Graphics/RenderTexture.hpp>
#include <Nazara/Graphics/FrameGraph.hpp>
#include <Nazara/Renderer/CommandBufferBuilder.hpp>
#include <Nazara/Renderer/Texture.hpp>
#include <Nazara/Graphics/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::OnBuildGraph(FrameGraph& graph, std::size_t attachmentIndex) const
{
graph.BindAttachmentToExternalTexture(attachmentIndex, m_targetTexture);
}
void RenderTexture::OnRenderEnd(RenderFrame& /*renderFrame*/, const BakedFrameGraph& /*frameGraph*/, std::size_t /*finalAttachment*/) const
{
}
const Vector2ui& RenderTexture::GetSize() const
{
return m_textureSize;
}
}

View File

@@ -0,0 +1,84 @@
// 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 <Nazara/Graphics/RenderWindow.hpp>
#include <Nazara/Graphics/BakedFrameGraph.hpp>
#include <Nazara/Graphics/FrameGraph.hpp>
#include <Nazara/Renderer/CommandBufferBuilder.hpp>
#include <Nazara/Renderer/RenderFrame.hpp>
#include <Nazara/Renderer/Swapchain.hpp>
#include <Nazara/Renderer/Texture.hpp>
#include <cassert>
#include <Nazara/Graphics/Debug.hpp>
namespace Nz
{
RenderWindow::RenderWindow(WindowSwapchain& swapchain) :
m_swapchain(nullptr),
m_windowSwapchain(&swapchain)
{
m_onSwapchainCreated.Connect(swapchain.OnSwapchainCreated, [this](WindowSwapchain* /*windowSwapchain*/, Swapchain& swapchain)
{
SetSwapchain(&swapchain);
});
m_onSwapchainDestroy.Connect(swapchain.OnSwapchainDestroy, [this](WindowSwapchain* /*windowSwapchain*/)
{
SetSwapchain(nullptr);
});
SetSwapchain(m_windowSwapchain->GetSwapchain());
}
void RenderWindow::OnRenderEnd(RenderFrame& renderFrame, const BakedFrameGraph& frameGraph, std::size_t finalAttachment) const
{
const std::shared_ptr<Texture>& texture = frameGraph.GetAttachmentTexture(finalAttachment);
Vector2ui textureSize = Vector2ui(texture->GetSize());
Boxui blitRegion(0, 0, 0, textureSize.x, textureSize.y, 1);
renderFrame.Execute([&](CommandBufferBuilder& builder)
{
builder.BeginDebugRegion("Blit to swapchain", Color::Blue());
{
builder.TextureBarrier(PipelineStage::ColorOutput, PipelineStage::Transfer, MemoryAccess::ColorWrite, MemoryAccess::TransferRead, TextureLayout::ColorOutput, TextureLayout::TransferSource, *texture);
builder.BlitTextureToSwapchain(*texture, blitRegion, TextureLayout::TransferSource, *m_swapchain, renderFrame.GetFramebufferIndex());
}
builder.EndDebugRegion();
}, QueueType::Graphics);
}
void RenderWindow::OnBuildGraph(FrameGraph& graph, std::size_t attachmentIndex) const
{
graph.AddBackbufferOutput(attachmentIndex);
}
const Vector2ui& RenderWindow::GetSize() const
{
if (m_swapchain)
return m_swapchain->GetSize();
else if (m_windowSwapchain)
return m_windowSwapchain->GetSize();
else
{
static Vector2ui dummySize(1, 1);
return dummySize;
}
}
void RenderWindow::SetSwapchain(Swapchain* swapchain)
{
m_swapchain = swapchain;
if (m_swapchain)
{
OnRenderTargetSizeChange(this, m_swapchain->GetSize());
m_onSwapchainResize.Connect(m_swapchain->OnSwapchainResize, [this]([[maybe_unused]] Swapchain* swapchain, const Vector2ui& newSize)
{
assert(m_swapchain == swapchain);
OnRenderTargetSizeChange(this, newSize);
});
}
}
}

View File

@@ -132,7 +132,7 @@ namespace Nz
void OpenGLSwapchain::NotifyResize(const Vector2ui& newSize)
{
OnRenderTargetSizeChange(this, newSize);
OnSwapchainResize(this, newSize);
m_size = newSize;
m_sizeInvalidated = true;

View File

@@ -1,45 +0,0 @@
// 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;
}
}

View File

@@ -3,7 +3,6 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/Swapchain.hpp>
#include <Nazara/Renderer/CommandBufferBuilder.hpp>
#include <Nazara/Renderer/Texture.hpp>
#include <Nazara/Renderer/Debug.hpp>
@@ -11,20 +10,6 @@ namespace Nz
{
Swapchain::~Swapchain() = default;
void Swapchain::BlitTexture(RenderFrame& renderFrame, CommandBufferBuilder& builder, const Texture& texture) const
{
Vector2ui textureSize = Vector2ui(texture.GetSize());
Boxui blitRegion(0, 0, 0, textureSize.x, textureSize.y, 1);
builder.TextureBarrier(PipelineStage::ColorOutput, PipelineStage::Transfer, MemoryAccess::ColorWrite, MemoryAccess::TransferRead, TextureLayout::ColorOutput, TextureLayout::TransferSource, texture);
builder.BeginDebugRegion("Blit to swapchain", Color::Blue());
{
builder.BlitTextureToSwapchain(texture, blitRegion, TextureLayout::TransferSource, *this, renderFrame.GetFramebufferIndex());
}
builder.EndDebugRegion();
}
void Swapchain::BuildRenderPass(PixelFormat colorFormat, PixelFormat depthFormat, std::vector<RenderPass::Attachment>& attachments, std::vector<RenderPass::SubpassDescription>& subpassDescriptions, std::vector<RenderPass::SubpassDependency>& subpassDependencies)
{
assert(colorFormat != PixelFormat::Undefined);

View File

@@ -42,11 +42,15 @@ namespace Nz
{
m_isMinimized = m_window->IsMinimized();
if (!m_isMinimized)
{
m_swapchain = m_renderDevice->InstantiateSwapchain(m_window->GetHandle(), m_window->GetSize(), m_parameters);
OnSwapchainCreated(this, *m_swapchain);
}
});
m_onDestruction.Connect(windowEvents.OnDestruction, [this](const WindowEventHandler* /*eventHandler*/)
{
OnSwapchainDestroy(this);
m_swapchain.reset();
m_isMinimized = true;
});
@@ -69,13 +73,15 @@ namespace Nz
m_onResized.Connect(windowEvents.OnResized, [this](const WindowEventHandler* /*eventHandler*/, const WindowEvent::SizeEvent& event)
{
m_swapchain->NotifyResize({ event.width, event.height });
OnRenderTargetSizeChange(this, m_swapchain->GetSize());
});
m_onRestored.Connect(windowEvents.OnRestored, [this](const WindowEventHandler* /*eventHandler*/)
{
if (!m_swapchain)
{
m_swapchain = m_renderDevice->InstantiateSwapchain(m_window->GetHandle(), m_window->GetSize(), m_parameters);
OnSwapchainCreated(this, *m_swapchain);
}
m_isMinimized = false;
});

View File

@@ -326,7 +326,7 @@ namespace Nz
void VulkanSwapchain::NotifyResize(const Vector2ui& newSize)
{
OnRenderTargetSizeChange(this, newSize);
OnSwapchainResize(this, newSize);
m_swapchainSize = newSize;
m_shouldRecreateSwapchain = true;