aboutsummaryrefslogtreecommitdiffstats
path: root/src/runtimerender/resourcemanager/qssgrenderbuffermanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtimerender/resourcemanager/qssgrenderbuffermanager.cpp')
-rw-r--r--src/runtimerender/resourcemanager/qssgrenderbuffermanager.cpp189
1 files changed, 99 insertions, 90 deletions
diff --git a/src/runtimerender/resourcemanager/qssgrenderbuffermanager.cpp b/src/runtimerender/resourcemanager/qssgrenderbuffermanager.cpp
index 721ba570..8d2fe95b 100644
--- a/src/runtimerender/resourcemanager/qssgrenderbuffermanager.cpp
+++ b/src/runtimerender/resourcemanager/qssgrenderbuffermanager.cpp
@@ -207,7 +207,7 @@ QSSGRenderImageTexture QSSGBufferManager::loadRenderImage(const QSSGRenderImage
CreateRhiTextureFlags rhiTexFlags = ScanForTransparency;
if (image->type == QSSGRenderGraphObject::Type::ImageCube)
rhiTexFlags |= CubeMap;
- if (!createRhiTexture(foundIt.value().renderImageTexture, theLoadedTexture.data(), inMipMode, rhiTexFlags, QFileInfo(path).fileName())) {
+ if (!setRhiTexture(foundIt.value().renderImageTexture, theLoadedTexture.data(), inMipMode, rhiTexFlags, QFileInfo(path).fileName())) {
foundIt.value() = ImageData();
} else {
#ifdef QSSG_RENDERBUFFER_DEBUGGING
@@ -237,10 +237,15 @@ QSSGRenderImageTexture QSSGBufferManager::loadTextureData(QSSGRenderTextureData
if (theImageData == customTextureMap.end()) {
theImageData = customTextureMap.insert(imageKey, ImageData());
} else if (data->generationId() != theImageData->generationId) {
- // release first
- releaseTextureData(imageKey);
- // reinsert the placeholder since releaseTextureData removed from map
- theImageData = customTextureMap.insert(imageKey, ImageData());
+ auto &renderImageTexture = theImageData.value().renderImageTexture;
+ if (toRhiFormat(data->format()) != renderImageTexture.m_texture->format()
+ || data->size() != renderImageTexture.m_texture->pixelSize()) {
+ // release first
+ releaseTextureData(imageKey);
+ // reinsert the placeholder since releaseTextureData removed from map
+ theImageData = customTextureMap.insert(imageKey, ImageData());
+ }
+ theImageData->generationId = data->generationId();
} else {
// Return the currently loaded texture
theImageData.value().usageCounts[currentLayer]++;
@@ -252,12 +257,14 @@ QSSGRenderImageTexture QSSGBufferManager::loadTextureData(QSSGRenderTextureData
if (!data->textureData().isNull()) {
theLoadedTexture.reset(QSSGLoadedTexture::loadTextureData(data));
theLoadedTexture->ownsData = false;
- if (createRhiTexture(theImageData.value().renderImageTexture, theLoadedTexture.data(), inMipMode, {}, data->debugObjectName)) {
-#ifdef QSSG_RENDERBUFFER_DEBUGGING
- qDebug() << "+ uploadTexture: " << data << currentLayer;
-#endif
- theImageData.value().generationId = data->generationId();
- increaseMemoryStat(theImageData.value().renderImageTexture.m_texture);
+
+ bool wasTextureCreated = false;
+
+ if (setRhiTexture(theImageData.value().renderImageTexture, theLoadedTexture.data(), inMipMode, {}, data->debugObjectName, &wasTextureCreated)) {
+ if (wasTextureCreated) {
+ theImageData.value().generationId = data->generationId();
+ increaseMemoryStat(theImageData.value().renderImageTexture.m_texture);
+ }
} else {
theImageData.value() = ImageData();
}
@@ -286,7 +293,7 @@ QSSGRenderImageTexture QSSGBufferManager::loadLightmap(const QSSGRenderModel &mo
qCWarning(WARNING, "Failed to load lightmap image: %s", qPrintable(imagePath));
foundIt = imageMap.insert(imageKey, ImageData());
if (theLoadedTexture) {
- if (!createRhiTexture(foundIt.value().renderImageTexture, theLoadedTexture.data(), MipModeDisable, {}, imagePath))
+ if (!setRhiTexture(foundIt.value().renderImageTexture, theLoadedTexture.data(), MipModeDisable, {}, imagePath))
foundIt.value() = ImageData();
result = foundIt.value().renderImageTexture;
}
@@ -887,111 +894,134 @@ bool QSSGBufferManager::createEnvironmentMap(const QSSGLoadedTexture *inImage, Q
return true;
}
-bool QSSGBufferManager::createRhiTexture(QSSGRenderImageTexture &texture,
- const QSSGLoadedTexture *inTexture,
- MipMode inMipMode,
- CreateRhiTextureFlags inFlags,
- const QString &debugObjectName)
+bool QSSGBufferManager::setRhiTexture(QSSGRenderImageTexture &texture,
+ const QSSGLoadedTexture *inTexture,
+ MipMode inMipMode,
+ CreateRhiTextureFlags inFlags,
+ const QString &debugObjectName,
+ bool *wasTextureCreated)
{
Q_ASSERT(inMipMode != MipModeFollowRenderImage);
QVarLengthArray<QRhiTextureUploadEntry, 16> textureUploads;
int textureSampleCount = 1;
QRhiTexture::Flags textureFlags;
- int mipmapCount = 1;
const bool checkTransp = inFlags.testFlag(ScanForTransparency);
bool hasTransp = false;
const auto &context = m_contextInterface->rhiContext();
auto *rhi = context->rhi();
- QRhiTexture::Format rhiFormat = QRhiTexture::UnknownFormat;
- QSize size;
- if (inTexture->format.format == QSSGRenderTextureFormat::Format::RGBE8)
- texture.m_flags.setRgbe8(true);
- if (inMipMode == MipModeBsdf && (inTexture->data || inTexture->textureFileData.isValid())) {
- // Before creating an environment map, check if the provided texture is a
- // pre-baked environment map
- if (inTexture->textureFileData.isValid() && inTexture->textureFileData.keyValueMetadata().contains("QT_IBL_BAKER_VERSION")) {
- Q_ASSERT(inTexture->textureFileData.numFaces() == 6);
- Q_ASSERT(inTexture->textureFileData.numLevels() >= 5);
-
- const QTextureFileData &tex = inTexture->textureFileData;
- rhiFormat = toRhiFormat(inTexture->format.format);
- size = tex.size();
- mipmapCount = tex.numLevels();
- const int faceCount = tex.numFaces();
- QRhiTexture *environmentCubeMap = rhi->newTexture(rhiFormat, size, 1, QRhiTexture::CubeMap | QRhiTexture::MipMapped);
- environmentCubeMap->setName(debugObjectName.toLatin1());
- environmentCubeMap->create();
+
+ QRhiTexture::Format rhiFormat = toRhiFormat(inTexture->format.format);
+ const QTextureFileData &texFileData = inTexture->textureFileData;
+ QSize size = texFileData.isValid() ? texFileData.size() : QSize(inTexture->width, inTexture->height);
+ int mipmapCount = texFileData.isValid() ? texFileData.numLevels() : 1;
+ bool generateMipmaps = false;
+
+ if (wasTextureCreated)
+ *wasTextureCreated = false;
+
+ if (texture.m_texture == nullptr) {
+ if (inTexture->format.format == QSSGRenderTextureFormat::Format::RGBE8)
+ texture.m_flags.setRgbe8(true);
+ if (inMipMode == MipModeBsdf && (inTexture->data || texFileData.isValid())) {
+ // Before creating an environment map, check if the provided texture is a
+ // pre-baked environment map
+ if (texFileData.isValid() && texFileData.keyValueMetadata().contains("QT_IBL_BAKER_VERSION")) {
+ Q_ASSERT(texFileData.numFaces() == 6);
+ Q_ASSERT(texFileData.numLevels() >= 5);
+
+ QRhiTexture *environmentCubeMap = rhi->newTexture(rhiFormat, size, 1, QRhiTexture::CubeMap | QRhiTexture::MipMapped);
+ environmentCubeMap->setName(debugObjectName.toLatin1());
+ environmentCubeMap->create();
+ texture.m_texture = environmentCubeMap;
+ context->registerTexture(texture.m_texture);
+ if (wasTextureCreated)
+ *wasTextureCreated = true;
+ // If we get this far then we need to create an environment map at runtime.
+ } else if (createEnvironmentMap(inTexture, &texture, debugObjectName)) {
+ context->registerTexture(texture.m_texture);
+ if (wasTextureCreated)
+ *wasTextureCreated = true;
+ return true;
+ } else {
+ qWarning() << "Failed to create environment map";
+ return false;
+ }
+ } else {
+ if (inMipMode == MipModeEnable && mipmapCount == 1) {
+ textureFlags |= QRhiTexture::Flag::UsedWithGenerateMips;
+ generateMipmaps = true;
+ mipmapCount = rhi->mipLevelsForSize(size);
+ }
+
+ if (mipmapCount > 1)
+ textureFlags |= QRhiTexture::Flag::MipMapped;
+
+ if (inFlags.testFlag(CubeMap))
+ textureFlags |= QRhiTexture::CubeMap;
+
+ texture.m_texture = rhi->newTexture(rhiFormat, size, textureSampleCount, textureFlags);
+
+ texture.m_texture->setName(debugObjectName.toLatin1());
+ texture.m_texture->create();
+ context->registerTexture(texture.m_texture);
+ if (wasTextureCreated)
+ *wasTextureCreated = true;
+ }
+ }
+
+ // Update resources
+ if (inMipMode == MipModeBsdf && (inTexture->data || texFileData.isValid())) {
+ if (texFileData.isValid() && texFileData.keyValueMetadata().contains("QT_IBL_BAKER_VERSION")) {
+ const int faceCount = texFileData.numFaces();
for (int layer = 0; layer < faceCount; ++layer) {
for (int level = 0; level < mipmapCount; ++level) {
QRhiTextureSubresourceUploadDescription subDesc;
subDesc.setSourceSize(sizeForMipLevel(level, size));
- subDesc.setData(tex.getDataView(level, layer).toByteArray());
+ subDesc.setData(texFileData.getDataView(level, layer).toByteArray());
textureUploads << QRhiTextureUploadEntry { layer, level, subDesc };
}
}
- texture.m_texture = environmentCubeMap;
QRhiTextureUploadDescription uploadDescription;
uploadDescription.setEntries(textureUploads.cbegin(), textureUploads.cend());
auto *rub = rhi->nextResourceUpdateBatch();
- rub->uploadTexture(environmentCubeMap, uploadDescription);
+ rub->uploadTexture(texture.m_texture, uploadDescription);
context->commandBuffer()->resourceUpdate(rub);
texture.m_mipmapCount = mipmapCount;
- context->registerTexture(texture.m_texture);
- return true;
- }
-
- // If we get this far then we need to create an environment map at runtime.
- if (createEnvironmentMap(inTexture, &texture, debugObjectName)) {
- context->registerTexture(texture.m_texture);
return true;
- } else {
- qWarning() << "Failed to create environment map";
- return false;
}
- } else if (inTexture->textureFileData.isValid()) {
- const QTextureFileData &tex = inTexture->textureFileData;
- size = tex.size();
- mipmapCount = tex.numLevels();
-
+ } else if (texFileData.isValid()) {
int numFaces = 1;
// Just having a container with 6 faces is not enough, we only treat it
// as a cubemap if it was requested to be treated as such. Otherwise
// only face 0 is used.
- if (tex.numFaces() == 6 && inFlags.testFlag(CubeMap))
+ if (texFileData.numFaces() == 6 && inFlags.testFlag(CubeMap))
numFaces = 6;
- for (int level = 0; level < tex.numLevels(); ++level) {
+ for (int level = 0; level < texFileData.numLevels(); ++level) {
QRhiTextureSubresourceUploadDescription subDesc;
subDesc.setSourceSize(sizeForMipLevel(level, size));
for (int face = 0; face < numFaces; ++face) {
- subDesc.setData(tex.getDataView(level, face).toByteArray());
+ subDesc.setData(texFileData.getDataView(level, face).toByteArray());
textureUploads << QRhiTextureUploadEntry{ face, level, subDesc };
}
}
-
- rhiFormat = toRhiFormat(inTexture->format.format);
if (checkTransp) {
- auto glFormat = tex.glInternalFormat() ? tex.glInternalFormat() : tex.glFormat();
+ auto glFormat = texFileData.glInternalFormat() ? texFileData.glInternalFormat() : texFileData.glFormat();
hasTransp = !QSGCompressedTexture::formatIsOpaque(glFormat);
}
} else {
QRhiTextureSubresourceUploadDescription subDesc;
if (!inTexture->image.isNull()) {
- rhiFormat = toRhiFormat(inTexture->format.format);
- size = inTexture->image.size();
subDesc.setImage(inTexture->image);
if (checkTransp)
hasTransp = QImageData::get(inTexture->image)->checkForAlphaPixels();
} else if (inTexture->data) {
- rhiFormat = toRhiFormat(inTexture->format.format);
- size = QSize(inTexture->width, inTexture->height);
QByteArray buf(static_cast<const char *>(inTexture->data), qMax(0, int(inTexture->dataSizeInBytes)));
subDesc.setData(buf);
if (checkTransp)
hasTransp = inTexture->scanForTransparency();
-
}
subDesc.setSourceSize(size);
if (!subDesc.data().isEmpty() || !subDesc.image().isNull())
@@ -1006,19 +1036,6 @@ bool QSSGBufferManager::createRhiTexture(QSSGRenderImageTexture &texture,
const auto validTexSize = size.width() <= maxTextureSize && size.height() <= maxTextureSize;
QSSG_ASSERT_X(validTexSize, qPrintable(textureSizeWarning(size, maxTextureSize)), return false);
- bool generateMipmaps = false;
- if (inMipMode == MipModeEnable && mipmapCount == 1) {
- textureFlags |= QRhiTexture::Flag::UsedWithGenerateMips;
- generateMipmaps = true;
- mipmapCount = rhi->mipLevelsForSize(size);
- }
-
- if (mipmapCount > 1)
- textureFlags |= QRhiTexture::Flag::MipMapped;
-
- if (inFlags.testFlag(CubeMap))
- textureFlags |= QRhiTexture::CubeMap;
-
if (textureUploads.isEmpty() || size.isEmpty() || rhiFormat == QRhiTexture::UnknownFormat) {
qWarning() << "Could not load texture";
return false;
@@ -1027,28 +1044,20 @@ bool QSSGBufferManager::createRhiTexture(QSSGRenderImageTexture &texture,
return false;
}
- auto *tex = rhi->newTexture(rhiFormat, size, textureSampleCount, textureFlags);
-
- QSSG_ASSERT(tex != nullptr, return false);
-
- tex->setName(debugObjectName.toLatin1());
- tex->create();
+ QSSG_ASSERT(texture.m_texture != nullptr, return false);
if (checkTransp)
texture.m_flags.setHasTransparency(hasTransp);
- texture.m_texture = tex;
QRhiTextureUploadDescription uploadDescription;
uploadDescription.setEntries(textureUploads.cbegin(), textureUploads.cend());
auto *rub = rhi->nextResourceUpdateBatch(); // TODO: optimize
- rub->uploadTexture(tex, uploadDescription);
+ rub->uploadTexture(texture.m_texture, uploadDescription);
if (generateMipmaps)
- rub->generateMips(tex);
+ rub->generateMips(texture.m_texture);
context->commandBuffer()->resourceUpdate(rub);
texture.m_mipmapCount = mipmapCount;
-
- context->registerTexture(texture.m_texture); // owned by the QSSGRhiContext from here on
return true;
}