Adding new storage backing for gpu::Texture, moving mip format into Storage abstraction

This commit is contained in:
Brad Davis 2017-02-17 17:17:56 -08:00
parent 07506b0078
commit 27e8750b9b
14 changed files with 178 additions and 154 deletions

View file

@ -362,7 +362,8 @@ void OpenGLDisplayPlugin::customizeContext() {
cursorData.texture->setSource("cursor texture");
auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha();
cursorData.texture->setUsage(usage.build());
cursorData.texture->assignStoredMip(0, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), image.byteCount(), image.constBits());
cursorData.texture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
cursorData.texture->assignStoredMip(0, image.byteCount(), image.constBits());
cursorData.texture->autoGenerateMips(-1);
}
}

View file

@ -302,7 +302,8 @@ void HmdDisplayPlugin::internalPresent() {
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
_previewTexture->setSource("HMD Preview Texture");
_previewTexture->setUsage(gpu::Texture::Usage::Builder().withColor().build());
_previewTexture->assignStoredMip(0, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), image.byteCount(), image.constBits());
_previewTexture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
_previewTexture->assignStoredMip(0, image.byteCount(), image.constBits());
_previewTexture->autoGenerateMips(-1);
}

View file

@ -71,7 +71,7 @@ GL41Texture::GL41Texture(const std::weak_ptr<GLBackend>& backend, const Texture&
: GLTexture(backend, texture, allocate()), _storageStamp { texture.getStamp() }, _size(texture.evalTotalSize()) {
incrementTextureGPUCount();
withPreservedTexture([&] {
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat());
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), _gpuObject.getStoredMipFormat());
const Sampler& sampler = _gpuObject.getSampler();
auto numMips = _gpuObject.evalNumMips();
for (uint16_t mipLevel = 0; mipLevel < numMips; ++mipLevel) {
@ -83,7 +83,6 @@ GL41Texture::GL41Texture(const std::weak_ptr<GLBackend>& backend, const Texture&
if (_gpuObject.isStoredMipFaceAvailable(mipLevel, face)) {
auto mip = _gpuObject.accessStoredMipFace(mipLevel, face);
mipData = mip->readData();
texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), mip->getFormat());
}
glTexImage2D(target, mipLevel, texelFormat.internalFormat, dimensions.x, dimensions.y, 0, texelFormat.format, texelFormat.type, mipData);
(void)CHECK_GL_ERROR();

View file

@ -142,7 +142,7 @@ void GL45Texture::copyMipFaceFromTexture(uint16_t sourceMip, uint16_t targetMip,
}
auto size = _gpuObject.evalMipDimensions(sourceMip);
auto mipData = _gpuObject.accessStoredMipFace(sourceMip, face);
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), mipData->getFormat());
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), _gpuObject.getStoredMipFormat());
copyMipFaceLinesFromTexture(targetMip, face, size, 0, texelFormat.format, texelFormat.type, mipData->readData());
}

View file

@ -84,7 +84,7 @@ TransferJob::TransferJob(const GL45VariableAllocationTexture& parent, uint16_t s
GLenum format;
GLenum type;
auto mipData = _parent._gpuObject.accessStoredMipFace(sourceMip, face);
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_parent._gpuObject.getTexelFormat(), mipData->getFormat());
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_parent._gpuObject.getTexelFormat(), _parent._gpuObject.getStoredMipFormat());
format = texelFormat.format;
type = texelFormat.type;

View file

@ -120,18 +120,6 @@ void Texture::setAllowedGPUMemoryUsage(Size size) {
uint8 Texture::NUM_FACES_PER_TYPE[NUM_TYPES] = { 1, 1, 1, 6 };
Texture::Pixels::Pixels(const Element& format, Size size, const Byte* bytes) :
_format(format),
_storage(new storage::MemoryStorage(size, bytes)) {
Texture::updateTextureCPUMemoryUsage(0, _storage->size());
}
Texture::Pixels::~Pixels() {
if (_storage) {
Texture::updateTextureCPUMemoryUsage(_storage->size(), 0);
}
}
void Texture::Storage::assignTexture(Texture* texture) {
_texture = texture;
if (_texture) {
@ -139,21 +127,12 @@ void Texture::Storage::assignTexture(Texture* texture) {
}
}
void Texture::Storage::reset() {
void Texture::MemoryStorage::reset() {
_mips.clear();
bumpStamp();
}
Texture::PixelsPointer Texture::Storage::editMipFace(uint16 level, uint8 face) {
if (level < _mips.size()) {
assert(face < _mips[level].size());
bumpStamp();
return _mips[level][face];
}
return PixelsPointer();
}
const Texture::PixelsPointer Texture::Storage::getMipFace(uint16 level, uint8 face) const {
const Texture::PixelsPointer Texture::MemoryStorage::getMipFace(uint16 level, uint8 face) const {
if (level < _mips.size()) {
assert(face < _mips[level].size());
return _mips[level][face];
@ -161,12 +140,12 @@ const Texture::PixelsPointer Texture::Storage::getMipFace(uint16 level, uint8 fa
return PixelsPointer();
}
bool Texture::Storage::isMipAvailable(uint16 level, uint8 face) const {
bool Texture::MemoryStorage::isMipAvailable(uint16 level, uint8 face) const {
PixelsPointer mipFace = getMipFace(level, face);
return (mipFace && mipFace->getSize());
}
bool Texture::Storage::allocateMip(uint16 level) {
bool Texture::MemoryStorage::allocateMip(uint16 level) {
bool changed = false;
if (level >= _mips.size()) {
_mips.resize(level+1, std::vector<PixelsPointer>(Texture::NUM_FACES_PER_TYPE[getType()]));
@ -176,7 +155,6 @@ bool Texture::Storage::allocateMip(uint16 level) {
auto& mip = _mips[level];
for (auto& face : mip) {
if (!face) {
face = std::make_shared<Pixels>();
changed = true;
}
}
@ -186,7 +164,7 @@ bool Texture::Storage::allocateMip(uint16 level) {
return changed;
}
bool Texture::Storage::assignMipData(uint16 level, const Element& format, Size size, const Byte* bytes) {
void Texture::MemoryStorage::assignMipData(uint16 level, const storage::StoragePointer& storagePointer) {
allocateMip(level);
auto& mip = _mips[level];
@ -195,33 +173,24 @@ bool Texture::Storage::assignMipData(uint16 level, const Element& format, Size s
// The bytes assigned here are supposed to contain all the faces bytes of the mip.
// For tex1D, 2D, 3D there is only one face
// For Cube, we expect the 6 faces in the order X+, X-, Y+, Y-, Z+, Z-
auto sizePerFace = size / mip.size();
auto faceBytes = bytes;
Size allocated = 0;
auto sizePerFace = storagePointer->size() / mip.size();
size_t offset = 0;
for (auto& face : mip) {
face.reset(new Pixels(format, size, bytes));
allocated += size;
faceBytes += sizePerFace;
face = storagePointer->createView(sizePerFace, offset);
offset += sizePerFace;
}
bumpStamp();
return allocated == size;
}
bool Texture::Storage::assignMipFaceData(uint16 level, const Element& format, Size size, const Byte* bytes, uint8 face) {
void Texture::MemoryStorage::assignMipFaceData(uint16 level, uint8 face, const storage::StoragePointer& storagePointer) {
allocateMip(level);
auto& mip = _mips[level];
Size allocated = 0;
if (face < mip.size()) {
mip[face].reset(new Pixels(format, size, bytes));
allocated += size;
mip[face] = storagePointer;
bumpStamp();
}
return allocated == size;
}
Texture* Texture::createExternal(const ExternalRecycler& recycler, const Sampler& sampler) {
@ -260,7 +229,7 @@ Texture* Texture::createCube(const Element& texelFormat, uint16 width, const Sam
Texture* Texture::create(TextureUsageType usageType, Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices, const Sampler& sampler)
{
Texture* tex = new Texture(usageType);
tex->_storage.reset(new Storage());
tex->_storage.reset(new MemoryStorage());
tex->_type = type;
tex->_storage->assignTexture(tex);
tex->_maxMip = 0;
@ -402,69 +371,83 @@ uint16 Texture::evalNumMips() const {
return evalNumMips({ _width, _height, _depth });
}
bool Texture::assignStoredMip(uint16 level, const Element& format, Size size, const Byte* bytes) {
void Texture::setStoredMipFormat(const Element& format) {
_storage->setFormat(format);
}
const Element& Texture::getStoredMipFormat() const {
return _storage->getFormat();
}
void Texture::assignStoredMip(uint16 level, Size size, const Byte* bytes) {
storage::StoragePointer storage { new storage::MemoryStorage(size, bytes) };
assignStoredMip(level, storage);
}
void Texture::assignStoredMipFace(uint16 level, uint8 face, Size size, const Byte* bytes) {
storage::StoragePointer storage { new storage::MemoryStorage(size, bytes) };
assignStoredMipFace(level, face, storage);
}
void Texture::assignStoredMip(uint16 level, storage::StoragePointer& storage) {
// Check that level accessed make sense
if (level != 0) {
if (_autoGenerateMips) {
return false;
return;
}
if (level >= evalNumMips()) {
return false;
return;
}
}
// THen check that the mem texture passed make sense with its format
Size expectedSize = evalStoredMipSize(level, format);
if (size == expectedSize) {
_storage->assignMipData(level, format, size, bytes);
Size expectedSize = evalStoredMipSize(level, getStoredMipFormat());
auto size = storage->size();
auto bytes = storage->data();
if (storage->size() == expectedSize) {
_storage->assignMipData(level, storage);
_maxMip = std::max(_maxMip, level);
_stamp++;
return true;
} else if (size > expectedSize) {
// NOTE: We are facing this case sometime because apparently QImage (from where we get the bits) is generating images
// and alligning the line of pixels to 32 bits.
// We should probably consider something a bit more smart to get the correct result but for now (UI elements)
// it seems to work...
_storage->assignMipData(level, format, size, bytes);
_storage->assignMipData(level, storage);
_maxMip = std::max(_maxMip, level);
_stamp++;
return true;
}
return false;
}
bool Texture::assignStoredMipFace(uint16 level, const Element& format, Size size, const Byte* bytes, uint8 face) {
void Texture::assignStoredMipFace(uint16 level, uint8 face, storage::StoragePointer& storage) {
// Check that level accessed make sense
if (level != 0) {
if (_autoGenerateMips) {
return false;
return;
}
if (level >= evalNumMips()) {
return false;
return;
}
}
// THen check that the mem texture passed make sense with its format
Size expectedSize = evalStoredMipFaceSize(level, format);
Size expectedSize = evalStoredMipFaceSize(level, getStoredMipFormat());
auto size = storage->size();
auto bytes = storage->data();
if (size == expectedSize) {
_storage->assignMipFaceData(level, format, size, bytes, face);
_storage->assignMipFaceData(level, face, storage);
_stamp++;
return true;
} else if (size > expectedSize) {
// NOTE: We are facing this case sometime because apparently QImage (from where we get the bits) is generating images
// and alligning the line of pixels to 32 bits.
// We should probably consider something a bit more smart to get the correct result but for now (UI elements)
// it seems to work...
_storage->assignMipFaceData(level, format, size, bytes, face);
_storage->assignMipFaceData(level, face, storage);
_stamp++;
return true;
}
return false;
}
uint16 Texture::autoGenerateMips(uint16 maxMip) {
bool changed = false;
if (!_autoGenerateMips) {
@ -498,7 +481,7 @@ uint16 Texture::getStoredMipHeight(uint16 level) const {
if (mip && mip->getSize()) {
return evalMipHeight(level);
}
return 0;
return 0;
}
uint16 Texture::getStoredMipDepth(uint16 level) const {
@ -770,8 +753,8 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<
for(int face=0; face < gpu::Texture::NUM_CUBE_FACES; face++) {
PROFILE_RANGE(render_gpu, "ProcessFace");
auto numComponents = cubeTexture.accessStoredMipFace(0,face)->getFormat().getScalarCount();
auto data = cubeTexture.accessStoredMipFace(0,face)->readData();
auto numComponents = cubeTexture.getStoredMipFormat().getScalarCount();
auto data = cubeTexture.accessStoredMipFace(0,face)->data();
if (data == nullptr) {
continue;
}

View file

@ -226,30 +226,7 @@ public:
bool operator!=(const Usage& usage) { return (_flags != usage._flags); }
};
class Pixels {
public:
using StoragePointer = storage::StoragePointer;
Pixels() {}
Pixels(const Pixels& pixels) = default;
Pixels(const Element& format, Size size, const Byte* bytes);
Pixels(const Element& format, StoragePointer& storage) : _format(format), _storage(storage.release()) {}
~Pixels();
const Byte* readData() const { return _storage->data(); }
Size getSize() const { return _storage->size(); }
const Element& getFormat() const { return _format; }
protected:
Element _format;
StoragePointer _storage;
friend class Texture;
};
typedef std::shared_ptr< Pixels > PixelsPointer;
using PixelsPointer = storage::StoragePointer;
enum Type {
TEX_1D = 0,
@ -272,35 +249,68 @@ public:
NUM_CUBE_FACES, // Not a valid vace index
};
class Storage {
public:
Storage() {}
virtual ~Storage() {}
virtual void reset();
virtual PixelsPointer editMipFace(uint16 level, uint8 face = 0);
virtual const PixelsPointer getMipFace(uint16 level, uint8 face = 0) const;
virtual bool allocateMip(uint16 level);
virtual bool assignMipData(uint16 level, const Element& format, Size size, const Byte* bytes);
virtual bool assignMipFaceData(uint16 level, const Element& format, Size size, const Byte* bytes, uint8 face);
virtual bool isMipAvailable(uint16 level, uint8 face = 0) const;
virtual void reset() = 0;
virtual const 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;
Texture::Type getType() const { return _type; }
Stamp getStamp() const { return _stamp; }
Stamp bumpStamp() { return ++_stamp; }
protected:
Stamp _stamp = 0;
Texture* _texture = nullptr; // Points to the parent texture (not owned)
Texture::Type _type = Texture::TEX_2D; // The type of texture is needed to know the number of faces to expect
std::vector<std::vector<PixelsPointer>> _mips; // an array of mips, each mip is an array of faces
void setFormat(const Element& format) { _format = format; }
const Element& getFormat() const { return _format; }
private:
Stamp _stamp { 0 };
Element _format;
Texture::Type _type { Texture::TEX_2D }; // The type of texture is needed to know the number of faces to expect
Texture* _texture { nullptr }; // Points to the parent texture (not owned)
virtual void assignTexture(Texture* tex); // Texture storage is pointing to ONE corrresponding Texture.
const Texture* getTexture() const { return _texture; }
friend class Texture;
};
class MemoryStorage : public Storage {
public:
void reset() override;
const 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;
protected:
bool allocateMip(uint16 level);
std::vector<std::vector<PixelsPointer>> _mips; // an array of mips, each mip is an array of faces
};
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;
void assignMipData(uint16 level, const storage::StoragePointer& storage) override {
throw std::runtime_error("Invalid call");
}
void assignMipFaceData(uint16 level, uint8 face, const storage::StoragePointer& storage) override {
throw std::runtime_error("Invalid call");
}
void reset() override { }
protected:
ktx::KTXUniquePointer _ktxData;
friend class Texture;
};
static Texture* create1D(const Element& texelFormat, uint16 width, const Sampler& sampler = Sampler());
static Texture* create2D(const Element& texelFormat, uint16 width, uint16 height, const Sampler& sampler = Sampler());
static Texture* create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth, const Sampler& sampler = Sampler());
@ -444,13 +454,21 @@ public:
// Managing Storage and mips
// Mip storage format is constant across all mips
void setStoredMipFormat(const Element& format);
const Element& getStoredMipFormat() const;
// Manually allocate the mips down until the specified maxMip
// this is just allocating the sysmem version of it
// in case autoGen is on, this doesn't allocate
// Explicitely assign mip data for a certain level
// If Bytes is NULL then simply allocate the space so mip sysmem can be accessed
bool assignStoredMip(uint16 level, const Element& format, Size size, const Byte* bytes);
bool assignStoredMipFace(uint16 level, const Element& format, Size size, const Byte* bytes, uint8 face);
void assignStoredMip(uint16 level, Size size, const Byte* bytes);
void assignStoredMipFace(uint16 level, uint8 face, Size size, const Byte* bytes);
void assignStoredMip(uint16 level, storage::StoragePointer& storage);
void assignStoredMipFace(uint16 level, uint8 face, storage::StoragePointer& storage);
// Access the the sub mips
bool isStoredMipFaceAvailable(uint16 level, uint8 face = 0) const { return _storage->isMipAvailable(level, face); }

View file

@ -116,9 +116,10 @@ Texture* Texture::unserialize(TextureUsageType usageType, const ktx::KTXUniquePo
Sampler());
// Assing the mips availables
tex->setStoredMipFormat(mipFormat);
uint16_t level = 0;
for (auto& image : srcData->_images) {
tex->assignStoredMip(level, mipFormat, image._imageSize, image._bytes);
tex->assignStoredMip(level, image._imageSize, image._bytes);
level++;
}

View file

@ -108,7 +108,8 @@ const gpu::TexturePointer& TextureCache::getPermutationNormalTexture() {
}
_permutationNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB), 256, 2));
_permutationNormalTexture->assignStoredMip(0, _blueTexture->getTexelFormat(), sizeof(data), data);
_permutationNormalTexture->setStoredMipFormat(_permutationNormalTexture->getTexelFormat());
_permutationNormalTexture->assignStoredMip(0, sizeof(data), data);
}
return _permutationNormalTexture;
}
@ -122,7 +123,8 @@ const gpu::TexturePointer& TextureCache::getWhiteTexture() {
if (!_whiteTexture) {
_whiteTexture = gpu::TexturePointer(gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1));
_whiteTexture->setSource("TextureCache::_whiteTexture");
_whiteTexture->assignStoredMip(0, _whiteTexture->getTexelFormat(), sizeof(OPAQUE_WHITE), OPAQUE_WHITE);
_whiteTexture->setStoredMipFormat(_whiteTexture->getTexelFormat());
_whiteTexture->assignStoredMip(0, sizeof(OPAQUE_WHITE), OPAQUE_WHITE);
}
return _whiteTexture;
}
@ -131,7 +133,8 @@ const gpu::TexturePointer& TextureCache::getGrayTexture() {
if (!_grayTexture) {
_grayTexture = gpu::TexturePointer(gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1));
_grayTexture->setSource("TextureCache::_grayTexture");
_grayTexture->assignStoredMip(0, _grayTexture->getTexelFormat(), sizeof(OPAQUE_GRAY), OPAQUE_GRAY);
_grayTexture->setStoredMipFormat(_grayTexture->getTexelFormat());
_grayTexture->assignStoredMip(0, sizeof(OPAQUE_GRAY), OPAQUE_GRAY);
}
return _grayTexture;
}
@ -140,7 +143,8 @@ const gpu::TexturePointer& TextureCache::getBlueTexture() {
if (!_blueTexture) {
_blueTexture = gpu::TexturePointer(gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1));
_blueTexture->setSource("TextureCache::_blueTexture");
_blueTexture->assignStoredMip(0, _blueTexture->getTexelFormat(), sizeof(OPAQUE_BLUE), OPAQUE_BLUE);
_blueTexture->setStoredMipFormat(_blueTexture->getTexelFormat());
_blueTexture->assignStoredMip(0, sizeof(OPAQUE_BLUE), OPAQUE_BLUE);
}
return _blueTexture;
}
@ -149,7 +153,8 @@ const gpu::TexturePointer& TextureCache::getBlackTexture() {
if (!_blackTexture) {
_blackTexture = gpu::TexturePointer(gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1));
_blackTexture->setSource("TextureCache::_blackTexture");
_blackTexture->assignStoredMip(0, _blackTexture->getTexelFormat(), sizeof(OPAQUE_BLACK), OPAQUE_BLACK);
_blackTexture->setStoredMipFormat(_blackTexture->getTexelFormat());
_blackTexture->assignStoredMip(0, sizeof(OPAQUE_BLACK), OPAQUE_BLACK);
}
return _blackTexture;
}

View file

@ -96,7 +96,7 @@ gpu::Texture* cacheTexture(const std::string& name, gpu::Texture* srcTexture, bo
// Prepare cache directory
QString path("hifi_ktx/");
QFileInfo originalFileInfo(path);
QString docsLocation = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
QString docsLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
path = docsLocation + "/" + path;
QFileInfo info(path);
if (!info.absoluteDir().exists()) {
@ -262,7 +262,7 @@ const QImage& image, bool isLinear, bool doCompress) {
#define CPU_MIPMAPS 1
void generateMips(gpu::Texture* texture, QImage& image, gpu::Element formatMip, bool fastResize) {
void generateMips(gpu::Texture* texture, QImage& image, bool fastResize) {
#if CPU_MIPMAPS
PROFILE_RANGE(resource_parse, "generateMips");
auto numMips = texture->evalNumMips();
@ -270,10 +270,10 @@ void generateMips(gpu::Texture* texture, QImage& image, gpu::Element formatMip,
QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level));
if (fastResize) {
image = image.scaled(mipSize);
texture->assignStoredMip(level, formatMip, image.byteCount(), image.constBits());
texture->assignStoredMip(level, image.byteCount(), image.constBits());
} else {
QImage mipImage = image.scaled(mipSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
texture->assignStoredMip(level, formatMip, mipImage.byteCount(), mipImage.constBits());
texture->assignStoredMip(level, mipImage.byteCount(), mipImage.constBits());
}
}
#else
@ -281,14 +281,14 @@ void generateMips(gpu::Texture* texture, QImage& image, gpu::Element formatMip,
#endif
}
void generateFaceMips(gpu::Texture* texture, QImage& image, gpu::Element formatMip, uint8 face) {
void generateFaceMips(gpu::Texture* texture, QImage& image, uint8 face) {
#if CPU_MIPMAPS
PROFILE_RANGE(resource_parse, "generateFaceMips");
auto numMips = texture->evalNumMips();
for (uint16 level = 1; level < numMips; ++level) {
QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level));
QImage mipImage = image.scaled(mipSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
texture->assignStoredMipFace(level, formatMip, mipImage.byteCount(), mipImage.constBits(), face);
texture->assignStoredMipFace(level, face, mipImage.byteCount(), mipImage.constBits());
}
#else
texture->autoGenerateMips(-1);
@ -322,11 +322,11 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag
}
}
theTexture->setUsage(usage.build());
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
theTexture->setStoredMipFormat(formatMip);
theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
if (generateMips) {
::generateMips(theTexture, image, formatMip, false);
::generateMips(theTexture, image, false);
}
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
@ -373,8 +373,9 @@ gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& src
theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
theTexture->setSource(srcImageName);
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
generateMips(theTexture, image, formatMip, true);
theTexture->setStoredMipFormat(formatMip);
theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
generateMips(theTexture, image, true);
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
}
@ -461,8 +462,9 @@ gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcIm
theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
theTexture->setSource(srcImageName);
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
generateMips(theTexture, image, formatMip, true);
theTexture->setStoredMipFormat(formatMip);
theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
generateMips(theTexture, image, true);
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
}
@ -496,8 +498,9 @@ gpu::Texture* TextureUsage::createRoughnessTextureFromImage(const QImage& srcIma
theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
theTexture->setSource(srcImageName);
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
generateMips(theTexture, image, formatMip, true);
theTexture->setStoredMipFormat(formatMip);
theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
generateMips(theTexture, image, true);
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
}
@ -535,8 +538,9 @@ gpu::Texture* TextureUsage::createRoughnessTextureFromGlossImage(const QImage& s
theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
theTexture->setSource(srcImageName);
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
generateMips(theTexture, image, formatMip, true);
theTexture->setStoredMipFormat(formatMip);
theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
generateMips(theTexture, image, true);
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
}
@ -571,8 +575,9 @@ gpu::Texture* TextureUsage::createMetallicTextureFromImage(const QImage& srcImag
theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
theTexture->setSource(srcImageName);
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
generateMips(theTexture, image, formatMip, true);
theTexture->setStoredMipFormat(formatMip);
theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
generateMips(theTexture, image, true);
theTexture = cacheTexture(std::to_string((size_t) theTexture), theTexture);
}
@ -886,11 +891,12 @@ gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcIm
if (faces.size() == gpu::Texture::NUM_FACES_PER_TYPE[gpu::Texture::TEX_CUBE]) {
theTexture = gpu::Texture::createCube(formatGPU, faces[0].width(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP));
theTexture->setSource(srcImageName);
theTexture->setStoredMipFormat(formatMip);
int f = 0;
for (auto& face : faces) {
theTexture->assignStoredMipFace(0, formatMip, face.byteCount(), face.constBits(), f);
theTexture->assignStoredMipFace(0, f, face.byteCount(), face.constBits());
if (generateMips) {
generateFaceMips(theTexture, face, formatMip, f);
generateFaceMips(theTexture, face, f);
}
f++;
}

View file

@ -209,7 +209,8 @@ void Font::read(QIODevice& in) {
}
_texture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height(),
gpu::Sampler(gpu::Sampler::FILTER_MIN_POINT_MAG_LINEAR)));
_texture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits());
_texture->setStoredMipFormat(formatMip);
_texture->assignStoredMip(0, image.byteCount(), image.constBits());
}
void Font::setupGPU() {

View file

@ -14,10 +14,13 @@ using namespace storage;
ViewStoragePointer Storage::createView(size_t viewSize, size_t offset) const {
auto selfSize = size();
if ((viewSize + offset) > selfSize) {
throw std::runtime_error("Unable to map file");
if (0 == viewSize) {
viewSize = selfSize;
}
return ViewStoragePointer(new ViewStorage(viewSize, data() + offset));
if ((viewSize + offset) > selfSize) {
throw std::runtime_error("Invalid mapping range");
}
return ViewStoragePointer(new ViewStorage(shared_from_this(), viewSize, data() + offset));
}
MemoryStoragePointer Storage::toMemoryStorage() const {

View file

@ -18,22 +18,27 @@
namespace storage {
class Storage;
using StoragePointer = std::unique_ptr<Storage>;
using StoragePointer = std::shared_ptr<const Storage>;
class MemoryStorage;
using MemoryStoragePointer = std::unique_ptr<MemoryStorage>;
using MemoryStoragePointer = std::shared_ptr<const MemoryStorage>;
class FileStorage;
using FileStoragePointer = std::unique_ptr<FileStorage>;
using FileStoragePointer = std::shared_ptr<const FileStorage>;
class ViewStorage;
using ViewStoragePointer = std::unique_ptr<ViewStorage>;
using ViewStoragePointer = std::shared_ptr<const ViewStorage>;
class Storage {
class Storage : public std::enable_shared_from_this<Storage> {
public:
virtual ~Storage() {}
virtual const uint8_t* data() const = 0;
virtual size_t size() const = 0;
ViewStoragePointer createView(size_t size, size_t offset = 0) const;
ViewStoragePointer createView(size_t size = 0, size_t offset = 0) const;
FileStoragePointer toFileStorage(const QString& filename) const;
MemoryStoragePointer toMemoryStorage() const;
// Aliases to prevent having to re-write a ton of code
inline size_t getSize() const { return size(); }
inline const uint8_t* readData() const { return data(); }
};
class MemoryStorage : public Storage {
@ -63,10 +68,11 @@ namespace storage {
class ViewStorage : public Storage {
public:
ViewStorage(size_t size, const uint8_t* data) : _size(size), _data(data) {}
ViewStorage(const storage::StoragePointer& owner, size_t size, const uint8_t* data) : _owner(owner), _size(size), _data(data) {}
const uint8_t* data() const override { return _data; }
size_t size() const override { return _size; }
private:
const storage::StoragePointer _owner;
const size_t _size;
const uint8_t* _data;
};

View file

@ -10,7 +10,7 @@ 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 gl gpu gpu-gl render model model-networking networking render-utils fbx entities entities-renderer animation audio avatars script-engine physics)
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()