diff options
Diffstat (limited to 'src/runtimerender/resourcemanager/qssgrenderbuffermanager.cpp')
| -rw-r--r-- | src/runtimerender/resourcemanager/qssgrenderbuffermanager.cpp | 189 |
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; } |
