start froxelization earlier
This commit is contained in:
committed by
Mathias Agopian
parent
53aac259a0
commit
b2fc46c320
@@ -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();
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user