mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 03:17:02 +02:00
Don't use the KTX cache for local files
This commit is contained in:
parent
d0be19ab41
commit
8cb0d0f8fd
2 changed files with 96 additions and 17 deletions
|
@ -37,7 +37,7 @@
|
||||||
|
|
||||||
#include <NumericalConstants.h>
|
#include <NumericalConstants.h>
|
||||||
#include <shared/NsightHelpers.h>
|
#include <shared/NsightHelpers.h>
|
||||||
|
#include <shared/FileUtils.h>
|
||||||
#include <Finally.h>
|
#include <Finally.h>
|
||||||
#include <Profile.h>
|
#include <Profile.h>
|
||||||
|
|
||||||
|
@ -50,10 +50,8 @@ Q_LOGGING_CATEGORY(trace_resource_parse_image, "trace.resource.parse.image")
|
||||||
Q_LOGGING_CATEGORY(trace_resource_parse_image_raw, "trace.resource.parse.image.raw")
|
Q_LOGGING_CATEGORY(trace_resource_parse_image_raw, "trace.resource.parse.image.raw")
|
||||||
Q_LOGGING_CATEGORY(trace_resource_parse_image_ktx, "trace.resource.parse.image.ktx")
|
Q_LOGGING_CATEGORY(trace_resource_parse_image_ktx, "trace.resource.parse.image.ktx")
|
||||||
|
|
||||||
#if !defined(DISABLE_KTX_CACHE)
|
|
||||||
const std::string TextureCache::KTX_DIRNAME { "ktx_cache" };
|
const std::string TextureCache::KTX_DIRNAME { "ktx_cache" };
|
||||||
const std::string TextureCache::KTX_EXT { "ktx" };
|
const std::string TextureCache::KTX_EXT { "ktx" };
|
||||||
#endif
|
|
||||||
|
|
||||||
static const QString RESOURCE_SCHEME = "resource";
|
static const QString RESOURCE_SCHEME = "resource";
|
||||||
static const QUrl SPECTATOR_CAMERA_FRAME_URL("resource://spectatorCameraFrame");
|
static const QUrl SPECTATOR_CAMERA_FRAME_URL("resource://spectatorCameraFrame");
|
||||||
|
@ -62,9 +60,12 @@ static const QUrl HMD_PREVIEW_FRAME_URL("resource://hmdPreviewFrame");
|
||||||
static const float SKYBOX_LOAD_PRIORITY { 10.0f }; // 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
|
static const float HIGH_MIPS_LOAD_PRIORITY { 9.0f }; // Make sure high mips loads after skybox but before models
|
||||||
|
|
||||||
|
#pragma optimize("", off)
|
||||||
|
|
||||||
TextureCache::TextureCache() {
|
TextureCache::TextureCache() {
|
||||||
#if !defined(DISABLE_KTX_CACHE)
|
|
||||||
_ktxCache->initialize();
|
_ktxCache->initialize();
|
||||||
|
#if defined(DISABLE_KTX_CACHE)
|
||||||
|
_ktxCache->wipe();
|
||||||
#endif
|
#endif
|
||||||
setUnusedResourceCacheSize(0);
|
setUnusedResourceCacheSize(0);
|
||||||
setObjectName("TextureCache");
|
setObjectName("TextureCache");
|
||||||
|
@ -294,6 +295,10 @@ _maxNumPixels(100)
|
||||||
_loaded = true;
|
_loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isLocalUrl(const QUrl& url) {
|
||||||
|
auto scheme = url.scheme();
|
||||||
|
return (scheme == URL_SCHEME_FILE || scheme == URL_SCHEME_QRC || scheme == RESOURCE_SCHEME);
|
||||||
|
}
|
||||||
|
|
||||||
NetworkTexture::NetworkTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels) :
|
NetworkTexture::NetworkTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels) :
|
||||||
Resource(url),
|
Resource(url),
|
||||||
|
@ -387,6 +392,21 @@ void NetworkTexture::makeRequest() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isLocalUrl(_url)) {
|
||||||
|
auto self = _self;
|
||||||
|
QtConcurrent::run(QThreadPool::globalInstance(), [self] {
|
||||||
|
auto resource = self.lock();
|
||||||
|
if (!resource) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkTexture* networkTexture = static_cast<NetworkTexture*>(resource.data());
|
||||||
|
networkTexture->makeLocalRequest();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// We special-handle ktx requests to run 2 concurrent requests right off the bat
|
// We special-handle ktx requests to run 2 concurrent requests right off the bat
|
||||||
PROFILE_ASYNC_BEGIN(resource, "Resource:" + getType(), QString::number(_requestID), { { "url", _url.toString() }, { "activeURL", _activeUrl.toString() } });
|
PROFILE_ASYNC_BEGIN(resource, "Resource:" + getType(), QString::number(_requestID), { { "url", _url.toString() }, { "activeURL", _activeUrl.toString() } });
|
||||||
|
|
||||||
|
@ -435,6 +455,74 @@ void NetworkTexture::makeRequest() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetworkTexture::makeLocalRequest() {
|
||||||
|
const QString scheme = _url.scheme();
|
||||||
|
QString path;
|
||||||
|
if (scheme == URL_SCHEME_FILE) {
|
||||||
|
path = _url.toLocalFile();
|
||||||
|
} else {
|
||||||
|
path = ":" + _url.path();
|
||||||
|
}
|
||||||
|
|
||||||
|
path = FileUtils::selectFile(path);
|
||||||
|
|
||||||
|
auto storage = std::make_shared<storage::FileStorage>(path);
|
||||||
|
std::unique_ptr<ktx::KTX> ktxFile;
|
||||||
|
if (storage) {
|
||||||
|
ktxFile = ktx::KTX::create(storage);
|
||||||
|
}
|
||||||
|
std::shared_ptr<ktx::KTXDescriptor> ktxDescriptor;
|
||||||
|
if (ktxFile) {
|
||||||
|
ktxDescriptor = std::make_shared<ktx::KTXDescriptor>(ktxFile->toDescriptor());
|
||||||
|
}
|
||||||
|
|
||||||
|
gpu::TexturePointer texture;
|
||||||
|
if (ktxDescriptor) {
|
||||||
|
std::string hash;
|
||||||
|
// Create bare ktx in memory
|
||||||
|
auto found = std::find_if(ktxDescriptor->keyValues.begin(), ktxDescriptor->keyValues.end(), [](const ktx::KeyValue& val) -> bool {
|
||||||
|
return val._key.compare(gpu::SOURCE_HASH_KEY) == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (found == ktxDescriptor->keyValues.end() || found->_value.size() != gpu::SOURCE_HASH_BYTES) {
|
||||||
|
hash = _url.toString().toLocal8Bit().toHex().toStdString();
|
||||||
|
} else {
|
||||||
|
// at this point the source hash is in binary 16-byte form
|
||||||
|
// and we need it in a hexadecimal string
|
||||||
|
auto binaryHash = QByteArray(reinterpret_cast<const char*>(found->_value.data()), gpu::SOURCE_HASH_BYTES);
|
||||||
|
hash = binaryHash.toHex().toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto textureCache = DependencyManager::get<TextureCache>();
|
||||||
|
texture = textureCache->getTextureByHash(hash);
|
||||||
|
if (!texture) {
|
||||||
|
texture = gpu::Texture::build(*ktxDescriptor);
|
||||||
|
if (texture) {
|
||||||
|
texture->setKtxBacking(path.toStdString());
|
||||||
|
texture->setSource(path.toStdString());
|
||||||
|
texture = textureCache->cacheTextureByHash(hash, texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!texture) {
|
||||||
|
qCDebug(networking).noquote() << "Failed load local KTX from" << path;
|
||||||
|
QMetaObject::invokeMethod(this, "setImage",
|
||||||
|
Q_ARG(gpu::TexturePointer, nullptr),
|
||||||
|
Q_ARG(int, 0),
|
||||||
|
Q_ARG(int, 0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ktxResourceState = PENDING_MIP_REQUEST;
|
||||||
|
_lowestKnownPopulatedMip = texture->minAvailableMipLevel();
|
||||||
|
QMetaObject::invokeMethod(this, "setImage",
|
||||||
|
Q_ARG(gpu::TexturePointer, texture),
|
||||||
|
Q_ARG(int, texture->getWidth()),
|
||||||
|
Q_ARG(int, texture->getHeight()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool NetworkTexture::handleFailedRequest(ResourceRequest::Result result) {
|
bool NetworkTexture::handleFailedRequest(ResourceRequest::Result result) {
|
||||||
if (!_sourceIsKTX && result == ResourceRequest::Result::RedirectFail) {
|
if (!_sourceIsKTX && result == ResourceRequest::Result::RedirectFail) {
|
||||||
auto newPath = _request->getRelativePathUrl();
|
auto newPath = _request->getRelativePathUrl();
|
||||||
|
@ -750,7 +838,6 @@ void NetworkTexture::handleFinishedInitialLoad() {
|
||||||
|
|
||||||
gpu::TexturePointer texture = textureCache->getTextureByHash(hash);
|
gpu::TexturePointer texture = textureCache->getTextureByHash(hash);
|
||||||
|
|
||||||
#if !defined(DISABLE_KTX_CACHE)
|
|
||||||
if (!texture) {
|
if (!texture) {
|
||||||
auto ktxFile = textureCache->_ktxCache->getFile(hash);
|
auto ktxFile = textureCache->_ktxCache->getFile(hash);
|
||||||
if (ktxFile) {
|
if (ktxFile) {
|
||||||
|
@ -763,9 +850,8 @@ void NetworkTexture::handleFinishedInitialLoad() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (!texture) {
|
|
||||||
|
|
||||||
|
if (!texture) {
|
||||||
auto memKtx = ktx::KTX::createBare(*header, keyValues);
|
auto memKtx = ktx::KTX::createBare(*header, keyValues);
|
||||||
if (!memKtx) {
|
if (!memKtx) {
|
||||||
qWarning() << " Ktx could not be created, bailing";
|
qWarning() << " Ktx could not be created, bailing";
|
||||||
|
@ -778,7 +864,6 @@ void NetworkTexture::handleFinishedInitialLoad() {
|
||||||
|
|
||||||
// Move ktx to file
|
// Move ktx to file
|
||||||
const char* data = reinterpret_cast<const char*>(memKtx->_storage->data());
|
const char* data = reinterpret_cast<const char*>(memKtx->_storage->data());
|
||||||
#if !defined(DISABLE_KTX_CACHE)
|
|
||||||
size_t length = memKtx->_storage->size();
|
size_t length = memKtx->_storage->size();
|
||||||
cache::FilePointer file;
|
cache::FilePointer file;
|
||||||
auto& ktxCache = textureCache->_ktxCache;
|
auto& ktxCache = textureCache->_ktxCache;
|
||||||
|
@ -790,14 +875,11 @@ void NetworkTexture::handleFinishedInitialLoad() {
|
||||||
Q_ARG(int, 0));
|
Q_ARG(int, 0));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
auto newKtxDescriptor = memKtx->toDescriptor();
|
auto newKtxDescriptor = memKtx->toDescriptor();
|
||||||
|
|
||||||
texture = gpu::Texture::build(newKtxDescriptor);
|
texture = gpu::Texture::build(newKtxDescriptor);
|
||||||
#if !defined(DISABLE_KTX_CACHE)
|
|
||||||
texture->setKtxBacking(file);
|
texture->setKtxBacking(file);
|
||||||
#endif
|
|
||||||
texture->setSource(filename);
|
texture->setSource(filename);
|
||||||
|
|
||||||
auto& images = originalKtxDescriptor->images;
|
auto& images = originalKtxDescriptor->images;
|
||||||
|
@ -940,7 +1022,6 @@ void ImageReader::read() {
|
||||||
// If we already have a live texture with the same hash, use it
|
// If we already have a live texture with the same hash, use it
|
||||||
auto texture = textureCache->getTextureByHash(hash);
|
auto texture = textureCache->getTextureByHash(hash);
|
||||||
|
|
||||||
#if !defined(DISABLE_KTX_CACHE)
|
|
||||||
// If there is no live texture, check if there's an existing KTX file
|
// If there is no live texture, check if there's an existing KTX file
|
||||||
if (!texture) {
|
if (!texture) {
|
||||||
auto ktxFile = textureCache->_ktxCache->getFile(hash);
|
auto ktxFile = textureCache->_ktxCache->getFile(hash);
|
||||||
|
@ -953,7 +1034,6 @@ void ImageReader::read() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// If we found the texture either because it's in use or via KTX deserialization,
|
// If we found the texture either because it's in use or via KTX deserialization,
|
||||||
// set the image and return immediately.
|
// set the image and return immediately.
|
||||||
|
@ -989,7 +1069,6 @@ void ImageReader::read() {
|
||||||
|
|
||||||
// Save the image into a KTXFile
|
// Save the image into a KTXFile
|
||||||
if (texture && textureCache) {
|
if (texture && textureCache) {
|
||||||
#if !defined(DISABLE_KTX_CACHE)
|
|
||||||
auto memKtx = gpu::Texture::serialize(*texture);
|
auto memKtx = gpu::Texture::serialize(*texture);
|
||||||
|
|
||||||
// Move the texture into a memory mapped file
|
// Move the texture into a memory mapped file
|
||||||
|
@ -1006,7 +1085,7 @@ void ImageReader::read() {
|
||||||
} else {
|
} else {
|
||||||
qCWarning(modelnetworking) << "Unable to serialize texture to KTX " << _url;
|
qCWarning(modelnetworking) << "Unable to serialize texture to KTX " << _url;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
// We replace the texture with the one stored in the cache. This deals with the possible race condition of two different
|
// We replace the texture with the one stored in the cache. This deals with the possible race condition of two different
|
||||||
// images with the same hash being loaded concurrently. Only one of them will make it into the cache by hash first and will
|
// images with the same hash being loaded concurrently. Only one of them will make it into the cache by hash first and will
|
||||||
// be the winner
|
// be the winner
|
||||||
|
|
|
@ -70,6 +70,7 @@ public slots:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void makeRequest() override;
|
void makeRequest() override;
|
||||||
|
void makeLocalRequest();
|
||||||
|
|
||||||
virtual bool isCacheable() const override { return _loaded; }
|
virtual bool isCacheable() const override { return _loaded; }
|
||||||
|
|
||||||
|
@ -194,12 +195,11 @@ private:
|
||||||
TextureCache();
|
TextureCache();
|
||||||
virtual ~TextureCache();
|
virtual ~TextureCache();
|
||||||
|
|
||||||
#if !defined(DISABLE_KTX_CACHE)
|
|
||||||
static const std::string KTX_DIRNAME;
|
static const std::string KTX_DIRNAME;
|
||||||
static const std::string KTX_EXT;
|
static const std::string KTX_EXT;
|
||||||
|
|
||||||
std::shared_ptr<cache::FileCache> _ktxCache { std::make_shared<KTXCache>(KTX_DIRNAME, KTX_EXT) };
|
std::shared_ptr<cache::FileCache> _ktxCache { std::make_shared<KTXCache>(KTX_DIRNAME, KTX_EXT) };
|
||||||
#endif
|
|
||||||
// Map from image hashes to texture weak pointers
|
// Map from image hashes to texture weak pointers
|
||||||
std::unordered_map<std::string, std::weak_ptr<gpu::Texture>> _texturesByHashes;
|
std::unordered_map<std::string, std::weak_ptr<gpu::Texture>> _texturesByHashes;
|
||||||
std::mutex _texturesByHashesMutex;
|
std::mutex _texturesByHashesMutex;
|
||||||
|
|
Loading…
Reference in a new issue