mirror of
https://github.com/lubosz/overte.git
synced 2025-04-16 14:16:36 +02:00
Add some testing / validation for KTX
This commit is contained in:
parent
c6b72dfe3c
commit
a2269f488f
7 changed files with 176 additions and 96 deletions
|
@ -93,6 +93,27 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) {
|
|||
}
|
||||
|
||||
auto ktxBuffer = ktx::KTX::create(header, images);
|
||||
|
||||
assert(0 == memcmp(&header, ktxBuffer->getHeader(), sizeof(ktx::Header)));
|
||||
assert(ktxBuffer->_images.size() == images.size());
|
||||
auto start = ktxBuffer->_storage->data();
|
||||
for (size_t i = 0; i < images.size(); ++i) {
|
||||
auto expected = images[i];
|
||||
auto actual = ktxBuffer->_images[i];
|
||||
assert(expected._padding == actual._padding);
|
||||
assert(expected._numFaces == actual._numFaces);
|
||||
assert(expected._imageSize == actual._imageSize);
|
||||
assert(expected._faceSize == actual._faceSize);
|
||||
assert(actual._faceBytes.size() == actual._numFaces);
|
||||
for (uint32_t face = 0; face < expected._numFaces; ++face) {
|
||||
auto expectedFace = expected._faceBytes[face];
|
||||
auto actualFace = actual._faceBytes[face];
|
||||
auto offset = actualFace - start;
|
||||
assert(offset % 4 == 0);
|
||||
assert(expectedFace != actualFace);
|
||||
assert(0 == memcmp(expectedFace, actualFace, expected._faceSize));
|
||||
}
|
||||
}
|
||||
return ktxBuffer;
|
||||
}
|
||||
|
||||
|
|
|
@ -86,11 +86,10 @@ void KTX::resetStorage(Storage* storage) {
|
|||
}
|
||||
|
||||
const Header* KTX::getHeader() const {
|
||||
if (_storage) {
|
||||
return reinterpret_cast<const Header*> (_storage->_bytes);
|
||||
} else {
|
||||
if (!_storage) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return reinterpret_cast<const Header*>(_storage->data());
|
||||
}
|
||||
|
||||
|
||||
|
@ -105,7 +104,7 @@ size_t KTX::getKeyValueDataSize() const {
|
|||
size_t KTX::getTexelsDataSize() const {
|
||||
if (_storage) {
|
||||
//return _storage->size() - (sizeof(Header) + getKeyValueDataSize());
|
||||
return (_storage->_bytes + _storage->_size) - getTexelsData();
|
||||
return (_storage->data() + _storage->size()) - getTexelsData();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -113,7 +112,7 @@ size_t KTX::getTexelsDataSize() const {
|
|||
|
||||
const Byte* KTX::getKeyValueData() const {
|
||||
if (_storage) {
|
||||
return (_storage->_bytes + sizeof(Header));
|
||||
return (_storage->data() + sizeof(Header));
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -121,16 +120,9 @@ const Byte* KTX::getKeyValueData() const {
|
|||
|
||||
const Byte* KTX::getTexelsData() const {
|
||||
if (_storage) {
|
||||
return (_storage->_bytes + sizeof(Header) + getKeyValueDataSize());
|
||||
return (_storage->data() + sizeof(Header) + getKeyValueDataSize());
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Byte* KTX::getTexelsData() {
|
||||
if (_storage) {
|
||||
return (_storage->_bytes + sizeof(Header) + getKeyValueDataSize());
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include <shared/Storage.h>
|
||||
|
||||
/* KTX Spec:
|
||||
|
||||
Byte[12] identifier
|
||||
|
@ -291,46 +293,8 @@ namespace ktx {
|
|||
NUM_CUBEMAPFACES = 6,
|
||||
};
|
||||
|
||||
|
||||
// Chunk of data
|
||||
struct Storage {
|
||||
size_t _size {0};
|
||||
Byte* _bytes {nullptr};
|
||||
|
||||
Byte* data() {
|
||||
return _bytes;
|
||||
}
|
||||
const Byte* data() const {
|
||||
return _bytes;
|
||||
}
|
||||
size_t size() const { return _size; }
|
||||
|
||||
~Storage() { if (_bytes) { delete _bytes; } }
|
||||
|
||||
Storage() {}
|
||||
Storage(size_t size) :
|
||||
_size(size)
|
||||
{
|
||||
if (_size) { _bytes = new Byte[_size]; }
|
||||
}
|
||||
|
||||
Storage(size_t size, Byte* bytes) :
|
||||
_size(size)
|
||||
{
|
||||
if (_size && _bytes) { _bytes = bytes; }
|
||||
}
|
||||
Storage(size_t size, const Byte* bytes) :
|
||||
Storage(size)
|
||||
{
|
||||
if (_size && _bytes && bytes) {
|
||||
memcpy(_bytes, bytes, size);
|
||||
}
|
||||
}
|
||||
Storage(const Storage& src) :
|
||||
Storage(src.size(), src.data())
|
||||
{}
|
||||
|
||||
};
|
||||
using Storage = storage::Storage;
|
||||
using StoragePointer = std::unique_ptr<Storage>;
|
||||
|
||||
// Header
|
||||
struct Header {
|
||||
|
@ -382,7 +346,8 @@ namespace ktx {
|
|||
|
||||
void setUncompressed(GLType type, uint32_t typeSize, GLFormat format, GLInternalFormat_Uncompressed internalFormat, GLBaseInternalFormat baseInternalFormat) {
|
||||
glType = (uint32_t) type;
|
||||
glTypeSize = 0;
|
||||
// FIXME this should correspond to the size of glType
|
||||
glTypeSize = 1;
|
||||
glFormat = (uint32_t) format;
|
||||
glInternalFormat = (uint32_t) internalFormat;
|
||||
glBaseInternalFormat = (uint32_t) baseInternalFormat;
|
||||
|
@ -456,13 +421,9 @@ namespace ktx {
|
|||
};
|
||||
using Images = std::vector<Image>;
|
||||
|
||||
|
||||
class KTX {
|
||||
void resetStorage(Storage* src);
|
||||
|
||||
void resetHeader(const Header& header);
|
||||
void resetImages(const Images& images);
|
||||
|
||||
KTX();
|
||||
public:
|
||||
|
||||
|
@ -498,12 +459,12 @@ namespace ktx {
|
|||
const Header* getHeader() const;
|
||||
const Byte* getKeyValueData() const;
|
||||
const Byte* getTexelsData() const;
|
||||
Byte* getTexelsData();
|
||||
const StoragePointer& getStorage() const { return _storage; }
|
||||
|
||||
size_t getKeyValueDataSize() const;
|
||||
size_t getTexelsDataSize() const;
|
||||
|
||||
std::unique_ptr<Storage> _storage;
|
||||
StoragePointer _storage;
|
||||
KeyValues _keyValues;
|
||||
Images _images;
|
||||
};
|
||||
|
|
|
@ -26,40 +26,15 @@ namespace ktx {
|
|||
const std::string _explanation;
|
||||
};
|
||||
|
||||
|
||||
void KTX::resetHeader(const Header& header) {
|
||||
if (!_storage) {
|
||||
return;
|
||||
}
|
||||
memcpy(_storage->_bytes, &header, sizeof(Header));
|
||||
}
|
||||
void KTX::resetImages(const Images& srcImages) {
|
||||
auto imagesDataPtr = getTexelsData();
|
||||
if (!imagesDataPtr) {
|
||||
return;
|
||||
}
|
||||
auto allocatedImagesDataSize = getTexelsDataSize();
|
||||
|
||||
// Just copy in our storage
|
||||
_images = writeImages(imagesDataPtr, allocatedImagesDataSize, srcImages);
|
||||
}
|
||||
|
||||
std::unique_ptr<KTX> KTX::create(const Header& header, const Images& images, const KeyValues& keyValues) {
|
||||
auto storageSize = evalStorageSize(header, images, keyValues);
|
||||
|
||||
std::unique_ptr<KTX> result(new KTX());
|
||||
|
||||
result->resetStorage(new Storage(storageSize));
|
||||
|
||||
result->resetHeader(header);
|
||||
|
||||
// read metadata
|
||||
result->_keyValues = keyValues;
|
||||
|
||||
// populate image table
|
||||
result->resetImages(images);
|
||||
|
||||
return result;
|
||||
std::unique_ptr<storage::Storage> storagePointer;
|
||||
{
|
||||
auto storageSize = ktx::KTX::evalStorageSize(header, images);
|
||||
auto memoryStorage = new storage::MemoryStorage(storageSize);
|
||||
ktx::KTX::write(memoryStorage->data(), memoryStorage->size(), header, images);
|
||||
storagePointer.reset(memoryStorage);
|
||||
}
|
||||
return create(storagePointer);
|
||||
}
|
||||
|
||||
size_t KTX::evalStorageSize(const Header& header, const Images& images, const KeyValues& keyValues) {
|
||||
|
@ -117,8 +92,6 @@ namespace ktx {
|
|||
size_t currentDataSize = 0;
|
||||
auto currentPtr = imagesDataPtr;
|
||||
|
||||
|
||||
|
||||
for (uint32_t l = 0; l < srcImages.size(); l++) {
|
||||
if (currentDataSize + sizeof(uint32_t) < allocatedImagesDataSize) {
|
||||
size_t imageSize = srcImages[l]._imageSize;
|
||||
|
|
1
scripts/developer/tests/.gitignore
vendored
Normal file
1
scripts/developer/tests/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
cube_texture.ktx
|
15
tests/ktx/CMakeLists.txt
Normal file
15
tests/ktx/CMakeLists.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
set(TARGET_NAME ktx-test)
|
||||
|
||||
if (WIN32)
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ignore:4049 /ignore:4217")
|
||||
endif()
|
||||
|
||||
# This is not a testcase -- just set it up as a regular hifi project
|
||||
setup_hifi_project(Quick Gui OpenGL)
|
||||
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/")
|
||||
|
||||
# link in the shared libraries
|
||||
link_hifi_libraries(shared octree ktx gl gpu gpu-gl render model model-networking networking render-utils fbx entities entities-renderer animation audio avatars script-engine physics)
|
||||
|
||||
package_libraries_for_deployment()
|
117
tests/ktx/src/main.cpp
Normal file
117
tests/ktx/src/main.cpp
Normal file
|
@ -0,0 +1,117 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2016/07/01
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
#include <QProcessEnvironment>
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QElapsedTimer>
|
||||
#include <QtCore/QLoggingCategory>
|
||||
#include <QtCore/QRegularExpression>
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/QThreadPool>
|
||||
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QResizeEvent>
|
||||
#include <QtGui/QWindow>
|
||||
|
||||
#include <QtWidgets/QFileDialog>
|
||||
#include <QtWidgets/QInputDialog>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QApplication>
|
||||
|
||||
#include <shared/RateCounter.h>
|
||||
#include <shared/NetworkUtils.h>
|
||||
#include <shared/FileLogger.h>
|
||||
#include <shared/FileUtils.h>
|
||||
#include <StatTracker.h>
|
||||
#include <LogHandler.h>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <gpu/Texture.h>
|
||||
#include <gl/Config.h>
|
||||
#include <model/TextureMap.h>
|
||||
#include <ktx/KTX.h>
|
||||
|
||||
|
||||
QSharedPointer<FileLogger> logger;
|
||||
|
||||
gpu::Texture* cacheTexture(const std::string& name, gpu::Texture* srcTexture, bool write = true, bool read = true);
|
||||
|
||||
|
||||
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {
|
||||
QString logMessage = LogHandler::getInstance().printMessage((LogMsgType)type, context, message);
|
||||
|
||||
if (!logMessage.isEmpty()) {
|
||||
#ifdef Q_OS_WIN
|
||||
OutputDebugStringA(logMessage.toLocal8Bit().constData());
|
||||
OutputDebugStringA("\n");
|
||||
#endif
|
||||
logger->addMessage(qPrintable(logMessage + "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
const char * LOG_FILTER_RULES = R"V0G0N(
|
||||
hifi.gpu=true
|
||||
)V0G0N";
|
||||
|
||||
QString getRootPath() {
|
||||
static std::once_flag once;
|
||||
static QString result;
|
||||
std::call_once(once, [&] {
|
||||
QFileInfo file(__FILE__);
|
||||
QDir parent = file.absolutePath();
|
||||
result = QDir::cleanPath(parent.currentPath() + "/../../..");
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
const QString TEST_IMAGE = getRootPath() + "/scripts/developer/tests/cube_texture.png";
|
||||
const QString TEST_IMAGE_KTX = getRootPath() + "/scripts/developer/tests/cube_texture.ktx";
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
QApplication app(argc, argv);
|
||||
QCoreApplication::setApplicationName("KTX");
|
||||
QCoreApplication::setOrganizationName("High Fidelity");
|
||||
QCoreApplication::setOrganizationDomain("highfidelity.com");
|
||||
logger.reset(new FileLogger());
|
||||
|
||||
DependencyManager::set<tracing::Tracer>();
|
||||
qInstallMessageHandler(messageHandler);
|
||||
QLoggingCategory::setFilterRules(LOG_FILTER_RULES);
|
||||
|
||||
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 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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "main.moc"
|
||||
|
Loading…
Reference in a new issue