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:
committed by
Mathias Agopian
parent
5c41b332ad
commit
d387e14d4c
@@ -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).
|
||||
|
||||
@@ -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) {
|
||||
[=, ¤t](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?
|
||||
}, [¤t](FrameGraphResources const& resources, auto const& data,
|
||||
backend::DriverApi&) {
|
||||
resources.detach(data.color,
|
||||
¤t.color, ¤t.desc);
|
||||
});
|
||||
|
||||
return exportHistoryPass->color;
|
||||
}
|
||||
|
||||
FrameGraphId<FrameGraphTexture> PostProcessManager::opaqueBlit(FrameGraph& fg,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
¤t.taa.color, ¤t.taa.desc);
|
||||
});
|
||||
input = ppm.taa(fg, input, view.getFrameHistory(), &FrameHistoryEntry::taa,
|
||||
taaOptions, colorGradingConfig);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user