progressing on io with ktx

This commit is contained in:
sam 2017-02-17 01:15:27 -08:00 committed by Brad Davis
parent 0d2e764bfd
commit b4745657e0
5 changed files with 185 additions and 79 deletions

View file

@ -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 {

View file

@ -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 };

View file

@ -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);

View file

@ -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

View file

@ -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);
}
}