diff --git a/filament/src/BufferPoolAllocator.h b/filament/src/BufferPoolAllocator.h index a7de04b2e8..432bd36792 100644 --- a/filament/src/BufferPoolAllocator.h +++ b/filament/src/BufferPoolAllocator.h @@ -18,8 +18,10 @@ #define TNT_FILAMENT_BUFFERPOOLALLOCATOR_H #include +#include #include +#include #include #include @@ -110,7 +112,7 @@ void* BufferPoolAllocator: if (UTILS_UNLIKELY(size > mSize)) { clearInternal(); // free all buffers // round to 4K allocations to help cutting down on calling malloc. - size_t roundedSize = ((size + sizeof(Header)) + (ALLOCATION_ROUNDING - 1)) & ~(ALLOCATION_ROUNDING - 1); + size_t const roundedSize = ((size + sizeof(Header)) + (ALLOCATION_ROUNDING - 1)) & ~(ALLOCATION_ROUNDING - 1); mSize = roundedSize - sizeof(Header); // record the new buffer size assert_invariant(mSize >= size); } @@ -119,7 +121,7 @@ void* BufferPoolAllocator: // larger than the requested size). if (UTILS_UNLIKELY(mEntries.empty())) { ++mOutstandingBuffers; - Header* p = (Header*)mAllocator.alloc(mSize + sizeof(Header), ALIGNMENT); + Header* p = static_cast(mAllocator.alloc(mSize + sizeof(Header), ALIGNMENT)); p->size = mSize; return p + 1; } diff --git a/filament/src/details/InstanceBuffer.cpp b/filament/src/details/InstanceBuffer.cpp index f70bc7e7a6..9c95481cd8 100644 --- a/filament/src/details/InstanceBuffer.cpp +++ b/filament/src/details/InstanceBuffer.cpp @@ -127,9 +127,8 @@ void FInstanceBuffer::setLocalTransforms( memcpy(mLocalTransforms.data() + offset, localTransforms, sizeof(math::mat4f) * count); } -void FInstanceBuffer::prepare(FEngine& engine, math::mat4f const& rootTransform, +void FInstanceBuffer::prepare(DriverApi& driver, math::mat4f const& rootTransform, const PerRenderableData& ubo) { - DriverApi& driver = engine.getDriverApi(); // TODO: allocate this staging buffer from a pool. constexpr uint32_t stagingBufferSize = sizeof(PerRenderableUib); diff --git a/filament/src/details/InstanceBuffer.h b/filament/src/details/InstanceBuffer.h index eb346fcd51..662682f3ad 100644 --- a/filament/src/details/InstanceBuffer.h +++ b/filament/src/details/InstanceBuffer.h @@ -21,6 +21,7 @@ #include +#include #include #include @@ -48,7 +49,7 @@ public: void setLocalTransforms(math::mat4f const* localTransforms, size_t count, size_t offset); - void prepare(FEngine& engine, math::mat4f const& rootTransform, const PerRenderableData& ubo); + void prepare(backend::DriverApi& driver, math::mat4f const& rootTransform, const PerRenderableData& ubo); utils::CString const& getName() const noexcept { return mName; } diff --git a/filament/src/details/Scene.cpp b/filament/src/details/Scene.cpp index b82ce6dde1..0edf5f1e05 100644 --- a/filament/src/details/Scene.cpp +++ b/filament/src/details/Scene.cpp @@ -17,18 +17,18 @@ #include "details/Scene.h" #include "Allocators.h" -#include "BufferPoolAllocator.h" -#include "backend/Handle.h" #include "components/LightManager.h" #include "components/RenderableManager.h" #include "components/TransformManager.h" #include "details/Engine.h" -#include "details/InstanceBuffer.h" #include "details/Skybox.h" +#include + #include + #include #include @@ -70,7 +70,7 @@ namespace filament { // ------------------------------------------------------------------------------------------------ FScene::FScene(FEngine& engine) : - mEngine(engine), mSharedState(std::make_shared()) { + mEngine(engine) { } FScene::~FScene() noexcept = default; @@ -406,66 +406,6 @@ void FScene::prepareVisibleRenderables(Range visibleRenderables) noexc } } -void FScene::updateUBOs( - Range visibleRenderables, - Handle renderableUbh) noexcept { - FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT); - FEngine::DriverApi& driver = mEngine.getDriverApi(); - - // don't allocate more than 16 KiB directly into the render stream - static constexpr size_t MAX_STREAM_ALLOCATION_COUNT = 64; // 16 KiB - const size_t count = visibleRenderables.size(); - PerRenderableData* buffer = [&]{ - if (count >= MAX_STREAM_ALLOCATION_COUNT) { - // use the heap allocator - auto& bufferPoolAllocator = mSharedState->mBufferPoolAllocator; - return static_cast(bufferPoolAllocator.get(count * sizeof(PerRenderableData))); - } else { - // allocate space into the command stream directly - return driver.allocatePod(count); - } - }(); - - PerRenderableData const* const uboData = mRenderableData.data(); - mat4f const* const worldTransformData = mRenderableData.data(); - - // prepare each InstanceBuffer. - FRenderableManager::InstancesInfo const* instancesData = mRenderableData.data(); - for (uint32_t const i : visibleRenderables) { - auto& instancesInfo = instancesData[i]; - if (UTILS_UNLIKELY(instancesInfo.buffer)) { - instancesInfo.buffer->prepare( - mEngine, worldTransformData[i], uboData[i]); - } - } - - // copy our data into the UBO for each visible renderable - for (uint32_t const i : visibleRenderables) { - buffer[i] = uboData[i]; - } - - // We capture state shared between Scene and the update buffer callback, because the Scene could - // be destroyed before the callback executes. - std::weak_ptr* const weakShared = - new (std::nothrow) std::weak_ptr(mSharedState); - - // update the UBO - driver.resetBufferObject(renderableUbh); - driver.updateBufferObjectUnsynchronized(renderableUbh, { - buffer, count * sizeof(PerRenderableData), - +[](void* p, size_t const s, void* user) { - std::weak_ptr* const weakShared = - static_cast*>(user); - if (s >= MAX_STREAM_ALLOCATION_COUNT * sizeof(PerRenderableData)) { - if (auto state = weakShared->lock()) { - state->mBufferPoolAllocator.put(p); - } - } - delete weakShared; - }, weakShared - }, 0); -} - void FScene::terminate(FEngine&) { } @@ -497,7 +437,7 @@ void FScene::prepareDynamicLights(const CameraInfo& camera, auto const* UTILS_RESTRICT shadowInfo = lightData.data(); for (size_t i = DIRECTIONAL_LIGHTS_COUNT, c = size; i < c; ++i) { const size_t gpuIndex = i - DIRECTIONAL_LIGHTS_COUNT; - auto li = instances[i]; + auto const li = instances[i]; lp[gpuIndex].positionFalloff = { spheres[i].xyz, lcm.getSquaredFalloffInv(li) }; lp[gpuIndex].direction = directions[i]; lp[gpuIndex].reserved1 = {}; @@ -627,7 +567,7 @@ bool FScene::hasContactShadows() const noexcept { // find out if at least one light has contact-shadow enabled // TODO: we could cache the result of this Loop in the LightManager - auto& lcm = mEngine.getLightManager(); + auto const& lcm = mEngine.getLightManager(); const auto *pFirst = mLightData.begin(); const auto *pLast = mLightData.end(); while (pFirst != pLast) { diff --git a/filament/src/details/Scene.h b/filament/src/details/Scene.h index 817fbd59b0..ef0a98b10f 100644 --- a/filament/src/details/Scene.h +++ b/filament/src/details/Scene.h @@ -26,28 +26,18 @@ #include "components/LightManager.h" #include "components/RenderableManager.h" -#include "components/TransformManager.h" -#include "BufferPoolAllocator.h" - -#include #include -#include - -#include #include #include #include #include -#include #include #include -#include - namespace filament { struct CameraInfo; @@ -136,14 +126,14 @@ public: RenderableSoa const& getRenderableData() const noexcept { return mRenderableData; } RenderableSoa& getRenderableData() noexcept { return mRenderableData; } - static inline uint32_t getPrimitiveCount(RenderableSoa const& soa, + static uint32_t getPrimitiveCount(RenderableSoa const& soa, uint32_t const first, uint32_t const last) noexcept { // the caller must guarantee that last is dereferenceable return soa.elementAt(last) - soa.elementAt(first); } - static inline uint32_t getPrimitiveCount(RenderableSoa const& soa, uint32_t const last) noexcept { + static uint32_t getPrimitiveCount(RenderableSoa const& soa, uint32_t const last) noexcept { // the caller must guarantee that last is dereferenceable return soa.elementAt(last); } @@ -186,9 +176,6 @@ public: LightSoa const& getLightData() const noexcept { return mLightData; } LightSoa& getLightData() noexcept { return mLightData; } - void updateUBOs(utils::Range visibleRenderables, - backend::Handle renderableUbh) noexcept; - bool hasContactShadows() const noexcept; private: @@ -230,12 +217,6 @@ private: RenderableSoa mRenderableData; LightSoa mLightData; bool mHasContactShadows = false; - - // State shared between Scene and driver callbacks. - struct SharedState { - BufferPoolAllocator<3> mBufferPoolAllocator = {}; - }; - std::shared_ptr mSharedState; }; FILAMENT_DOWNCAST(Scene) diff --git a/filament/src/details/View.cpp b/filament/src/details/View.cpp index 6f66946cbb..aa80777c85 100644 --- a/filament/src/details/View.cpp +++ b/filament/src/details/View.cpp @@ -17,6 +17,7 @@ #include "details/View.h" #include "Allocators.h" +#include "BufferPoolAllocator.h" #include "Culler.h" #include "DebugRegistry.h" #include "FrameHistory.h" @@ -27,8 +28,11 @@ #include "ShadowMap.h" #include "ShadowMapManager.h" +#include "components/TransformManager.h" + #include "details/Engine.h" #include "details/IndirectLight.h" +#include "details/InstanceBuffer.h" #include "details/RenderTarget.h" #include "details/Renderer.h" #include "details/Scene.h" @@ -54,6 +58,7 @@ #include #include #include +#include #include #include @@ -71,6 +76,7 @@ #include #include #include +#include #include #include @@ -93,7 +99,8 @@ FView::FView(FEngine& engine) mUniforms(engine.getDriverApi()), mColorPassDescriptorSet{ { engine, false, mUniforms }, - { engine, true, mUniforms } } + { engine, true, mUniforms } }, + mSharedState(std::make_shared()) { DriverApi& driver = engine.getDriverApi(); @@ -766,7 +773,7 @@ void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootAren // TODO: should we shrink the underlying UBO at some point? } assert_invariant(mRenderableUbh); - scene->updateUBOs(merged, mRenderableUbh); + updateUBOs(driver, renderableData, merged, mRenderableUbh); mCommonRenderableDescriptorSet.setBuffer( engine.getPerRenderableDescriptorSetLayout(), @@ -885,6 +892,65 @@ void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootAren colorPassDescriptorSet.prepareMaterialGlobals(mMaterialGlobals); } +void FView::updateUBOs( + FEngine::DriverApi& driver, + FScene::RenderableSoa& renderableData, + utils::Range visibleRenderables, + Handle renderableUbh) noexcept { + FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT); + + // don't allocate more than 16 KiB directly into the render stream + static constexpr size_t MAX_STREAM_ALLOCATION_COUNT = 64; // 16 KiB + const size_t count = visibleRenderables.size(); + PerRenderableData* buffer = [&]{ + if (count >= MAX_STREAM_ALLOCATION_COUNT) { + // use the heap allocator + auto& bufferPoolAllocator = mSharedState->mBufferPoolAllocator; + return static_cast(bufferPoolAllocator.get(count * sizeof(PerRenderableData))); + } + // allocate space into the command stream directly + return driver.allocatePod(count); + }(); + + PerRenderableData const* const uboData = renderableData.data(); + mat4f const* const worldTransformData = renderableData.data(); + + // prepare each InstanceBuffer. + FRenderableManager::InstancesInfo const* instancesData = renderableData.data(); + for (uint32_t const i : visibleRenderables) { + auto& instancesInfo = instancesData[i]; + if (UTILS_UNLIKELY(instancesInfo.buffer)) { + instancesInfo.buffer->prepare(driver, worldTransformData[i], uboData[i]); + } + } + + // copy our data into the UBO for each visible renderable + for (uint32_t const i : visibleRenderables) { + buffer[i] = uboData[i]; + } + + // We capture state shared between Scene and the update buffer callback, because the Scene could + // be destroyed before the callback executes. + std::weak_ptr* const weakShared = + new (std::nothrow) std::weak_ptr(mSharedState); + + // update the UBO + driver.resetBufferObject(renderableUbh); + driver.updateBufferObjectUnsynchronized(renderableUbh, { + buffer, count * sizeof(PerRenderableData), + +[](void* p, size_t const s, void* user) { + std::weak_ptr const* const weakShared = + static_cast*>(user); + if (s >= MAX_STREAM_ALLOCATION_COUNT * sizeof(PerRenderableData)) { + if (auto state = weakShared->lock()) { + state->mBufferPoolAllocator.put(p); + } + } + delete weakShared; + }, weakShared + }, 0); +} + void FView::computeVisibilityMasks( uint8_t const visibleLayers, uint8_t const* UTILS_RESTRICT layers, diff --git a/filament/src/details/View.h b/filament/src/details/View.h index 48b77b72fa..bc7a84dbce 100644 --- a/filament/src/details/View.h +++ b/filament/src/details/View.h @@ -20,6 +20,7 @@ #include "downcast.h" #include "Allocators.h" +#include "BufferPoolAllocator.h" #include "Culler.h" #include "FrameHistory.h" #include "FrameInfo.h" @@ -29,8 +30,6 @@ #include "ds/ColorPassDescriptorSet.h" #include "ds/DescriptorSet.h" -#include "ds/PostProcessDescriptorSet.h" -#include "ds/SsrPassDescriptorSet.h" #include "ds/TypedUniformBuffer.h" #include "components/LightManager.h" @@ -41,11 +40,8 @@ #include "details/RenderTarget.h" #include "details/Scene.h" -#include #include -#include - #include #include #include @@ -54,7 +50,6 @@ #include #include -#include #include #include #include @@ -68,8 +63,8 @@ namespace filament::fgviewer { } #endif -#include #include +#include #include #include @@ -298,7 +293,7 @@ public: return mGuardBandOptions; } - void setColorGrading(FColorGrading* colorGrading) noexcept { + void setColorGrading(FColorGrading const* colorGrading) noexcept { mColorGrading = colorGrading == nullptr ? mDefaultColorGrading : colorGrading; } @@ -441,9 +436,8 @@ public: backend::TargetBufferFlags getRenderTargetAttachmentMask() const noexcept { if (mRenderTarget == nullptr) { return backend::TargetBufferFlags::NONE; - } else { - return mRenderTarget->getAttachmentMask(); } + return mRenderTarget->getAttachmentMask(); } static void cullRenderables(utils::JobSystem& js, FScene::RenderableSoa& renderableData, @@ -484,7 +478,7 @@ public: return mFogEntity; } - TypedUniformBuffer& getFrameUniforms() noexcept { + TypedUniformBuffer& getFrameUniforms() const noexcept { return mUniforms; } @@ -508,7 +502,7 @@ private: PickingQueryResultCallback const callback) noexcept { return new(std::nothrow) FPickingQuery(x, y, handler, callback); } - static void put(FPickingQuery* pQuery) noexcept { + static void put(FPickingQuery const* pQuery) noexcept { delete pQuery; } mutable FPickingQuery* next = nullptr; @@ -518,12 +512,17 @@ private: backend::CallbackHandler* const handler; PickingQueryResultCallback const callback; // picking query result - PickingQueryResult result; + PickingQueryResult result{}; }; void prepareVisibleRenderables(utils::JobSystem& js, Frustum const& frustum, FScene::RenderableSoa& renderableData) const noexcept; + void updateUBOs(backend::DriverApi& driver, + FScene::RenderableSoa& renderableData, + utils::Range visibleRenderables, + backend::Handle renderableUbh) noexcept; + static void prepareVisibleLights(FLightManager const& lcm, utils::Slice scratch, math::mat4f const& viewMatrix, Frustum const& frustum, @@ -620,6 +619,12 @@ private: mutable bool mHasShadowing = false; mutable bool mNeedsShadowMap = false; + // State shared between Scene and driver callbacks. + struct SharedState { + BufferPoolAllocator<3> mBufferPoolAllocator = {}; + }; + std::shared_ptr mSharedState; + std::unique_ptr mShadowMapManager; MaterialGlobals mMaterialGlobals = {{