mirror of
https://github.com/overte-org/overte.git
synced 2025-04-13 13:12:11 +02:00
progressing on io with ktx
This commit is contained in:
parent
0d2e764bfd
commit
b4745657e0
5 changed files with 185 additions and 79 deletions
|
@ -263,27 +263,27 @@ Texture* Texture::createExternal(const ExternalRecycler& recycler, const Sampler
|
|||
}
|
||||
|
||||
Texture* Texture::createRenderBuffer(const Element& texelFormat, uint16 width, uint16 height, const Sampler& sampler) {
|
||||
return create(TextureUsageType::RENDERBUFFER, TEX_2D, texelFormat, width, height, 1, 1, 1, sampler);
|
||||
return create(TextureUsageType::RENDERBUFFER, TEX_2D, texelFormat, width, height, 1, 1, 0, sampler);
|
||||
}
|
||||
|
||||
Texture* Texture::create1D(const Element& texelFormat, uint16 width, const Sampler& sampler) {
|
||||
return create(TextureUsageType::RESOURCE, TEX_1D, texelFormat, width, 1, 1, 1, 1, sampler);
|
||||
return create(TextureUsageType::RESOURCE, TEX_1D, texelFormat, width, 1, 1, 1, 0, sampler);
|
||||
}
|
||||
|
||||
Texture* Texture::create2D(const Element& texelFormat, uint16 width, uint16 height, const Sampler& sampler) {
|
||||
return create(TextureUsageType::RESOURCE, TEX_2D, texelFormat, width, height, 1, 1, 1, sampler);
|
||||
return create(TextureUsageType::RESOURCE, TEX_2D, texelFormat, width, height, 1, 1, 0, sampler);
|
||||
}
|
||||
|
||||
Texture* Texture::createStrict(const Element& texelFormat, uint16 width, uint16 height, const Sampler& sampler) {
|
||||
return create(TextureUsageType::STRICT_RESOURCE, TEX_2D, texelFormat, width, height, 1, 1, 1, sampler);
|
||||
return create(TextureUsageType::STRICT_RESOURCE, TEX_2D, texelFormat, width, height, 1, 1, 0, sampler);
|
||||
}
|
||||
|
||||
Texture* Texture::create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth, const Sampler& sampler) {
|
||||
return create(TextureUsageType::RESOURCE, TEX_3D, texelFormat, width, height, depth, 1, 1, sampler);
|
||||
return create(TextureUsageType::RESOURCE, TEX_3D, texelFormat, width, height, depth, 1, 0, sampler);
|
||||
}
|
||||
|
||||
Texture* Texture::createCube(const Element& texelFormat, uint16 width, const Sampler& sampler) {
|
||||
return create(TextureUsageType::RESOURCE, TEX_CUBE, texelFormat, width, width, 1, 1, 1, sampler);
|
||||
return create(TextureUsageType::RESOURCE, TEX_CUBE, texelFormat, width, width, 1, 1, 0, sampler);
|
||||
}
|
||||
|
||||
Texture* Texture::create(TextureUsageType usageType, Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices, const Sampler& sampler)
|
||||
|
@ -326,7 +326,7 @@ Texture::~Texture() {
|
|||
}
|
||||
|
||||
Texture::Size Texture::resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices) {
|
||||
if (width && height && depth && numSamples && numSlices) {
|
||||
if (width && height && depth && numSamples) {
|
||||
bool changed = false;
|
||||
|
||||
if ( _type != type) {
|
||||
|
@ -387,20 +387,20 @@ Texture::Size Texture::resize(Type type, const Element& texelFormat, uint16 widt
|
|||
}
|
||||
|
||||
Texture::Size Texture::resize1D(uint16 width, uint16 numSamples) {
|
||||
return resize(TEX_1D, getTexelFormat(), width, 1, 1, numSamples, 1);
|
||||
return resize(TEX_1D, getTexelFormat(), width, 1, 1, numSamples, 0);
|
||||
}
|
||||
Texture::Size Texture::resize2D(uint16 width, uint16 height, uint16 numSamples) {
|
||||
return resize(TEX_2D, getTexelFormat(), width, height, 1, numSamples, 1);
|
||||
return resize(TEX_2D, getTexelFormat(), width, height, 1, numSamples, 0);
|
||||
}
|
||||
Texture::Size Texture::resize3D(uint16 width, uint16 height, uint16 depth, uint16 numSamples) {
|
||||
return resize(TEX_3D, getTexelFormat(), width, height, depth, numSamples, 1);
|
||||
return resize(TEX_3D, getTexelFormat(), width, height, depth, numSamples, 0);
|
||||
}
|
||||
Texture::Size Texture::resizeCube(uint16 width, uint16 numSamples) {
|
||||
return resize(TEX_CUBE, getTexelFormat(), width, 1, 1, numSamples, 1);
|
||||
return resize(TEX_CUBE, getTexelFormat(), width, 1, 1, numSamples, 0);
|
||||
}
|
||||
|
||||
Texture::Size Texture::reformat(const Element& texelFormat) {
|
||||
return resize(_type, texelFormat, getWidth(), getHeight(), getDepth(), getNumSamples(), getNumSlices());
|
||||
return resize(_type, texelFormat, getWidth(), getHeight(), getDepth(), getNumSamples(), _numSlices);
|
||||
}
|
||||
|
||||
bool Texture::isColorRenderTarget() const {
|
||||
|
|
|
@ -359,7 +359,12 @@ public:
|
|||
|
||||
uint32 getNumTexels() const { return _width * _height * _depth * getNumFaces(); }
|
||||
|
||||
uint16 getNumSlices() const { return _numSlices; }
|
||||
// The texture is an array if the _numSlices is not 0.
|
||||
// otherwise, if _numSLices is 0, then the texture is NOT an array
|
||||
// The number of slices returned is 1 at the minimum (if not an array) or the actual _numSlices.
|
||||
bool isArray() const { return _numSlices > 0; }
|
||||
uint16 getNumSlices() const { return (isArray() ? _numSlices : 1); }
|
||||
|
||||
uint16 getNumSamples() const { return _numSamples; }
|
||||
|
||||
|
||||
|
@ -511,12 +516,12 @@ protected:
|
|||
uint32 _size = 0;
|
||||
Element _texelFormat;
|
||||
|
||||
uint16 _width = 1;
|
||||
uint16 _height = 1;
|
||||
uint16 _depth = 1;
|
||||
uint16 _width { 1 };
|
||||
uint16 _height { 1 };
|
||||
uint16 _depth { 1 };
|
||||
|
||||
uint16 _numSamples = 1;
|
||||
uint16 _numSlices = 1;
|
||||
uint16 _numSamples { 1 };
|
||||
uint16 _numSlices { 0 }; // if _numSlices is 0, the texture is not an "Array", the getNumSlices reported is 1
|
||||
|
||||
uint16 _maxMip { 0 };
|
||||
uint16 _minMip { 0 };
|
||||
|
|
|
@ -16,12 +16,57 @@
|
|||
using namespace gpu;
|
||||
|
||||
ktx::KTXUniquePointer Texture::serialize(const Texture& texture) {
|
||||
|
||||
ktx::Header header;
|
||||
|
||||
// From texture format to ktx format description
|
||||
auto texelFormat = texture.getTexelFormat();
|
||||
if ( !( (texelFormat == Format::COLOR_RGBA_32)
|
||||
|| (texelFormat == Format::COLOR_SRGBA_32)
|
||||
))
|
||||
return nullptr;
|
||||
|
||||
header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 4, ktx::GLFormat::BGRA, ktx::GLInternalFormat_Uncompressed::RGBA8, ktx::GLBaseInternalFormat::RGBA);
|
||||
header.pixelWidth = texture.getWidth();
|
||||
header.pixelHeight = texture.getHeight();
|
||||
header.numberOfMipmapLevels = texture.mipLevels();
|
||||
|
||||
// Set Dimensions
|
||||
switch (texture.getType()) {
|
||||
case TEX_1D: {
|
||||
if (texture.isArray()) {
|
||||
header.set1DArray(texture.getWidth(), texture.getNumSlices());
|
||||
} else {
|
||||
header.set1D(texture.getWidth());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TEX_2D: {
|
||||
if (texture.isArray()) {
|
||||
header.set2DArray(texture.getWidth(), texture.getHeight(), texture.getNumSlices());
|
||||
} else {
|
||||
header.set2D(texture.getWidth(), texture.getHeight());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TEX_3D: {
|
||||
if (texture.isArray()) {
|
||||
header.set3DArray(texture.getWidth(), texture.getHeight(), texture.getDepth(), texture.getNumSlices());
|
||||
} else {
|
||||
header.set3D(texture.getWidth(), texture.getHeight(), texture.getDepth());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TEX_CUBE: {
|
||||
if (texture.isArray()) {
|
||||
header.setCubeArray(texture.getWidth(), texture.getHeight(), texture.getNumSlices());
|
||||
} else {
|
||||
header.setCube(texture.getWidth(), texture.getHeight());
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Number level of mips coming
|
||||
header.numberOfMipmapLevels = texture.maxMip();
|
||||
|
||||
ktx::Images images;
|
||||
for (uint32_t level = 0; level < header.numberOfMipmapLevels; level++) {
|
||||
|
@ -34,17 +79,42 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) {
|
|||
auto ktxBuffer = ktx::KTX::create(header, images);
|
||||
return ktxBuffer;
|
||||
}
|
||||
|
||||
Texture* Texture::unserialize(const ktx::KTXUniquePointer& srcData) {
|
||||
if (!srcData) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto& header = *srcData->getHeader();
|
||||
|
||||
Format mipFormat = Format::COLOR_SBGRA_32;
|
||||
Format pixelFormat = Format::COLOR_SRGBA_32;
|
||||
Format texelFormat = Format::COLOR_SRGBA_32;
|
||||
|
||||
auto tex = Texture::create2D(pixelFormat, header.getPixelWidth(), header.getPixelHeight());
|
||||
// Find Texture Type based on dimensions
|
||||
Type type = TEX_1D;
|
||||
if (header.pixelWidth == 0) {
|
||||
return nullptr;
|
||||
} else if (header.pixelHeight == 0) {
|
||||
type = TEX_1D;
|
||||
} else if (header.pixelDepth == 0) {
|
||||
if (header.numberOfFaces == ktx::NUM_CUBEMAPFACES) {
|
||||
type = TEX_CUBE;
|
||||
} else {
|
||||
type = TEX_2D;
|
||||
}
|
||||
} else {
|
||||
type = TEX_3D;
|
||||
}
|
||||
|
||||
auto tex = Texture::create( type,
|
||||
texelFormat,
|
||||
header.getPixelWidth(),
|
||||
header.getPixelHeight(),
|
||||
header.getPixelDepth(),
|
||||
1, // num Samples
|
||||
header.getNumberOfSlices(),
|
||||
Sampler());
|
||||
|
||||
// Assing the mips availables
|
||||
uint16_t level = 0;
|
||||
for (auto& image : srcData->_images) {
|
||||
tex->assignStoredMip(level, mipFormat, image._imageSize, image._bytes);
|
||||
|
|
|
@ -353,7 +353,7 @@ namespace ktx {
|
|||
uint32_t glInternalFormat;
|
||||
uint32_t glBaseInternalFormat;
|
||||
|
||||
uint32_t pixelWidth { 0 };
|
||||
uint32_t pixelWidth { 1 };
|
||||
uint32_t pixelHeight { 0 };
|
||||
uint32_t pixelDepth { 0 };
|
||||
uint32_t numberOfArrayElements { 0 };
|
||||
|
@ -393,6 +393,23 @@ namespace ktx {
|
|||
glInternalFormat = (uint32_t) internalFormat;
|
||||
glBaseInternalFormat = (uint32_t) baseInternalFormat;
|
||||
}
|
||||
|
||||
void setDimensions(uint32_t width, uint32_t height = 0, uint32_t depth = 0, uint32_t numSlices = 0, uint32_t numFaces = 1) {
|
||||
pixelWidth = (width > 0 ? width : 1);
|
||||
pixelHeight = height;
|
||||
pixelDepth = depth;
|
||||
numberOfArrayElements = numSlices;
|
||||
numberOfFaces = ((numFaces == 1) || (numFaces == NUM_CUBEMAPFACES) ? numFaces : 1);
|
||||
}
|
||||
void set1D(uint32_t width) { setDimensions(width); }
|
||||
void set1DArray(uint32_t width, uint32_t numSlices) { setDimensions(width, 0, 0, (numSlices > 0 ? numSlices : 1)); }
|
||||
void set2D(uint32_t width, uint32_t height) { setDimensions(width, height); }
|
||||
void set2DArray(uint32_t width, uint32_t height, uint32_t numSlices) { setDimensions(width, height, 0, (numSlices > 0 ? numSlices : 1)); }
|
||||
void set3D(uint32_t width, uint32_t height, uint32_t depth) { setDimensions(width, height, depth); }
|
||||
void set3DArray(uint32_t width, uint32_t height, uint32_t depth, uint32_t numSlices) { setDimensions(width, height, depth, (numSlices > 0 ? numSlices : 1)); }
|
||||
void setCube(uint32_t width, uint32_t height) { setDimensions(width, height, 0, 0, NUM_CUBEMAPFACES); }
|
||||
void setCubeArray(uint32_t width, uint32_t height, uint32_t numSlices) { setDimensions(width, height, 0, (numSlices > 0 ? numSlices : 1), NUM_CUBEMAPFACES); }
|
||||
|
||||
};
|
||||
|
||||
// Key Values
|
||||
|
|
|
@ -85,6 +85,61 @@ QImage processSourceImage(const QImage& srcImage, bool cubemap) {
|
|||
return srcImage;
|
||||
}
|
||||
|
||||
gpu::Texture* cacheTexture(const std::string& name, gpu::Texture* srcTexture, bool write = true, bool read = true) {
|
||||
if (!srcTexture) {
|
||||
return nullptr;
|
||||
}
|
||||
gpu::Texture* returnedTexture = srcTexture;
|
||||
|
||||
auto theKTX = Texture::serialize(*srcTexture);
|
||||
if (theKTX) {
|
||||
// Prepare cache directory
|
||||
QString path("hifi_ktx/");
|
||||
QFileInfo originalFileInfo(path);
|
||||
QString docsLocation = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
path = docsLocation + "/" + path;
|
||||
QFileInfo info(path);
|
||||
if (!info.absoluteDir().exists()) {
|
||||
QString originalRelativePath = originalFileInfo.path();
|
||||
QDir(docsLocation).mkpath(originalRelativePath);
|
||||
}
|
||||
std::string filename(path.toStdString());
|
||||
filename += name;
|
||||
filename += ".ktx";
|
||||
|
||||
if (write) {
|
||||
FILE* file = fopen (filename.c_str(),"wb");
|
||||
if (file != nullptr) {
|
||||
fwrite(theKTX->_storage->data(), 1, theKTX->_storage->size(), file);
|
||||
fclose (file);
|
||||
}
|
||||
}
|
||||
|
||||
if (read) {
|
||||
FILE* file = fopen (filename.c_str(),"rb");
|
||||
if (file != nullptr) {
|
||||
// obtain file size:
|
||||
fseek (file , 0 , SEEK_END);
|
||||
auto size = ftell(file);
|
||||
rewind(file);
|
||||
|
||||
std::unique_ptr<ktx::Storage> storage(new ktx::Storage(size));
|
||||
fread(storage->_bytes, 1, storage->_size, file);
|
||||
fclose (file);
|
||||
|
||||
//then create a new texture out of the ktx
|
||||
auto theNewTexure = Texture::unserialize(ktx::KTX::create(storage));
|
||||
|
||||
if (theNewTexure) {
|
||||
returnedTexture = theNewTexure;
|
||||
delete srcTexture;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnedTexture;
|
||||
}
|
||||
|
||||
void TextureMap::setTextureSource(TextureSourcePointer& textureSource) {
|
||||
_textureSource = textureSource;
|
||||
}
|
||||
|
@ -273,57 +328,10 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag
|
|||
if (generateMips) {
|
||||
::generateMips(theTexture, image, formatMip, false);
|
||||
}
|
||||
auto theKTX = Texture::serialize(*theTexture);
|
||||
if (theKTX) {
|
||||
// save that!
|
||||
QString path("hifi_ktx/");
|
||||
QFileInfo originalFileInfo(path);
|
||||
QString docsLocation = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
path = docsLocation + "/" + path;
|
||||
QFileInfo info(path);
|
||||
if (!info.absoluteDir().exists()) {
|
||||
QString originalRelativePath = originalFileInfo.path();
|
||||
QDir(docsLocation).mkpath(originalRelativePath);
|
||||
}
|
||||
|
||||
std::string filename(path.toStdString());
|
||||
filename += std::to_string((size_t) theTexture);
|
||||
filename += ".ktx";
|
||||
|
||||
{
|
||||
FILE* file = fopen (filename.c_str(),"wb");
|
||||
if (file != nullptr) {
|
||||
fwrite(theKTX->_storage->data(), 1, theKTX->_storage->size(), file);
|
||||
fclose (file);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
FILE* file = fopen (filename.c_str(),"rb");
|
||||
if (file != nullptr) {
|
||||
// obtain file size:
|
||||
fseek (file , 0 , SEEK_END);
|
||||
auto size = ftell(file);
|
||||
rewind(file);
|
||||
|
||||
std::unique_ptr<ktx::Storage> storage(new ktx::Storage(size));
|
||||
fread(storage->_bytes, 1, storage->_size, file);
|
||||
fclose (file);
|
||||
|
||||
//then create a new texture out of the ktx
|
||||
auto theNewTexure = Texture::unserialize(ktx::KTX::create(storage));
|
||||
|
||||
if (theNewTexure) {
|
||||
auto srcTexture = theTexture;
|
||||
theTexture = theNewTexure;
|
||||
delete srcTexture;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
|
||||
}
|
||||
|
||||
|
||||
return theTexture;
|
||||
}
|
||||
|
||||
|
@ -367,6 +375,8 @@ gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& src
|
|||
theTexture->setSource(srcImageName);
|
||||
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
|
||||
generateMips(theTexture, image, formatMip, true);
|
||||
|
||||
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
|
||||
}
|
||||
|
||||
return theTexture;
|
||||
|
@ -453,6 +463,8 @@ gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcIm
|
|||
theTexture->setSource(srcImageName);
|
||||
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
|
||||
generateMips(theTexture, image, formatMip, true);
|
||||
|
||||
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
|
||||
}
|
||||
|
||||
return theTexture;
|
||||
|
@ -486,8 +498,8 @@ gpu::Texture* TextureUsage::createRoughnessTextureFromImage(const QImage& srcIma
|
|||
theTexture->setSource(srcImageName);
|
||||
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
|
||||
generateMips(theTexture, image, formatMip, true);
|
||||
|
||||
// FIXME queue for transfer to GPU and block on completion
|
||||
|
||||
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
|
||||
}
|
||||
|
||||
return theTexture;
|
||||
|
@ -525,8 +537,8 @@ gpu::Texture* TextureUsage::createRoughnessTextureFromGlossImage(const QImage& s
|
|||
theTexture->setSource(srcImageName);
|
||||
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
|
||||
generateMips(theTexture, image, formatMip, true);
|
||||
|
||||
// FIXME queue for transfer to GPU and block on completion
|
||||
|
||||
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
|
||||
}
|
||||
|
||||
return theTexture;
|
||||
|
@ -562,7 +574,7 @@ gpu::Texture* TextureUsage::createMetallicTextureFromImage(const QImage& srcImag
|
|||
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
|
||||
generateMips(theTexture, image, formatMip, true);
|
||||
|
||||
// FIXME queue for transfer to GPU and block on completion
|
||||
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
|
||||
}
|
||||
|
||||
return theTexture;
|
||||
|
@ -893,6 +905,8 @@ gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcIm
|
|||
PROFILE_RANGE(resource_parse, "generateIrradiance");
|
||||
theTexture->generateIrradiance();
|
||||
}
|
||||
|
||||
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue