diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 9b23b4e695..3b8ae508eb 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -324,11 +324,11 @@ public: void reset() override { } protected: - std::shared_ptr maybeOpenFile(); + std::shared_ptr maybeOpenFile() const; - std::mutex _cacheFileCreateMutex; - std::mutex _cacheFileWriteMutex; - std::weak_ptr _cacheFile; + mutable std::mutex _cacheFileCreateMutex; + mutable std::mutex _cacheFileWriteMutex; + mutable std::weak_ptr _cacheFile; std::string _filename; std::atomic _minMipLevelAvailable; diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index efff6c7afe..d2f93c0036 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -128,7 +128,7 @@ KtxStorage::KtxStorage(const std::string& filename) : _filename(filename) { } } -std::shared_ptr KtxStorage::maybeOpenFile() { +std::shared_ptr KtxStorage::maybeOpenFile() const { std::shared_ptr file = _cacheFile.lock(); if (file) { return file; @@ -154,7 +154,8 @@ PixelsPointer KtxStorage::getMipFace(uint16 level, uint8 face) const { auto faceOffset = _ktxDescriptor->getMipFaceTexelsOffset(level, face); auto faceSize = _ktxDescriptor->getMipFaceTexelsSize(level, face); if (faceSize != 0 && faceOffset != 0) { - result = std::make_shared(_filename.c_str())->createView(faceSize, faceOffset)->toMemoryStorage(); + auto file = maybeOpenFile(); + result = file->createView(faceSize, faceOffset)->toMemoryStorage(); } return result; } diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 55704236e3..961b3b3e7b 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -50,7 +50,8 @@ Q_LOGGING_CATEGORY(trace_resource_parse_image_ktx, "trace.resource.parse.image.k const std::string TextureCache::KTX_DIRNAME { "ktx_cache" }; const std::string TextureCache::KTX_EXT { "ktx" }; -static const int SKYBOX_LOAD_PRIORITY { 10 }; // Make sure skybox loads first +static const float SKYBOX_LOAD_PRIORITY { 10.0f }; // Make sure skybox loads first +static const float HIGH_MIPS_LOAD_PRIORITY { 9.0f }; // Make sure high mips loads after skybox but before models TextureCache::TextureCache() : _ktxCache(KTX_DIRNAME, KTX_EXT) { @@ -261,9 +262,6 @@ QSharedPointer TextureCache::createResource(const QUrl& url, const QSh auto content = textureExtra ? textureExtra->content : QByteArray(); auto maxNumPixels = textureExtra ? textureExtra->maxNumPixels : ABSOLUTE_MAX_TEXTURE_NUM_PIXELS; NetworkTexture* texture = new NetworkTexture(url, type, content, maxNumPixels); - if (type == image::TextureUsage::CUBE_TEXTURE) { - texture->setLoadPriority(this, SKYBOX_LOAD_PRIORITY); - } return QSharedPointer(texture, &Resource::deleter); } @@ -276,6 +274,12 @@ NetworkTexture::NetworkTexture(const QUrl& url, image::TextureUsage::Type type, _textureSource = std::make_shared(); _lowestRequestedMipLevel = 0; + if (type == image::TextureUsage::CUBE_TEXTURE) { + setLoadPriority(this, SKYBOX_LOAD_PRIORITY); + } else if (_sourceIsKTX) { + setLoadPriority(this, HIGH_MIPS_LOAD_PRIORITY); + } + if (!url.isValid()) { _loaded = true; } @@ -330,6 +334,22 @@ private: int _maxNumPixels; }; +NetworkTexture::~NetworkTexture() { + if (_ktxHeaderRequest || _ktxMipRequest) { + if (_ktxHeaderRequest) { + _ktxHeaderRequest->disconnect(this); + _ktxHeaderRequest->deleteLater(); + _ktxHeaderRequest = nullptr; + } + if (_ktxMipRequest) { + _ktxMipRequest->disconnect(this); + _ktxMipRequest->deleteLater(); + _ktxMipRequest = nullptr; + } + ResourceCache::requestCompleted(_self); + } +} + const uint16_t NetworkTexture::NULL_MIP_LEVEL = std::numeric_limits::max(); void NetworkTexture::makeRequest() { if (!_sourceIsKTX) { @@ -394,12 +414,18 @@ void NetworkTexture::startRequestForNextMipLevel() { } if (_ktxResourceState == WAITING_FOR_MIP_REQUEST) { + auto self = _self.lock(); + if (!self) { + return; + } + _ktxResourceState = PENDING_MIP_REQUEST; init(); - setLoadPriority(this, -static_cast(_originalKtxDescriptor->header.numberOfMipmapLevels) + _lowestKnownPopulatedMip); + float priority = -(float)_originalKtxDescriptor->header.numberOfMipmapLevels + (float)_lowestKnownPopulatedMip; + setLoadPriority(this, priority); _url.setFragment(QString::number(_lowestKnownPopulatedMip - 1)); - TextureCache::attemptRequest(_self); + TextureCache::attemptRequest(self); } } @@ -468,19 +494,16 @@ void NetworkTexture::ktxMipRequestFinished() { texture->assignStoredMip(_ktxMipLevelRangeInFlight.first, _ktxMipRequest->getData().size(), reinterpret_cast(_ktxMipRequest->getData().data())); _lowestKnownPopulatedMip = _textureSource->getGPUTexture()->minAvailableMipLevel(); - } - else { + } else { qWarning(networking) << "Trying to update mips but texture is null"; } finishedLoading(true); _ktxResourceState = WAITING_FOR_MIP_REQUEST; - } - else { + } else { finishedLoading(false); if (handleFailedRequest(_ktxMipRequest->getResult())) { _ktxResourceState = PENDING_MIP_REQUEST; - } - else { + } else { qWarning(networking) << "Failed to load mip: " << _url; _ktxResourceState = FAILED_TO_LOAD; } @@ -492,8 +515,7 @@ void NetworkTexture::ktxMipRequestFinished() { if (_ktxResourceState == WAITING_FOR_MIP_REQUEST && _lowestRequestedMipLevel < _lowestKnownPopulatedMip) { startRequestForNextMipLevel(); } - } - else { + } else { qWarning() << "Mip request finished in an unexpected state: " << _ktxResourceState; } } diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 1e61b9ecee..c7a7799216 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -46,6 +46,7 @@ class NetworkTexture : public Resource, public Texture { public: NetworkTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels); + ~NetworkTexture() override; QString getType() const override { return "NetworkTexture"; } diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index d4c7d63ee5..51c8d8554a 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -344,7 +344,7 @@ class Resource : public QObject { public: Resource(const QUrl& url); - ~Resource(); + virtual ~Resource(); virtual QString getType() const { return "Resource"; }