trying to get hashes working

This commit is contained in:
SamGondelman 2019-02-05 18:27:27 -08:00
parent 3ee448a89a
commit 9193704173
6 changed files with 89 additions and 30 deletions

View file

@ -417,7 +417,7 @@ MaterialCache& MaterialCache::instance() {
}
NetworkMaterialResourcePointer MaterialCache::getMaterial(const QUrl& url) {
return ResourceCache::getResource(url, QUrl()).staticCast<NetworkMaterialResource>();
return ResourceCache::getResource(url).staticCast<NetworkMaterialResource>();
}
QSharedPointer<Resource> MaterialCache::createResource(const QUrl& url) {

View file

@ -40,6 +40,50 @@ public:
bool combineParts;
};
// From: https://stackoverflow.com/questions/41145012/how-to-hash-qvariant
class QVariantHasher {
public:
QVariantHasher() : buff(&bb), ds(&buff) {
bb.reserve(1000);
buff.open(QIODevice::WriteOnly);
}
uint hash(const QVariant& v) {
buff.seek(0);
ds << v;
return qHashBits(bb.constData(), buff.pos());
}
private:
QByteArray bb;
QBuffer buff;
QDataStream ds;
};
namespace std {
template <>
struct hash<QVariantHash> {
size_t operator()(const QVariantHash& a) const {
QVariantHasher hasher;
return hasher.hash(a);
}
};
template <>
struct hash<QUrl> {
size_t operator()(const QUrl& a) const {
return qHash(a);
}
};
template <>
struct hash<GeometryExtra> {
size_t operator()(const GeometryExtra& a) const {
size_t result = 0;
hash_combine(result, a.mapping, a.textureBaseUrl, a.combineParts);
return result;
}
};
}
QUrl resolveTextureBaseUrl(const QUrl& url, const QUrl& textureBaseUrl) {
return textureBaseUrl.isValid() ? textureBaseUrl : url;
}
@ -110,7 +154,7 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) {
GeometryExtra extra { _mapping, _textureBaseUrl, false };
// Get the raw GeometryResource
_geometryResource = modelCache->getResource(url, QUrl(), &extra).staticCast<GeometryResource>();
_geometryResource = modelCache->getResource(url, QUrl(), &extra, std::hash<GeometryExtra>()(extra)).staticCast<GeometryResource>();
// Avoid caching nested resources - their references will be held by the parent
_geometryResource->_isCacheable = false;
@ -355,7 +399,7 @@ GeometryResource::Pointer ModelCache::getGeometryResource(const QUrl& url,
const QVariantHash& mapping, const QUrl& textureBaseUrl) {
bool combineParts = true;
GeometryExtra geometryExtra = { mapping, textureBaseUrl, combineParts };
GeometryResource::Pointer resource = getResource(url, QUrl(), &geometryExtra).staticCast<GeometryResource>();
GeometryResource::Pointer resource = getResource(url, QUrl(), &geometryExtra, std::hash<GeometryExtra>()(geometryExtra)).staticCast<GeometryResource>();
if (resource) {
if (resource->isLoaded() && resource->shouldSetTextures()) {
resource->setTextures();
@ -368,7 +412,7 @@ GeometryResource::Pointer ModelCache::getCollisionGeometryResource(const QUrl& u
const QVariantHash& mapping, const QUrl& textureBaseUrl) {
bool combineParts = false;
GeometryExtra geometryExtra = { mapping, textureBaseUrl, combineParts };
GeometryResource::Pointer resource = getResource(url, QUrl(), &geometryExtra).staticCast<GeometryResource>();
GeometryResource::Pointer resource = getResource(url, QUrl(), &geometryExtra, std::hash<GeometryExtra>()(geometryExtra)).staticCast<GeometryResource>();
if (resource) {
if (resource->isLoaded() && resource->shouldSetTextures()) {
resource->setTextures();

View file

@ -21,7 +21,7 @@ ShaderCache& ShaderCache::instance() {
}
NetworkShaderPointer ShaderCache::getShader(const QUrl& url) {
return ResourceCache::getResource(url, QUrl()).staticCast<NetworkShader>();
return ResourceCache::getResource(url).staticCast<NetworkShader>();
}
QSharedPointer<Resource> ShaderCache::createResource(const QUrl& url) {

View file

@ -194,10 +194,28 @@ public:
int maxNumPixels;
};
namespace std {
template <>
struct hash<QByteArray> {
size_t operator()(const QByteArray& a) const {
return qHash(a);
}
};
template <>
struct hash<TextureExtra> {
size_t operator()(const TextureExtra& a) const {
size_t result = 0;
hash_combine(result, (int)a.type, a.content, a.maxNumPixels);
return result;
}
};
}
ScriptableResource* TextureCache::prefetch(const QUrl& url, int type, int maxNumPixels) {
auto byteArray = QByteArray();
TextureExtra extra = { (image::TextureUsage::Type)type, byteArray, maxNumPixels };
return ResourceCache::prefetch(url, &extra);
return ResourceCache::prefetch(url, &extra, std::hash<TextureExtra>()(extra));
}
NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels) {
@ -211,7 +229,7 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUs
modifiedUrl.setQuery(query.toString());
}
TextureExtra extra = { type, content, maxNumPixels };
return ResourceCache::getResource(modifiedUrl, QUrl(), &extra).staticCast<NetworkTexture>();
return ResourceCache::getResource(modifiedUrl, QUrl(), &extra, std::hash<TextureExtra>()(extra)).staticCast<NetworkTexture>();
}
gpu::TexturePointer TextureCache::getTextureByHash(const std::string& hash) {

View file

@ -158,8 +158,8 @@ void ScriptableResourceCache::updateTotalSize(const qint64& deltaSize) {
_resourceCache->updateTotalSize(deltaSize);
}
ScriptableResource* ScriptableResourceCache::prefetch(const QUrl& url, void* extra) {
return _resourceCache->prefetch(url, extra);
ScriptableResource* ScriptableResourceCache::prefetch(const QUrl& url, void* extra, size_t extraHash) {
return _resourceCache->prefetch(url, extra, extraHash);
}
@ -211,20 +211,20 @@ void ScriptableResource::disconnectHelper() {
}
}
ScriptableResource* ResourceCache::prefetch(const QUrl& url, void* extra) {
ScriptableResource* ResourceCache::prefetch(const QUrl& url, void* extra, size_t extraHash) {
ScriptableResource* result = nullptr;
if (QThread::currentThread() != thread()) {
// Must be called in thread to ensure getResource returns a valid pointer
BLOCKING_INVOKE_METHOD(this, "prefetch",
Q_RETURN_ARG(ScriptableResource*, result),
Q_ARG(QUrl, url), Q_ARG(void*, extra));
Q_ARG(QUrl, url), Q_ARG(void*, extra), Q_ARG(size_t, extraHash));
return result;
}
result = new ScriptableResource(url);
auto resource = getResource(url, QUrl(), extra);
auto resource = getResource(url, QUrl(), extra, extraHash);
result->_resource = resource;
result->setObjectName(url.toString());
@ -298,7 +298,7 @@ void ResourceCache::refreshAll() {
clearUnusedResources();
resetUnusedResourceCounter();
QHash<QUrl, QHash<int, QWeakPointer<Resource>>> allResources;
QHash<QUrl, QHash<size_t, QWeakPointer<Resource>>> allResources;
{
QReadLocker locker(&_resourcesLock);
allResources = _resources;
@ -343,13 +343,8 @@ void ResourceCache::setRequestLimit(uint32_t limit) {
}
}
QSharedPointer<Resource> ResourceCache::getResource(const QUrl& url, const QUrl& fallback, void* extra, int extraHash) {
QSharedPointer<Resource> ResourceCache::getResource(const QUrl& url, const QUrl& fallback, void* extra, size_t extraHash) {
QSharedPointer<Resource> resource;
if (extra && extraHash < 0) {
qDebug() << "ResourceCache::getResource: ERROR! Non-null extra, but invalid extraHash";
return resource;
}
{
QReadLocker locker(&_resourcesLock);
auto& resourcesWithExtraHash = _resources[url];
@ -553,8 +548,8 @@ bool ResourceCache::attemptHighestPriorityRequest() {
static int requestID = 0;
Resource::Resource(const Resource& other) :
QObject(),
_url(other._url),
_extraHash(other._extraHash),
_effectiveBaseURL(other._effectiveBaseURL),
_activeUrl(other._activeUrl),
_requestByteRange(other._requestByteRange),
@ -566,7 +561,8 @@ Resource::Resource(const Resource& other) :
_bytesReceived(other._bytesReceived),
_bytesTotal(other._bytesTotal),
_bytes(other._bytes),
_requestID(++requestID) {
_requestID(++requestID),
_extraHash(other._extraHash) {
if (!other._loaded) {
_startedLoading = false;
}

View file

@ -231,15 +231,16 @@ protected slots:
// Prefetches a resource to be held by the QScriptEngine.
// Left as a protected member so subclasses can overload prefetch
// and delegate to it (see TextureCache::prefetch(const QUrl&, int).
ScriptableResource* prefetch(const QUrl& url, void* extra);
ScriptableResource* prefetch(const QUrl& url, void* extra, size_t extraHash);
// FIXME: The return type is not recognized by JavaScript.
/// Loads a resource from the specified URL and returns it.
/// If the caller is on a different thread than the ResourceCache,
/// returns an empty smart pointer and loads its asynchronously.
/// \param fallback a fallback URL to load if the desired one is unavailable
/// \param extra extra data to pass to the creator, if appropriate
QSharedPointer<Resource> getResource(const QUrl& url, const QUrl& fallback = QUrl(), void* extra = NULL, int extraHash = -1);
// FIXME: std::numeric_limits<size_t>::max() could be a valid extraHash
QSharedPointer<Resource> getResource(const QUrl& url, const QUrl& fallback = QUrl()) { return getResource(url, fallback, nullptr, std::numeric_limits<size_t>::max()); }
QSharedPointer<Resource> getResource(const QUrl& url, const QUrl& fallback, void* extra, size_t extraHash);
private slots:
void clearATPAssets();
@ -250,7 +251,7 @@ protected:
// which should be a QScriptEngine with ScriptableResource registered, so that
// the QScriptEngine will delete the pointer when it is garbage collected.
// JSDoc is provided on more general function signature.
Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url) { return prefetch(url, nullptr); }
Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url) { return prefetch(url, nullptr, std::numeric_limits<size_t>::max()); }
/// Creates a new resource.
virtual QSharedPointer<Resource> createResource(const QUrl& url) = 0;
@ -277,7 +278,7 @@ private:
void resetResourceCounters();
// Resources
QHash<QUrl, QHash<int, QWeakPointer<Resource>>> _resources;
QHash<QUrl, QHash<size_t, QWeakPointer<Resource>>> _resources;
QReadWriteLock _resourcesLock { QReadWriteLock::Recursive };
int _lastLRUKey = 0;
@ -331,10 +332,10 @@ public:
* Prefetches a resource.
* @function ResourceCache.prefetch
* @param {string} url - URL of the resource to prefetch.
* @param {object} [extra=null]
* @returns {ResourceObject}
*/
Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, void* extra = nullptr);
Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url) { return prefetch(url, nullptr, std::numeric_limits<size_t>::max()); }
Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, void* extra, size_t extraHash);
signals:
@ -416,7 +417,7 @@ public:
unsigned int getDownloadAttemptsRemaining() { return _attemptsRemaining; }
virtual void setExtra(void* extra) {};
void setExtraHash(int extraHash) { _extraHash = extraHash; }
void setExtraHash(size_t extraHash) { _extraHash = extraHash; }
signals:
/// Fired when the resource begins downloading.
@ -495,7 +496,7 @@ protected:
int _requestID;
ResourceRequest* _request{ nullptr };
int _extraHash { -1 };
size_t _extraHash;
public slots:
void handleDownloadProgress(uint64_t bytesReceived, uint64_t bytesTotal);