fix screen-space reflection when sub-pass colorgrading is used
the problem was that in that case, SSR was using the colorgraded color buffer as history.
This commit is contained in:
committed by
Mathias Agopian
parent
a7317e7a99
commit
c84f5d2a7f
@@ -153,6 +153,8 @@ FrameGraphId<FrameGraphTexture> RendererUtils::colorPass(
|
||||
}
|
||||
|
||||
if (colorGradingConfig.asSubpass) {
|
||||
assert_invariant(config.msaa <= 1);
|
||||
assert_invariant(colorBufferDesc.samples <= 1);
|
||||
data.output = builder.createTexture("Tonemapped Buffer", {
|
||||
.width = colorBufferDesc.width,
|
||||
.height = colorBufferDesc.height,
|
||||
@@ -263,7 +265,9 @@ FrameGraphId<FrameGraphTexture> RendererUtils::colorPass(
|
||||
// when color grading is done as a subpass, the output of the color-pass is the ldr buffer
|
||||
auto output = colorGradingConfig.asSubpass ? colorPass->output : colorPass->color;
|
||||
|
||||
blackboard["color"] = output;
|
||||
// linear color buffer
|
||||
blackboard["color"] = colorPass->color;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -275,7 +279,7 @@ std::pair<FrameGraphId<FrameGraphTexture>, bool> RendererUtils::refractionPass(
|
||||
RenderPass const& pass) noexcept {
|
||||
|
||||
auto& blackboard = fg.getBlackboard();
|
||||
auto input = blackboard.get<FrameGraphTexture>("color");
|
||||
|
||||
FrameGraphId<FrameGraphTexture> output;
|
||||
|
||||
// find the first refractive object in channel 2
|
||||
@@ -295,13 +299,13 @@ std::pair<FrameGraphId<FrameGraphTexture>, bool> RendererUtils::refractionPass(
|
||||
PostProcessManager& ppm = engine.getPostProcessManager();
|
||||
|
||||
// clear the color/depth buffers, which will orphan (and cull) the color pass
|
||||
input.clear();
|
||||
blackboard.remove("color");
|
||||
blackboard.remove("depth");
|
||||
|
||||
config.hasScreenSpaceReflectionsOrRefractions = true;
|
||||
|
||||
input = RendererUtils::colorPass(fg, "Color Pass (opaque)", engine, view, {
|
||||
FrameGraphId<FrameGraphTexture> const input = RendererUtils::colorPass(fg,
|
||||
"Color Pass (opaque)", engine, view, {
|
||||
// When rendering the opaques, we need to conserve the sample buffer,
|
||||
// so create a config that specifies the sample count.
|
||||
.width = config.physicalViewport.width,
|
||||
@@ -330,7 +334,8 @@ std::pair<FrameGraphId<FrameGraphTexture>, bool> RendererUtils::refractionPass(
|
||||
output = RendererUtils::colorPass(fg, "Color Pass (transparent)", engine, view, {
|
||||
.width = config.physicalViewport.width,
|
||||
.height = config.physicalViewport.height },
|
||||
config, colorGradingConfig, pass.getExecutor(refraction, pass.end()));
|
||||
config, colorGradingConfig,
|
||||
pass.getExecutor(refraction, pass.end()));
|
||||
|
||||
if (config.msaa > 1 && !colorGradingConfig.asSubpass) {
|
||||
// We need to do a resolve here because later passes (such as color grading or DoF) will
|
||||
@@ -339,8 +344,8 @@ std::pair<FrameGraphId<FrameGraphTexture>, bool> RendererUtils::refractionPass(
|
||||
// conserve the multi-sample buffer.
|
||||
output = ppm.resolve(fg, "Resolved Color Buffer", output, { .levels = 1 });
|
||||
}
|
||||
} else {
|
||||
output = input;
|
||||
// this becomes the screen-space reflection history
|
||||
blackboard["color"] = output;
|
||||
}
|
||||
return { output, hasScreenSpaceRefraction };
|
||||
}
|
||||
|
||||
@@ -655,16 +655,16 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
// on qualcomm hardware -- we might need a backend dependent toggle at some point
|
||||
const PostProcessManager::ColorGradingConfig colorGradingConfig{
|
||||
.asSubpass =
|
||||
hasColorGrading &&
|
||||
msaaSampleCount <= 1 &&
|
||||
!bloomOptions.enabled && !dofOptions.enabled && !taaOptions.enabled &&
|
||||
driver.isFrameBufferFetchSupported() &&
|
||||
hasColorGrading &&
|
||||
!bloomOptions.enabled && !dofOptions.enabled && !taaOptions.enabled &&
|
||||
!engine.debug.renderer.disable_subpasses,
|
||||
.customResolve =
|
||||
msaaOptions.customResolve &&
|
||||
msaaSampleCount > 1 &&
|
||||
hasColorGrading &&
|
||||
driver.isFrameBufferFetchMultiSampleSupported() &&
|
||||
msaaOptions.customResolve &&
|
||||
hasColorGrading &&
|
||||
!engine.debug.renderer.disable_subpasses,
|
||||
.translucent = needsAlphaChannel,
|
||||
.fxaa = hasFXAA,
|
||||
@@ -673,6 +673,9 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
TextureFormat::RGBA8 : getLdrFormat(needsAlphaChannel)
|
||||
};
|
||||
|
||||
// by construction (msaaSampleCount) both asSubpass and customResolve can't be true
|
||||
assert_invariant(colorGradingConfig.asSubpass + colorGradingConfig.customResolve < 2);
|
||||
|
||||
// whether we're scaled at all
|
||||
bool scaled = any(notEqual(scale, float2(1.0f)));
|
||||
|
||||
@@ -1108,20 +1111,26 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
colorBufferDesc, config, colorGradingConfigForColor, pass.getExecutor());
|
||||
|
||||
if (view.isScreenSpaceRefractionEnabled() && !pass.empty()) {
|
||||
// this cancels the colorPass() call above if refraction is active.
|
||||
// the color pass + refraction + color-grading as subpass if needed
|
||||
// This cancels the colorPass() call above if refraction is active.
|
||||
// The color pass + refraction + color-grading as subpass if needed
|
||||
const auto [output, enabled] = RendererUtils::refractionPass(fg, mEngine, view,
|
||||
config, ssrConfig, colorGradingConfigForColor, pass);
|
||||
colorPassOutput = output;
|
||||
hasScreenSpaceRefraction = enabled;
|
||||
if (enabled) {
|
||||
colorPassOutput = output;
|
||||
}
|
||||
}
|
||||
|
||||
// Here, colorPassOutput can be either tonemapped or not; it's tonemapped if color gradding
|
||||
// is done as a subpass.
|
||||
|
||||
if (colorGradingConfig.customResolve) {
|
||||
// TODO: we have to "uncompress" (i.e. detonemap) the color buffer here because it's used
|
||||
// by many other passes (Bloom, TAA, DoF, etc...). We could make this more
|
||||
// efficient by using ARM_shader_framebuffer_fetch. We use a load/store (i.e.
|
||||
// subpass) here because it's more convenient.
|
||||
colorPassOutput = ppm.customResolveUncompressPass(fg, colorPassOutput);
|
||||
blackboard["color"] = colorPassOutput;
|
||||
}
|
||||
|
||||
// export the color buffer if screen-space reflections are enabled
|
||||
@@ -1137,7 +1146,10 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
// The "output" of this pass is going to be used during the next frame as
|
||||
// an "import".
|
||||
builder.sideEffect();
|
||||
data.history = builder.sample(colorPassOutput); // FIXME: an access must be declared for detach(), why?
|
||||
|
||||
// we can't use colorPassOutput here because it could be tonemapped
|
||||
auto color = blackboard.get<FrameGraphTexture>("color");
|
||||
data.history = builder.sample(color); // FIXME: an access must be declared for detach(), why?
|
||||
}, [&view, projection](FrameGraphResources const& resources, auto const& data,
|
||||
backend::DriverApi&) {
|
||||
auto& history = view.getFrameHistory();
|
||||
|
||||
Reference in New Issue
Block a user