Implement KTXStorage::assignMipData and add writing of mips to

TextureCache
This commit is contained in:
Ryan Huffman 2017-04-13 17:03:59 -07:00 committed by Atlante45
parent cf3dc12542
commit e9bb895bff
4 changed files with 50 additions and 5 deletions

View file

@ -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;

View file

@ -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) {

View file

@ -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;
{

View file

@ -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<uint8_t*>(_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