From 0e9b783ca378ed455a4cde15ca88bda6b424c299 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 1 Apr 2016 13:14:04 -0700 Subject: [PATCH 1/2] Release skybox texs when not rendering --- .../src/EntityTreeRenderer.cpp | 19 +++++++++++++++---- libraries/model/src/model/Skybox.h | 2 ++ .../src/procedural/ProceduralSkybox.cpp | 8 ++++++++ .../src/procedural/ProceduralSkybox.h | 2 ++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index edc7f7d754..b87329d5b6 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -297,7 +297,14 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptrgetLocation(); auto sceneTime = sceneStage->getTime(); + // Skybox and procedural skybox data + auto skybox = std::dynamic_pointer_cast(skyStage->getSkybox()); + static QString userData; + if (!zone) { + userData = QString(); + skybox->clear(); + _pendingSkyboxTexture = false; _skyboxTexture.clear(); @@ -373,9 +380,7 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptrgetBackgroundMode()) { case BACKGROUND_MODE_SKYBOX: { - auto skybox = std::dynamic_pointer_cast(skyStage->getSkybox()); skybox->setColor(zone->getSkyboxProperties().getColorVec3()); - static QString userData; if (userData != zone->getUserData()) { userData = zone->getUserData(); skybox->parse(userData); @@ -414,9 +419,15 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptrsetBackgroundMode(model::SunSkyStage::SKY_DOME); // let the application background through - _pendingSkyboxTexture = false; + // Clear the skybox to release its textures + userData = QString(); + skybox->clear(); + _skyboxTexture.clear(); + _pendingSkyboxTexture = false; + + // Let the application background through + skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME); break; } diff --git a/libraries/model/src/model/Skybox.h b/libraries/model/src/model/Skybox.h index e9e7ee8b26..8c9e7bb1d6 100755 --- a/libraries/model/src/model/Skybox.h +++ b/libraries/model/src/model/Skybox.h @@ -35,6 +35,8 @@ public: void setCubemap(const gpu::TexturePointer& cubemap); const gpu::TexturePointer& getCubemap() const { return _cubemap; } + virtual void clear() { setCubemap(nullptr); } + void prepare(gpu::Batch& batch, int textureSlot = SKYBOX_SKYMAP_SLOT, int bufferSlot = SKYBOX_CONSTANTS_SLOT) const; virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const; diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index 4ff38eac74..1aa59c90d7 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -25,6 +25,14 @@ ProceduralSkybox::ProceduralSkybox() : model::Skybox() { _procedural._state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); } +void ProceduralSkybox::clear() { + // Parse and prepare a procedural with no shaders to release textures + parse(QString()); + _procedural.ready(); + + Skybox::clear(); +} + void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const { if (_procedural.ready()) { ProceduralSkybox::render(batch, frustum, (*this)); diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.h b/libraries/procedural/src/procedural/ProceduralSkybox.h index e817ce271d..2b8f2327a0 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.h +++ b/libraries/procedural/src/procedural/ProceduralSkybox.h @@ -24,6 +24,8 @@ public: void parse(const QString& userData) { _procedural.parse(userData); } + virtual void clear() override; + virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const; static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox); From eb2e254aa6372e99a4c0d370a850eb35271e388f Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 1 Apr 2016 14:20:28 -0700 Subject: [PATCH 2/2] Release px resources when unused --- .../procedural/src/procedural/Procedural.cpp | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index d3aed38198..cedf76b37a 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -96,6 +96,7 @@ bool Procedural::parseVersion(const QJsonValue& version) { bool Procedural::parseUrl(const QUrl& shaderUrl) { if (!shaderUrl.isValid()) { qWarning() << "Invalid shader URL: " << shaderUrl; + _networkShader.reset(); return false; } @@ -110,6 +111,7 @@ bool Procedural::parseUrl(const QUrl& shaderUrl) { _shaderPath = _shaderUrl.toLocalFile(); qDebug() << "Shader path: " << _shaderPath; if (!QFile(_shaderPath).exists()) { + _networkShader.reset(); return false;; } } else { @@ -135,9 +137,14 @@ bool Procedural::parseTextures(const QJsonArray& channels) { auto textureCache = DependencyManager::get(); size_t channelCount = std::min(MAX_PROCEDURAL_TEXTURE_CHANNELS, (size_t)_parsedChannels.size()); - for (size_t i = 0; i < channelCount; ++i) { - QString url = _parsedChannels.at((int)i).toString(); - _channels[i] = textureCache->getTexture(QUrl(url)); + size_t channel = 0; + for (; channel < channelCount; ++channel) { + QString url = _parsedChannels.at((int)channel).toString(); + _channels[channel] = textureCache->getTexture(QUrl(url)); + } + for (; channel < MAX_PROCEDURAL_TEXTURE_CHANNELS; ++channel) { + // Release those textures no longer in use + _channels[channel] = textureCache->getTexture(QUrl()); } _channelsDirty = true; @@ -149,20 +156,21 @@ bool Procedural::parseTextures(const QJsonArray& channels) { void Procedural::parse(const QJsonObject& proceduralData) { _enabled = false; - if (proceduralData.isEmpty()) { - return; - } - auto version = proceduralData[VERSION_KEY]; auto shaderUrl = proceduralData[URL_KEY].toString(); shaderUrl = ResourceManager::normalizeURL(shaderUrl); auto uniforms = proceduralData[UNIFORMS_KEY].toObject(); auto channels = proceduralData[CHANNELS_KEY].toArray(); - if (parseVersion(version) && - parseUrl(shaderUrl) && - parseUniforms(uniforms) && - parseTextures(channels)) { + bool isValid = true; + + // Run through parsing regardless of validity to clear old cached resources + isValid = parseVersion(version) && isValid; + isValid = parseUrl(shaderUrl) && isValid; + isValid = parseUniforms(uniforms) && isValid; + isValid = parseTextures(channels) && isValid; + + if (!proceduralData.isEmpty() && isValid) { _enabled = true; } }