The lights UBO must be per-View
We used to have a UBO for lights per scene, however it's better to have one per view, since it depends on the camera heavily and is limited in size. Not doing so, could force us to upload the same UBO multiple times per frame, for e.g. if the same scene was used in multiple views.
This commit is contained in:
committed by
Mathias Agopian
parent
912b301790
commit
84bfbac5fa
@@ -44,10 +44,6 @@ namespace details {
|
||||
FScene::FScene(FEngine& engine) :
|
||||
mEngine(engine),
|
||||
mIndirectLight(engine.getDefaultIndirectLight()) {
|
||||
FEngine::DriverApi& driver = engine.getDriverApi();
|
||||
mLightUBO = driver.createUniformBuffer(CONFIG_MAX_LIGHT_COUNT * sizeof(LightsUib),
|
||||
driver::BufferUsage::DYNAMIC);
|
||||
driver.bindUniformBuffer(BindingPoints::LIGHTS, mLightUBO);
|
||||
}
|
||||
|
||||
FScene::~FScene() noexcept = default;
|
||||
@@ -215,10 +211,9 @@ void FScene::updateUBOs(utils::Range<uint32_t> visibleRenderables) noexcept {
|
||||
void FScene::terminate(FEngine& engine) {
|
||||
// free-up UBOs
|
||||
engine.getDriverApi().destroyUniformBuffer(mRenderableUBO);
|
||||
engine.getDriverApi().destroyUniformBuffer(mLightUBO);
|
||||
}
|
||||
|
||||
void FScene::prepareDynamicLights(const CameraInfo& camera, ArenaScope& rootArena) noexcept {
|
||||
void FScene::prepareDynamicLights(const CameraInfo& camera, ArenaScope& rootArena, Handle<HwUniformBuffer> lightUbh) noexcept {
|
||||
FEngine::DriverApi& driver = mEngine.getDriverApi();
|
||||
FLightManager& lcm = mEngine.getLightManager();
|
||||
FScene::LightSoa& lightData = getLightData();
|
||||
@@ -269,7 +264,7 @@ void FScene::prepareDynamicLights(const CameraInfo& camera, ArenaScope& rootAren
|
||||
lp[gpuIndex].spotScaleOffset.xy = { lcm.getSpotParams(li).scaleOffset };
|
||||
}
|
||||
|
||||
driver.updateUniformBuffer(mLightUBO, { lp, positionalLightCount * sizeof(LightsUib) });
|
||||
driver.updateUniformBuffer(lightUbh, { lp, positionalLightCount * sizeof(LightsUib) });
|
||||
}
|
||||
|
||||
// These methods need to exist so clang honors the __restrict__ keyword, which in turn
|
||||
|
||||
+15
-13
@@ -61,34 +61,36 @@ FView::FView(FEngine& engine)
|
||||
mPerViewSb(engine.getPerViewSib()),
|
||||
mClipSpace01(engine.getBackend() == Backend::VULKAN),
|
||||
mDirectionalShadowMap(engine) {
|
||||
DriverApi& driverApi = engine.getDriverApi();
|
||||
|
||||
mPerViewUbh = driverApi.createUniformBuffer(mPerViewUb.getSize(), driver::BufferUsage::DYNAMIC);
|
||||
mPerViewSbh = driverApi.createSamplerBuffer(mPerViewSb.getSize());
|
||||
DriverApi& driver = engine.getDriverApi();
|
||||
|
||||
// set-up samplers
|
||||
mPerViewSb.setBuffer(PerViewSib::RECORDS, mFroxelizer.getRecordBuffer());
|
||||
mPerViewSb.setBuffer(PerViewSib::FROXELS, mFroxelizer.getFroxelBuffer());
|
||||
|
||||
if (engine.getDFG()->isValid()) {
|
||||
TextureSampler sampler(TextureSampler::MagFilter::LINEAR);
|
||||
mPerViewSb.setSampler(PerViewSib::IBL_DFG_LUT,
|
||||
engine.getDFG()->getTexture(), sampler.getSamplerParams());
|
||||
}
|
||||
mPerViewSbh = driver.createSamplerBuffer(mPerViewSb.getSize());
|
||||
driver.updateSamplerBuffer(mPerViewSbh, SamplerBuffer(mPerViewSb));
|
||||
|
||||
mIsDynamicResolutionSupported = driverApi.isFrameTimeSupported();
|
||||
// allocate ubos
|
||||
mPerViewUbh = driver.createUniformBuffer(mPerViewUb.getSize(), driver::BufferUsage::DYNAMIC);
|
||||
mLightUbh = driver.createUniformBuffer(CONFIG_MAX_LIGHT_COUNT * sizeof(LightsUib), driver::BufferUsage::DYNAMIC);
|
||||
|
||||
driverApi.updateSamplerBuffer(mPerViewSbh, SamplerBuffer(mPerViewSb));
|
||||
mIsDynamicResolutionSupported = driver.isFrameTimeSupported();
|
||||
}
|
||||
|
||||
FView::~FView() noexcept = default;
|
||||
|
||||
void FView::terminate(FEngine& engine) {
|
||||
// Here we would cleanly free resources we've allocated or we own (currently none).
|
||||
DriverApi& driverApi = engine.getDriverApi();
|
||||
driverApi.destroyUniformBuffer(mPerViewUbh);
|
||||
driverApi.destroySamplerBuffer(mPerViewSbh);
|
||||
mDirectionalShadowMap.terminate(driverApi);
|
||||
mFroxelizer.terminate(driverApi);
|
||||
DriverApi& driver = engine.getDriverApi();
|
||||
driver.destroyUniformBuffer(mPerViewUbh);
|
||||
driver.destroyUniformBuffer(mLightUbh);
|
||||
driver.destroySamplerBuffer(mPerViewSbh);
|
||||
mDirectionalShadowMap.terminate(driver);
|
||||
mFroxelizer.terminate(driver);
|
||||
}
|
||||
|
||||
void FView::setViewport(Viewport const& viewport) noexcept {
|
||||
@@ -308,7 +310,7 @@ void FView::prepareLighting(FEngine& engine, FEngine::DriverApi& driver, ArenaSc
|
||||
const CameraInfo& camera = mViewingCameraInfo;
|
||||
FScene* const scene = mScene;
|
||||
|
||||
scene->prepareDynamicLights(camera, arena);
|
||||
scene->prepareDynamicLights(camera, arena, mLightUbh);
|
||||
|
||||
// here the array of visible lights has been shrunk to CONFIG_MAX_LIGHT_COUNT
|
||||
auto const& lightData = scene->getLightData();
|
||||
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
void terminate(FEngine& engine);
|
||||
|
||||
void prepare(const math::mat4f& worldOriginTansform);
|
||||
void prepareDynamicLights(const CameraInfo& camera, ArenaScope& arena) noexcept;
|
||||
void prepareDynamicLights(const CameraInfo& camera, ArenaScope& arena, Handle<HwUniformBuffer> lightUbh) noexcept;
|
||||
void computeBounds(Aabb& castersBox, Aabb& receiversBox, uint32_t visibleLayers) const noexcept;
|
||||
|
||||
|
||||
@@ -183,7 +183,6 @@ private:
|
||||
uint32_t mRenderableUBOSize = 0;
|
||||
|
||||
Handle<HwUniformBuffer> mRenderableUBO; // TODO: should this UBO be per-view?
|
||||
Handle<HwUniformBuffer> mLightUBO; // TODO: should this UBO be per-view?
|
||||
};
|
||||
|
||||
FILAMENT_UPCAST(Scene)
|
||||
|
||||
@@ -216,8 +216,9 @@ private:
|
||||
size_t count) const;
|
||||
|
||||
void bindPerViewUniformsAndSamplers(FEngine::DriverApi& driver) const noexcept {
|
||||
driver.bindUniformBuffer(BindingPoints::PER_VIEW, getUbh());
|
||||
driver.bindSamplers(BindingPoints::PER_VIEW, getUsh());
|
||||
driver.bindUniformBuffer(BindingPoints::PER_VIEW, mPerViewUbh);
|
||||
driver.bindUniformBuffer(BindingPoints::LIGHTS, mLightUbh);
|
||||
driver.bindSamplers(BindingPoints::PER_VIEW, mPerViewSbh);
|
||||
}
|
||||
|
||||
// we don't inline this one, because the function is quite large and there is not much to
|
||||
@@ -229,12 +230,12 @@ private:
|
||||
// these are accessed in the render loop, keep together
|
||||
Handle<HwSamplerBuffer> mPerViewSbh;
|
||||
Handle<HwUniformBuffer> mPerViewUbh;
|
||||
Handle<HwUniformBuffer> mLightUbh;
|
||||
|
||||
UniformBuffer& getUb() const noexcept { return mPerViewUb; }
|
||||
Handle<HwUniformBuffer> getUbh() const noexcept { return mPerViewUbh; }
|
||||
|
||||
SamplerBuffer& getUs() const noexcept { return mPerViewSb; }
|
||||
Handle<HwSamplerBuffer> getUsh() const noexcept { return mPerViewSbh; }
|
||||
Handle<HwUniformBuffer> getUbh() const noexcept { return mPerViewUbh; }
|
||||
Handle<HwUniformBuffer> getLightUbh() const noexcept { return mLightUbh; }
|
||||
|
||||
|
||||
FScene* mScene = nullptr;
|
||||
FCamera* mCullingCamera = nullptr;
|
||||
@@ -270,6 +271,9 @@ private:
|
||||
mutable UniformBuffer mPerViewUb;
|
||||
mutable SamplerBuffer mPerViewSb;
|
||||
|
||||
SamplerBuffer& getUs() const noexcept { return mPerViewSb; }
|
||||
UniformBuffer& getUb() const noexcept { return mPerViewUb; }
|
||||
|
||||
utils::CString mName;
|
||||
const bool mClipSpace01;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user