cleanup TAA

The new SSR code allows to clean-up TAA code a bit.
TAA should now be more standalone/abstracted.
This commit is contained in:
Mathias Agopian
2022-02-14 16:43:24 -08:00
committed by Mathias Agopian
parent 5c41b332ad
commit d387e14d4c
4 changed files with 85 additions and 69 deletions
+10 -2
View File
@@ -28,18 +28,18 @@ namespace filament {
// when adding things here, please update:
// FView::commitFrameHistory()
struct FrameHistoryEntry {
struct {
struct TemporalAA{
FrameGraphTexture color;
FrameGraphTexture::Descriptor desc;
math::mat4f projection; // world space to clip space
math::float2 jitter{};
uint32_t frameId = 0; // used for halton sequence
} taa;
struct {
FrameGraphTexture color;
FrameGraphTexture::Descriptor desc;
math::mat4f projection;
} ssr;
uint32_t frameId = 0;
};
/*
@@ -72,6 +72,14 @@ public:
return mCurrentEntry;
}
T& getPrevious() noexcept {
return mContainer[0];
}
const T& getPrevious() const noexcept {
return mContainer[0];
}
// This pushes the current frame info to the FIFO, effectively destroying
// the oldest state (note: only the structure is destroyed, handles stored in it may
// have to be destroyed prior to calling this).
+62 -24
View File
@@ -2459,33 +2459,54 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::fxaa(FrameGraph& fg,
return ppFXAA->output;
}
void PostProcessManager::prepareTaa(FrameHistory& frameHistory,
CameraInfo const& cameraInfo,
TemporalAntiAliasingOptions const& taaOptions) const noexcept {
auto const& previous = frameHistory[0];
auto& current = frameHistory.getCurrent();
// get sample position within a pixel [-0.5, 0.5]
void PostProcessManager::prepareTaa(FrameGraph& fg, filament::Viewport const& svp,
FrameHistory& frameHistory,
FrameHistoryEntry::TemporalAA FrameHistoryEntry::*pTaa,
CameraInfo* inoutCameraInfo,
PerViewUniforms& uniforms) const noexcept {
auto const& previous = frameHistory.getPrevious().*pTaa;
auto& current = frameHistory.getCurrent().*pTaa;
// compute projection
current.projection = inoutCameraInfo->projection * (inoutCameraInfo->view * inoutCameraInfo->worldOrigin);
current.frameId = previous.frameId + 1;
// sample position within a pixel [-0.5, 0.5]
const float2 jitter = halton(previous.frameId) - 0.5f;
// save this frame's sample position
current.taa.jitter = jitter;
current.jitter = jitter;
float2 jitterInClipSpace = jitter * (2.0f / float2{ svp.width, svp.height });
// update projection matrix
inoutCameraInfo->projection[2].xy -= jitterInClipSpace;
fg.addTrivialSideEffectPass("Jitter Camera",
[=, &uniforms] (DriverApi& driver) {
uniforms.prepareCamera(*inoutCameraInfo);
uniforms.commit(driver);
});
}
FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
FrameGraphId<FrameGraphTexture> input, FrameHistory& frameHistory,
FrameGraphId<FrameGraphTexture> input,
FrameHistory& frameHistory,
FrameHistoryEntry::TemporalAA FrameHistoryEntry::*pTaa,
TemporalAntiAliasingOptions const& taaOptions,
ColorGradingConfig colorGradingConfig) noexcept {
FrameHistoryEntry const& entry = frameHistory[0];
auto const& previous = frameHistory.getPrevious().*pTaa;
auto& current = frameHistory.getCurrent().*pTaa;
FrameGraphId<FrameGraphTexture> colorHistory;
mat4f const* historyProjection = nullptr;
if (UTILS_UNLIKELY(!entry.taa.color.handle)) {
mat4f historyProjection;
if (UTILS_UNLIKELY(!previous.color.handle)) {
// if we don't have a history yet, just use the current color buffer as history
colorHistory = input;
historyProjection = &frameHistory.getCurrent().taa.projection;
historyProjection = current.projection;
} else {
colorHistory = fg.import("TAA history", entry.taa.desc,
FrameGraphTexture::Usage::SAMPLEABLE, entry.taa.color);
historyProjection = &entry.taa.projection;
colorHistory = fg.import("TAA history", previous.desc,
FrameGraphTexture::Usage::SAMPLEABLE, previous.color);
historyProjection = previous.projection;
}
Blackboard& blackboard = fg.getBlackboard();
@@ -2499,7 +2520,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
FrameGraphId<FrameGraphTexture> output;
FrameGraphId<FrameGraphTexture> tonemappedOutput;
};
auto& taa = fg.addPass<TAAData>("TAA",
auto& taaPass = fg.addPass<TAAData>("TAA",
[&](FrameGraph::Builder& builder, auto& data) {
auto desc = fg.getDescriptor(input);
data.color = builder.sample(input);
@@ -2521,7 +2542,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
.attachments = { .color = { data.output, data.tonemappedOutput }}
});
},
[=, &frameHistory](FrameGraphResources const& resources, auto const& data, DriverApi& driver) {
[=, &current](FrameGraphResources const& resources, auto const& data, DriverApi& driver) {
constexpr mat4f normalizedToClip{mat4f::row_major_init{
2, 0, 0, -1,
@@ -2536,8 +2557,6 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
{ -1.0f, 1.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f },
};
FrameHistoryEntry& current = frameHistory.getCurrent();
float sum = 0.0;
float weights[9];
@@ -2545,7 +2564,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
// unrolling it.
#pragma nounroll
for (size_t i = 0; i < 9; i++) {
float2 d = sampleOffsets[i] - current.taa.jitter;
float2 d = sampleOffsets[i] - current.jitter;
d *= 1.0f / taaOptions.filterWidth;
// this is a gaussian fit of a 3.3 Blackman Harris window
// see: "High Quality Temporal Supersampling" by Bruan Karis
@@ -2572,8 +2591,8 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
});
mi->setParameter("filterWeights", weights, 9);
mi->setParameter("reprojection",
*historyProjection *
inverse(current.taa.projection) *
historyProjection *
inverse(current.projection) *
normalizedToClip);
mi->commit(driver);
@@ -2592,7 +2611,26 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
}
driver.endRenderPass();
});
return colorGradingConfig.asSubpass ? taa->tonemappedOutput : taa->output;
input = colorGradingConfig.asSubpass ? taaPass->tonemappedOutput : taaPass->output;
struct ExportColorHistoryData {
FrameGraphId<FrameGraphTexture> color;
};
auto& exportHistoryPass = fg.addPass<ExportColorHistoryData>("Export TAA history",
[&](FrameGraph::Builder& builder, auto& data) {
// We need to use sideEffect here to ensure this pass won't be culled.
// The "output" of this pass is going to be used during the next frame as
// an "import".
builder.sideEffect();
data.color = builder.sample(input); // FIXME: an access must be declared for detach(), why?
}, [&current](FrameGraphResources const& resources, auto const& data,
backend::DriverApi&) {
resources.detach(data.color,
&current.color, &current.desc);
});
return exportHistoryPass->color;
}
FrameGraphId<FrameGraphTexture> PostProcessManager::opaqueBlit(FrameGraph& fg,
+8 -3
View File
@@ -139,11 +139,16 @@ public:
bool translucent) noexcept;
// Temporal Anti-aliasing
void prepareTaa(FrameHistory& frameHistory, CameraInfo const& cameraInfo,
TemporalAntiAliasingOptions const& taaOptions) const noexcept;
void prepareTaa(FrameGraph& fg, filament::Viewport const& svp,
FrameHistory& frameHistory,
FrameHistoryEntry::TemporalAA FrameHistoryEntry::*pTaa,
CameraInfo* inoutCameraInfo,
PerViewUniforms& uniforms) const noexcept;
FrameGraphId<FrameGraphTexture> taa(FrameGraph& fg,
FrameGraphId<FrameGraphTexture> input, FrameHistory& frameHistory,
FrameGraphId<FrameGraphTexture> input,
FrameHistory& frameHistory,
FrameHistoryEntry::TemporalAA FrameHistoryEntry::*pTaa,
TemporalAntiAliasingOptions const& taaOptions,
ColorGradingConfig colorGradingConfig) noexcept;
+5 -40
View File
@@ -463,28 +463,9 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
// Store this frame's camera projection in the frame history.
if (UTILS_UNLIKELY(taaOptions.enabled)) {
auto& history = view.getFrameHistory();
auto& current = history.getCurrent();
auto const& previous = history[0];
current.taa.projection = cameraInfo.projection * (cameraInfo.view * cameraInfo.worldOrigin);
// update frame id
current.frameId = previous.frameId + 1; // TODO: should probably be done somewhere else
}
// Apply the TAA jitter to everything after the structure pass, starting with the color pass.
if (taaOptions.enabled) {
auto& history = view.getFrameHistory();
ppm.prepareTaa(history, cameraInfo, taaOptions);
// convert the sample position to jitter in clip-space
float2 jitterInClipSpace =
history.getCurrent().taa.jitter * (2.0f / float2{ svp.width, svp.height });
// update projection matrix
cameraInfo.projection[2].xy -= jitterInClipSpace;
fg.addTrivialSideEffectPass("Jitter Camera", [=, &view] (DriverApi& driver) {
view.prepareCamera(cameraInfo);
view.commitUniforms(driver);
});
// Apply the TAA jitter to everything after the structure pass, starting with the color pass.
ppm.prepareTaa(fg, svp, view.getFrameHistory(), &FrameHistoryEntry::taa,
&cameraInfo, view.getPerViewUniforms());
}
// --------------------------------------------------------------------------------------------
@@ -635,24 +616,8 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
// TAA for color pass
if (taaOptions.enabled) {
input = ppm.taa(fg, input, view.getFrameHistory(), taaOptions, colorGradingConfig);
struct ExportColorHistoryData {
FrameGraphId<FrameGraphTexture> color;
};
fg.addPass<ExportColorHistoryData>("Export TAA history",
[&](FrameGraph::Builder& builder, auto& data) {
// We need to use sideEffect here to ensure this pass won't be culled.
// The "output" of this pass is going to be used during the next frame as
// an "import".
builder.sideEffect();
data.color = builder.sample(input); // FIXME: an access must be declared for detach(), why?
}, [&view](FrameGraphResources const& resources, auto const& data,
backend::DriverApi&) {
FrameHistoryEntry& current = view.getFrameHistory().getCurrent();
resources.detach(data.color,
&current.taa.color, &current.taa.desc);
});
input = ppm.taa(fg, input, view.getFrameHistory(), &FrameHistoryEntry::taa,
taaOptions, colorGradingConfig);
}
// --------------------------------------------------------------------------------------------