mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 05:37:17 +02:00
Merge pull request #10470 from huffman/fix/ktx-cubemaps
Fix progressive loading of KTX cubemaps
This commit is contained in:
commit
82c7188376
4 changed files with 25 additions and 14 deletions
|
@ -238,8 +238,9 @@ void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& stor
|
||||||
throw std::runtime_error("Invalid level");
|
throw std::runtime_error("Invalid level");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (storage->size() != _ktxDescriptor->images[level]._imageSize) {
|
auto& imageDesc = _ktxDescriptor->images[level];
|
||||||
qWarning() << "Invalid image size: " << storage->size() << ", expected: " << _ktxDescriptor->images[level]._imageSize
|
if (storage->size() != imageDesc._imageSize) {
|
||||||
|
qWarning() << "Invalid image size: " << storage->size() << ", expected: " << imageDesc._imageSize
|
||||||
<< ", level: " << level << ", filename: " << QString::fromStdString(_filename);
|
<< ", level: " << level << ", filename: " << QString::fromStdString(_filename);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -258,7 +259,7 @@ void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& stor
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(imageData, storage->data(), _ktxDescriptor->images[level]._imageSize);
|
memcpy(imageData, storage->data(), storage->size());
|
||||||
_minMipLevelAvailable = level;
|
_minMipLevelAvailable = level;
|
||||||
if (_offsetToMinMipKV > 0) {
|
if (_offsetToMinMipKV > 0) {
|
||||||
auto minMipKeyData = file->mutableData() + ktx::KTX_HEADER_SIZE + _offsetToMinMipKV;
|
auto minMipKeyData = file->mutableData() + ktx::KTX_HEADER_SIZE + _offsetToMinMipKV;
|
||||||
|
|
|
@ -38,15 +38,15 @@ UInt32 numberOfArrayElements
|
||||||
UInt32 numberOfFaces
|
UInt32 numberOfFaces
|
||||||
UInt32 numberOfMipmapLevels
|
UInt32 numberOfMipmapLevels
|
||||||
UInt32 bytesOfKeyValueData
|
UInt32 bytesOfKeyValueData
|
||||||
|
|
||||||
for each keyValuePair that fits in bytesOfKeyValueData
|
for each keyValuePair that fits in bytesOfKeyValueData
|
||||||
UInt32 keyAndValueByteSize
|
UInt32 keyAndValueByteSize
|
||||||
Byte keyAndValue[keyAndValueByteSize]
|
Byte keyAndValue[keyAndValueByteSize]
|
||||||
Byte valuePadding[3 - ((keyAndValueByteSize + 3) % 4)]
|
Byte valuePadding[3 - ((keyAndValueByteSize + 3) % 4)]
|
||||||
end
|
end
|
||||||
|
|
||||||
for each mipmap_level in numberOfMipmapLevels*
|
for each mipmap_level in numberOfMipmapLevels*
|
||||||
UInt32 imageSize;
|
UInt32 imageSize;
|
||||||
for each array_element in numberOfArrayElements*
|
for each array_element in numberOfArrayElements*
|
||||||
for each face in numberOfFaces
|
for each face in numberOfFaces
|
||||||
for each z_slice in pixelDepth*
|
for each z_slice in pixelDepth*
|
||||||
|
@ -269,7 +269,7 @@ namespace ktx {
|
||||||
COMPRESSED_RG11_EAC = 0x9272,
|
COMPRESSED_RG11_EAC = 0x9272,
|
||||||
COMPRESSED_SIGNED_RG11_EAC = 0x9273,
|
COMPRESSED_SIGNED_RG11_EAC = 0x9273,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class GLBaseInternalFormat : uint32_t {
|
enum class GLBaseInternalFormat : uint32_t {
|
||||||
// GL 4.4 Table 8.11
|
// GL 4.4 Table 8.11
|
||||||
DEPTH_COMPONENT = 0x1902,
|
DEPTH_COMPONENT = 0x1902,
|
||||||
|
@ -419,9 +419,9 @@ namespace ktx {
|
||||||
using FaceOffsets = std::vector<size_t>;
|
using FaceOffsets = std::vector<size_t>;
|
||||||
using FaceBytes = std::vector<const Byte*>;
|
using FaceBytes = std::vector<const Byte*>;
|
||||||
|
|
||||||
|
const uint32_t _numFaces;
|
||||||
// This is the byte offset from the _start_ of the image region. For example, level 0
|
// This is the byte offset from the _start_ of the image region. For example, level 0
|
||||||
// will have a byte offset of 0.
|
// will have a byte offset of 0.
|
||||||
const uint32_t _numFaces;
|
|
||||||
const size_t _imageOffset;
|
const size_t _imageOffset;
|
||||||
const uint32_t _imageSize;
|
const uint32_t _imageSize;
|
||||||
const uint32_t _faceSize;
|
const uint32_t _faceSize;
|
||||||
|
@ -466,7 +466,7 @@ namespace ktx {
|
||||||
|
|
||||||
class KTX;
|
class KTX;
|
||||||
|
|
||||||
// A KTX descriptor is a lightweight container for all the information about a serialized KTX file, but without the
|
// A KTX descriptor is a lightweight container for all the information about a serialized KTX file, but without the
|
||||||
// actual image / face data available.
|
// actual image / face data available.
|
||||||
struct KTXDescriptor {
|
struct KTXDescriptor {
|
||||||
KTXDescriptor(const Header& header, const KeyValues& keyValues, const ImageDescriptors& imageDescriptors) : header(header), keyValues(keyValues), images(imageDescriptors) {}
|
KTXDescriptor(const Header& header, const KeyValues& keyValues, const ImageDescriptors& imageDescriptors) : header(header), keyValues(keyValues), images(imageDescriptors) {}
|
||||||
|
@ -495,7 +495,7 @@ namespace ktx {
|
||||||
// Instead of creating a full Copy of the src data in a KTX object, the write serialization can be performed with the
|
// Instead of creating a full Copy of the src data in a KTX object, the write serialization can be performed with the
|
||||||
// following two functions
|
// following two functions
|
||||||
// size_t sizeNeeded = KTX::evalStorageSize(header, images);
|
// size_t sizeNeeded = KTX::evalStorageSize(header, images);
|
||||||
//
|
//
|
||||||
// //allocate a buffer of size "sizeNeeded" or map a file with enough capacity
|
// //allocate a buffer of size "sizeNeeded" or map a file with enough capacity
|
||||||
// Byte* destBytes = new Byte[sizeNeeded];
|
// Byte* destBytes = new Byte[sizeNeeded];
|
||||||
//
|
//
|
||||||
|
|
|
@ -127,6 +127,7 @@ namespace ktx {
|
||||||
size_t KTX::writeWithoutImages(Byte* destBytes, size_t destByteSize, const Header& header, const ImageDescriptors& descriptors, const KeyValues& keyValues) {
|
size_t KTX::writeWithoutImages(Byte* destBytes, size_t destByteSize, const Header& header, const ImageDescriptors& descriptors, const KeyValues& keyValues) {
|
||||||
// Check again that we have enough destination capacity
|
// Check again that we have enough destination capacity
|
||||||
if (!destBytes || (destByteSize < evalStorageSize(header, descriptors, keyValues))) {
|
if (!destBytes || (destByteSize < evalStorageSize(header, descriptors, keyValues))) {
|
||||||
|
qWarning() << "Destination capacity is insufficient to write KTX without images";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,13 +150,15 @@ namespace ktx {
|
||||||
for (size_t i = 0; i < descriptors.size(); ++i) {
|
for (size_t i = 0; i < descriptors.size(); ++i) {
|
||||||
auto ptr = reinterpret_cast<uint32_t*>(currentDestPtr);
|
auto ptr = reinterpret_cast<uint32_t*>(currentDestPtr);
|
||||||
*ptr = descriptors[i]._imageSize;
|
*ptr = descriptors[i]._imageSize;
|
||||||
ptr++;
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
ptr++;
|
||||||
for (size_t k = 0; k < descriptors[i]._imageSize/4; k++) {
|
for (size_t k = 0; k < descriptors[i]._imageSize/4; k++) {
|
||||||
*(ptr + k) = 0xFFFFFFFF;
|
*(ptr + k) = 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
currentDestPtr += descriptors[i]._imageSize + sizeof(uint32_t);
|
currentDestPtr += sizeof(uint32_t);
|
||||||
|
currentDestPtr += descriptors[i]._imageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
return destByteSize;
|
return destByteSize;
|
||||||
|
|
|
@ -501,12 +501,19 @@ void NetworkTexture::ktxMipRequestFinished() {
|
||||||
if (texture) {
|
if (texture) {
|
||||||
texture->assignStoredMip(_ktxMipLevelRangeInFlight.first,
|
texture->assignStoredMip(_ktxMipLevelRangeInFlight.first,
|
||||||
_ktxMipRequest->getData().size(), reinterpret_cast<uint8_t*>(_ktxMipRequest->getData().data()));
|
_ktxMipRequest->getData().size(), reinterpret_cast<uint8_t*>(_ktxMipRequest->getData().data()));
|
||||||
_lowestKnownPopulatedMip = _textureSource->getGPUTexture()->minAvailableMipLevel();
|
|
||||||
|
if (texture->minAvailableMipLevel() <= _ktxMipLevelRangeInFlight.first) {
|
||||||
|
_lowestKnownPopulatedMip = texture->minAvailableMipLevel();
|
||||||
|
_ktxResourceState = WAITING_FOR_MIP_REQUEST;
|
||||||
|
} else {
|
||||||
|
qWarning(networking) << "Failed to load mip: " << _url << ":" << _ktxMipLevelRangeInFlight.first;
|
||||||
|
_ktxResourceState = FAILED_TO_LOAD;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
_ktxResourceState = WAITING_FOR_MIP_REQUEST;
|
||||||
qWarning(networking) << "Trying to update mips but texture is null";
|
qWarning(networking) << "Trying to update mips but texture is null";
|
||||||
}
|
}
|
||||||
finishedLoading(true);
|
finishedLoading(true);
|
||||||
_ktxResourceState = WAITING_FOR_MIP_REQUEST;
|
|
||||||
} else {
|
} else {
|
||||||
finishedLoading(false);
|
finishedLoading(false);
|
||||||
if (handleFailedRequest(_ktxMipRequest->getResult())) {
|
if (handleFailedRequest(_ktxMipRequest->getResult())) {
|
||||||
|
|
Loading…
Reference in a new issue