Graphics/FrameGraph: Reuse textures if possible

This commit is contained in:
Jérôme Leclercq
2021-12-05 16:53:02 +01:00
parent 3b1bf480e6
commit 4eb96849db
4 changed files with 75 additions and 5 deletions

View File

@@ -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)
{