From 40fbe2d1e5dd8b36db967babe346be57bde4dbf3 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 9 Mar 2016 17:33:07 -0800 Subject: [PATCH 1/7] Reuse procedurals on entities --- .../entities-renderer/src/RenderableBoxEntityItem.cpp | 7 ++++--- .../entities-renderer/src/RenderableSphereEntityItem.cpp | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp index 671043813e..58d9b6b391 100644 --- a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp @@ -31,7 +31,9 @@ EntityItemPointer RenderableBoxEntityItem::factory(const EntityItemID& entityID, void RenderableBoxEntityItem::setUserData(const QString& value) { if (value != getUserData()) { BoxEntityItem::setUserData(value); - _procedural.reset(); + if (_procedural) { + _procedural->parse(value); + } } } @@ -40,7 +42,6 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { Q_ASSERT(getType() == EntityTypes::Box); Q_ASSERT(args->_batch); - if (!_procedural) { _procedural.reset(new Procedural(this->getUserData())); _procedural->_vertexSource = simple_vert; @@ -62,7 +63,7 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { } batch.setModelTransform(transToCenter); // we want to include the scale as well - if (_procedural && _procedural->ready()) { + if (_procedural->ready()) { _procedural->prepare(batch, getPosition(), getDimensions()); auto color = _procedural->getColor(cubeColor); batch._glColor4f(color.r, color.g, color.b, color.a); diff --git a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp index b5867fb1ee..78ff77ce89 100644 --- a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp @@ -36,7 +36,9 @@ EntityItemPointer RenderableSphereEntityItem::factory(const EntityItemID& entity void RenderableSphereEntityItem::setUserData(const QString& value) { if (value != getUserData()) { SphereEntityItem::setUserData(value); - _procedural.reset(); + if (_procedural) { + _procedural->parse(value); + } } } From 4022474b48e1eef6c267b79ae65a95b4135f05ae Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 9 Mar 2016 17:33:19 -0800 Subject: [PATCH 2/7] Constrain procedural updates to render thread --- .../procedural/src/procedural/Procedural.cpp | 153 +++++++++++------- .../procedural/src/procedural/Procedural.h | 46 ++++-- 2 files changed, 132 insertions(+), 67 deletions(-) diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index b1e4bd53ed..f7c4a783aa 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -69,74 +69,108 @@ Procedural::Procedural(const QString& userDataJson) { } void Procedural::parse(const QString& userDataJson) { - _enabled = false; auto proceduralData = getProceduralData(userDataJson); - if (proceduralData.isObject()) { - parse(proceduralData.toObject()); - } + // Instead of parsing, prep for a parse on the rendering thread + // This will be called by Procedural::ready + _proceduralData = proceduralData.toObject(); + _proceduralDataDirty = true; } -void Procedural::parse(const QJsonObject& proceduralData) { - // grab the version number - { - auto version = proceduralData[VERSION_KEY]; - if (version.isDouble()) { - _version = (uint8_t)(floor(version.toDouble())); - } +bool Procedural::parseVersion(const QJsonValue& version) { + if (version.isDouble()) { + _version = (uint8_t)(floor(version.toDouble())); + } else { + // All unversioned shaders default to V1 + _version = 1; + } + return (_version == 1 || _version == 2); +} + +bool Procedural::parseUrl(const QUrl& shaderUrl) { + if (!shaderUrl.isValid()) { + qWarning() << "Invalid shader URL: " << shaderUrl; + return false; } - // Get the path to the shader - { - QString shaderUrl = proceduralData[URL_KEY].toString(); - shaderUrl = ResourceManager::normalizeURL(shaderUrl); - _shaderUrl = QUrl(shaderUrl); - if (!_shaderUrl.isValid()) { - qWarning() << "Invalid shader URL: " << shaderUrl; - return; - } - - if (_shaderUrl.isLocalFile()) { - _shaderPath = _shaderUrl.toLocalFile(); - qDebug() << "Shader path: " << _shaderPath; - if (!QFile(_shaderPath).exists()) { - return; - } - } else { - qDebug() << "Shader url: " << _shaderUrl; - _networkShader = ShaderCache::instance().getShader(_shaderUrl); - } + if (_shaderUrl == shaderUrl) { + return true; } - // Grab any custom uniforms - { - auto uniforms = proceduralData[UNIFORMS_KEY]; - if (uniforms.isObject()) { - _parsedUniforms = uniforms.toObject(); + _shaderUrl = shaderUrl; + + if (_shaderUrl.isLocalFile()) { + _shaderPath = _shaderUrl.toLocalFile(); + qDebug() << "Shader path: " << _shaderPath; + if (!QFile(_shaderPath).exists()) { + return false;; } + } else { + qDebug() << "Shader url: " << _shaderUrl; + _networkShader = ShaderCache::instance().getShader(_shaderUrl); } - // Grab any textures - { - auto channels = proceduralData[CHANNELS_KEY]; - if (channels.isArray()) { - auto textureCache = DependencyManager::get(); - _parsedChannels = channels.toArray(); - 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)); - } - } + return true; +} + +bool Procedural::parseUniforms(const QJsonObject& uniforms) { + if (_parsedUniforms != uniforms) { + _parsedUniforms = uniforms; + _uniformsDirty = true; + } + + return true; +} + +bool Procedural::parseTextures(const QJsonArray& channels) { + if (_parsedChannels != channels) { + _parsedChannels = 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)); + } + + _channelsDirty = true; + } + + return true; +} + +void Procedural::parse(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(proceduralData[VERSION_KEY]) && + parseUrl(shaderUrl) && + parseUniforms(uniforms) && + parseTextures(channels)) { + _enabled = true; } - _enabled = true; } bool Procedural::ready() { + // Load any changes to the procedural + if (_proceduralDataDirty) { + parse(_proceduralData); + _proceduralDataDirty = false; + } + if (!_enabled) { return false; } - // Do we have a network or local shader + // Do we have a network or local shader, and if so, is it loaded? if (_shaderPath.isEmpty() && (!_networkShader || !_networkShader->isLoaded())) { return false; } @@ -160,15 +194,14 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm QFile file(_shaderPath); file.open(QIODevice::ReadOnly); _shaderSource = QTextStream(&file).readAll(); - _pipelineDirty = true; + _shaderDirty = true; _shaderModified = lastModified; } } else if (_networkShader && _networkShader->isLoaded()) { _shaderSource = _networkShader->_source; } - if (!_pipeline || _pipelineDirty) { - _pipelineDirty = true; + if (!_pipeline || _shaderDirty) { if (!_vertexShader) { _vertexShader = gpu::Shader::createVertex(_vertexSource); } @@ -214,11 +247,15 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm batch.setPipeline(_pipeline); - if (_pipelineDirty) { - _pipelineDirty = false; + if (_shaderDirty || _uniformsDirty) { setupUniforms(); } + if (_shaderDirty || _uniformsDirty || _channelsDirty) { + setupChannels(_shaderDirty || _uniformsDirty); + } + + _shaderDirty = _uniformsDirty = _channelsDirty = false; for (auto lambda : _uniforms) { lambda(batch); @@ -359,8 +396,14 @@ void Procedural::setupUniforms() { batch._glUniform(_standardUniformSlots[POSITION], _entityPosition); }); } +} +void Procedural::setupChannels(bool shouldCreate) { if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[CHANNEL_RESOLUTION]) { + if (!shouldCreate) { + // Instead of modifying the last element, just remove and recreate it. + _uniforms.pop_back(); + } _uniforms.push_back([=](gpu::Batch& batch) { vec3 channelSizes[MAX_PROCEDURAL_TEXTURE_CHANNELS]; for (size_t i = 0; i < MAX_PROCEDURAL_TEXTURE_CHANNELS; ++i) { diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 1b02fbd435..41493664b1 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -28,27 +28,24 @@ const size_t MAX_PROCEDURAL_TEXTURE_CHANNELS{ 4 }; // FIXME better encapsulation // FIXME better mechanism for extending to things rendered using shaders other than simple.slv struct Procedural { +public: static QJsonValue getProceduralData(const QString& proceduralJson); Procedural(const QString& userDataJson); void parse(const QString& userDataJson); - void parse(const QJsonObject&); + bool ready(); void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size); - void setupUniforms(); + glm::vec4 getColor(const glm::vec4& entityColor); - bool _enabled{ false }; - uint8_t _version{ 1 }; + bool _enabled { false }; + uint8_t _version { 1 }; std::string _vertexSource; std::string _fragmentSource; - QString _shaderSource; - QString _shaderPath; - QUrl _shaderUrl; - quint64 _shaderModified{ 0 }; - bool _pipelineDirty{ true }; + gpu::StatePointer _state; enum StandardUniforms { DATE, @@ -60,23 +57,48 @@ struct Procedural { NUM_STANDARD_UNIFORMS }; - int32_t _standardUniformSlots[NUM_STANDARD_UNIFORMS]; - +protected: + // Procedural metadata uint64_t _start{ 0 }; int32_t _frameCount{ 0 }; + + // Rendering object descriptions, from userData + QJsonObject _proceduralData; + QString _shaderSource; + QString _shaderPath; + QUrl _shaderUrl; + quint64 _shaderModified { 0 }; NetworkShaderPointer _networkShader; QJsonObject _parsedUniforms; QJsonArray _parsedChannels; + bool _proceduralDataDirty { true }; + bool _shaderDirty { true }; + bool _uniformsDirty { true }; + bool _channelsDirty { true }; + // Rendering objects UniformLambdas _uniforms; + int32_t _standardUniformSlots[NUM_STANDARD_UNIFORMS]; NetworkTexturePointer _channels[MAX_PROCEDURAL_TEXTURE_CHANNELS]; gpu::PipelinePointer _pipeline; gpu::ShaderPointer _vertexShader; gpu::ShaderPointer _fragmentShader; gpu::ShaderPointer _shader; - gpu::StatePointer _state; + + // Entity metadata glm::vec3 _entityDimensions; glm::vec3 _entityPosition; + +private: + // This should only be called from the render thread, as it shares data with Procedural::prepare + void parse(QJsonObject); + bool parseVersion(const QJsonValue& version); + bool parseUrl(const QUrl& url); + bool parseUniforms(const QJsonObject& uniforms); + bool parseTextures(const QJsonArray& channels); + + void setupUniforms(); + void setupChannels(bool shouldCreate); }; #endif From 74e1d322215e67244ea22823565758fcb2aa19b6 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 9 Mar 2016 17:48:24 -0800 Subject: [PATCH 3/7] Reuse procedural on skybox --- .../src/EntityTreeRenderer.cpp | 7 +----- .../procedural/src/procedural/Procedural.cpp | 3 +++ .../procedural/src/procedural/Procedural.h | 7 +++--- .../src/procedural/ProceduralSkybox.cpp | 23 ++++++++----------- .../src/procedural/ProceduralSkybox.h | 6 ++--- 5 files changed, 19 insertions(+), 27 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 44c3146b41..421213151a 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -341,12 +341,7 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptrgetUserData()) { userData = zone->getUserData(); - auto procedural = std::make_shared(userData); - if (procedural->_enabled) { - skybox->setProcedural(procedural); - } else { - skybox->setProcedural(ProceduralPointer()); - } + skybox->setProcedural(userData); } if (zone->getSkyboxProperties().getURL().isEmpty()) { skybox->setCubemap(gpu::TexturePointer()); diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index f7c4a783aa..cc9e5841ed 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -62,6 +62,9 @@ QJsonValue Procedural::getProceduralData(const QString& proceduralJson) { return doc.object()[PROCEDURAL_USER_DATA_KEY]; } +Procedural::Procedural() { + _state = std::make_shared(); +} Procedural::Procedural(const QString& userDataJson) { parse(userDataJson); diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 41493664b1..0d602eab4f 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -31,6 +31,7 @@ struct Procedural { public: static QJsonValue getProceduralData(const QString& proceduralJson); + Procedural(); Procedural(const QString& userDataJson); void parse(const QString& userDataJson); @@ -39,7 +40,6 @@ public: glm::vec4 getColor(const glm::vec4& entityColor); - bool _enabled { false }; uint8_t _version { 1 }; std::string _vertexSource; @@ -59,8 +59,9 @@ public: protected: // Procedural metadata - uint64_t _start{ 0 }; - int32_t _frameCount{ 0 }; + bool _enabled { false }; + uint64_t _start { 0 }; + int32_t _frameCount { 0 }; // Rendering object descriptions, from userData QJsonObject _proceduralData; diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index 167d49cbaf..f3ee08dd7a 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -19,6 +19,10 @@ #include "ProceduralSkybox_frag.h" ProceduralSkybox::ProceduralSkybox() : model::Skybox() { + _procedural._vertexSource = ProceduralSkybox_vert; + _procedural._fragmentSource = ProceduralSkybox_frag; + // Adjust the pipeline state for background using the stencil test + _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)); } ProceduralSkybox::ProceduralSkybox(const ProceduralSkybox& skybox) : @@ -27,14 +31,8 @@ ProceduralSkybox::ProceduralSkybox(const ProceduralSkybox& skybox) : } -void ProceduralSkybox::setProcedural(const ProceduralPointer& procedural) { - _procedural = procedural; - if (_procedural) { - _procedural->_vertexSource = ProceduralSkybox_vert; - _procedural->_fragmentSource = ProceduralSkybox_frag; - // Adjust the pipeline state for background using the stencil test - _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::setProcedural(const QString& userData) { + _procedural.parse(userData); } void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const { @@ -42,12 +40,10 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) con } void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const ProceduralSkybox& skybox) { - if (!(skybox._procedural)) { + if (!(skybox._procedural.ready())) { skybox.updateDataBuffer(); Skybox::render(batch, viewFrustum, skybox); - } - - if (skybox._procedural && skybox._procedural->_enabled && skybox._procedural->ready()) { + } else { gpu::TexturePointer skymap = skybox.getCubemap(); // FIXME: skymap->isDefined may not be threadsafe assert(skymap && skymap->isDefined()); @@ -62,8 +58,7 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, batch.setModelTransform(Transform()); // only for Mac batch.setResourceTexture(0, skybox.getCubemap()); - skybox._procedural->prepare(batch, glm::vec3(0), glm::vec3(1)); + skybox._procedural.prepare(batch, glm::vec3(0), glm::vec3(1)); batch.draw(gpu::TRIANGLE_STRIP, 4); } } - diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.h b/libraries/procedural/src/procedural/ProceduralSkybox.h index 057a1ccc74..37cc2baaaf 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.h +++ b/libraries/procedural/src/procedural/ProceduralSkybox.h @@ -17,8 +17,6 @@ #include "Procedural.h" -typedef std::shared_ptr ProceduralPointer; - class ProceduralSkybox: public model::Skybox { public: ProceduralSkybox(); @@ -26,13 +24,13 @@ public: ProceduralSkybox& operator= (const ProceduralSkybox& skybox); virtual ~ProceduralSkybox() {}; - void setProcedural(const ProceduralPointer& procedural); + void setProcedural(const QString& userData); virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const; static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox); protected: - ProceduralPointer _procedural; + mutable Procedural _procedural; }; typedef std::shared_ptr< ProceduralSkybox > ProceduralSkyboxPointer; From 1640314076cf29cf6f51b28499322dc0c9743201 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 10 Mar 2016 10:12:22 -0800 Subject: [PATCH 4/7] Use one procedural for skybox (avoid copies) --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 2 +- .../procedural/src/procedural/ProceduralSkybox.cpp | 10 ---------- libraries/procedural/src/procedural/ProceduralSkybox.h | 4 +--- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 421213151a..5cf1b1548a 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -341,7 +341,7 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptrgetUserData()) { userData = zone->getUserData(); - skybox->setProcedural(userData); + skybox->parse(userData); } if (zone->getSkyboxProperties().getURL().isEmpty()) { skybox->setCubemap(gpu::TexturePointer()); diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index f3ee08dd7a..9c311acb3d 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -25,16 +25,6 @@ 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)); } -ProceduralSkybox::ProceduralSkybox(const ProceduralSkybox& skybox) : - model::Skybox(skybox), - _procedural(skybox._procedural) { - -} - -void ProceduralSkybox::setProcedural(const QString& userData) { - _procedural.parse(userData); -} - void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const { ProceduralSkybox::render(batch, frustum, (*this)); } diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.h b/libraries/procedural/src/procedural/ProceduralSkybox.h index 37cc2baaaf..e817ce271d 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.h +++ b/libraries/procedural/src/procedural/ProceduralSkybox.h @@ -20,11 +20,9 @@ class ProceduralSkybox: public model::Skybox { public: ProceduralSkybox(); - ProceduralSkybox(const ProceduralSkybox& skybox); - ProceduralSkybox& operator= (const ProceduralSkybox& skybox); virtual ~ProceduralSkybox() {}; - void setProcedural(const QString& userData); + void parse(const QString& userData) { _procedural.parse(userData); } virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const; static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox); From 9b89e46e65eb4b80d13d2cfbaadc4f36e123c924 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 10 Mar 2016 10:12:55 -0800 Subject: [PATCH 5/7] Make procedural userData thread-safe --- libraries/procedural/src/procedural/Procedural.cpp | 2 ++ libraries/procedural/src/procedural/Procedural.h | 1 + 2 files changed, 3 insertions(+) diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index cc9e5841ed..6cf9f05372 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -75,6 +75,7 @@ void Procedural::parse(const QString& userDataJson) { auto proceduralData = getProceduralData(userDataJson); // Instead of parsing, prep for a parse on the rendering thread // This will be called by Procedural::ready + std::lock_guard lock(_proceduralDataMutex); _proceduralData = proceduralData.toObject(); _proceduralDataDirty = true; } @@ -165,6 +166,7 @@ void Procedural::parse(QJsonObject proceduralData) { bool Procedural::ready() { // Load any changes to the procedural if (_proceduralDataDirty) { + std::lock_guard lock(_proceduralDataMutex); parse(_proceduralData); _proceduralDataDirty = false; } diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 0d602eab4f..75872ca2bc 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -65,6 +65,7 @@ protected: // Rendering object descriptions, from userData QJsonObject _proceduralData; + std::mutex _proceduralDataMutex; QString _shaderSource; QString _shaderPath; QUrl _shaderUrl; From 64042327eca3e3bff21b4ca17c937d30b6e555f1 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 10 Mar 2016 11:08:15 -0800 Subject: [PATCH 6/7] Use version tmp var --- libraries/procedural/src/procedural/Procedural.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 6cf9f05372..9670b66676 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -155,7 +155,7 @@ void Procedural::parse(QJsonObject proceduralData) { auto uniforms = proceduralData[UNIFORMS_KEY].toObject(); auto channels = proceduralData[CHANNELS_KEY].toArray(); - if (parseVersion(proceduralData[VERSION_KEY]) && + if (parseVersion(version) && parseUrl(shaderUrl) && parseUniforms(uniforms) && parseTextures(channels)) { From 505ae71e30fa4c571f690b6af1fb8f7819e93e4d Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 10 Mar 2016 15:22:19 -0800 Subject: [PATCH 7/7] Pass px userData by const ref --- libraries/procedural/src/procedural/Procedural.cpp | 2 +- libraries/procedural/src/procedural/Procedural.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 9670b66676..11df332c5c 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -142,7 +142,7 @@ bool Procedural::parseTextures(const QJsonArray& channels) { return true; } -void Procedural::parse(QJsonObject proceduralData) { +void Procedural::parse(const QJsonObject& proceduralData) { _enabled = false; if (proceduralData.isEmpty()) { diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 75872ca2bc..cac3f782e4 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -93,7 +93,7 @@ protected: private: // This should only be called from the render thread, as it shares data with Procedural::prepare - void parse(QJsonObject); + void parse(const QJsonObject&); bool parseVersion(const QJsonValue& version); bool parseUrl(const QUrl& url); bool parseUniforms(const QJsonObject& uniforms);