Graphics/FrameGraph: Reuse textures if possible
This commit is contained in:
parent
3b1bf480e6
commit
4eb96849db
|
|
@ -45,6 +45,7 @@ namespace Nz
|
|||
using BarrierList = std::vector<PassBarriers>;
|
||||
using PassList = std::vector<std::size_t /*PassIndex*/>;
|
||||
using AttachmentIdToPassMap = std::unordered_map<std::size_t /*resourceIndex*/, PassList /*passIndexes*/>;
|
||||
using AttachmentIdToPassId = std::unordered_map<std::size_t /*attachmentId*/, std::size_t /*passId*/>;
|
||||
using AttachmentIdToTextureId = std::unordered_map<std::size_t /*attachmentId*/, std::size_t /*textureId*/>;
|
||||
using PassIdToPhysicalPassIndex = std::unordered_map<std::size_t /*passId*/, std::size_t /*physicalPassId*/>;
|
||||
using TextureTransition = BakedFrameGraph::TextureTransition;
|
||||
|
|
@ -88,6 +89,7 @@ namespace Nz
|
|||
std::vector<std::shared_ptr<RenderPass>> renderPasses;
|
||||
std::vector<PhysicalPassData> physicalPasses;
|
||||
std::vector<TextureData> textures;
|
||||
AttachmentIdToPassId attachmentLastUse;
|
||||
AttachmentIdToPassMap attachmentReadList;
|
||||
AttachmentIdToPassMap attachmentWriteList;
|
||||
AttachmentIdToTextureId attachmentToTextures;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ namespace Nz
|
|||
inline std::size_t AddInput(std::size_t attachmentId);
|
||||
inline std::size_t AddOutput(std::size_t attachmentId);
|
||||
|
||||
template<typename F> void ForEachAttachment(F&& func) const;
|
||||
|
||||
inline const CommandCallback& GetCommandCallback() const;
|
||||
inline const std::optional<DepthStencilClear>& GetDepthStencilClear() const;
|
||||
inline std::size_t GetDepthStencilInput() const;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,25 @@ namespace Nz
|
|||
|
||||
return outputIndex;
|
||||
}
|
||||
template<typename F>
|
||||
void FramePass::ForEachAttachment(F&& func) const
|
||||
{
|
||||
for (const auto& input : m_inputs)
|
||||
func(input.attachmentId);
|
||||
|
||||
for (const auto& output : m_outputs)
|
||||
func(output.attachmentId);
|
||||
|
||||
if (m_depthStencilInput != FramePass::InvalidAttachmentId)
|
||||
{
|
||||
func(m_depthStencilInput);
|
||||
|
||||
if (m_depthStencilOutput != FramePass::InvalidAttachmentId && m_depthStencilOutput != m_depthStencilInput)
|
||||
func(m_depthStencilOutput);
|
||||
}
|
||||
else if (m_depthStencilOutput != FramePass::InvalidAttachmentId)
|
||||
func(m_depthStencilOutput);
|
||||
}
|
||||
|
||||
inline auto FramePass::GetCommandCallback() const -> const CommandCallback&
|
||||
{
|
||||
|
|
|
|||
|
|
@ -179,17 +179,38 @@ namespace Nz
|
|||
|
||||
void FrameGraph::AssignPhysicalTextures()
|
||||
{
|
||||
std::vector<std::size_t> texturePool;
|
||||
|
||||
auto RegisterTexture = [&](std::size_t attachmentIndex)
|
||||
{
|
||||
if (auto it = m_pending.attachmentToTextures.find(attachmentIndex); it == m_pending.attachmentToTextures.end())
|
||||
{
|
||||
const auto& attachmentData = m_attachments[attachmentIndex];
|
||||
|
||||
// Fetch from reuse pool if possible
|
||||
for (auto it = texturePool.begin(); it != texturePool.end(); ++it)
|
||||
{
|
||||
std::size_t textureId = *it;
|
||||
|
||||
TextureData& data = m_pending.textures[textureId];
|
||||
if (data.format != attachmentData.format ||
|
||||
data.width != attachmentData.width ||
|
||||
data.height != attachmentData.height)
|
||||
continue;
|
||||
|
||||
texturePool.erase(it);
|
||||
m_pending.attachmentToTextures.emplace(attachmentIndex, textureId);
|
||||
|
||||
return textureId;
|
||||
}
|
||||
|
||||
std::size_t textureId = m_pending.textures.size();
|
||||
m_pending.attachmentToTextures.emplace(attachmentIndex, textureId);
|
||||
|
||||
TextureData& data = m_pending.textures.emplace_back();
|
||||
data.format = m_attachments[attachmentIndex].format;
|
||||
data.width = m_attachments[attachmentIndex].width;
|
||||
data.height = m_attachments[attachmentIndex].height;
|
||||
data.format = attachmentData.format;
|
||||
data.width = attachmentData.width;
|
||||
data.height = attachmentData.height;
|
||||
|
||||
return textureId;
|
||||
}
|
||||
|
|
@ -197,6 +218,16 @@ namespace Nz
|
|||
return it->second;
|
||||
};
|
||||
|
||||
// Assign last use pass index for every attachment
|
||||
for (std::size_t passIndex : m_pending.passList)
|
||||
{
|
||||
const FramePass& framePass = m_framePasses[passIndex];
|
||||
framePass.ForEachAttachment([&](std::size_t attachmentId)
|
||||
{
|
||||
m_pending.attachmentLastUse[attachmentId] = passIndex;
|
||||
});
|
||||
}
|
||||
|
||||
for (std::size_t passIndex : m_pending.passList)
|
||||
{
|
||||
const FramePass& framePass = m_framePasses[passIndex];
|
||||
|
|
@ -240,6 +271,24 @@ namespace Nz
|
|||
TextureData& attachmentData = m_pending.textures[textureId];
|
||||
attachmentData.usage |= TextureUsage::DepthStencilAttachment;
|
||||
}
|
||||
|
||||
framePass.ForEachAttachment([&](std::size_t attachmentId)
|
||||
{
|
||||
std::size_t lastUsingPassId = Retrieve(m_pending.attachmentLastUse, attachmentId);
|
||||
|
||||
// If this pass is the last one where this attachment is used, push the texture to the reuse pool
|
||||
if (passIndex == lastUsingPassId)
|
||||
{
|
||||
std::size_t textureId = Retrieve(m_pending.attachmentToTextures, attachmentId);
|
||||
|
||||
// For input/output depth-stencil buffer, the same texture can be used
|
||||
if (texturePool.empty() || texturePool.back() != textureId)
|
||||
{
|
||||
assert(std::find(texturePool.begin(), texturePool.end(), textureId) == texturePool.end());
|
||||
texturePool.push_back(textureId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Add TextureUsage::Sampled to backbuffer output
|
||||
|
|
@ -274,7 +323,6 @@ namespace Nz
|
|||
|
||||
return barrier;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
for (std::size_t passId : m_pending.passList)
|
||||
|
|
@ -779,7 +827,6 @@ namespace Nz
|
|||
const FramePass& framePass = m_framePasses[subpass.passIndex];
|
||||
std::size_t dsInputAttachment = framePass.GetDepthStencilInput();
|
||||
std::size_t dsOutputAttachement = framePass.GetDepthStencilOutput();
|
||||
bool depthRead = false;
|
||||
|
||||
if (dsInputAttachment != FramePass::InvalidAttachmentId && dsOutputAttachement != FramePass::InvalidAttachmentId)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue