start froxelization earlier

This commit is contained in:
Mathias Agopian
2023-02-17 17:53:55 -08:00
committed by Mathias Agopian
parent 53aac259a0
commit b2fc46c320
6 changed files with 77 additions and 50 deletions

View File

@@ -560,6 +560,8 @@ void Froxelizer::froxelizeLoop(FEngine& engine,
spheres, directions, instances, &viewMatrix, &lcm ]
(size_t count, size_t offset, size_t stride) {
SYSTRACE_NAME("FroxelizeLoop Job");
const mat4f& projection = mProjection;
const mat3f& vn = viewMatrix.upperLeft();

View File

@@ -70,7 +70,7 @@ void ShadowMapManager::terminate(FEngine& engine) {
ShadowMapManager::ShadowTechnique ShadowMapManager::update(FEngine& engine, FView& view,
CameraInfo const& cameraInfo,
FScene::RenderableSoa& renderableData, FScene::LightSoa& lightData) noexcept {
FScene::RenderableSoa& renderableData, FScene::LightSoa const& lightData) noexcept {
ShadowTechnique shadowTechnique = {};
calculateTextureRequirements(engine, view, lightData);
@@ -436,7 +436,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEngine& engine,
FView& view, CameraInfo const& cameraInfo, FScene::RenderableSoa& renderableData,
FScene::LightSoa& lightData, ShadowMap::SceneInfo sceneInfo) noexcept {
FScene::LightSoa const& lightData, ShadowMap::SceneInfo sceneInfo) noexcept {
FScene* scene = view.getScene();
auto& lcm = engine.getLightManager();
@@ -785,9 +785,13 @@ void ShadowMapManager::preparePointShadowMap(ShadowMap& shadowMap,
}
ShadowMapManager::ShadowTechnique ShadowMapManager::updateSpotShadowMaps(FEngine& engine,
FScene::LightSoa& lightData) noexcept {
FScene::LightSoa const& lightData) noexcept {
FScene::ShadowInfo* const shadowInfo = lightData.data<FScene::SHADOW_INFO>();
// The const_cast here is a little ugly, but conceptually lightData should be const,
// it's just that we're using it to store some temporary data. with SoA we can't have
// a `mutable` element, so that's a workaround.
FScene::ShadowInfo* const shadowInfo = const_cast<FScene::ShadowInfo*>(
lightData.data<FScene::SHADOW_INFO>());
ShadowTechnique shadowTechnique{};
if (!mSpotShadowMaps.empty()) {
@@ -821,7 +825,7 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateSpotShadowMaps(FEngine
}
void ShadowMapManager::calculateTextureRequirements(FEngine&, FView& view,
FScene::LightSoa&) noexcept {
FScene::LightSoa const&) noexcept {
// Lay out the shadow maps. For now, we take the largest requested dimension and allocate a
// texture of that size. Each cascade / shadow map gets its own layer in the array texture.

View File

@@ -83,7 +83,7 @@ public:
// Returns true if any of the shadow maps have visible shadows.
ShadowMapManager::ShadowTechnique update(FEngine& engine, FView& view,
CameraInfo const& cameraInfo,
FScene::RenderableSoa& renderableData, FScene::LightSoa& lightData) noexcept;
FScene::RenderableSoa& renderableData, FScene::LightSoa const& lightData) noexcept;
// Renders all the shadow maps.
FrameGraphId<FrameGraphTexture> render(FEngine& engine, FrameGraph& fg, RenderPass const& pass,
@@ -110,13 +110,13 @@ public:
private:
ShadowMapManager::ShadowTechnique updateCascadeShadowMaps(FEngine& engine,
FView& view, CameraInfo const& cameraInfo, FScene::RenderableSoa& renderableData,
FScene::LightSoa& lightData, ShadowMap::SceneInfo sceneInfo) noexcept;
FScene::LightSoa const& lightData, ShadowMap::SceneInfo sceneInfo) noexcept;
ShadowMapManager::ShadowTechnique updateSpotShadowMaps(FEngine& engine,
FScene::LightSoa& lightData) noexcept;
FScene::LightSoa const& lightData) noexcept;
void calculateTextureRequirements(FEngine& engine, FView& view,
FScene::LightSoa& lightData) noexcept;
void calculateTextureRequirements(FEngine&, FView& view,
FScene::LightSoa const&) noexcept;
void prepareSpotShadowMap(ShadowMap& shadowMap,
FEngine& engine, FView& view, CameraInfo const& mainCameraInfo,

View File

@@ -610,14 +610,6 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
view.prepareUpscaler(scale);
// start froxelization immediately, it has no dependencies
JobSystem::Job* jobFroxelize = nullptr;
if (view.hasDynamicLighting()) {
jobFroxelize = js.runAndRetain(js.createJob(nullptr,
[&engine, &view, &viewMatrix = cameraInfo.view](JobSystem&, JobSystem::Job*) {
view.froxelize(engine, viewMatrix); }));
}
/*
* Allocate command buffer
*/
@@ -895,8 +887,8 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
// We use a framegraph pass to wait for froxelization to finish (so it can be done
// in parallel with .compile()
if (jobFroxelize) {
auto *sync = jobFroxelize;
auto sync = view.getFroxelizerSync();
if (sync) {
js.waitAndRelease(sync);
view.commitFroxels(driver);
}

View File

@@ -268,7 +268,7 @@ bool FView::isSkyboxVisible() const noexcept {
}
void FView::prepareShadowing(FEngine& engine, FScene::RenderableSoa& renderableData,
FScene::LightSoa& lightData, CameraInfo const& cameraInfo) noexcept {
FScene::LightSoa const& lightData, CameraInfo const& cameraInfo) noexcept {
SYSTRACE_CALL();
mHasShadowing = false;
@@ -333,8 +333,8 @@ void FView::prepareShadowing(FEngine& engine, FScene::RenderableSoa& renderableD
mNeedsShadowMap = any(shadowTechnique & ShadowMapManager::ShadowTechnique::SHADOW_MAP);
}
void FView::prepareLighting(FEngine& engine, FEngine::DriverApi& driver, ArenaScope& arena,
filament::Viewport const& viewport, CameraInfo const& cameraInfo) noexcept {
void FView::prepareLighting(FEngine& engine, ArenaScope& arena,
CameraInfo const& cameraInfo) noexcept {
SYSTRACE_CALL();
SYSTRACE_CONTEXT();
@@ -345,15 +345,8 @@ void FView::prepareLighting(FEngine& engine, FEngine::DriverApi& driver, ArenaSc
* Dynamic lights
*/
mHasDynamicLighting = scene->getLightData().size() > FScene::DIRECTIONAL_LIGHTS_COUNT;
if (mHasDynamicLighting) {
if (hasDynamicLighting()) {
scene->prepareDynamicLights(cameraInfo, arena, mLightUbh);
Froxelizer& froxelizer = mFroxelizer;
if (froxelizer.prepare(driver, arena, viewport,
cameraInfo.projection, cameraInfo.zn, cameraInfo.zf)) {
// update our uniform buffer if needed
mPerViewUniforms.prepareDynamicLights(mFroxelizer);
}
}
// here the array of visible lights has been shrunk to CONFIG_MAX_LIGHT_COUNT
@@ -364,7 +357,6 @@ void FView::prepareLighting(FEngine& engine, FEngine::DriverApi& driver, ArenaSc
*/
const float exposure = Exposure::exposure(cameraInfo.ev100);
mPerViewUniforms.prepareExposure(cameraInfo.ev100);
/*
@@ -382,7 +374,6 @@ void FView::prepareLighting(FEngine& engine, FEngine::DriverApi& driver, ArenaSc
FSkybox const* const skybox = scene->getSkybox();
intensity = skybox ? skybox->getIntensity() : FIndirectLight::DEFAULT_INTENSITY;
}
mPerViewUniforms.prepareAmbientLight(engine, *ibl, intensity, exposure);
/*
@@ -392,7 +383,6 @@ void FView::prepareLighting(FEngine& engine, FEngine::DriverApi& driver, ArenaSc
FLightManager::Instance const directionalLight = lightData.elementAt<FScene::LIGHT_INSTANCE>(0);
const float3 sceneSpaceDirection = lightData.elementAt<FScene::DIRECTION>(0); // guaranteed normalized
mPerViewUniforms.prepareDirectionalLight(engine, exposure, sceneSpaceDirection, directionalLight);
mHasDirectionalLight = directionalLight.isValid();
}
CameraInfo FView::computeCameraInfo(FEngine& engine) const noexcept {
@@ -428,7 +418,7 @@ CameraInfo FView::computeCameraInfo(FEngine& engine) const noexcept {
}
void FView::prepare(FEngine& engine, DriverApi& driver, ArenaScope& arena,
filament::Viewport const& viewport, CameraInfo const& cameraInfo,
filament::Viewport viewport, CameraInfo cameraInfo,
float4 const& userTime, bool needsAlphaChannel) noexcept {
SYSTRACE_CALL();
@@ -471,15 +461,23 @@ void FView::prepare(FEngine& engine, DriverApi& driver, ArenaScope& arena,
* Light culling: runs in parallel with Renderable culling (below)
*/
JobSystem::Job* froxelizeLightsJob = nullptr;
JobSystem::Job* prepareVisibleLightsJob = nullptr;
if (scene->getLightData().size() > FScene::DIRECTIONAL_LIGHTS_COUNT) {
// create and start the prepareVisibleLights job
// note: this job updates LightData (non const)
prepareVisibleLightsJob = js.runAndRetain(js.createJob(nullptr,
[&cullingFrustum, &engine, &arena, &cameraInfo, scene](JobSystem&, JobSystem::Job*) {
[&engine, &arena, &viewMatrix = cameraInfo.view, &cullingFrustum,
&lightData = scene->getLightData()]
(JobSystem&, JobSystem::Job*) {
FView::prepareVisibleLights(engine.getLightManager(), arena,
cameraInfo.view, cullingFrustum, scene->getLightData());
viewMatrix, cullingFrustum, lightData);
}));
}
// this is used later (in Renderer.cpp) to wait for froxelization to finishes
setFroxelizerSync(froxelizeLightsJob);
Range merged;
FScene::RenderableSoa& renderableData = scene->getRenderableData();
@@ -505,7 +503,40 @@ void FView::prepare(FEngine& engine, DriverApi& driver, ArenaScope& arena,
if (prepareVisibleLightsJob) {
js.waitAndRelease(prepareVisibleLightsJob);
}
prepareShadowing(engine, renderableData, scene->getLightData(), cameraInfo);
// lightData is const from this point on (can only happen after prepareVisibleLightsJob)
auto const& lightData = scene->getLightData();
// now we know if we have dynamic lighting (i.e.: dynamic lights are visible)
mHasDynamicLighting = lightData.size() > FScene::DIRECTIONAL_LIGHTS_COUNT;
// we also know if we have a directional light
FLightManager::Instance const directionalLight =
lightData.elementAt<FScene::LIGHT_INSTANCE>(0);
mHasDirectionalLight = directionalLight.isValid();
// As soon as prepareVisibleLight finishes, we can kick-off the froxelization
if (hasDynamicLighting()) {
auto& froxelizer = mFroxelizer;
if (froxelizer.prepare(driver, arena, viewport,
cameraInfo.projection, cameraInfo.zn, cameraInfo.zf)) {
// TODO: might be more consistent to do this in prepareLighting(), but it's not
// strictly necessary
mPerViewUniforms.prepareDynamicLights(mFroxelizer);
}
// We need to pass viewMatrix by value here because it extends the scope of this
// function.
std::function<void(JobSystem&, JobSystem::Job*)> froxelizerWork =
[&froxelizer = mFroxelizer, &engine, viewMatrix = cameraInfo.view, &lightData]
(JobSystem&, JobSystem::Job*) {
froxelizer.froxelizeLights(engine, viewMatrix, lightData);
};
froxelizeLightsJob = js.runAndRetain(js.createJob(nullptr, std::move(froxelizerWork)));
}
setFroxelizerSync(froxelizeLightsJob);
prepareShadowing(engine, renderableData, lightData, cameraInfo);
/*
* Partition the SoA so that renderables are partitioned w.r.t their visibility into the
@@ -602,7 +633,7 @@ void FView::prepare(FEngine& engine, DriverApi& driver, ArenaScope& arena,
* Relies on FScene::prepare() and prepareVisibleLights()
*/
prepareLighting(engine, driver, arena, viewport, cameraInfo);
prepareLighting(engine, arena, cameraInfo);
/*
* Update driver state
@@ -733,12 +764,6 @@ void FView::cleanupRenderPasses() const noexcept {
mPerViewUniforms.unbindSamplers();
}
void FView::froxelize(FEngine& engine, mat4f const& viewMatrix) const noexcept {
SYSTRACE_CALL();
assert_invariant(mHasDynamicLighting);
mFroxelizer.froxelizeLights(engine, viewMatrix, mScene->getLightData());
}
void FView::commitUniforms(DriverApi& driver) const noexcept {
mPerViewUniforms.commit(driver);
}

View File

@@ -88,8 +88,10 @@ public:
CameraInfo computeCameraInfo(FEngine& engine) const noexcept;
// note: viewport/cameraInfo are passed by value to make it clear that prepare cannot
// keep references on them that would outlive the scope of prepare() (e.g. with JobSystem).
void prepare(FEngine& engine, backend::DriverApi& driver, ArenaScope& arena,
filament::Viewport const& viewport, CameraInfo const& cameraInfo,
filament::Viewport viewport, CameraInfo cameraInfo,
math::float4 const& userTime, bool needsAlphaChannel) noexcept;
void bindPerViewUniformsAndSamplers(FEngine::DriverApi& driver) const noexcept;
@@ -141,9 +143,8 @@ public:
const filament::Viewport& logicalViewport) const noexcept;
void prepareShadowing(FEngine& engine, FScene::RenderableSoa& renderableData,
FScene::LightSoa& lightData, CameraInfo const& cameraInfo) noexcept;
void prepareLighting(FEngine& engine, FEngine::DriverApi& driver, ArenaScope& arena,
filament::Viewport const& viewport, CameraInfo const &cameraInfo) noexcept;
FScene::LightSoa const& lightData, CameraInfo const& cameraInfo) noexcept;
void prepareLighting(FEngine& engine, ArenaScope& arena, CameraInfo const& cameraInfo) noexcept;
void prepareSSAO(backend::Handle<backend::HwTexture> ssao) const noexcept;
void prepareSSR(backend::Handle<backend::HwTexture> ssr, float refractionLodOffset,
@@ -153,10 +154,12 @@ public:
void prepareShadowMapping(bool highPrecision) const noexcept;
void cleanupRenderPasses() const noexcept;
void froxelize(FEngine& engine, math::mat4f const& viewMatrix) const noexcept;
void commitUniforms(backend::DriverApi& driver) const noexcept;
void commitFroxels(backend::DriverApi& driverApi) const noexcept;
utils::JobSystem::Job* getFroxelizerSync() const noexcept { return mFroxelizerSync; }
void setFroxelizerSync(utils::JobSystem::Job* sync) noexcept { mFroxelizerSync = sync; }
bool hasDirectionalLight() const noexcept { return mHasDirectionalLight; }
bool hasDynamicLighting() const noexcept { return mHasDynamicLighting; }
bool hasShadowing() const noexcept { return mHasShadowing; }
@@ -474,6 +477,7 @@ private:
FCamera* mViewingCamera = nullptr;
mutable Froxelizer mFroxelizer;
utils::JobSystem::Job* mFroxelizerSync = nullptr;
Viewport mViewport;
bool mCulling = true;