summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/engine/Qt3DSRenderRuntimeBinding.cpp57
-rw-r--r--src/runtime/Qt3DSApplication.cpp26
-rw-r--r--src/runtimerender/Qt3DSRenderInputStreamFactory.cpp9
-rw-r--r--src/runtimerender/Qt3DSRenderInputStreamFactory.h1
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderImage.cpp18
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderImage.h4
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp8
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp255
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h12
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp20
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.h2
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp74
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h1
13 files changed, 336 insertions, 151 deletions
diff --git a/src/engine/Qt3DSRenderRuntimeBinding.cpp b/src/engine/Qt3DSRenderRuntimeBinding.cpp
index 2a6cbde..50ef3df 100644
--- a/src/engine/Qt3DSRenderRuntimeBinding.cpp
+++ b/src/engine/Qt3DSRenderRuntimeBinding.cpp
@@ -703,7 +703,7 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
nvvector<SGraphObject *>::iterator end = vec.end();
while (it != end) {
if ((*it)->m_Type == type)
- callable(static_cast<T*>(*it));
+ callable(static_cast<T*>(*it), preferKtx());
++it;
}
}
@@ -711,12 +711,14 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
void PostLoadStep()
{
IBufferManager &mgr = m_Context->GetBufferManager();
- forAllObjects<SImage>(m_GraphObjectList, GraphObjectTypes::Image, [&mgr](SImage *image){
+ forAllObjects<SImage>(m_GraphObjectList, GraphObjectTypes::Image,
+ [&mgr](SImage *image, bool preferKtx){
if (image->m_ImagePath.IsValid() && qt3ds::runtime::isImagePath(
image->m_ImagePath.c_str())) {
const bool ibl = image->m_MappingMode == ImageMappingModes::LightProbe;
- image->m_LoadedTextureData = mgr.CreateReloadableImage(image->m_ImagePath,
- false, ibl);
+ const auto unified = IBufferManager::resolveImagePath(
+ QString::fromLatin1(image->m_ImagePath.c_str()), preferKtx);
+ image->m_LoadedTextureData = mgr.CreateReloadableImage(unified, false, ibl);
image->m_LoadedTextureData->m_callbacks.push_back(image);
}
});
@@ -930,8 +932,8 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
const QVector<QString> slideSourcePaths = inParser->GetSlideSourcePaths();
IBufferManager &theManager(m_Context->m_Context->GetBufferManager());
// List of image paths to be loaded in parallel at the end.
- eastl::vector<CRegisteredString> theSourcePathList;
- eastl::vector<CRegisteredString> iblList;
+ QVector<CRegisteredString> theSourcePathList;
+ QVector<CRegisteredString> iblList;
for (QT3DSU32 idx = 0, end = theSourcePathData.size(); idx < end; ++idx) {
const eastl::string &theValue = theSourcePathData[idx];
CRegisteredString theSourcePath =
@@ -962,23 +964,25 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
}
}
}
-
+ const auto preferKtx = theScene->m_Presentation->m_preferKTX;
+ const auto flipCompressed = theScene->m_Presentation->m_flipCompressedTextures;
+ const auto contextType = m_Context->m_Context->GetRenderContext().GetRenderContextType();
// Fire off parallel loading of the source paths
- QT3DSU64 imageBatchId = m_Context->m_Context->GetImageBatchLoader().LoadImageBatch(
+ auto &batchLoader = m_Context->m_Context->GetImageBatchLoader();
+ theSourcePathList = IBufferManager::resolveSourcePaths(*m_Context->m_StringTable,
+ theSourcePathList, preferKtx);
+ iblList = IBufferManager::resolveSourcePaths(*m_Context->m_StringTable, iblList,
+ preferKtx);
+
+ QT3DSU64 imageBatchId = batchLoader.LoadImageBatch(
toConstDataRef(theSourcePathList.data(), theSourcePathList.size()),
- CRegisteredString(), nullptr, m_Context->m_Context->GetRenderContext()
- .GetRenderContextType(),
- theScene->m_Presentation->m_preferKTX, false,
- theScene->m_Presentation->m_flipCompressedTextures);
- QT3DSU64 iblImageBatchId = m_Context->m_Context->GetImageBatchLoader().LoadImageBatch(
+ CRegisteredString(), nullptr, contextType, false, flipCompressed);
+ QT3DSU64 iblImageBatchId = batchLoader.LoadImageBatch(
toConstDataRef(iblList.data(), iblList.size()),
- CRegisteredString(), nullptr, m_Context->m_Context->GetRenderContext()
- .GetRenderContextType(),
- theScene->m_Presentation->m_preferKTX, true,
- theScene->m_Presentation->m_flipCompressedTextures);
- m_Context->m_Context->GetImageBatchLoader().BlockUntilLoaded(
+ CRegisteredString(), nullptr, contextType, true, flipCompressed);
+ batchLoader.BlockUntilLoaded(
static_cast<TImageBatchId>(imageBatchId));
- m_Context->m_Context->GetImageBatchLoader().BlockUntilLoaded(
+ batchLoader.BlockUntilLoaded(
static_cast<TImageBatchId>(iblImageBatchId));
theIScene = QT3DS_NEW(m_Context->GetAllocator(),
@@ -1123,10 +1127,8 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
// this means graphics have been initialized
eastl::string theSourcePathStr;
IBufferManager &theManager(m_Context->m_Context->GetBufferManager());
- nvvector<CRegisteredString> imagePathList(m_Context->GetAllocator(),
- "imagePathList");
- nvvector<CRegisteredString> iblImagePathList(m_Context->GetAllocator(),
- "iblImagePathList");
+ QVector<CRegisteredString> imagePathList;
+ QVector<CRegisteredString> iblImagePathList;
for (QT3DSU32 idx = 0, end = m_SourcePaths.size(); idx < end; ++idx) {
theSourcePathStr.assign(m_SourcePaths[idx].first);
bool hasTransparency = m_SourcePaths[idx].second.first;
@@ -1159,12 +1161,17 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
{
QT3DS_PERF_SCOPED_TIMER(m_Context->m_CoreContext->GetPerfTimer(),
"Binding: Initial Batch Image Load")
+ auto &batchLoader = m_Context->m_Context->GetImageBatchLoader();
+ imagePathList = IBufferManager::resolveSourcePaths(*m_Context->m_StringTable,
+ imagePathList, pktx);
+ iblImagePathList = IBufferManager::resolveSourcePaths(*m_Context->m_StringTable,
+ iblImagePathList, pktx);
- m_Context->m_Context->GetImageBatchLoader().LoadImageBatch(
+ batchLoader.LoadImageBatch(
toConstDataRef(imagePathList.data(), imagePathList.size()),
CRegisteredString(), nullptr, m_Context->m_Context->GetRenderContext()
.GetRenderContextType(), pktx, false);
- m_Context->m_Context->GetImageBatchLoader().LoadImageBatch(
+ batchLoader.LoadImageBatch(
toConstDataRef(iblImagePathList.data(), iblImagePathList.size()),
CRegisteredString(), nullptr, m_Context->m_Context->GetRenderContext()
.GetRenderContextType(), pktx, true);
diff --git a/src/runtime/Qt3DSApplication.cpp b/src/runtime/Qt3DSApplication.cpp
index 6bc7b1b..5c6dbb7 100644
--- a/src/runtime/Qt3DSApplication.cpp
+++ b/src/runtime/Qt3DSApplication.cpp
@@ -350,11 +350,12 @@ struct STextureUploadRenderTask : public IRenderTask, public IImageLoadListener
if (!m_deleteSet.isEmpty())
m_bufferManager.unloadSet(m_deleteSet);
if (!m_uploadSet.isEmpty()) {
- nvvector<CRegisteredString> sourcePaths(m_bufferManager.GetStringTable().GetAllocator(),
- "TempSourcePathList");
+ QVector<CRegisteredString> sourcePaths;
for (auto &s : qAsConst(m_uploadSet))
sourcePaths.push_back(m_bufferManager.GetStringTable().RegisterStr(s));
- QT3DSU32 id = m_batchLoader.LoadImageBatch(sourcePaths, CRegisteredString(),
+ QT3DSU32 id = m_batchLoader.LoadImageBatch(toConstDataRef(sourcePaths.data(),
+ sourcePaths.size()),
+ CRegisteredString(),
this, m_type, m_preferKtx, false);
if (id) {
m_batches[id] = m_uploadSet;
@@ -362,11 +363,12 @@ struct STextureUploadRenderTask : public IRenderTask, public IImageLoadListener
}
}
if (!m_uploadWaitSet.isEmpty()) {
- nvvector<CRegisteredString> sourcePaths(m_bufferManager.GetStringTable().GetAllocator(),
- "TempSourcePathList");
+ QVector<CRegisteredString> sourcePaths;
for (auto &s : qAsConst(m_uploadWaitSet))
sourcePaths.push_back(m_bufferManager.GetStringTable().RegisterStr(s));
- QT3DSU32 id = m_batchLoader.LoadImageBatch(sourcePaths, CRegisteredString(),
+ QT3DSU32 id = m_batchLoader.LoadImageBatch(toConstDataRef(sourcePaths.data(),
+ sourcePaths.size()),
+ CRegisteredString(),
this, m_type, m_preferKtx, false);
if (id) {
m_batchLoader.BlockUntilLoaded(id);
@@ -382,14 +384,16 @@ struct STextureUploadRenderTask : public IRenderTask, public IImageLoadListener
m_uploadWaitSet.unite(set);
else
m_uploadSet.unite(set);
- m_deleteSet.subtract(set);
+ const auto unified = IBufferManager::resolveImageSet(set, m_preferKtx);
+ m_deleteSet.subtract(unified);
}
void remove(const QSet<QString> &set)
{
+ const auto unified = IBufferManager::resolveImageSet(set, m_preferKtx);
QMutexLocker loc(&m_updateMutex);
- m_uploadSet.subtract(set);
- m_uploadWaitSet.subtract(set);
- m_deleteSet.unite(set);
+ m_uploadSet.subtract(unified);
+ m_uploadWaitSet.subtract(unified);
+ m_deleteSet.unite(unified);
}
bool persistent() const override
{
@@ -402,7 +406,7 @@ struct STextureUploadRenderTask : public IRenderTask, public IImageLoadListener
}
void OnImageBatchComplete(QT3DSU64 inBatch) override
{
- m_bufferManager.loadSet(m_batches[inBatch]);
+ m_bufferManager.loadSet(m_batches[inBatch], m_flipCompressedTextures);
}
};
diff --git a/src/runtimerender/Qt3DSRenderInputStreamFactory.cpp b/src/runtimerender/Qt3DSRenderInputStreamFactory.cpp
index 1a418b1..5b02164 100644
--- a/src/runtimerender/Qt3DSRenderInputStreamFactory.cpp
+++ b/src/runtimerender/Qt3DSRenderInputStreamFactory.cpp
@@ -205,6 +205,15 @@ struct SFactory : public IInputStreamFactory
}
return false;
}
+ bool GetPathForStream(IRefCountedInputStream *stream, QString &outFile) override
+ {
+ if (stream) {
+ SInputStream *theRealStream = static_cast<SInputStream *>(stream);
+ outFile = theRealStream->m_Path;
+ return true;
+ }
+ return false;
+ }
};
}
diff --git a/src/runtimerender/Qt3DSRenderInputStreamFactory.h b/src/runtimerender/Qt3DSRenderInputStreamFactory.h
index e82134b..fdc9e75 100644
--- a/src/runtimerender/Qt3DSRenderInputStreamFactory.h
+++ b/src/runtimerender/Qt3DSRenderInputStreamFactory.h
@@ -57,6 +57,7 @@ namespace render {
// else returns false
virtual bool GetPathForFile(const QString &inFilename, QString &outFile,
bool inQuiet = false) = 0;
+ virtual bool GetPathForStream(IRefCountedInputStream *stream, QString &outFile) = 0;
// Create an input stream factory using this foundation and an platform-optional app
// directory
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderImage.cpp b/src/runtimerender/graphobjects/Qt3DSRenderImage.cpp
index 44e7f12..458f3bf 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderImage.cpp
+++ b/src/runtimerender/graphobjects/Qt3DSRenderImage.cpp
@@ -67,7 +67,8 @@ static void HandleOffscreenResult(SImage &theImage, SImageTextureData &newImage,
}
bool SImage::ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager &inRenderManager,
- IRenderPluginManager &inPluginManager, bool forIbl, bool flipCompressed)
+ IRenderPluginManager &inPluginManager, bool preferKtx, bool forIbl,
+ bool flipCompressed)
{
bool wasDirty = m_Flags.IsDirty();
@@ -93,17 +94,22 @@ bool SImage::ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager
}
}
+ // Do not recheck image path if we are not dirty and we already have a texture
+ if (!wasDirty)
+ newImage.m_Texture = m_TextureData.m_Texture;
+
if (newImage.m_Texture == nullptr) {
m_LastFrameOffscreenRenderer = nullptr;
if (m_ImagePath.IsValid() && !m_OffscreenRendererId.IsValid()
&& !inRenderManager.HasOffscreenRenderer(m_ImagePath)) {
// Image has sourcepath set
- if (!m_LoadedTextureData
- || m_LoadedTextureData->m_path != QString::fromUtf8(m_ImagePath.c_str())) {
+ const QString unifiedPath = IBufferManager::resolveImagePath(
+ QString::fromUtf8(m_ImagePath.c_str()), preferKtx);
+ if (!m_LoadedTextureData || m_LoadedTextureData->m_path != unifiedPath) {
if (m_LoadedTextureData)
m_LoadedTextureData->m_callbacks.removeOne(this);
forIbl = forIbl || m_MappingMode == ImageMappingModes::LightProbe;
- m_LoadedTextureData = inBufferManager.CreateReloadableImage(m_ImagePath, false,
+ m_LoadedTextureData = inBufferManager.CreateReloadableImage(unifiedPath, false,
forIbl, flipCompressed);
m_LoadedTextureData->m_callbacks.push_back(this);
}
@@ -114,8 +120,8 @@ bool SImage::ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager
newImage.m_BSDFMipMap = m_LoadedTextureData->m_BSDFMipMap;
} else if (m_Flags.IsForceLoad()) {
QSet<QString> ls;
- ls.insert(QString(m_ImagePath));
- inBufferManager.loadSet(ls);
+ ls.insert(unifiedPath);
+ inBufferManager.loadSet(ls, flipCompressed);
newImage.m_Texture = m_LoadedTextureData->m_Texture;
newImage.m_TextureFlags = m_LoadedTextureData->m_TextureFlags;
newImage.m_BSDFMipMap = m_LoadedTextureData->m_BSDFMipMap;
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderImage.h b/src/runtimerender/graphobjects/Qt3DSRenderImage.h
index 26b4377..04d890f 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderImage.h
+++ b/src/runtimerender/graphobjects/Qt3DSRenderImage.h
@@ -89,8 +89,8 @@ namespace render {
// Or finds the image.
// and sets up the texture transform
bool ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager &inRenderManager,
- IRenderPluginManager &pluginManager, bool forIbl = false,
- bool flipCompressed = false);
+ IRenderPluginManager &pluginManager, bool preferKtx, bool forIbl,
+ bool flipCompressed);
void CalculateTextureTransform();
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp
index 26d2c71..677440e 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp
@@ -641,7 +641,9 @@ namespace render {
qt3dsContext.GetOffscreenRenderManager());
IRenderPluginManager &theRenderPluginManager(qt3dsContext.GetRenderPluginManager());
if (inImage.ClearDirty(bufferManager, theOffscreenRenderManager, theRenderPluginManager,
- false, m_Layer.m_Scene->m_Presentation->m_flipCompressedTextures))
+ m_Layer.m_Scene->m_Presentation->m_preferKTX,
+ inImage.m_MappingMode == ImageMappingModes::LightProbe,
+ m_Layer.m_Scene->m_Presentation->m_flipCompressedTextures))
ioFlags |= RenderPreparationResultFlagValues::Dirty;
// All objects with offscreen renderers are pickable so we can pass the pick through to the
@@ -1180,7 +1182,9 @@ namespace render {
IQt3DSRenderContext &theContext(m_Renderer.GetQt3DSContext());
return inLightProbe.ClearDirty(theContext.GetBufferManager(),
theContext.GetOffscreenRenderManager(),
- theContext.GetRenderPluginManager(), true);
+ theContext.GetRenderPluginManager(),
+ m_Layer.m_Scene->m_Presentation->m_preferKTX, true,
+ m_Layer.m_Scene->m_Presentation->m_flipCompressedTextures);
}
struct SLightNodeMarker
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp
index 43f7541..87fe54c 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp
@@ -54,6 +54,207 @@
using namespace qt3ds::render;
+namespace qt3ds {
+namespace render {
+
+static const QString QT3DSTUDIO_TAG = QStringLiteral("qt3dstudio");
+
+static QFileInfo matchCaseInsensitiveFile(const QString& file)
+{
+ const auto searchFromPaths = [](QString file) -> QFileInfo {
+ QFileInfo fileInfo(file);
+ if (fileInfo.exists())
+ return fileInfo;
+
+ const QStringList searchDirectories = QDir::searchPaths(QT3DSTUDIO_TAG);
+ for (const auto &directoryPath : searchDirectories) {
+ auto path = QDir::cleanPath(directoryPath + '/' + file);
+ QFileInfo info(path);
+ if (info.exists())
+ return info;
+ }
+ return fileInfo;
+ };
+
+ QFileInfo info = searchFromPaths(file);
+ if (info.exists())
+ return info;
+
+ QString searchPath = file;
+
+ // Trying relative to search directories.
+ // First remove any ../ and ./ from the path
+ if (searchPath.startsWith(QLatin1String("../")))
+ searchPath = searchPath.right(searchPath.length() - 3);
+ else if (searchPath.startsWith(QLatin1String("./")))
+ searchPath = searchPath.right(searchPath.length() - 2);
+
+ int loops = 0;
+ while (++loops <= 4) {
+ info = searchFromPaths(searchPath);
+ if (info.exists())
+ return info;
+ searchPath.prepend(QLatin1String("../"));
+ }
+
+ return info;
+}
+
+static bool checkFileExists(const QString &tryFile, bool relative, QString &outFile)
+{
+ QFileInfo info;
+ if (relative)
+ info = matchCaseInsensitiveFile(tryFile);
+ else
+ info.setFile(tryFile);
+ if (info.exists()) {
+ outFile = info.filePath();
+ return true;
+ }
+ if (!relative) {
+ // Some textures, for example environment maps for custom materials,
+ // have absolute path at this point. It points to the wrong place with
+ // the new project structure, so we need to split it up and construct
+ // the new absolute path here.
+ QString wholePath = tryFile;
+ QStringList splitPath = wholePath.split(QLatin1String("../"));
+ if (splitPath.size() > 1) {
+ QString searchPath = splitPath.first() + splitPath.last();
+ int loops = 0;
+ while (++loops <= 3) {
+ info.setFile(searchPath);
+ if (info.exists()) {
+ outFile = info.filePath();
+ return true;
+ }
+ searchPath = splitPath.at(0);
+ for (int i = 0; i < loops; i++)
+ searchPath.append(QLatin1String("../"));
+ searchPath.append(splitPath.last());
+ }
+ }
+ }
+ return false;
+}
+
+// Locate existing file by adding a supported suffix to localFile.
+static bool existingImageFileForPath(const QString &localFile, bool relative, bool preferKTX,
+ QString &outPath)
+{
+ // Do nothing if given filepath exists without suffix
+ QFileInfo fi(localFile);
+ if (fi.exists()) {
+ outPath = localFile;
+ return true;
+ }
+
+ // Lists of supported image formats in preferred-first order.
+ const QStringList compressedFormats {"ktx", "astc", "dds"};
+ const QStringList nonCompressedFormats {"hdr", "png", "jpg", "jpeg", "gif"};
+
+ // Depending on preferKTX, check compressed formats before or after non-compressed ones.
+ QStringList supportedFormats = preferKTX ? compressedFormats + nonCompressedFormats
+ : nonCompressedFormats + compressedFormats;
+
+ // Check first if file exists from resources as that
+ // is common and optimal for integrity case.
+ for (const QString &suffix : supportedFormats) {
+ QString tryFile = ":/" + localFile + "." + suffix;
+ if (checkFileExists(tryFile, relative, outPath))
+ return true;
+ }
+ // If not found, check still file path as-is
+ for (const QString &suffix : supportedFormats) {
+ QString tryFile = localFile + "." + suffix;
+ if (checkFileExists(tryFile, relative, outPath))
+ return true;
+ }
+
+ outPath = localFile;
+ return false;
+}
+
+// Return resolved image path for unresolved source path.
+// Handle preferKtx, search paths, empty suffixes, schemas etc.
+QString IBufferManager::resolveImagePath(const QString &sourcePath, bool preferKtx)
+{
+ QString path = sourcePath;
+ QUrl urlPath(path);
+
+ // Do nothing for image providers
+ if (urlPath.scheme() == QLatin1String("image"))
+ return sourcePath;
+
+ // Normalize the path
+ path = CFileTools::NormalizePathForQtUsage(path);
+ urlPath.setUrl(path);
+
+ const bool hasSuffix = urlPath.fileName().contains(QLatin1Char('.'));
+ const bool relative = urlPath.isRelative();
+
+ // Find an image file corresponding to only filename without suffix
+ if (!hasSuffix) {
+ QString outPath;
+ if (!existingImageFileForPath(path, relative, preferKtx, outPath)) {
+ qCWarning(WARNING, "Failed to resolve path %s", qPrintable(sourcePath));
+ return {};
+ }
+ return outPath;
+ }
+
+ // First check ktx files if preferKtx is set
+ if (preferKtx) {
+ QString ktxSource = path;
+ const bool originalIsKtx = path.endsWith(QLatin1String("ktx"), Qt::CaseInsensitive);
+ if (!originalIsKtx) {
+ const int index = ktxSource.lastIndexOf(QLatin1Char('.'));
+ ktxSource = ktxSource.left(index);
+ ktxSource.append(QLatin1String(".ktx"));
+ }
+ QString result;
+ if (checkFileExists(ktxSource, relative, result))
+ return result;
+ if (originalIsKtx) {
+ qCWarning(WARNING, "Failed to resolve path %s", qPrintable(sourcePath));
+ return {};
+ }
+ }
+
+ QString result;
+ if (checkFileExists(path, relative, result))
+ return result;
+
+ qCWarning(WARNING, "Failed to resolve path %s", qPrintable(sourcePath));
+ return {};
+}
+
+QSet<QString> IBufferManager::resolveImageSet(const QSet<QString> &set, bool preferKtx)
+{
+ QSet<QString> ret;
+ for (auto &sourcePath : set) {
+ auto unified = resolveImagePath(sourcePath, preferKtx);
+ if (!unified.isEmpty())
+ ret.insert(unified);
+ }
+ return ret;
+}
+
+QVector<CRegisteredString> IBufferManager::resolveSourcePaths(
+ IStringTable &strTable, const QVector<CRegisteredString> &sourcePaths, bool preferKtx)
+{
+ QVector<CRegisteredString> ret;
+ for (int i = 0; i < sourcePaths.size(); i++) {
+ QString path = QString::fromLatin1(sourcePaths[i].c_str());
+ auto unified = strTable.RegisterStr(IBufferManager::resolveImagePath(path, preferKtx));
+ if (unified.IsValid())
+ ret.append(unified);
+ }
+ return ret;
+}
+
+}
+}
+
namespace {
using eastl::hash;
@@ -122,6 +323,7 @@ struct SBufferManager : public IBufferManager
QHash<QString, QSharedPointer<QQmlImageProviderBase> > m_imageProviders;
QHash<QString, ReloadableTexturePtr> m_reloadableTextures;
+ ReloadableTexturePtr m_nullTexture;
static const char8_t *GetPrimitivesDirectory() { return "res//primitives"; }
@@ -296,24 +498,25 @@ struct SBufferManager : public IBufferManager
void loadSet(const QSet<QString> &imageSet, bool flipCompressed) override
{
- for (const auto &x : imageSet) {
- if (!m_reloadableTextures.contains(x)) {
- auto img = CreateReloadableImage(m_StrTable->RegisterStr(qPrintable(x)), false,
- false, flipCompressed);
- img->m_initialized = false;
- loadTextureImage(*m_reloadableTextures[x]);
- } else if (!m_reloadableTextures[x]->m_loaded) {
- loadTextureImage(*m_reloadableTextures[x]);
+ for (const auto &sourcePath : imageSet) {
+ if (!m_reloadableTextures.contains(sourcePath)) {
+ auto img = CreateReloadableImage(sourcePath, false, false, flipCompressed);
+ if (img != m_nullTexture) {
+ img->m_initialized = false;
+ loadTextureImage(*m_reloadableTextures[sourcePath]);
+ }
+ } else if (!m_reloadableTextures[sourcePath]->m_loaded) {
+ loadTextureImage(*m_reloadableTextures[sourcePath]);
}
}
}
void unloadSet(const QSet<QString> &imageSet) override
{
- for (const auto &x : imageSet) {
- if (m_reloadableTextures.contains(x)) {
- if (m_reloadableTextures[x]->m_loaded)
- unloadTextureImage(*m_reloadableTextures[x]);
+ for (const auto &sourcePath : imageSet) {
+ if (m_reloadableTextures.contains(sourcePath)) {
+ if (m_reloadableTextures[sourcePath]->m_loaded)
+ unloadTextureImage(*m_reloadableTextures[sourcePath]);
}
}
}
@@ -328,18 +531,20 @@ struct SBufferManager : public IBufferManager
}
}
- virtual ReloadableTexturePtr CreateReloadableImage(CRegisteredString inSourcePath,
+ virtual ReloadableTexturePtr CreateReloadableImage(const QString &inSourcePath,
bool inForceScanForTransparency,
bool inBsdfMipmaps,
bool flipCompressed) override
{
- // Remove schema and root from keys. To prevent loading twice file "qrc:///foo" and "foo"
- QString path = QString::fromLatin1(inSourcePath.c_str());
- path = QUrl(path).path();
- if (path.startsWith(QLatin1String("/")))
- path = path.right(path.length() - 1);
-
+ const auto path = inSourcePath;
const bool inserted = m_reloadableTextures.contains(path);
+ if (path.isNull()) {
+ if (m_nullTexture.isNull()) {
+ m_nullTexture = ReloadableTexturePtr::create();
+ m_nullTexture->m_initialized = true;
+ }
+ return m_nullTexture;
+ }
if (!inserted || (inserted && m_reloadableTextures[path]->m_initialized == false)) {
if (!inserted)
m_reloadableTextures.insert(path, ReloadableTexturePtr::create());
@@ -361,13 +566,13 @@ struct SBufferManager : public IBufferManager
// Failed to look up image from map, perhaps external of UIP/UIA image
// Try with full URI and load from filesystem.
if (theIter == m_ImageMap.end())
- theIter = m_ImageMap.find(getImagePath(QString::fromLatin1(inSourcePath.c_str())));
+ theIter = m_ImageMap.find(getImagePath(inSourcePath));
if (theIter == m_ImageMap.end()) {
loadTextureImage(*m_reloadableTextures[path], flipCompressed);
imagePath = getImagePath(path);
theIter = m_ImageMap.find(imagePath);
if (theIter == m_ImageMap.end())
- theIter = m_ImageMap.find(getImagePath(QString::fromLatin1(inSourcePath.c_str())));
+ theIter = m_ImageMap.find(getImagePath(inSourcePath));
}
#endif
if (theIter != m_ImageMap.end()) {
@@ -390,7 +595,7 @@ struct SBufferManager : public IBufferManager
QT3DS_PERF_SCOPED_TIMER(m_PerfTimer, "BufferManager: Image Decompression")
theLoadedImage = SLoadedTexture::Load(
inImagePath.c_str(), m_Context->GetFoundation(), *m_InputStreamFactory,
- true, inFlipCompressed, m_Context->GetRenderContextType(), false, this);
+ true, inFlipCompressed, m_Context->GetRenderContextType(), this);
// Hackish solution to custom materials not finding their textures if they are used
// in sub-presentations.
if (!theLoadedImage) {
@@ -403,7 +608,7 @@ struct SBufferManager : public IBufferManager
theLoadedImage = SLoadedTexture::Load(
searchPathRel.toUtf8(), m_Context->GetFoundation(),
*m_InputStreamFactory, true, false,
- m_Context->GetRenderContextType(), false, this);
+ m_Context->GetRenderContextType(), this);
}
if (!theLoadedImage) {
@@ -415,7 +620,7 @@ struct SBufferManager : public IBufferManager
theLoadedImage = SLoadedTexture::Load(
searchPath.toUtf8(), m_Context->GetFoundation(),
*m_InputStreamFactory, true, false,
- m_Context->GetRenderContextType(), false, this);
+ m_Context->GetRenderContextType(), this);
searchPath.prepend(QLatin1String("../"));
}
}
@@ -435,7 +640,7 @@ struct SBufferManager : public IBufferManager
theLoadedImage = SLoadedTexture::Load(
searchPath.toUtf8(), m_Context->GetFoundation(),
*m_InputStreamFactory, true, false,
- m_Context->GetRenderContextType(), false, this);
+ m_Context->GetRenderContextType(), this);
searchPath = splitPath.at(0);
for (int i = 0; i < loops; i++)
searchPath.append(QLatin1String("../"));
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h b/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h
index 0debd9c..159e02b 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h
@@ -79,6 +79,12 @@ namespace render {
bool inIgnoreIfLoaded) = 0;
virtual void UnaliasImagePath(CRegisteredString inSourcePath) = 0;
+ // Return resolved imagepaths from unresolved sourcepaths
+ static QString resolveImagePath(const QString &sourcePath, bool preferKtx);
+ static QSet<QString> resolveImageSet(const QSet<QString> &set, bool preferKtx);
+ static QVector<CRegisteredString> resolveSourcePaths(IStringTable &strTable,
+ const QVector<CRegisteredString> &sourcePaths, bool preferKtx);
+
// Returns the given source path unless the source path is aliased; in which case returns
// the aliased path.
virtual CRegisteredString GetImagePath(CRegisteredString inSourcePath) = 0;
@@ -93,15 +99,15 @@ namespace render {
bool inForceScanForTransparency = false,
bool inBsdfMipmaps = false) = 0;
- virtual ReloadableTexturePtr CreateReloadableImage(CRegisteredString inSourcePath,
+ virtual ReloadableTexturePtr CreateReloadableImage(const QString &inSourcePath,
bool inForceScanForTransparency = false,
bool inBsdfMipmaps = false,
bool flipCompressed = false) = 0;
virtual void enableReloadableResources(bool enable) = 0;
virtual bool isReloadableResourcesEnabled() const = 0;
- virtual void loadSet(const QSet<QString> &imageSet, bool flipCompressed = false) = 0;
- virtual void unloadSet(const QSet<QString> &imageSet) = 0;
+ virtual void loadSet(const QSet<QString> &unifiedImageSet, bool flipCompressed) = 0;
+ virtual void unloadSet(const QSet<QString> &unifiedImageSet) = 0;
virtual void reloadAll(bool flipCompressed) = 0;
virtual void loadCustomMesh(const QString &name, qt3dsimp::Mesh *mesh) = 0;
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp
index 28e0e4a..01ec9d4 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp
@@ -108,7 +108,6 @@ struct SImageLoaderBatch
QT3DSU32 m_FinalizedImageCount;
QT3DSU32 m_NumImages;
NVRenderContextType m_contextType;
- bool m_preferKTX;
bool m_flipCompressedTextures;
bool m_ibl;
@@ -118,14 +117,14 @@ struct SImageLoaderBatch
CRegisteredString inImageTillLoaded,
IImageLoadListener *inListener,
NVRenderContextType contextType,
- bool preferKTX, bool iblImage,
+ bool iblImage,
bool flipCompressedTextures);
// Called from main thread
SImageLoaderBatch(SBatchLoader &inLoader, IImageLoadListener *inLoadListener,
const TLoadingImageList &inImageList, TImageBatchId inBatchId,
- QT3DSU32 inImageCount, NVRenderContextType contextType,
- bool preferKTX, bool ibl, bool flipCompressedTextures);
+ QT3DSU32 inImageCount, NVRenderContextType contextType, bool ibl,
+ bool flipCompressedTextures);
// Called from main thread
~SImageLoaderBatch();
@@ -265,7 +264,7 @@ struct SBatchLoader : public IImageBatchLoader
CRegisteredString inImageTillLoaded,
IImageLoadListener *inListener,
NVRenderContextType contextType,
- bool preferKTX, bool iblImages,
+ bool iblImages,
bool flipCompressedTextures) override
{
if (inSourcePaths.size() == 0)
@@ -282,7 +281,7 @@ struct SBatchLoader : public IImageBatchLoader
SImageLoaderBatch *theBatch(SImageLoaderBatch::CreateLoaderBatch(
*this, theBatchId, inSourcePaths, inImageTillLoaded, inListener, contextType,
- preferKTX, iblImages, flipCompressedTextures));
+ iblImages, flipCompressedTextures));
if (theBatch) {
m_Batches.insert(eastl::make_pair(theBatchId, theBatch));
return theBatchId;
@@ -394,7 +393,6 @@ void SLoadingImage::LoadImage(void *inImg)
theThis->m_Batch->m_Loader.m_InputStreamFactory, true,
theThis->m_Batch->m_flipCompressedTextures,
theThis->m_Batch->m_contextType,
- theThis->m_Batch->m_preferKTX,
&theThis->m_Batch->m_Loader.m_BufferManager);
// if ( theTexture )
// theTexture->EnsureMultiplerOfFour( theThis->m_Batch->m_Loader.m_Foundation,
@@ -437,8 +435,7 @@ SImageLoaderBatch::CreateLoaderBatch(SBatchLoader &inLoader, TImageBatchId inBat
NVConstDataRef<CRegisteredString> inSourcePaths,
CRegisteredString inImageTillLoaded,
IImageLoadListener *inListener,
- NVRenderContextType contextType,
- bool preferKTX, bool iblImages,
+ NVRenderContextType contextType, bool iblImages,
bool flipCompressedTextures)
{
TLoadingImageList theImages;
@@ -477,7 +474,7 @@ SImageLoaderBatch::CreateLoaderBatch(SBatchLoader &inLoader, TImageBatchId inBat
(SImageLoaderBatch *)inLoader.m_BatchPool.allocate(__FILE__, __LINE__);
new (theBatch)
SImageLoaderBatch(inLoader, inListener, theImages, inBatchId, theLoadingImageCount,
- contextType, preferKTX, iblImages, flipCompressedTextures);
+ contextType, iblImages, flipCompressedTextures);
return theBatch;
}
return NULL;
@@ -486,7 +483,7 @@ SImageLoaderBatch::CreateLoaderBatch(SBatchLoader &inLoader, TImageBatchId inBat
SImageLoaderBatch::SImageLoaderBatch(SBatchLoader &inLoader, IImageLoadListener *inLoadListener,
const TLoadingImageList &inImageList, TImageBatchId inBatchId,
QT3DSU32 inImageCount, NVRenderContextType contextType,
- bool preferKTX, bool ibl, bool flipCompressedTextures)
+ bool ibl, bool flipCompressedTextures)
: m_Loader(inLoader)
, m_LoadListener(inLoadListener)
, m_LoadEvent(inLoader.m_Foundation.getAllocator())
@@ -497,7 +494,6 @@ SImageLoaderBatch::SImageLoaderBatch(SBatchLoader &inLoader, IImageLoadListener
, m_FinalizedImageCount(0)
, m_NumImages(inImageCount)
, m_contextType(contextType)
- , m_preferKTX(preferKTX)
, m_ibl(ibl)
, m_flipCompressedTextures(flipCompressedTextures)
{
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.h b/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.h
index 64caa21..03b5599 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.h
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.h
@@ -73,7 +73,7 @@ namespace render {
CRegisteredString inImageTillLoaded,
IImageLoadListener *inListener,
NVRenderContextType type,
- bool preferKTX, bool iblImages,
+ bool iblImages,
bool flipCompressedTextures = false) = 0;
// Blocks if any of the images in the batch are in flight
virtual void CancelImageBatchLoading(TImageBatchId inBatchId) = 0;
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp
index 8046a10..634e3c0 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp
@@ -908,78 +908,26 @@ void SLoadedTexture::ReleaseDecompressedTexture(STextureData inImage)
m_Allocator.deallocate(inImage.data);
}
-// Locate existing file by adding a supported suffix to localFile.
-// If localFile already contains suffix or exiting file isn't found
-// returns localFile unchanged.
-static QString existingImageFileForPath(const QString &localFile, bool preferKTX)
-{
- // Do nothing if given filepath exists or already has a suffix
- QFileInfo fi(localFile);
- if (!fi.suffix().isEmpty() || fi.exists())
- return localFile;
-
- // Lists of supported image formats in preferred-first order.
- const QStringList compressedFormats {"ktx", "astc", "dds"};
- const QStringList nonCompressedFormats {"hdr", "png", "jpg", "jpeg", "gif"};
-
- // Depending on preferKTX, check compressed formats before or after non-compressed ones.
- QStringList supportedFormats = preferKTX ? compressedFormats + nonCompressedFormats
- : nonCompressedFormats + compressedFormats;
-
- // Check first if file exists from resources as that
- // is common and optimal for integrity case.
- for (const QString &suffix : supportedFormats) {
- QString tryFile = ":/" + localFile + "." + suffix;
- if (QFileInfo::exists(tryFile))
- return tryFile;
- }
- // If not found, check still file path as-is
- for (const QString &suffix : supportedFormats) {
- QString tryFile = localFile + "." + suffix;
- if (QFileInfo::exists(tryFile))
- return tryFile;
- }
-
- return localFile;
-}
-
-SLoadedTexture *SLoadedTexture::Load(const QString &inPath, NVFoundationBase &inFoundation,
+SLoadedTexture *SLoadedTexture::Load(const QString &path, NVFoundationBase &inFoundation,
IInputStreamFactory &inFactory, bool inFlipY,
bool inFlipCompressed,
- NVRenderContextType renderContextType, bool preferKTX,
+ NVRenderContextType renderContextType,
IBufferManager *bufferManager)
{
- if (inPath.isEmpty())
+ if (path.isEmpty())
return nullptr;
- if (QUrl(inPath).scheme() == QLatin1String("image"))
- return LoadQImage(inPath, inFlipY, inFoundation, renderContextType, bufferManager);
+ if (QUrl(path).scheme() == QLatin1String("image"))
+ return LoadQImage(path, inFlipY, inFoundation, renderContextType, bufferManager);
- // If inPath doesn't have suffix, try to find most optimal existing one
- QString path = existingImageFileForPath(inPath, preferKTX);
+ SLoadedTexture *theLoadedImage = nullptr;
+ NVScopedRefCounted<IRefCountedInputStream> theStream(inFactory.GetStreamForFile(path, true));
- // If preferKTX is true, always check KTX path first
- QString ktxSource = path;
- if (preferKTX) {
- ktxSource = ktxSource.left(ktxSource.lastIndexOf(QLatin1Char('.')));
- ktxSource.append(QLatin1String(".ktx"));
- }
+ if (!theStream.mPtr)
+ return nullptr;
- SLoadedTexture *theLoadedImage = nullptr;
- // We will get invalid error logs of files not found if we don't force quiet mode
- // If the file is actually missing, it will be logged later (loaded image is null)
- NVScopedRefCounted<IRefCountedInputStream> theStream(
- inFactory.GetStreamForFile(preferKTX ? ktxSource : path, true));
- if (!theStream.mPtr) {
- if (preferKTX)
- theStream = inFactory.GetStreamForFile(path, true);
- else
- return nullptr;
- } else {
- path = ktxSource;
- }
QString fileName;
- inFactory.GetPathForFile(path, fileName, true);
+ inFactory.GetPathForStream(theStream.mPtr, fileName);
if (theStream.mPtr && path.size() > 3) {
if (path.endsWith(QLatin1String("png"), Qt::CaseInsensitive)
|| path.endsWith(QLatin1String("jpg"), Qt::CaseInsensitive)
@@ -1006,7 +954,7 @@ SLoadedTexture *SLoadedTexture::Load(const QString &inPath, NVFoundationBase &in
inFlipCompressed);
theLoadedImage = LoadASTC(fileName, inFlipY, inFoundation, renderContextType);
} else {
- qCWarning(INTERNAL_ERROR, "Unrecognized image extension: %s", qPrintable(inPath));
+ qCWarning(INTERNAL_ERROR, "Unrecognized image extension: %s", qPrintable(path));
}
}
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h
index 44d07de..c2aca9e 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h
@@ -157,7 +157,6 @@ namespace render {
bool inFlipCompressed = false,
NVRenderContextType renderContextType
= NVRenderContextValues::NullContext,
- bool preferKTX = false,
IBufferManager *bufferManager = nullptr);
static SLoadedTexture *LoadDDS(IInStream &inStream, QT3DSI32 flipVertical,
NVFoundationBase &fnd,