From 14275b1cf31090cb8e9a759202527e6efda43b2e Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 15 Nov 2017 15:42:04 +0100 Subject: [PATCH] Added asserts in LightStage to catch shadow disappearance when domain is automatically reloaded --- .../src/DeferredLightingEffect.cpp | 2 +- libraries/render-utils/src/LightClusters.cpp | 2 +- libraries/render-utils/src/LightStage.cpp | 45 ++++++++++++----- libraries/render-utils/src/LightStage.h | 50 +++++++++++-------- 4 files changed, 63 insertions(+), 36 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index dcb16c08f8..646b19198b 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -620,7 +620,7 @@ void RenderDeferredLocals::run(const render::RenderContextPointer& renderContext auto& lightIndices = lightClusters->_visibleLightIndices; if (!lightIndices.empty() && lightIndices[0] > 0) { // Bind the global list of lights and the visible lights this frame - batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, lightClusters->_lightStage->_lightArrayBuffer); + batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, lightClusters->_lightStage->getLightArrayBuffer()); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustumGridBuffer); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer); diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index ab1e194498..eedb9053c7 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -727,7 +727,7 @@ void DebugLightClusters::run(const render::RenderContextPointer& renderContext, batch.setModelTransform(Transform()); // Bind the Light CLuster data strucutre - batch.setUniformBuffer(LIGHT_GPU_SLOT, lightClusters->_lightStage->_lightArrayBuffer); + batch.setUniformBuffer(LIGHT_GPU_SLOT, lightClusters->_lightStage->getLightArrayBuffer()); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustumGridBuffer); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, lightClusters->_clusterContentBuffer); diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 160fa2deea..ba705e56cb 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -25,11 +25,17 @@ LightStage::Shadow::Schema::Schema() : } +gpu::FramebufferPointer LightStage::Shadow::framebuffer; +gpu::TexturePointer LightStage::Shadow::map; + LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum{ std::make_shared() } { - framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(MAP_SIZE)); - map = framebuffer->getDepthStencilBuffer(); Schema schema; _schemaBuffer = std::make_shared(sizeof(Schema), (const gpu::Byte*) &schema); + + if (!framebuffer) { + framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(MAP_SIZE)); + map = framebuffer->getDepthStencilBuffer(); + } } void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum, @@ -122,11 +128,9 @@ LightStage::Index LightStage::findLight(const LightPointer& light) const { } else { return (*found).second; } - } LightStage::Index LightStage::addLight(const LightPointer& light) { - auto found = _lightMap.find(light); if (found == _lightMap.end()) { auto lightId = _lights.newElement(light); @@ -137,6 +141,7 @@ LightStage::Index LightStage::addLight(const LightPointer& light) { if (lightId >= (Index) _descs.size()) { _descs.emplace_back(Desc()); } else { + assert(_descs[lightId].shadowId == INVALID_INDEX); _descs.emplace(_descs.begin() + lightId, Desc()); } @@ -155,6 +160,7 @@ LightStage::Index LightStage::addShadow(Index lightIndex) { auto light = getLight(lightIndex); Index shadowId = INVALID_INDEX; if (light) { + assert(_descs[lightIndex].shadowId == INVALID_INDEX); shadowId = _shadows.newElement(std::make_shared(light)); _descs[lightIndex].shadowId = shadowId; } @@ -162,18 +168,20 @@ LightStage::Index LightStage::addShadow(Index lightIndex) { } LightStage::LightPointer LightStage::removeLight(Index index) { - LightPointer removed = _lights.freeElement(index); - - if (removed) { + LightPointer removedLight = _lights.freeElement(index); + if (removedLight) { auto shadowId = _descs[index].shadowId; // Remove shadow if one exists for this light if (shadowId != INVALID_INDEX) { - _shadows.freeElement(shadowId); + auto removedShadow = _shadows.freeElement(shadowId); + assert(removedShadow); + assert(removedShadow->getLight() == removedLight); } - _lightMap.erase(removed); + _lightMap.erase(removedLight); _descs[index] = Desc(); } - return removed; + assert(_descs.size() <= index || _descs[index].shadowId == INVALID_INDEX); + return removedLight; } LightStage::LightPointer LightStage::getCurrentKeyLight() const { @@ -197,7 +205,9 @@ LightStage::ShadowPointer LightStage::getCurrentKeyShadow() const { if (!_currentFrame._sunLights.empty()) { keyLightId = _currentFrame._sunLights.front(); } - return getShadow(keyLightId); + auto shadow = getShadow(keyLightId); + assert(shadow == nullptr || shadow->getLight() == getLight(keyLightId)); + return shadow; } LightStage::LightAndShadow LightStage::getCurrentKeyLightAndShadow() const { @@ -205,7 +215,18 @@ LightStage::LightAndShadow LightStage::getCurrentKeyLightAndShadow() const { if (!_currentFrame._sunLights.empty()) { keyLightId = _currentFrame._sunLights.front(); } - return LightAndShadow(getLight(keyLightId), getShadow(keyLightId)); + auto shadow = getShadow(keyLightId); + auto light = getLight(keyLightId); + assert(shadow == nullptr || shadow->getLight() == light); + return LightAndShadow(light, shadow); +} + +LightStage::Index LightStage::getShadowId(Index lightId) const { + if (checkLightId(lightId)) { + return _descs[lightId].shadowId; + } else { + return INVALID_INDEX; + } } void LightStage::updateLightArrayBuffer(Index lightId) { diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 052c8dd222..fa581c8315 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -58,10 +58,15 @@ public: const UniformBufferView& getBuffer() const { return _schemaBuffer; } - gpu::FramebufferPointer framebuffer; - gpu::TexturePointer map; + // Shadow maps are shared among all lights for the moment as only one key light + // is used. + static gpu::FramebufferPointer framebuffer; + static gpu::TexturePointer map; + + const model::LightPointer& getLight() const { return _light; } protected: + model::LightPointer _light; std::shared_ptr _frustum; @@ -78,16 +83,11 @@ public: }; UniformBufferView _schemaBuffer = nullptr; - friend class Light; }; + using ShadowPointer = std::shared_ptr; using Shadows = render::indexed_container::IndexedPointerVector; - struct Desc { - Index shadowId { INVALID_INDEX }; - }; - using Descs = std::vector; - Index findLight(const LightPointer& light) const; Index addLight(const LightPointer& light); @@ -105,20 +105,18 @@ public: return _lights.get(lightId); } - Index getShadowId(Index lightId) const { - if (checkLightId(lightId)) { - return _descs[lightId].shadowId; - } else { - return INVALID_INDEX; - } - } + Index getShadowId(Index lightId) const; + ShadowPointer getShadow(Index lightId) const { return _shadows.get(getShadowId(lightId)); } using LightAndShadow = std::pair; LightAndShadow getLightAndShadow(Index lightId) const { - return LightAndShadow(getLight(lightId), getShadow(lightId)); + auto light = getLight(lightId); + auto shadow = getShadow(lightId); + assert(shadow == nullptr || shadow->getLight() == light); + return LightAndShadow(light, shadow); } LightPointer getCurrentKeyLight() const; @@ -128,9 +126,8 @@ public: LightStage(); - Lights _lights; - LightMap _lightMap; - Descs _descs; + gpu::BufferPointer getLightArrayBuffer() const { return _lightArrayBuffer; } + void updateLightArrayBuffer(Index lightId); class Frame { public: @@ -159,15 +156,24 @@ public: Frame _currentFrame; - gpu::BufferPointer _lightArrayBuffer; - void updateLightArrayBuffer(Index lightId); +protected: + struct Desc { + Index shadowId{ INVALID_INDEX }; + }; + using Descs = std::vector; + + gpu::BufferPointer _lightArrayBuffer; + + Lights _lights; Shadows _shadows; + Descs _descs; + LightMap _lightMap; + }; using LightStagePointer = std::shared_ptr; - class LightStageSetup { public: using JobModel = render::Job::Model;