make sure "structure" pass is culled when not needed

the structure (depth path) wasn't culled even if both ssao and
contact-shadows were disabled.
This commit is contained in:
Pixelflinger
2020-03-30 13:35:26 -07:00
committed by Mathias Agopian
parent e43466d2bc
commit 968dbdb847
5 changed files with 47 additions and 21 deletions

View File

@@ -602,10 +602,11 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::screenSpaceAmbientOclusion(
FrameGraphId<FrameGraphTexture> PostProcessManager::structure(FrameGraph& fg,
const RenderPass& pass, uint32_t width, uint32_t height, float scale) noexcept {
// structure pass -- automatically culled if not used
// used for SSAO currently. It consists of a mipmapped depth path
// mipmapping is tunned for SSAO
struct DepthPassData {
// structure pass -- automatically culled if not used, currently used by:
// - ssao
// - contact shadows
// It consists of a mipmapped depth pass, tuned for SSAO
struct StructurePassData {
FrameGraphId<FrameGraphTexture> depth;
FrameGraphRenderTargetHandle rt;
};
@@ -618,8 +619,8 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::structure(FrameGraph& fg,
const size_t levelCount = FTexture::maxLevelCount(width, height) - 5;
assert(levelCount >= 1);
// SSAO generates its own depth pass at the requested resolution
auto& ssaoDepthPass = fg.addPass<DepthPassData>("SSAO Depth Pass",
// generate depth pass at the requested resolution
auto& structurePass = fg.addPass<StructurePassData>("Structure Pass",
[&](FrameGraph::Builder& builder, auto& data) {
data.depth = builder.createTexture("Depth Buffer", {
.width = width, .height = height,
@@ -628,7 +629,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::structure(FrameGraph& fg,
data.depth = builder.write(builder.read(data.depth));
data.rt = builder.createRenderTarget("SSAO Depth Target", {
data.rt = builder.createRenderTarget("Structure Target", {
.attachments = {{}, data.depth },
.clearFlags = TargetBufferFlags::DEPTH
});
@@ -638,7 +639,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::structure(FrameGraph& fg,
pass.execute(resources.getPassName(), out.target, out.params);
});
auto depth = ssaoDepthPass.getData().depth;
auto depth = structurePass.getData().depth;
/*
* create depth mipmap chain

View File

@@ -315,7 +315,7 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
// --------------------------------------------------------------------------------------------
// structure pass -- automatically culled if not used
// Currently it consists of a simple depth pass.
// This is normally used by SSAO
// This is normally used by SSAO and contact-shadows
// TODO: this should be a FrameGraph pass to participate to automatic culling
pass.newCommandBuffer();
@@ -348,7 +348,8 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
.hdrFormat = hdrFormat,
.msaa = msaa,
.clearFlags = clearFlags,
.clearColor = clearColor
.clearColor = clearColor,
.hasContactShadows = scene.hasContactShadows()
};
// We use a framegraph pass to wait for froxelization to finish (so it can be done
@@ -576,7 +577,8 @@ FrameGraphId<FrameGraphTexture> FRenderer::colorPass(FrameGraph& fg, const char*
data.color = blackboard.get<FrameGraphTexture>("color");
data.structure = blackboard.get<FrameGraphTexture>("structure");
if (data.structure.isValid()) {
if (config.hasContactShadows) {
assert(data.structure.isValid());
data.structure = builder.sample(data.structure);
}

View File

@@ -178,6 +178,7 @@ void FScene::updateUBOs(utils::Range<uint32_t> visibleRenderables, backend::Hand
// allocate space into the command stream directly
void* const buffer = driver.allocate(size);
bool hasContactShadows = false;
auto& sceneData = mRenderableData;
for (uint32_t i : visibleRenderables) {
mat4f const& model = sceneData.elementAt<WORLD_TRANSFORM>(i);
@@ -206,20 +207,27 @@ void FScene::updateUBOs(utils::Range<uint32_t> visibleRenderables, backend::Hand
// Note that we cast bools to uint32. Booleans are byte-sized in C++, but we need to
// initialize all 32 bits in the UBO field.
UniformBuffer::setUniform(buffer, offset + offsetof(PerRenderableUib, skinningEnabled),
uint32_t(sceneData.elementAt<VISIBILITY_STATE>(i).skinning));
UniformBuffer::setUniform(buffer, offset + offsetof(PerRenderableUib, morphingEnabled),
uint32_t(sceneData.elementAt<VISIBILITY_STATE>(i).morphing));
UniformBuffer::setUniform(buffer, offset + offsetof(PerRenderableUib, screenSpaceContactShadows),
uint32_t(sceneData.elementAt<VISIBILITY_STATE>(i).screenSpaceContactShadows));
FRenderableManager::Visibility visibility = sceneData.elementAt<VISIBILITY_STATE>(i);
hasContactShadows = hasContactShadows || visibility.screenSpaceContactShadows;
UniformBuffer::setUniform(buffer,
offset + offsetof(PerRenderableUib, skinningEnabled),
uint32_t(visibility.skinning));
UniformBuffer::setUniform(buffer,
offset + offsetof(PerRenderableUib, morphWeights), sceneData.elementAt<MORPH_WEIGHTS>(i));
offset + offsetof(PerRenderableUib, morphingEnabled),
uint32_t(visibility.morphing));
UniformBuffer::setUniform(buffer,
offset + offsetof(PerRenderableUib, screenSpaceContactShadows),
uint32_t(visibility.screenSpaceContactShadows));
UniformBuffer::setUniform(buffer,
offset + offsetof(PerRenderableUib, morphWeights),
sceneData.elementAt<MORPH_WEIGHTS>(i));
}
// TODO: handle static objects separately
mHasContactShadows = hasContactShadows;
mRenderableViewUbh = renderableUbh;
driver.loadUniformBuffer(renderableUbh, { buffer, size });
}
@@ -390,6 +398,17 @@ void FScene::setSkybox(FSkybox const* skybox) noexcept {
}
}
bool FScene::hasContactShadows() const noexcept {
bool hasContactShadows = mHasContactShadows;
auto& lcm = mEngine.getLightManager();
FLightManager::Instance directionalLight = mLightData.elementAt<LIGHT_INSTANCE>(0);
if (directionalLight.isValid()) {
auto const& shadowOoptions = lcm.getShadowOptions(directionalLight);
hasContactShadows = hasContactShadows && shadowOoptions.screenSpaceContactShadows;
}
return hasContactShadows;
}
} // namespace details
// ------------------------------------------------------------------------------------------------

View File

@@ -109,6 +109,7 @@ private:
backend::TargetBufferFlags clearFlags;
math::float4 clearColor = {};
float refractionLodOffset;
bool hasContactShadows;
};
FrameGraphId<FrameGraphTexture> colorPass(FrameGraph& fg, const char* name,

View File

@@ -194,6 +194,8 @@ public:
void updateUBOs(utils::Range<uint32_t> visibleRenderables, backend::Handle<backend::HwUniformBuffer> renderableUbh) noexcept;
bool hasContactShadows() const noexcept;
private:
static inline void computeLightRanges(math::float2* zrange,
CameraInfo const& camera, const math::float4* spheres, size_t count) noexcept;
@@ -215,13 +217,14 @@ private:
/*
* The data below is valid only during a view pass. i.e. if a scene is used in multiple
* views, the data below is update for each view.
* views, the data below is updated for each view.
* In essence, this data should be owned by View, but it's so scene-specific, that for now
* we store it here.
*/
RenderableSoa mRenderableData;
LightSoa mLightData;
backend::Handle<backend::HwUniformBuffer> mRenderableViewUbh; // This is actually owned by the view.
bool mHasContactShadows = false;
};
FILAMENT_UPCAST(Scene)