From 62422690d05e037a7ea7680db3563755a68bfad1 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 22 Feb 2017 15:44:06 -0800 Subject: [PATCH] More KTX testing, functionality --- libraries/gpu/src/gpu/Texture.cpp | 33 +++++++++++++--- libraries/gpu/src/gpu/Texture.h | 12 ++++-- libraries/ktx/src/ktx/KTX.cpp | 12 ++++++ libraries/ktx/src/ktx/KTX.h | 1 + tests/ktx/src/main.cpp | 65 ++++++++++++++++++++++++------- 5 files changed, 98 insertions(+), 25 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index aa81b34914..4b2156ec79 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include "GPULogging.h" @@ -120,19 +121,24 @@ void Texture::setAllowedGPUMemoryUsage(Size size) { uint8 Texture::NUM_FACES_PER_TYPE[NUM_TYPES] = { 1, 1, 1, 6 }; -void Texture::Storage::assignTexture(Texture* texture) { +using Storage = Texture::Storage; +using PixelsPointer = Texture::PixelsPointer; +using MemoryStorage = Texture::MemoryStorage; +using KtxStorage = Texture::KtxStorage; + +void Storage::assignTexture(Texture* texture) { _texture = texture; if (_texture) { _type = _texture->getType(); } } -void Texture::MemoryStorage::reset() { +void MemoryStorage::reset() { _mips.clear(); bumpStamp(); } -const Texture::PixelsPointer Texture::MemoryStorage::getMipFace(uint16 level, uint8 face) const { +PixelsPointer MemoryStorage::getMipFace(uint16 level, uint8 face) const { if (level < _mips.size()) { assert(face < _mips[level].size()); return _mips[level][face]; @@ -140,12 +146,12 @@ const Texture::PixelsPointer Texture::MemoryStorage::getMipFace(uint16 level, ui return PixelsPointer(); } -bool Texture::MemoryStorage::isMipAvailable(uint16 level, uint8 face) const { +bool MemoryStorage::isMipAvailable(uint16 level, uint8 face) const { PixelsPointer mipFace = getMipFace(level, face); return (mipFace && mipFace->getSize()); } -bool Texture::MemoryStorage::allocateMip(uint16 level) { +bool MemoryStorage::allocateMip(uint16 level) { bool changed = false; if (level >= _mips.size()) { _mips.resize(level+1, std::vector(Texture::NUM_FACES_PER_TYPE[getType()])); @@ -164,7 +170,7 @@ bool Texture::MemoryStorage::allocateMip(uint16 level) { return changed; } -void Texture::MemoryStorage::assignMipData(uint16 level, const storage::StoragePointer& storagePointer) { +void MemoryStorage::assignMipData(uint16 level, const storage::StoragePointer& storagePointer) { allocateMip(level); auto& mip = _mips[level]; @@ -193,6 +199,13 @@ void Texture::MemoryStorage::assignMipFaceData(uint16 level, uint8 face, const s } } +KtxStorage::KtxStorage(ktx::KTXUniquePointer& ktxData) : _ktxData(ktxData.release()) { +} + +PixelsPointer KtxStorage::getMipFace(uint16 level, uint8 face) const { + return _ktxData->getMipFaceTexelsData(level, face); +} + Texture* Texture::createExternal(const ExternalRecycler& recycler, const Sampler& sampler) { Texture* tex = new Texture(TextureUsageType::EXTERNAL); tex->_type = TEX_2D; @@ -963,3 +976,11 @@ Texture::ExternalUpdates Texture::getUpdates() const { return result; } +void Texture::setStorage(std::unique_ptr& newStorage) { + _storage.swap(newStorage); +} + +void Texture::setKtxBacking(ktx::KTXUniquePointer& ktxBacking) { + auto newBacking = std::unique_ptr(new KtxStorage(ktxBacking)); + setStorage(newBacking); +} \ No newline at end of file diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index a8fd9e3b0d..637b098504 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -256,7 +256,7 @@ public: virtual ~Storage() {} virtual void reset() = 0; - virtual const PixelsPointer getMipFace(uint16 level, uint8 face = 0) const = 0; + virtual PixelsPointer getMipFace(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; @@ -281,7 +281,7 @@ public: class MemoryStorage : public Storage { public: void reset() override; - const PixelsPointer getMipFace(uint16 level, uint8 face = 0) const override; + PixelsPointer getMipFace(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; @@ -294,8 +294,9 @@ public: class KtxStorage : public Storage { public: KtxStorage(ktx::KTXUniquePointer& ktxData); - const PixelsPointer getMipFace(uint16 level, uint8 face = 0) const override; - bool isMipAvailable(uint16 level, uint8 face = 0) const override; + PixelsPointer getMipFace(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; } void assignMipData(uint16 level, const storage::StoragePointer& storage) override { throw std::runtime_error("Invalid call"); @@ -474,6 +475,9 @@ public: 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); } + void setStorage(std::unique_ptr& newStorage); + void setKtxBacking(ktx::KTXUniquePointer& newBacking); + // access sizes for the stored mips uint16 getStoredMipWidth(uint16 level) const; uint16 getStoredMipHeight(uint16 level) const; diff --git a/libraries/ktx/src/ktx/KTX.cpp b/libraries/ktx/src/ktx/KTX.cpp index ea7653e1ed..e30bde64d6 100644 --- a/libraries/ktx/src/ktx/KTX.cpp +++ b/libraries/ktx/src/ktx/KTX.cpp @@ -126,3 +126,15 @@ const Byte* KTX::getTexelsData() const { } } +storage::StoragePointer KTX::getMipFaceTexelsData(uint16_t mip, uint8_t face) const { + storage::StoragePointer result; + if (mip < _images.size()) { + const auto& faces = _images[mip]; + if (face < faces._numFaces) { + auto faceOffset = faces._faceBytes[face] - _storage->data(); + auto faceSize = faces._faceSize; + result = _storage->createView(faceSize, faceOffset); + } + } + return result; +} diff --git a/libraries/ktx/src/ktx/KTX.h b/libraries/ktx/src/ktx/KTX.h index c1521a52b9..783f7e428c 100644 --- a/libraries/ktx/src/ktx/KTX.h +++ b/libraries/ktx/src/ktx/KTX.h @@ -459,6 +459,7 @@ namespace ktx { 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; } size_t getKeyValueDataSize() const; diff --git a/tests/ktx/src/main.cpp b/tests/ktx/src/main.cpp index a3c3b99960..2dbf2f60d7 100644 --- a/tests/ktx/src/main.cpp +++ b/tests/ktx/src/main.cpp @@ -87,6 +87,8 @@ int main(int argc, char** argv) { QCoreApplication::setOrganizationDomain("highfidelity.com"); logger.reset(new FileLogger()); + Q_ASSERT(sizeof(ktx::Header) == 12 + (sizeof(uint32_t) * 13)); + DependencyManager::set(); qInstallMessageHandler(messageHandler); QLoggingCategory::setFilterRules(LOG_FILTER_RULES); @@ -94,22 +96,55 @@ int main(int argc, char** argv) { QImage image(TEST_IMAGE); gpu::Texture* testTexture = model::TextureUsage::process2DTextureColorFromImage(image, TEST_IMAGE.toStdString(), true, false, true); - auto ktxPtr = gpu::Texture::serialize(*testTexture); - const auto& ktxStorage = ktxPtr->getStorage(); - auto header = ktxPtr->getHeader(); - assert(sizeof(ktx::Header) == 12 + (sizeof(uint32_t) * 13)); - QFile outFile(TEST_IMAGE_KTX); - if (!outFile.open(QFile::Truncate | QFile::ReadWrite)) { - throw std::runtime_error("Unable to open file"); + auto ktxMemory = gpu::Texture::serialize(*testTexture); + { + const auto& ktxStorage = ktxMemory->getStorage(); + auto header = ktxMemory->getHeader(); + QFile outFile(TEST_IMAGE_KTX); + if (!outFile.open(QFile::Truncate | QFile::ReadWrite)) { + throw std::runtime_error("Unable to open file"); + } + //auto ktxSize = sizeof(ktx::Header); // ktxStorage->size() + auto ktxSize = ktxStorage->size(); + outFile.resize(ktxSize); + auto dest = outFile.map(0, ktxSize); + memcpy(dest, ktxStorage->data(), ktxSize); + outFile.unmap(dest); + outFile.close(); } - //auto ktxSize = sizeof(ktx::Header); // ktxStorage->size() - auto ktxSize = ktxStorage->size(); - outFile.resize(ktxSize); - auto dest = outFile.map(0, ktxSize); - memcpy(dest, ktxStorage->data(), ktxSize); - outFile.unmap(dest); - outFile.close(); -// gpu::Texture* ktxTexture = cacheTexture(TEST_IMAGE.toStdString(), testTexture, true, true); + + auto ktxFile = ktx::KTX::create(std::unique_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); return 0; }