From e9bb895bff8c122fa5f73dee722e92dfa835ff68 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 13 Apr 2017 17:03:59 -0700 Subject: [PATCH] Implement KTXStorage::assignMipData and add writing of mips to TextureCache --- libraries/gpu/src/gpu/Texture.cpp | 1 + libraries/gpu/src/gpu/Texture_ktx.cpp | 30 +++++++++++++++++-- libraries/ktx/src/ktx/Writer.cpp | 6 ++-- .../src/model-networking/TextureCache.cpp | 18 +++++++++++ 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 6a1e5ca699..205cf3a65a 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -118,6 +118,7 @@ Texture::Size Texture::getAllowedGPUMemoryUsage() { return _allowedCPUMemoryUsage; } + void Texture::setAllowedGPUMemoryUsage(Size size) { qCDebug(gpulogging) << "New MAX texture memory " << BYTES_TO_MB(size) << " MB"; _allowedCPUMemoryUsage = size; diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 65dc48f634..ede1f21c1f 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -56,7 +56,8 @@ KtxStorage::KtxStorage(const std::string& filename) : _filename(filename) { if (found != keyValues.end()) { _minMipLevelAvailable = found->_value[0]; } else { - _minMipLevelAvailable = 4;// _ktxDescriptor->header.numberOfMipmapLevels; + // Assume all mip levels are available + _minMipLevelAvailable = 0; } } @@ -93,7 +94,32 @@ bool KtxStorage::isMipAvailable(uint16 level, uint8 face) const { } void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& storage) { - throw std::runtime_error("Invalid call"); + if (level != _minMipLevelAvailable - 1) { + qWarning() << "Invalid level to be stored"; + return; + } + + if (level >= _ktxDescriptor->images.size()) { + throw std::runtime_error("Invalid level"); + } + + if (storage->size() != _ktxDescriptor->images[level]._imageSize) { + throw std::runtime_error("Invalid image size for level"); + } + + + ktx::StoragePointer file { new storage::FileStorage(_filename.c_str()) }; + auto data = file->mutableData(); + data += file->size(); + + // TODO Cache this data inside Image or ImageDescriptor? + for (auto i = _ktxDescriptor->header.numberOfMipmapLevels - 1; i >= level; --i) { + data -= _ktxDescriptor->images[i]._imageSize; + data -= 4; + } + data += 4; + memcpy(data, storage->data(), _ktxDescriptor->images[level]._imageSize); + _minMipLevelAvailable = level; } void KtxStorage::assignMipFaceData(uint16 level, uint8 face, const storage::StoragePointer& storage) { diff --git a/libraries/ktx/src/ktx/Writer.cpp b/libraries/ktx/src/ktx/Writer.cpp index 20d4d598a9..d149d559f9 100644 --- a/libraries/ktx/src/ktx/Writer.cpp +++ b/libraries/ktx/src/ktx/Writer.cpp @@ -45,10 +45,10 @@ namespace ktx { auto newHeader = header; - Byte minMip = header.numberOfMipmapLevels - 6; + Byte minMip = header.numberOfMipmapLevels; auto newKeyValues = keyValues; - //newKeyValues.emplace_back(KeyValue(HIFI_MIN_POPULATED_MIP_KEY, sizeof(Byte), &minMip)); - //newHeader.bytesOfKeyValueData = KeyValue::serializedKeyValuesByteSize(newKeyValues); + newKeyValues.emplace_back(KeyValue(HIFI_MIN_POPULATED_MIP_KEY, sizeof(Byte), &minMip)); + newHeader.bytesOfKeyValueData = KeyValue::serializedKeyValuesByteSize(newKeyValues); StoragePointer storagePointer; { diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 26691db083..93a25330b1 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -387,6 +387,7 @@ void NetworkTexture::startMipRangeRequest(uint16_t low, uint16_t high) { _ktxMipRequest = ResourceManager::createResourceRequest(this, _activeUrl); qDebug() << ">>> Making request to " << _url << " for " << low << " to " << high; + _ktxMipLevelRangeInFlight = { low, high }; if (isHighMipRequest) { // This is a special case where we load the high 7 mips ByteRange range; @@ -479,6 +480,23 @@ void NetworkTexture::maybeCreateKTX() { texture->setKtxBacking(file->getFilepath()); texture->setSource(filename); + auto& images = _ktxDescriptor->images; + size_t imageSizeRemaining = _ktxHighMipData.size(); + uint8_t* ktxData = reinterpret_cast(_ktxHighMipData.data()); + ktxData += _ktxHighMipData.size(); + // TODO Move image offset calculation to ktx ImageDescriptor + for (uint16_t i = images.size() - 1; i >= 0; --i) { + auto& image = images[i]; + if (image._imageSize > imageSizeRemaining) { + break; + } + qDebug() << "Transferring " << i; + ktxData -= image._imageSize; + texture->assignStoredMip(i, image._imageSize, ktxData); + ktxData -= 4; + imageSizeRemaining - image._imageSize - 4; + } + // 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 // be the winner