mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 14:08:51 +02:00
More KTX testing, functionality
This commit is contained in:
parent
05efac9ddf
commit
62422690d0
5 changed files with 98 additions and 25 deletions
|
@ -19,6 +19,7 @@
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
#include <Trace.h>
|
#include <Trace.h>
|
||||||
|
|
||||||
|
#include <ktx/KTX.h>
|
||||||
#include <NumericalConstants.h>
|
#include <NumericalConstants.h>
|
||||||
|
|
||||||
#include "GPULogging.h"
|
#include "GPULogging.h"
|
||||||
|
@ -120,19 +121,24 @@ void Texture::setAllowedGPUMemoryUsage(Size size) {
|
||||||
|
|
||||||
uint8 Texture::NUM_FACES_PER_TYPE[NUM_TYPES] = { 1, 1, 1, 6 };
|
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;
|
_texture = texture;
|
||||||
if (_texture) {
|
if (_texture) {
|
||||||
_type = _texture->getType();
|
_type = _texture->getType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::MemoryStorage::reset() {
|
void MemoryStorage::reset() {
|
||||||
_mips.clear();
|
_mips.clear();
|
||||||
bumpStamp();
|
bumpStamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Texture::PixelsPointer Texture::MemoryStorage::getMipFace(uint16 level, uint8 face) const {
|
PixelsPointer MemoryStorage::getMipFace(uint16 level, uint8 face) const {
|
||||||
if (level < _mips.size()) {
|
if (level < _mips.size()) {
|
||||||
assert(face < _mips[level].size());
|
assert(face < _mips[level].size());
|
||||||
return _mips[level][face];
|
return _mips[level][face];
|
||||||
|
@ -140,12 +146,12 @@ const Texture::PixelsPointer Texture::MemoryStorage::getMipFace(uint16 level, ui
|
||||||
return PixelsPointer();
|
return PixelsPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Texture::MemoryStorage::isMipAvailable(uint16 level, uint8 face) const {
|
bool MemoryStorage::isMipAvailable(uint16 level, uint8 face) const {
|
||||||
PixelsPointer mipFace = getMipFace(level, face);
|
PixelsPointer mipFace = getMipFace(level, face);
|
||||||
return (mipFace && mipFace->getSize());
|
return (mipFace && mipFace->getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Texture::MemoryStorage::allocateMip(uint16 level) {
|
bool MemoryStorage::allocateMip(uint16 level) {
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
if (level >= _mips.size()) {
|
if (level >= _mips.size()) {
|
||||||
_mips.resize(level+1, std::vector<PixelsPointer>(Texture::NUM_FACES_PER_TYPE[getType()]));
|
_mips.resize(level+1, std::vector<PixelsPointer>(Texture::NUM_FACES_PER_TYPE[getType()]));
|
||||||
|
@ -164,7 +170,7 @@ bool Texture::MemoryStorage::allocateMip(uint16 level) {
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::MemoryStorage::assignMipData(uint16 level, const storage::StoragePointer& storagePointer) {
|
void MemoryStorage::assignMipData(uint16 level, const storage::StoragePointer& storagePointer) {
|
||||||
|
|
||||||
allocateMip(level);
|
allocateMip(level);
|
||||||
auto& mip = _mips[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* Texture::createExternal(const ExternalRecycler& recycler, const Sampler& sampler) {
|
||||||
Texture* tex = new Texture(TextureUsageType::EXTERNAL);
|
Texture* tex = new Texture(TextureUsageType::EXTERNAL);
|
||||||
tex->_type = TEX_2D;
|
tex->_type = TEX_2D;
|
||||||
|
@ -963,3 +976,11 @@ Texture::ExternalUpdates Texture::getUpdates() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Texture::setStorage(std::unique_ptr<Storage>& newStorage) {
|
||||||
|
_storage.swap(newStorage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Texture::setKtxBacking(ktx::KTXUniquePointer& ktxBacking) {
|
||||||
|
auto newBacking = std::unique_ptr<Storage>(new KtxStorage(ktxBacking));
|
||||||
|
setStorage(newBacking);
|
||||||
|
}
|
|
@ -256,7 +256,7 @@ public:
|
||||||
virtual ~Storage() {}
|
virtual ~Storage() {}
|
||||||
|
|
||||||
virtual void reset() = 0;
|
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 assignMipData(uint16 level, const storage::StoragePointer& storage) = 0;
|
||||||
virtual void assignMipFaceData(uint16 level, uint8 face, 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;
|
virtual bool isMipAvailable(uint16 level, uint8 face = 0) const = 0;
|
||||||
|
@ -281,7 +281,7 @@ public:
|
||||||
class MemoryStorage : public Storage {
|
class MemoryStorage : public Storage {
|
||||||
public:
|
public:
|
||||||
void reset() override;
|
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 assignMipData(uint16 level, const storage::StoragePointer& storage) override;
|
||||||
void assignMipFaceData(uint16 level, uint8 face, 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;
|
bool isMipAvailable(uint16 level, uint8 face = 0) const override;
|
||||||
|
@ -294,8 +294,9 @@ public:
|
||||||
class KtxStorage : public Storage {
|
class KtxStorage : public Storage {
|
||||||
public:
|
public:
|
||||||
KtxStorage(ktx::KTXUniquePointer& ktxData);
|
KtxStorage(ktx::KTXUniquePointer& ktxData);
|
||||||
const PixelsPointer getMipFace(uint16 level, uint8 face = 0) const override;
|
PixelsPointer getMipFace(uint16 level, uint8 face = 0) const override;
|
||||||
bool isMipAvailable(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 {
|
void assignMipData(uint16 level, const storage::StoragePointer& storage) override {
|
||||||
throw std::runtime_error("Invalid call");
|
throw std::runtime_error("Invalid call");
|
||||||
|
@ -474,6 +475,9 @@ public:
|
||||||
bool isStoredMipFaceAvailable(uint16 level, uint8 face = 0) const { return _storage->isMipAvailable(level, face); }
|
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); }
|
const PixelsPointer accessStoredMipFace(uint16 level, uint8 face = 0) const { return _storage->getMipFace(level, face); }
|
||||||
|
|
||||||
|
void setStorage(std::unique_ptr<Storage>& newStorage);
|
||||||
|
void setKtxBacking(ktx::KTXUniquePointer& newBacking);
|
||||||
|
|
||||||
// access sizes for the stored mips
|
// access sizes for the stored mips
|
||||||
uint16 getStoredMipWidth(uint16 level) const;
|
uint16 getStoredMipWidth(uint16 level) const;
|
||||||
uint16 getStoredMipHeight(uint16 level) const;
|
uint16 getStoredMipHeight(uint16 level) const;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -459,6 +459,7 @@ namespace ktx {
|
||||||
const Header* getHeader() const;
|
const Header* getHeader() const;
|
||||||
const Byte* getKeyValueData() const;
|
const Byte* getKeyValueData() const;
|
||||||
const Byte* getTexelsData() const;
|
const Byte* getTexelsData() const;
|
||||||
|
storage::StoragePointer getMipFaceTexelsData(uint16_t mip = 0, uint8_t face = 0) const;
|
||||||
const StoragePointer& getStorage() const { return _storage; }
|
const StoragePointer& getStorage() const { return _storage; }
|
||||||
|
|
||||||
size_t getKeyValueDataSize() const;
|
size_t getKeyValueDataSize() const;
|
||||||
|
|
|
@ -87,6 +87,8 @@ int main(int argc, char** argv) {
|
||||||
QCoreApplication::setOrganizationDomain("highfidelity.com");
|
QCoreApplication::setOrganizationDomain("highfidelity.com");
|
||||||
logger.reset(new FileLogger());
|
logger.reset(new FileLogger());
|
||||||
|
|
||||||
|
Q_ASSERT(sizeof(ktx::Header) == 12 + (sizeof(uint32_t) * 13));
|
||||||
|
|
||||||
DependencyManager::set<tracing::Tracer>();
|
DependencyManager::set<tracing::Tracer>();
|
||||||
qInstallMessageHandler(messageHandler);
|
qInstallMessageHandler(messageHandler);
|
||||||
QLoggingCategory::setFilterRules(LOG_FILTER_RULES);
|
QLoggingCategory::setFilterRules(LOG_FILTER_RULES);
|
||||||
|
@ -94,22 +96,55 @@ int main(int argc, char** argv) {
|
||||||
QImage image(TEST_IMAGE);
|
QImage image(TEST_IMAGE);
|
||||||
gpu::Texture* testTexture = model::TextureUsage::process2DTextureColorFromImage(image, TEST_IMAGE.toStdString(), true, false, true);
|
gpu::Texture* testTexture = model::TextureUsage::process2DTextureColorFromImage(image, TEST_IMAGE.toStdString(), true, false, true);
|
||||||
|
|
||||||
auto ktxPtr = gpu::Texture::serialize(*testTexture);
|
auto ktxMemory = gpu::Texture::serialize(*testTexture);
|
||||||
const auto& ktxStorage = ktxPtr->getStorage();
|
{
|
||||||
auto header = ktxPtr->getHeader();
|
const auto& ktxStorage = ktxMemory->getStorage();
|
||||||
assert(sizeof(ktx::Header) == 12 + (sizeof(uint32_t) * 13));
|
auto header = ktxMemory->getHeader();
|
||||||
QFile outFile(TEST_IMAGE_KTX);
|
QFile outFile(TEST_IMAGE_KTX);
|
||||||
if (!outFile.open(QFile::Truncate | QFile::ReadWrite)) {
|
if (!outFile.open(QFile::Truncate | QFile::ReadWrite)) {
|
||||||
throw std::runtime_error("Unable to open file");
|
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();
|
auto ktxFile = ktx::KTX::create(std::unique_ptr<storage::Storage>(new storage::FileStorage(TEST_IMAGE_KTX)));
|
||||||
outFile.resize(ktxSize);
|
{
|
||||||
auto dest = outFile.map(0, ktxSize);
|
const auto& memStorage = ktxMemory->getStorage();
|
||||||
memcpy(dest, ktxStorage->data(), ktxSize);
|
const auto& fileStorage = ktxFile->getStorage();
|
||||||
outFile.unmap(dest);
|
Q_ASSERT(memStorage->size() == fileStorage->size());
|
||||||
outFile.close();
|
Q_ASSERT(memStorage->data() != fileStorage->data());
|
||||||
// gpu::Texture* ktxTexture = cacheTexture(TEST_IMAGE.toStdString(), testTexture, true, true);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue