From a6b7578c3c923578aa60133b4a1695320edce081 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 5 Oct 2017 11:53:16 -0700 Subject: [PATCH] start fixing asynch issue, fixes model loading! --- .../src/RenderableEntityItem.cpp | 36 +++---- .../src/RenderableEntityItem.h | 4 +- .../src/RenderableModelEntityItem.cpp | 2 - .../src/RenderableShapeEntityItem.cpp | 53 +++++----- .../src/RenderableWebEntityItem.cpp | 98 +++++++++---------- .../src/RenderableWebEntityItem.h | 1 - libraries/render-utils/src/Model.cpp | 7 +- libraries/render-utils/src/Model.h | 2 +- 8 files changed, 102 insertions(+), 101 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 3f1e89b86c..c38d106bfa 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -329,25 +329,27 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity return false; } -void EntityRenderer::doRenderUpdateAsynchronous(const EntityItemPointer& entity) { - auto transparent = isTransparent(); - if (_prevIsTransparent && !transparent) { - _isFading = false; - } - _prevIsTransparent = transparent; +void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) { + withWriteLock([&] { + auto transparent = isTransparent(); + if (_prevIsTransparent && !transparent) { + _isFading = false; + } + _prevIsTransparent = transparent; - bool success = false; - auto bound = entity->getAABox(success); - if (success) { - _bound = bound; - } - auto newModelTransform = entity->getTransformToCenter(success); - if (success) { - _modelTransform = newModelTransform; - } + bool success = false; + auto bound = entity->getAABox(success); + if (success) { + _bound = bound; + } + auto newModelTransform = entity->getTransformToCenter(success); + if (success) { + _modelTransform = newModelTransform; + } - _moving = entity->isMovingRelativeToParent(); - _visible = entity->getVisible(); + _moving = entity->isMovingRelativeToParent(); + _visible = entity->getVisible(); + }); } void EntityRenderer::onAddToScene(const EntityItemPointer& entity) { diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 6b47ff8b1d..6581e923bd 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -73,12 +73,12 @@ protected: // Will be called on the main thread from updateInScene. This can be used to fetch things like // network textures or model geometry from resource caches - virtual void doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) { } + virtual void doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity); // Will be called by the lambda posted to the scene in updateInScene. // This function will execute on the rendering thread, so you cannot use network caches to fetch // data in this method if using multi-threaded rendering - virtual void doRenderUpdateAsynchronous(const EntityItemPointer& entity); + virtual void doRenderUpdateAsynchronous(const EntityItemPointer& entity) { } // Called by the `render` method after `needsRenderUpdate` virtual void doRender(RenderArgs* args) = 0; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 11c97f6716..064eacdb35 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1145,7 +1145,6 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce model->removeFromScene(scene, transaction); withWriteLock([&] { _model.reset(); }); } - emit requestRenderUpdate(); return; } @@ -1169,7 +1168,6 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce // Nothing else to do unless the model is loaded if (!model->isLoaded()) { - emit needsRenderUpdate(); return; } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 8fcf2c090d..4028f105c8 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -88,31 +88,33 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce } _color = vec4(toGlm(entity->getXColor()), entity->getLocalRenderAlpha()); + + _shape = entity->getShape(); + _position = entity->getPosition(); + _dimensions = entity->getDimensions(); + _orientation = entity->getOrientation(); + + if (_shape == entity::Sphere) { + _modelTransform.postScale(SPHERE_ENTITY_SCALE); + } + + _modelTransform.postScale(_dimensions); }); } void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { - if (_procedural.isEnabled() && _procedural.isFading()) { - float isFading = Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) < 1.0f; - _procedural.setIsFading(isFading); - } - - _shape = entity->getShape(); - _position = entity->getPosition(); - _dimensions = entity->getDimensions(); - _orientation = entity->getOrientation(); - - if (_shape == entity::Sphere) { - _modelTransform.postScale(SPHERE_ENTITY_SCALE); - } - - _modelTransform.postScale(_dimensions); + withReadLock([&] { + if (_procedural.isEnabled() && _procedural.isFading()) { + float isFading = Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) < 1.0f; + _procedural.setIsFading(isFading); + } + }); } bool ShapeEntityRenderer::isTransparent() const { if (_procedural.isEnabled() && _procedural.isFading()) { return Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) < 1.0f; - } + } // return _entity->getLocalRenderAlpha() < 1.0f || Parent::isTransparent(); return Parent::isTransparent(); @@ -126,15 +128,16 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { gpu::Batch& batch = *args->_batch; - auto geometryShape = MAPPING[_shape]; - batch.setModelTransform(_modelTransform); // use a transform with scale, rotation, registration point and translation - + GeometryCache::Shape geometryShape; bool proceduralRender = false; - glm::vec4 outColor = _color; + glm::vec4 outColor; withReadLock([&] { + geometryShape = MAPPING[_shape]; + batch.setModelTransform(_modelTransform); // use a transform with scale, rotation, registration point and translation + outColor = _color; if (_procedural.isReady()) { _procedural.prepare(batch, _position, _dimensions, _orientation); - auto outColor = _procedural.getColor(_color); + outColor = _procedural.getColor(_color); outColor.a *= _procedural.isFading() ? Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) : 1.0f; proceduralRender = true; } @@ -149,13 +152,13 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { } } else { // FIXME, support instanced multi-shape rendering using multidraw indirect - _color.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; + outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; auto geometryCache = DependencyManager::get(); - auto pipeline = _color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); + auto pipeline = outColor.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { - geometryCache->renderWireShapeInstance(args, batch, geometryShape, _color, pipeline); + geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline); } else { - geometryCache->renderSolidShapeInstance(args, batch, geometryShape, _color, pipeline); + geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline); } } diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 0561fa5130..4688ef5d2b 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -118,31 +118,30 @@ void WebEntityRenderer::onTimeout() { } void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { - // This work must be done on the main thread - if (!hasWebSurface()) { - buildWebSurface(entity); - } + withWriteLock([&] { + // This work must be done on the main thread + if (!hasWebSurface()) { + buildWebSurface(entity); + } - if (_contextPosition != entity->getPosition()) { - // update globalPosition - _contextPosition = entity->getPosition(); - _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(_contextPosition)); - } + if (_contextPosition != entity->getPosition()) { + // update globalPosition + _contextPosition = entity->getPosition(); + _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(_contextPosition)); + } - if (_lastSourceUrl != entity->getSourceUrl()) { - _lastSourceUrl = entity->getSourceUrl(); - loadSourceURL(); - } + if (_lastSourceUrl != entity->getSourceUrl()) { + _lastSourceUrl = entity->getSourceUrl(); + loadSourceURL(); + } - _lastDPI = entity->getDPI(); + _lastDPI = entity->getDPI(); - glm::vec2 windowSize = getWindowSize(entity); - _webSurface->resize(QSize(windowSize.x, windowSize.y)); -} + glm::vec2 windowSize = getWindowSize(entity); + _webSurface->resize(QSize(windowSize.x, windowSize.y)); -void WebEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { - Parent::doRenderUpdateAsynchronousTyped(entity); - _modelTransform.postScale(entity->getDimensions()); + _modelTransform.postScale(entity->getDimensions()); + }); } void WebEntityRenderer::doRender(RenderArgs* args) { @@ -180,7 +179,9 @@ void WebEntityRenderer::doRender(RenderArgs* args) { static const glm::vec2 texMin(0.0f), texMax(1.0f), topLeft(-0.5f), bottomRight(0.5f); gpu::Batch& batch = *args->_batch; - batch.setModelTransform(_modelTransform); + withReadLock([&] { + batch.setModelTransform(_modelTransform); + }); batch.setResourceTexture(0, _texture); float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio); @@ -190,7 +191,7 @@ void WebEntityRenderer::doRender(RenderArgs* args) { } bool WebEntityRenderer::hasWebSurface() { - return resultWithReadLock([&] { return (bool)_webSurface; }); + return (bool)_webSurface; } bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) { @@ -213,11 +214,8 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) { }; { - QSharedPointer webSurface = QSharedPointer(new OffscreenQmlSurface(), deleter); - webSurface->create(); - withWriteLock([&] { - _webSurface = webSurface; - }); + _webSurface = QSharedPointer(new OffscreenQmlSurface(), deleter); + _webSurface->create(); } // FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces @@ -322,33 +320,31 @@ glm::vec2 WebEntityRenderer::getWindowSize(const TypedEntityPointer& entity) con } void WebEntityRenderer::loadSourceURL() { - withWriteLock([&] { - const QUrl sourceUrl(_lastSourceUrl); - if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" || - _lastSourceUrl.toLower().endsWith(".htm") || _lastSourceUrl.toLower().endsWith(".html")) { - _contentType = htmlContent; - _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "qml/controls/")); + const QUrl sourceUrl(_lastSourceUrl); + if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" || + _lastSourceUrl.toLower().endsWith(".htm") || _lastSourceUrl.toLower().endsWith(".html")) { + _contentType = htmlContent; + _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "qml/controls/")); - // We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS. - if (sourceUrl.host().endsWith("youtube.com", Qt::CaseInsensitive)) { - _webSurface->setMaxFps(YOUTUBE_MAX_FPS); - } else { - _webSurface->setMaxFps(DEFAULT_MAX_FPS); - } - - _webSurface->load("WebEntityView.qml", [this](QQmlContext* context, QObject* item) { - item->setProperty("url", _lastSourceUrl); - }); + // We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS. + if (sourceUrl.host().endsWith("youtube.com", Qt::CaseInsensitive)) { + _webSurface->setMaxFps(YOUTUBE_MAX_FPS); } else { - _contentType = qmlContent; - _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath())); - _webSurface->load(_lastSourceUrl); - if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") { - auto tabletScriptingInterface = DependencyManager::get(); - tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data()); - } + _webSurface->setMaxFps(DEFAULT_MAX_FPS); } - }); + + _webSurface->load("WebEntityView.qml", [this](QQmlContext* context, QObject* item) { + item->setProperty("url", _lastSourceUrl); + }); + } else { + _contentType = qmlContent; + _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath())); + _webSurface->load(_lastSourceUrl); + if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") { + auto tabletScriptingInterface = DependencyManager::get(); + tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data()); + } + } } void WebEntityRenderer::handlePointerEvent(const TypedEntityPointer& entity, const PointerEvent& event) { diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index a67eb39670..4b7e7e25a1 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -29,7 +29,6 @@ protected: virtual bool needsRenderUpdate() const override; virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; - virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override; virtual void doRender(RenderArgs* args) override; virtual bool isTransparent() const override; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 837f485417..b6b85783eb 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -267,6 +267,11 @@ void Model::updateRenderItems() { }); } +void Model::setRenderItemsNeedUpdate() { + _renderItemsNeedUpdate = true; + emit requestRenderUpdate(); +} + void Model::initJointTransforms() { if (isLoaded()) { glm::mat4 modelOffset = glm::scale(_scale) * glm::translate(_offset); @@ -814,13 +819,11 @@ void Model::setTextures(const QVariantMap& textures) { _needsUpdateTextures = true; _needsFixupInScene = true; _renderGeometry->setTextures(textures); - emit requestRenderUpdate(); } else { // FIXME(Huffman): Disconnect previously connected lambdas so we don't set textures multiple // after the geometry has finished loading. connect(&_renderWatcher, &GeometryResourceWatcher::finished, this, [this, textures]() { _renderGeometry->setTextures(textures); - emit requestRenderUpdate(); }); } } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 95dc171ff5..a742b46d6a 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -103,7 +103,7 @@ public: bool isLayeredInFront() const { return _isLayeredInFront; } virtual void updateRenderItems(); - void setRenderItemsNeedUpdate() { _renderItemsNeedUpdate = true; emit requestRenderUpdate(); } + void setRenderItemsNeedUpdate(); bool getRenderItemsNeedUpdate() { return _renderItemsNeedUpdate; } AABox getRenderableMeshBound() const; const render::ItemIDs& fetchRenderItemIDs() const;