diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendVariableTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendVariableTexture.cpp index 188fff9979..4083f09251 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendVariableTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendVariableTexture.cpp @@ -85,14 +85,16 @@ TransferJob::TransferJob(const GL45VariableAllocationTexture& parent, uint16_t s auto transferDimensions = _parent._gpuObject.evalMipDimensions(sourceMip); GLenum format; GLenum type; - auto mipData = _parent._gpuObject.accessStoredMipFace(sourceMip, face); GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_parent._gpuObject.getTexelFormat(), _parent._gpuObject.getStoredMipFormat()); format = texelFormat.format; type = texelFormat.type; + auto mipSize = _parent._gpuObject.getStoredMipFaceSize(sourceMip, face); + if (0 == lines) { - _transferSize = mipData->getSize(); + _transferSize = mipSize; _bufferingLambda = [=] { + auto mipData = _parent._gpuObject.accessStoredMipFace(sourceMip, face); _buffer.resize(_transferSize); memcpy(&_buffer[0], mipData->readData(), _transferSize); _bufferingCompleted = true; @@ -101,11 +103,11 @@ TransferJob::TransferJob(const GL45VariableAllocationTexture& parent, uint16_t s } else { transferDimensions.y = lines; auto dimensions = _parent._gpuObject.evalMipDimensions(sourceMip); - auto mipSize = mipData->getSize(); auto bytesPerLine = (uint32_t)mipSize / dimensions.y; - _transferSize = bytesPerLine * lines; auto sourceOffset = bytesPerLine * lineOffset; + _transferSize = bytesPerLine * lines; _bufferingLambda = [=] { + auto mipData = _parent._gpuObject.accessStoredMipFace(sourceMip, face); _buffer.resize(_transferSize); memcpy(&_buffer[0], mipData->readData() + sourceOffset, _transferSize); _bufferingCompleted = true; @@ -585,10 +587,10 @@ void GL45ResourceTexture::populateTransferQueue() { // break down the transfers into chunks so that no single transfer is // consuming more than X bandwidth - auto mipData = _gpuObject.accessStoredMipFace(sourceMip, face); + auto mipSize = _gpuObject.getStoredMipFaceSize(sourceMip, face); const auto lines = mipDimensions.y; - auto bytesPerLine = (uint32_t)mipData->getSize() / lines; - Q_ASSERT(0 == (mipData->getSize() % lines)); + auto bytesPerLine = mipSize / lines; + Q_ASSERT(0 == (mipSize % lines)); uint32_t linesPerTransfer = (uint32_t)(MAX_TRANSFER_SIZE / bytesPerLine); uint32_t lineOffset = 0; while (lineOffset < lines) { diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 1f66b2900e..38019c5a03 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -149,6 +149,10 @@ PixelsPointer MemoryStorage::getMipFace(uint16 level, uint8 face) const { return PixelsPointer(); } +Size MemoryStorage::getMipFaceSize(uint16 level, uint8 face) const { + return getMipFace(level, face)->getSize(); +} + bool MemoryStorage::isMipAvailable(uint16 level, uint8 face) const { PixelsPointer mipFace = getMipFace(level, face); return (mipFace && mipFace->getSize()); @@ -478,43 +482,39 @@ uint16 Texture::autoGenerateMips(uint16 maxMip) { } uint16 Texture::getStoredMipWidth(uint16 level) const { - PixelsPointer mipFace = accessStoredMipFace(level); - if (mipFace && mipFace->getSize()) { - return evalMipWidth(level); + if (!isStoredMipFaceAvailable(level)) { + return 0; } - return 0; + return evalMipWidth(level); } uint16 Texture::getStoredMipHeight(uint16 level) const { - PixelsPointer mip = accessStoredMipFace(level); - if (mip && mip->getSize()) { - return evalMipHeight(level); + if (!isStoredMipFaceAvailable(level)) { + return 0; } - return 0; + return evalMipHeight(level); } uint16 Texture::getStoredMipDepth(uint16 level) const { - PixelsPointer mipFace = accessStoredMipFace(level); - if (mipFace && mipFace->getSize()) { - return evalMipDepth(level); + if (!isStoredMipFaceAvailable(level)) { + return 0; } - return 0; + return evalMipDepth(level); } uint32 Texture::getStoredMipNumTexels(uint16 level) const { - PixelsPointer mipFace = accessStoredMipFace(level); - if (mipFace && mipFace->getSize()) { - return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level); + if (!isStoredMipFaceAvailable(level)) { + return 0; } - return 0; + return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level); } uint32 Texture::getStoredMipSize(uint16 level) const { - PixelsPointer mipFace = accessStoredMipFace(level); - if (mipFace && mipFace->getSize()) { - return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level) * getTexelFormat().getSize(); + if (!isStoredMipFaceAvailable(level)) { + return 0; } - return 0; + + return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level) * getTexelFormat().getSize(); } gpu::Resource::Size Texture::getStoredSize() const { diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index ce71b41b77..d6185df0d4 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -25,6 +25,8 @@ namespace ktx { class KTX; using KTXUniquePointer = std::unique_ptr; + struct KTXDescriptor; + using KTXDescriptorPointer = std::unique_ptr; struct Header; } @@ -261,6 +263,7 @@ public: virtual void reset() = 0; virtual PixelsPointer getMipFace(uint16 level, uint8 face = 0) const = 0; + virtual Size getMipFaceSize(uint16 level, uint8 face = 0) const = 0; virtual void assignMipData(uint16 level, const storage::StoragePointer& storage) = 0; virtual void assignMipFaceData(uint16 level, uint8 face, const storage::StoragePointer& storage) = 0; virtual bool isMipAvailable(uint16 level, uint8 face = 0) const = 0; @@ -286,6 +289,7 @@ public: public: void reset() override; PixelsPointer getMipFace(uint16 level, uint8 face = 0) const override; + Size getMipFaceSize(uint16 level, uint8 face = 0) const override; void assignMipData(uint16 level, const storage::StoragePointer& storage) override; void assignMipFaceData(uint16 level, uint8 face, const storage::StoragePointer& storage) override; bool isMipAvailable(uint16 level, uint8 face = 0) const override; @@ -297,8 +301,9 @@ public: class KtxStorage : public Storage { public: - KtxStorage(ktx::KTXUniquePointer& ktxData); + KtxStorage(const std::string& filename); PixelsPointer getMipFace(uint16 level, uint8 face = 0) const override; + Size getMipFaceSize(uint16 level, uint8 face = 0) const override; // By convention, all mip levels and faces MUST be populated when using KTX backing bool isMipAvailable(uint16 level, uint8 face = 0) const override { return true; } @@ -312,7 +317,8 @@ public: void reset() override { } protected: - ktx::KTXUniquePointer _ktxData; + std::string _filename; + ktx::KTXDescriptorPointer _ktxDescriptor; friend class Texture; }; @@ -475,9 +481,10 @@ public: // Access the the sub mips bool isStoredMipFaceAvailable(uint16 level, uint8 face = 0) const { return _storage->isMipAvailable(level, face); } const PixelsPointer accessStoredMipFace(uint16 level, uint8 face = 0) const { return _storage->getMipFace(level, face); } + Size getStoredMipFaceSize(uint16 level, uint8 face = 0) const { return _storage->getMipFaceSize(level, face); } void setStorage(std::unique_ptr& newStorage); - void setKtxBacking(ktx::KTXUniquePointer& newBacking); + void setKtxBacking(const std::string& filename); // access sizes for the stored mips uint16 getStoredMipWidth(uint16 level) const; @@ -515,7 +522,7 @@ public: // Textures can be serialized directly to ktx data file, here is how static ktx::KTXUniquePointer serialize(const Texture& texture); - static Texture* unserialize(const ktx::KTXUniquePointer& srcData, TextureUsageType usageType = TextureUsageType::RESOURCE, Usage usage = Usage(), const Sampler::Desc& sampler = Sampler::Desc()); + static Texture* unserialize(const std::string& ktxFile, TextureUsageType usageType = TextureUsageType::RESOURCE, Usage usage = Usage(), const Sampler::Desc& sampler = Sampler::Desc()); static bool evalKTXFormat(const Element& mipFormat, const Element& texelFormat, ktx::Header& header); static bool evalTextureFormat(const ktx::Header& header, Element& mipFormat, Element& texelFormat); diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index ab5be7475a..913ced8141 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -42,30 +42,37 @@ struct GPUKTXPayload { std::string GPUKTXPayload::KEY { "hifi.gpu" }; -KtxStorage::KtxStorage(ktx::KTXUniquePointer& ktxData) { - - // if the source ktx is valid let's config this KtxStorage correctly - if (ktxData && ktxData->getHeader()) { - - // now that we know the ktx, let's get the header info to configure this Texture::Storage: - Format mipFormat = Format::COLOR_BGRA_32; - Format texelFormat = Format::COLOR_SRGBA_32; - if (Texture::evalTextureFormat(*ktxData->getHeader(), mipFormat, texelFormat)) { - _format = mipFormat; - } - - +KtxStorage::KtxStorage(const std::string& filename) : _filename(filename) { + { + ktx::StoragePointer storage { new storage::FileStorage(_filename.c_str()) }; + auto ktxPointer = ktx::KTX::create(storage); + _ktxDescriptor.reset(new ktx::KTXDescriptor(ktxPointer->toDescriptor())); } - _ktxData.reset(ktxData.release()); + // now that we know the ktx, let's get the header info to configure this Texture::Storage: + Format mipFormat = Format::COLOR_BGRA_32; + Format texelFormat = Format::COLOR_SRGBA_32; + if (Texture::evalTextureFormat(_ktxDescriptor->header, mipFormat, texelFormat)) { + _format = mipFormat; + } } PixelsPointer KtxStorage::getMipFace(uint16 level, uint8 face) const { - return _ktxData->getMipFaceTexelsData(level, face); + storage::StoragePointer result; + auto faceOffset = _ktxDescriptor->getMipFaceTexelsOffset(level, face); + auto faceSize = _ktxDescriptor->getMipFaceTexelsSize(level, face); + if (faceSize != 0 && faceOffset != 0) { + result = std::make_shared(_filename.c_str())->createView(faceSize, faceOffset)->toMemoryStorage(); + } + return result; } -void Texture::setKtxBacking(ktx::KTXUniquePointer& ktxBacking) { - auto newBacking = std::unique_ptr(new KtxStorage(ktxBacking)); +Size KtxStorage::getMipFaceSize(uint16 level, uint8 face) const { + return _ktxDescriptor->getMipFaceTexelsSize(level, face); +} + +void Texture::setKtxBacking(const std::string& filename) { + auto newBacking = std::unique_ptr(new KtxStorage(filename)); setStorage(newBacking); } @@ -177,11 +184,9 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { return ktxBuffer; } -Texture* Texture::unserialize(const ktx::KTXUniquePointer& srcData, TextureUsageType usageType, Usage usage, const Sampler::Desc& sampler) { - if (!srcData) { - return nullptr; - } - const auto& header = *srcData->getHeader(); +Texture* Texture::unserialize(const std::string& ktxfile, TextureUsageType usageType, Usage usage, const Sampler::Desc& sampler) { + ktx::KTXDescriptor descriptor { ktx::KTX::create(ktx::StoragePointer { new storage::FileStorage(ktxfile.c_str()) })->toDescriptor() }; + const auto& header = descriptor.header; Format mipFormat = Format::COLOR_BGRA_32; Format texelFormat = Format::COLOR_SRGBA_32; @@ -209,7 +214,7 @@ Texture* Texture::unserialize(const ktx::KTXUniquePointer& srcData, TextureUsage // If found, use the GPUKTXPayload gpuktxKeyValue; - bool isGPUKTXPayload = GPUKTXPayload::findInKeyValues(srcData->_keyValues, gpuktxKeyValue); + bool isGPUKTXPayload = GPUKTXPayload::findInKeyValues(descriptor.keyValues, gpuktxKeyValue); auto tex = Texture::create( (isGPUKTXPayload ? gpuktxKeyValue._usageType : usageType), type, @@ -225,14 +230,7 @@ Texture* Texture::unserialize(const ktx::KTXUniquePointer& srcData, TextureUsage // Assing the mips availables tex->setStoredMipFormat(mipFormat); - uint16_t level = 0; - for (auto& image : srcData->_images) { - for (uint32_t face = 0; face < image._numFaces; face++) { - tex->assignStoredMipFace(level, face, image._faceSize, image._faceBytes[face]); - } - level++; - } - + tex->setKtxBacking(ktxfile); return tex; } diff --git a/libraries/ktx/src/ktx/KTX.cpp b/libraries/ktx/src/ktx/KTX.cpp index bbd4e1bc86..6fca39788b 100644 --- a/libraries/ktx/src/ktx/KTX.cpp +++ b/libraries/ktx/src/ktx/KTX.cpp @@ -108,47 +108,39 @@ KTX::~KTX() { void KTX::resetStorage(const StoragePointer& storage) { _storage = storage; + if (_storage->size() >= sizeof(Header)) { + memcpy(&_header, _storage->data(), sizeof(Header)); + } } -const Header* KTX::getHeader() const { - if (!_storage) { - return nullptr; - } - return reinterpret_cast(_storage->data()); +const Header& KTX::getHeader() const { + return _header; } size_t KTX::getKeyValueDataSize() const { - if (_storage) { - return getHeader()->bytesOfKeyValueData; - } else { - return 0; - } + return _header.bytesOfKeyValueData; } size_t KTX::getTexelsDataSize() const { - if (_storage) { - //return _storage->size() - (sizeof(Header) + getKeyValueDataSize()); - return (_storage->data() + _storage->size()) - getTexelsData(); - } else { + if (!_storage) { return 0; } + return (_storage->data() + _storage->size()) - getTexelsData(); } const Byte* KTX::getKeyValueData() const { - if (_storage) { - return (_storage->data() + sizeof(Header)); - } else { + if (!_storage) { return nullptr; } + return (_storage->data() + sizeof(Header)); } const Byte* KTX::getTexelsData() const { - if (_storage) { - return (_storage->data() + sizeof(Header) + getKeyValueDataSize()); - } else { + if (!_storage) { return nullptr; } + return (_storage->data() + sizeof(Header) + getKeyValueDataSize()); } storage::StoragePointer KTX::getMipFaceTexelsData(uint16_t mip, uint8_t face) const { @@ -163,3 +155,58 @@ storage::StoragePointer KTX::getMipFaceTexelsData(uint16_t mip, uint8_t face) co } return result; } + +size_t KTXDescriptor::getMipFaceTexelsSize(uint16_t mip, uint8_t face) const { + size_t result { 0 }; + if (mip < images.size()) { + const auto& faces = images[mip]; + if (face < faces._numFaces) { + result = faces._faceSize; + } + } + return result; +} + +size_t KTXDescriptor::getMipFaceTexelsOffset(uint16_t mip, uint8_t face) const { + size_t result { 0 }; + if (mip < images.size()) { + const auto& faces = images[mip]; + if (face < faces._numFaces) { + result = faces._faceOffsets[face]; + } + } + return result; +} + +ImageDescriptor Image::toImageDescriptor(const Byte* baseAddress) const { + FaceOffsets offsets; + offsets.resize(_faceBytes.size()); + for (size_t face = 0; face < _numFaces; ++face) { + offsets[face] = _faceBytes[face] - baseAddress; + } + // Note, implicit cast of *this to const ImageHeader& + return ImageDescriptor(*this, offsets); +} + +Image ImageDescriptor::toImage(const ktx::StoragePointer& storage) const { + FaceBytes faces; + faces.resize(_faceOffsets.size()); + for (size_t face = 0; face < _numFaces; ++face) { + faces[face] = storage->data() + _faceOffsets[face]; + } + // Note, implicit cast of *this to const ImageHeader& + return Image(*this, faces); +} + +KTXDescriptor KTX::toDescriptor() const { + ImageDescriptors newDescriptors; + auto storageStart = _storage ? _storage->data() : nullptr; + for (size_t i = 0; i < _images.size(); ++i) { + newDescriptors.emplace_back(_images[i].toImageDescriptor(storageStart)); + } + return { this->_header, this->_keyValues, newDescriptors }; +} + +KTX::KTX(const StoragePointer& storage, const Header& header, const KeyValues& keyValues, const Images& images) + : _header(header), _storage(storage), _keyValues(keyValues), _images(images) { +} \ No newline at end of file diff --git a/libraries/ktx/src/ktx/KTX.h b/libraries/ktx/src/ktx/KTX.h index 8e901b1105..f09986991a 100644 --- a/libraries/ktx/src/ktx/KTX.h +++ b/libraries/ktx/src/ktx/KTX.h @@ -407,43 +407,69 @@ namespace ktx { }; using KeyValues = KeyValue::KeyValues; - - struct Image { + struct ImageHeader { + using FaceOffsets = std::vector; using FaceBytes = std::vector; - - uint32_t _numFaces{ 1 }; - uint32_t _imageSize; - uint32_t _faceSize; - uint32_t _padding; - FaceBytes _faceBytes; - - - Image(uint32_t imageSize, uint32_t padding, const Byte* bytes) : - _numFaces(1), - _imageSize(imageSize), + const uint32_t _numFaces; + const uint32_t _imageSize; + const uint32_t _faceSize; + const uint32_t _padding; + ImageHeader(bool cube, uint32_t imageSize, uint32_t padding) : + _numFaces(cube ? NUM_CUBEMAPFACES : 1), + _imageSize(imageSize * _numFaces), _faceSize(imageSize), - _padding(padding), - _faceBytes(1, bytes) {} + _padding(padding) { + } + }; + struct Image; + + struct ImageDescriptor : public ImageHeader { + const FaceOffsets _faceOffsets; + ImageDescriptor(const ImageHeader& header, const FaceOffsets& offsets) : ImageHeader(header), _faceOffsets(offsets) {} + Image toImage(const ktx::StoragePointer& storage) const; + }; + + using ImageDescriptors = std::vector; + + struct Image : public ImageHeader { + FaceBytes _faceBytes; + Image(const ImageHeader& header, const FaceBytes& faces) : ImageHeader(header), _faceBytes(faces) {} + Image(uint32_t imageSize, uint32_t padding, const Byte* bytes) : + ImageHeader(false, imageSize, padding), + _faceBytes(1, bytes) {} Image(uint32_t pageSize, uint32_t padding, const FaceBytes& cubeFaceBytes) : - _numFaces(NUM_CUBEMAPFACES), - _imageSize(pageSize * NUM_CUBEMAPFACES), - _faceSize(pageSize), - _padding(padding) + ImageHeader(true, pageSize, padding) { if (cubeFaceBytes.size() == NUM_CUBEMAPFACES) { _faceBytes = cubeFaceBytes; } } + + ImageDescriptor toImageDescriptor(const Byte* baseAddress) const; }; + using Images = std::vector; + class KTX; + + // A KTX descriptor is a lightweight container for all the information about a serialized KTX file, but without the + // actual image / face data available. + struct KTXDescriptor { + KTXDescriptor(const Header& header, const KeyValues& keyValues, const ImageDescriptors& imageDescriptors) : header(header), keyValues(keyValues), images(imageDescriptors) {} + const Header header; + const KeyValues keyValues; + const ImageDescriptors images; + size_t getMipFaceTexelsSize(uint16_t mip = 0, uint8_t face = 0) const; + size_t getMipFaceTexelsOffset(uint16_t mip = 0, uint8_t face = 0) const; + }; + class KTX { void resetStorage(const StoragePointer& src); KTX(); + KTX(const StoragePointer& storage, const Header& header, const KeyValues& keyValues, const Images& images); public: - ~KTX(); // Define a KTX object manually to write it somewhere (in a file on disk?) @@ -475,18 +501,23 @@ namespace ktx { static Images parseImages(const Header& header, size_t srcSize, const Byte* srcBytes); // Access raw pointers to the main sections of the KTX - const Header* getHeader() const; + const Header& getHeader() const; + const Byte* getKeyValueData() const; const Byte* getTexelsData() const; storage::StoragePointer getMipFaceTexelsData(uint16_t mip = 0, uint8_t face = 0) const; const StoragePointer& getStorage() const { return _storage; } + KTXDescriptor toDescriptor() const; size_t getKeyValueDataSize() const; size_t getTexelsDataSize() const; + Header _header; StoragePointer _storage; KeyValues _keyValues; Images _images; + + friend struct KTXDescriptor; }; } diff --git a/libraries/ktx/src/ktx/Reader.cpp b/libraries/ktx/src/ktx/Reader.cpp index 277ce42e69..bf72faeba5 100644 --- a/libraries/ktx/src/ktx/Reader.cpp +++ b/libraries/ktx/src/ktx/Reader.cpp @@ -185,10 +185,10 @@ namespace ktx { result->resetStorage(src); // read metadata - result->_keyValues = parseKeyValues(result->getHeader()->bytesOfKeyValueData, result->getKeyValueData()); + result->_keyValues = parseKeyValues(result->getHeader().bytesOfKeyValueData, result->getKeyValueData()); // populate image table - result->_images = parseImages(*result->getHeader(), result->getTexelsDataSize(), result->getTexelsData()); + result->_images = parseImages(result->getHeader(), result->getTexelsDataSize(), result->getTexelsData()); return result; } diff --git a/libraries/model-networking/src/model-networking/KTXCache.cpp b/libraries/model-networking/src/model-networking/KTXCache.cpp index 63d35fe4a4..8ec1c4e41c 100644 --- a/libraries/model-networking/src/model-networking/KTXCache.cpp +++ b/libraries/model-networking/src/model-networking/KTXCache.cpp @@ -38,10 +38,3 @@ std::unique_ptr KTXCache::createFile(Metadata&& metadata, const std::strin KTXFile::KTXFile(Metadata&& metadata, const std::string& filepath) : cache::File(std::move(metadata), filepath) {} -std::unique_ptr KTXFile::getKTX() const { - ktx::StoragePointer storage = std::make_shared(getFilepath().c_str()); - if (*storage) { - return ktx::KTX::create(storage); - } - return {}; -} diff --git a/libraries/model-networking/src/model-networking/KTXCache.h b/libraries/model-networking/src/model-networking/KTXCache.h index 4ef5e52721..bbf7ceadea 100644 --- a/libraries/model-networking/src/model-networking/KTXCache.h +++ b/libraries/model-networking/src/model-networking/KTXCache.h @@ -39,9 +39,6 @@ protected: class KTXFile : public cache::File { Q_OBJECT -public: - std::unique_ptr getKTX() const; - protected: friend class KTXCache; diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 5dfaddd471..98b03eba1e 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -438,15 +438,9 @@ void NetworkTexture::loadContent(const QByteArray& content) { if (!texture) { KTXFilePointer ktxFile = textureCache->_ktxCache.getFile(hash); if (ktxFile) { - // Ensure that the KTX deserialization worked - auto ktx = ktxFile->getKTX(); - if (ktx) { - texture.reset(gpu::Texture::unserialize(ktx)); - // Ensure that the texture population worked - if (texture) { - texture->setKtxBacking(ktx); - texture = textureCache->cacheTextureByHash(hash, texture); - } + texture.reset(gpu::Texture::unserialize(ktxFile->getFilepath())); + if (texture) { + texture = textureCache->cacheTextureByHash(hash, texture); } } } @@ -586,10 +580,7 @@ void ImageReader::read() { qCWarning(modelnetworking) << _url << "file cache failed"; } else { resource.staticCast()->_file = file; - auto fileKtx = file->getKTX(); - if (fileKtx) { - texture->setKtxBacking(fileKtx); - } + texture->setKtxBacking(file->getFilepath()); } } diff --git a/tests/ktx/src/main.cpp b/tests/ktx/src/main.cpp index aa6795e17b..3a6fcabf43 100644 --- a/tests/ktx/src/main.cpp +++ b/tests/ktx/src/main.cpp @@ -111,38 +111,40 @@ int main(int argc, char** argv) { outFile.close(); } - auto ktxFile = ktx::KTX::create(std::shared_ptr(new storage::FileStorage(TEST_IMAGE_KTX))); { - const auto& memStorage = ktxMemory->getStorage(); - const auto& fileStorage = ktxFile->getStorage(); - Q_ASSERT(memStorage->size() == fileStorage->size()); - Q_ASSERT(memStorage->data() != fileStorage->data()); - Q_ASSERT(0 == memcmp(memStorage->data(), fileStorage->data(), memStorage->size())); - Q_ASSERT(ktxFile->_images.size() == ktxMemory->_images.size()); - auto imageCount = ktxFile->_images.size(); - auto startMemory = ktxMemory->_storage->data(); - auto startFile = ktxFile->_storage->data(); - for (size_t i = 0; i < imageCount; ++i) { - auto memImages = ktxMemory->_images[i]; - auto fileImages = ktxFile->_images[i]; - Q_ASSERT(memImages._padding == fileImages._padding); - Q_ASSERT(memImages._numFaces == fileImages._numFaces); - Q_ASSERT(memImages._imageSize == fileImages._imageSize); - Q_ASSERT(memImages._faceSize == fileImages._faceSize); - Q_ASSERT(memImages._faceBytes.size() == memImages._numFaces); - Q_ASSERT(fileImages._faceBytes.size() == fileImages._numFaces); - auto faceCount = fileImages._numFaces; - for (uint32_t face = 0; face < faceCount; ++face) { - auto memFace = memImages._faceBytes[face]; - auto memOffset = memFace - startMemory; - auto fileFace = fileImages._faceBytes[face]; - auto fileOffset = fileFace - startFile; - Q_ASSERT(memOffset % 4 == 0); - Q_ASSERT(memOffset == fileOffset); + auto ktxFile = ktx::KTX::create(std::shared_ptr(new storage::FileStorage(TEST_IMAGE_KTX))); + { + const auto& memStorage = ktxMemory->getStorage(); + const auto& fileStorage = ktxFile->getStorage(); + Q_ASSERT(memStorage->size() == fileStorage->size()); + Q_ASSERT(memStorage->data() != fileStorage->data()); + Q_ASSERT(0 == memcmp(memStorage->data(), fileStorage->data(), memStorage->size())); + Q_ASSERT(ktxFile->_images.size() == ktxMemory->_images.size()); + auto imageCount = ktxFile->_images.size(); + auto startMemory = ktxMemory->_storage->data(); + auto startFile = ktxFile->_storage->data(); + for (size_t i = 0; i < imageCount; ++i) { + auto memImages = ktxMemory->_images[i]; + auto fileImages = ktxFile->_images[i]; + Q_ASSERT(memImages._padding == fileImages._padding); + Q_ASSERT(memImages._numFaces == fileImages._numFaces); + Q_ASSERT(memImages._imageSize == fileImages._imageSize); + Q_ASSERT(memImages._faceSize == fileImages._faceSize); + Q_ASSERT(memImages._faceBytes.size() == memImages._numFaces); + Q_ASSERT(fileImages._faceBytes.size() == fileImages._numFaces); + auto faceCount = fileImages._numFaces; + for (uint32_t face = 0; face < faceCount; ++face) { + auto memFace = memImages._faceBytes[face]; + auto memOffset = memFace - startMemory; + auto fileFace = fileImages._faceBytes[face]; + auto fileOffset = fileFace - startFile; + Q_ASSERT(memOffset % 4 == 0); + Q_ASSERT(memOffset == fileOffset); + } } } } - testTexture->setKtxBacking(ktxFile); + testTexture->setKtxBacking(TEST_IMAGE_KTX.toStdString()); return 0; }