ssao is now done in quarter resolution

- this means that we cannot share the depth pass between ssao and color
passes, so all this code is removed, which simplify things a lot.

- the depth pass code is moved into the ssao codepath since they're now
intimately linked.

- and finals ssao shader can't rely on frameUniform which is set up with
the main buffer's size (instead of 1/4 res).
This commit is contained in:
Pixelflinger
2019-05-22 23:10:19 -07:00
committed by Mathias Agopian
parent 43115e1f3b
commit 507aeb1e34
6 changed files with 68 additions and 96 deletions

View File

@@ -20,6 +20,8 @@
#include "fg/FrameGraph.h"
#include "RenderPass.h"
#include "details/Material.h"
#include "details/MaterialInstance.h"
#include "generated/resources/materials.h"
@@ -285,12 +287,40 @@ FrameGraphResource PostProcessManager::dynamicScaling(FrameGraph& fg,
}
FrameGraphResource PostProcessManager::ssao(FrameGraph& fg, FrameGraphResource depth,
View::AmbientOcclusionOptions const& options) noexcept {
FrameGraphResource PostProcessManager::ssao(FrameGraph& fg, RenderPass& pass,
filament::Viewport const& svp, View::AmbientOcclusionOptions const& options) noexcept {
FEngine* engine = mEngine;
Handle<HwRenderPrimitive> fullScreenRenderPrimitive = engine->getFullScreenRenderPrimitive();
// SSAO depth pass -- automatically culled if not used
struct DepthPassData {
FrameGraphResource depth;
};
RenderPass::Command const* first = pass.getCommands().begin();
RenderPass::Command const* last = pass.getCommands().end();
// SSAO generates its own depth path at 1/4 resolution
auto& ssaoDepthPass = fg.addPass<DepthPassData>("SSAO Depth Pass",
[&svp](FrameGraph::Builder& builder, DepthPassData& data) {
data.depth = builder.createTexture("Depth Buffer", {
.width = svp.width / 2, .height = svp.height / 2,
.format = TextureFormat::DEPTH24 });
data.depth = builder.useRenderTarget("SSAO Depth Target",
{ .attachments.depth = data.depth }, TargetBufferFlags::DEPTH).depth;
},
[&pass, first, last](FrameGraphPassResources const& resources,
DepthPassData const& data, DriverApi& driver) {
assert(depthPassBegin && depthPassEnd);
auto out = resources.getRenderTarget(data.depth);
pass.execute(resources.getPassName(), out.target, out.params, first, last);
});
FrameGraphResource depth = ssaoDepthPass.getData().depth;
struct SSAOPassData {
FrameGraphResource depth;
FrameGraphResource ssao;
@@ -316,10 +346,13 @@ FrameGraphResource PostProcessManager::ssao(FrameGraph& fg, FrameGraphResource d
SSAOPassData const& data, DriverApi& driver) {
auto depth = resources.getTexture(data.depth);
auto ssao = resources.getRenderTarget(data.ssao);
auto const& desc = resources.getDescriptor(data.ssao);
SamplerParams params;
FMaterialInstance* const pInstance = mSSAOMaterialInstance;
pInstance->setParameter("depth", depth, params);
pInstance->setParameter("resolution",
float4{ desc.width, desc.height, 1.0f / desc.width, 1.0f / desc.height });
pInstance->setParameter("radius", data.options.radius);
pInstance->setParameter("invRadiusSquared", 1.0f / (data.options.radius * data.options.radius));
pInstance->setParameter("projectionScaleRadius", 500.0f * data.options.radius);

View File

@@ -33,6 +33,7 @@ class FMaterial;
class FMaterialInstance;
class FEngine;
class FView;
class RenderPass;
} // namespace details
class PostProcessManager {
@@ -58,7 +59,8 @@ public:
FrameGraph& fg, FrameGraphResource input) noexcept;
FrameGraphResource ssao(FrameGraph& fg, FrameGraphResource depth,
FrameGraphResource ssao(FrameGraph& fg, details::RenderPass& pass,
filament::Viewport const& svp,
View::AmbientOcclusionOptions const& options) noexcept;
backend::Handle<backend::HwTexture> getNoSSAOTexture() const {

View File

@@ -225,7 +225,7 @@ public:
void setRenderFlags(RenderFlags flags) noexcept;
Command const* appendSortedCommands(CommandTypeFlags const commandTypeFlags) noexcept;
void execute(const char* name,
backend::Handle <backend::HwRenderTarget> renderTarget,
backend::Handle<backend::HwRenderTarget> renderTarget,
backend::RenderPassParams params,
Command const* first, Command const* last) const noexcept;

View File

@@ -255,93 +255,26 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
view.commitUniforms(driver);
RenderPass::CommandTypeFlags commandType = getCommandType(view.getDepthPrepass());
// It's unclear if it's always better to reuse the depth pass, as it has to be saved and
// reloaded from memory -- as opposed to just regenerating it. Skinning is not an added concern,
// because either way, we have to go through the geometry twice.
constexpr bool REUSE_SSAO_DEPTH = true;
// --------------------------------------------------------------------------------------------
const bool useSSAO = view.getAmbientOcclusion() != View::AmbientOcclusion::NONE;
Command const* depthPassBegin = nullptr;
Command const* depthPassEnd = nullptr;
Command const* colorPassBegin = nullptr;
Command const* colorPassEnd = nullptr;
// We need an extra pass for SSAO if SSAO is enabled and:
// - we don't want to reuse the regular depth path for SSAO, or
// - we have MSAA (because SSAO is never done in MSAA), or
// - we don't have a depth prepass in the first place
const bool extraDepthPassForSSAO = useSSAO &&
(!REUSE_SSAO_DEPTH || msaa > 1 || !(commandType & RenderPass::CommandTypeFlags::DEPTH));
// depth buffer is shared between SSAO and the color pass
const bool sharedDepthPass = useSSAO && !extraDepthPassForSSAO;
if (sharedDepthPass) {
// When SSAO is active and it's sharing the depth pass with the color pass
// (meaning that we don't have MSAA), we add alpha tested objects to the scene, they're
// needed for SSAO and they won't hurt the color pass.
commandType = RenderPass::CommandTypeFlags(commandType &
~RenderPass::CommandTypeFlags::DEPTH_FILTER_ALPHA_MASKED_OBJECTS);
}
if (extraDepthPassForSSAO) {
// We don't have a depth prepass, so we need to generate the depth for the SSAO pass
depthPassBegin = commands.end();
depthPassEnd = pass.appendSortedCommands(RenderPass::CommandTypeFlags::DEPTH);
}
// generate the normal commands
colorPassBegin = commands.end();
colorPassEnd = pass.appendSortedCommands(commandType);
if (sharedDepthPass) {
assert(commandType & RenderPass::CommandTypeFlags::DEPTH);
// isolate the depth-only commands
depthPassBegin = commands.begin();
depthPassEnd = std::partition_point(commands.begin(), commands.end(),
[](Command const& command) {
return (command.key & RenderPass::PASS_MASK) == uint64_t(RenderPass::Pass::DEPTH);
});
}
// --------------------------------------------------------------------------------------------
// SSAO depth pass -- automatically culled if not used
struct DepthPassData {
FrameGraphResource depth;
};
auto& ssaoDepthPass = fg.addPass<DepthPassData>("SSAO Depth Pass",
[&svp](FrameGraph::Builder& builder, DepthPassData& data) {
data.depth = builder.createTexture("Depth Buffer", {
.width = svp.width, .height = svp.height,
.format = TextureFormat::DEPTH24 });
data.depth = builder.useRenderTarget("SSAO Depth Target",
{ .attachments.depth = data.depth }, TargetBufferFlags::DEPTH).depth;
},
[&pass, depthPassBegin, depthPassEnd](FrameGraphPassResources const& resources,
DepthPassData const& data, DriverApi& driver) {
assert(depthPassBegin && depthPassEnd);
auto out = resources.getRenderTarget(data.depth);
pass.execute(resources.getPassName(), out.target, out.params,
depthPassBegin, depthPassEnd);
});
FrameGraphResource depth = ssaoDepthPass.getData().depth;
// SSAO pass -- automatically culled if not used
FrameGraphResource ssao = ppm.ssao(fg, depth, view.getAmbientOcclusionOptions());
if (useSSAO) {
pass.appendSortedCommands(RenderPass::CommandTypeFlags::DEPTH);
}
FrameGraphResource ssao = ppm.ssao(fg, pass, svp, view.getAmbientOcclusionOptions());
// --------------------------------------------------------------------------------------------
// generate the normal commands
RenderPass::CommandTypeFlags commandType = getCommandType(view.getDepthPrepass());
Command const* colorPassBegin = commands.end();
Command const* colorPassEnd = pass.appendSortedCommands(commandType);
// We only honor the view's color buffer clear flags, depth/stencil are handled by the framefraph
TargetBufferFlags clearFlags = view.getClearFlags() & TargetBufferFlags::COLOR;
if (!sharedDepthPass) {
clearFlags |= TargetBufferFlags::DEPTH;
}
TargetBufferFlags clearFlags = view.getClearFlags() & TargetBufferFlags::COLOR | TargetBufferFlags::DEPTH;
struct ColorPassData {
FrameGraphResource color;
@@ -350,7 +283,7 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
};
auto& colorPass = fg.addPass<ColorPassData>("Color Pass",
[&svp, hdrFormat, colorPassNeedsDepthBuffer, msaa, clearFlags, depth, useSSAO, ssao, sharedDepthPass]
[&svp, hdrFormat, colorPassNeedsDepthBuffer, msaa, clearFlags, useSSAO, ssao]
(FrameGraph::Builder& builder, ColorPassData& data) {
if (useSSAO) {
@@ -360,16 +293,12 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
data.color = builder.createTexture("Color Buffer",
{ .width = svp.width, .height = svp.height, .format = hdrFormat, .samples = msaa });
if (sharedDepthPass) {
data.depth = depth;
} else {
if (colorPassNeedsDepthBuffer) {
data.depth = builder.createTexture("Depth Buffer", {
.width = svp.width, .height = svp.height,
.format = TextureFormat::DEPTH24,
.samples = msaa
});
}
if (colorPassNeedsDepthBuffer) {
data.depth = builder.createTexture("Depth Buffer", {
.width = svp.width, .height = svp.height,
.format = TextureFormat::DEPTH24,
.samples = msaa
});
}
FrameGraphRenderTarget::Descriptor desc{

View File

@@ -6,6 +6,10 @@ material {
name : depth,
precision: high
},
{
type : float4,
name : resolution
},
{
type : float,
name : radius
@@ -166,7 +170,7 @@ fragment {
float ssRadius = max(1.0, tap.z * ssDiskRadius); // at least 1 pixel screen-space radius
ivec2 ssSamplePos = ssOrigin + ivec2(ssRadius * tap.xy);
vec2 uvSamplePos = (vec2(ssSamplePos) + vec2(0.5)) * frameUniforms.resolution.zw;
vec2 uvSamplePos = (vec2(ssSamplePos) + vec2(0.5)) * materialParams.resolution.zw;
highp float occlusionDepth = linearizeDepth(texelFetch(materialParams_depth, clampToEdge(ssSamplePos), 0).r);
highp vec3 p = computeViewSpacePositionFromDepth(uvSamplePos * 2.0 - 1.0, occlusionDepth);
@@ -211,7 +215,7 @@ fragment {
}
normal = normalize(normal);
ivec2 ssOrigin = ivec2(uv * frameUniforms.resolution.xy);
ivec2 ssOrigin = ivec2(uv * materialParams.resolution.xy);
float occlusion = 0.0;
for (uint i = 0u; i < kSpiralSampleCount; i++) {
occlusion += computeAmbientOcclusionSAO(i, ssDiskRadius, ssOrigin, origin, normal, noise);

View File

@@ -6,6 +6,10 @@ material {
name : depth,
precision: high
},
{
type : float4,
name : resolution
},
{
type : float,
name : radius