Rebasing with current upstream

This commit is contained in:
samcake 2017-02-21 10:07:42 -08:00
commit ba54b5ce11
14 changed files with 178 additions and 154 deletions

View file

@ -362,7 +362,8 @@ void OpenGLDisplayPlugin::customizeContext() {
cursorData.texture->setSource("cursor texture"); cursorData.texture->setSource("cursor texture");
auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha(); auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha();
cursorData.texture->setUsage(usage.build()); 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); cursorData.texture->autoGenerateMips(-1);
} }
} }

View file

@ -302,7 +302,8 @@ void HmdDisplayPlugin::internalPresent() {
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
_previewTexture->setSource("HMD Preview Texture"); _previewTexture->setSource("HMD Preview Texture");
_previewTexture->setUsage(gpu::Texture::Usage::Builder().withColor().build()); _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); _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()) { : GLTexture(backend, texture, allocate()), _storageStamp { texture.getStamp() }, _size(texture.evalTotalSize()) {
incrementTextureGPUCount(); incrementTextureGPUCount();
withPreservedTexture([&] { withPreservedTexture([&] {
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat()); GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), _gpuObject.getStoredMipFormat());
const Sampler& sampler = _gpuObject.getSampler(); const Sampler& sampler = _gpuObject.getSampler();
auto numMips = _gpuObject.evalNumMips(); auto numMips = _gpuObject.evalNumMips();
for (uint16_t mipLevel = 0; mipLevel < numMips; ++mipLevel) { 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)) { if (_gpuObject.isStoredMipFaceAvailable(mipLevel, face)) {
auto mip = _gpuObject.accessStoredMipFace(mipLevel, face); auto mip = _gpuObject.accessStoredMipFace(mipLevel, face);
mipData = mip->readData(); 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); glTexImage2D(target, mipLevel, texelFormat.internalFormat, dimensions.x, dimensions.y, 0, texelFormat.format, texelFormat.type, mipData);
(void)CHECK_GL_ERROR(); (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 size = _gpuObject.evalMipDimensions(sourceMip);
auto mipData = _gpuObject.accessStoredMipFace(sourceMip, face); 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()); 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 format;
GLenum type; GLenum type;
auto mipData = _parent._gpuObject.accessStoredMipFace(sourceMip, face); 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; format = texelFormat.format;
type = texelFormat.type; 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 }; 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) { void Texture::Storage::assignTexture(Texture* texture) {
_texture = texture; _texture = texture;
if (_texture) { if (_texture) {
@ -139,21 +127,12 @@ void Texture::Storage::assignTexture(Texture* texture) {
} }
} }
void Texture::Storage::reset() { void Texture::MemoryStorage::reset() {
_mips.clear(); _mips.clear();
bumpStamp(); bumpStamp();
} }
Texture::PixelsPointer Texture::Storage::editMipFace(uint16 level, uint8 face) { const Texture::PixelsPointer Texture::MemoryStorage::getMipFace(uint16 level, uint8 face) const {
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 {
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];
@ -161,12 +140,12 @@ const Texture::PixelsPointer Texture::Storage::getMipFace(uint16 level, uint8 fa
return PixelsPointer(); 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); PixelsPointer mipFace = getMipFace(level, face);
return (mipFace && mipFace->getSize()); return (mipFace && mipFace->getSize());
} }
bool Texture::Storage::allocateMip(uint16 level) { bool Texture::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()]));
@ -176,7 +155,6 @@ bool Texture::Storage::allocateMip(uint16 level) {
auto& mip = _mips[level]; auto& mip = _mips[level];
for (auto& face : mip) { for (auto& face : mip) {
if (!face) { if (!face) {
face = std::make_shared<Pixels>();
changed = true; changed = true;
} }
} }
@ -186,7 +164,7 @@ bool Texture::Storage::allocateMip(uint16 level) {
return changed; 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); allocateMip(level);
auto& mip = _mips[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. // 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 tex1D, 2D, 3D there is only one face
// For Cube, we expect the 6 faces in the order X+, X-, Y+, Y-, Z+, Z- // For Cube, we expect the 6 faces in the order X+, X-, Y+, Y-, Z+, Z-
auto sizePerFace = size / mip.size(); auto sizePerFace = storagePointer->size() / mip.size();
auto faceBytes = bytes; size_t offset = 0;
Size allocated = 0;
for (auto& face : mip) { for (auto& face : mip) {
face.reset(new Pixels(format, size, bytes)); face = storagePointer->createView(sizePerFace, offset);
allocated += size; offset += sizePerFace;
faceBytes += sizePerFace;
} }
bumpStamp(); 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); allocateMip(level);
auto& mip = _mips[level]; auto& mip = _mips[level];
Size allocated = 0;
if (face < mip.size()) { if (face < mip.size()) {
mip[face].reset(new Pixels(format, size, bytes)); mip[face] = storagePointer;
allocated += size;
bumpStamp(); bumpStamp();
} }
return allocated == size;
} }
Texture* Texture::createExternal(const ExternalRecycler& recycler, const Sampler& sampler) { 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* 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); Texture* tex = new Texture(usageType);
tex->_storage.reset(new Storage()); tex->_storage.reset(new MemoryStorage());
tex->_type = type; tex->_type = type;
tex->_storage->assignTexture(tex); tex->_storage->assignTexture(tex);
tex->_maxMip = 0; tex->_maxMip = 0;
@ -402,71 +371,85 @@ uint16 Texture::evalNumMips() const {
return evalNumMips({ _width, _height, _depth }); 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 // Check that level accessed make sense
if (level != 0) { if (level != 0) {
if (_autoGenerateMips) { if (_autoGenerateMips) {
return false; return;
} }
if (level >= evalNumMips()) { if (level >= evalNumMips()) {
return false; return;
} }
} }
// THen check that the mem texture passed make sense with its format // THen check that the mem texture passed make sense with its format
Size expectedSize = evalStoredMipSize(level, format); Size expectedSize = evalStoredMipSize(level, getStoredMipFormat());
if (size == expectedSize) { auto size = storage->size();
_storage->assignMipData(level, format, size, bytes); auto bytes = storage->data();
if (storage->size() == expectedSize) {
_storage->assignMipData(level, storage);
_maxMip = std::max(_maxMip, level); _maxMip = std::max(_maxMip, level);
_stamp++; _stamp++;
return true;
} else if (size > expectedSize) { } else if (size > expectedSize) {
// NOTE: We are facing this case sometime because apparently QImage (from where we get the bits) is generating images // 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. // 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) // We should probably consider something a bit more smart to get the correct result but for now (UI elements)
// it seems to work... // it seems to work...
_storage->assignMipData(level, format, size, bytes); _storage->assignMipData(level, storage);
_maxMip = std::max(_maxMip, level); _maxMip = std::max(_maxMip, level);
_stamp++; _stamp++;
return true;
} }
return false;
} }
void Texture::assignStoredMipFace(uint16 level, uint8 face, storage::StoragePointer& storage) {
bool Texture::assignStoredMipFace(uint16 level, const Element& format, Size size, const Byte* bytes, uint8 face) {
// Check that level accessed make sense // Check that level accessed make sense
if (level != 0) { if (level != 0) {
if (_autoGenerateMips) { if (_autoGenerateMips) {
return false; return;
} }
if (level >= evalNumMips()) { if (level >= evalNumMips()) {
return false; return;
} }
} }
// THen check that the mem texture passed make sense with its format // 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) { if (size == expectedSize) {
_storage->assignMipFaceData(level, format, size, bytes, face); _storage->assignMipFaceData(level, face, storage);
_maxMip = std::max(_maxMip, level); _maxMip = std::max(_maxMip, level);
_stamp++; _stamp++;
return true;
} else if (size > expectedSize) { } else if (size > expectedSize) {
// NOTE: We are facing this case sometime because apparently QImage (from where we get the bits) is generating images // 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. // 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) // We should probably consider something a bit more smart to get the correct result but for now (UI elements)
// it seems to work... // it seems to work...
_storage->assignMipFaceData(level, format, size, bytes, face); _storage->assignMipFaceData(level, face, storage);
_maxMip = std::max(_maxMip, level); _maxMip = std::max(_maxMip, level);
_stamp++; _stamp++;
return true;
} }
return false;
} }
uint16 Texture::autoGenerateMips(uint16 maxMip) { uint16 Texture::autoGenerateMips(uint16 maxMip) {
bool changed = false; bool changed = false;
if (!_autoGenerateMips) { if (!_autoGenerateMips) {
@ -500,7 +483,7 @@ uint16 Texture::getStoredMipHeight(uint16 level) const {
if (mip && mip->getSize()) { if (mip && mip->getSize()) {
return evalMipHeight(level); return evalMipHeight(level);
} }
return 0; return 0;
} }
uint16 Texture::getStoredMipDepth(uint16 level) const { uint16 Texture::getStoredMipDepth(uint16 level) const {
@ -772,8 +755,8 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<
for(int face=0; face < gpu::Texture::NUM_CUBE_FACES; face++) { for(int face=0; face < gpu::Texture::NUM_CUBE_FACES; face++) {
PROFILE_RANGE(render_gpu, "ProcessFace"); PROFILE_RANGE(render_gpu, "ProcessFace");
auto numComponents = cubeTexture.accessStoredMipFace(0,face)->getFormat().getScalarCount(); auto numComponents = cubeTexture.getStoredMipFormat().getScalarCount();
auto data = cubeTexture.accessStoredMipFace(0,face)->readData(); auto data = cubeTexture.accessStoredMipFace(0,face)->data();
if (data == nullptr) { if (data == nullptr) {
continue; continue;
} }

View file

@ -226,30 +226,7 @@ public:
bool operator!=(const Usage& usage) { return (_flags != usage._flags); } bool operator!=(const Usage& usage) { return (_flags != usage._flags); }
}; };
using PixelsPointer = storage::StoragePointer;
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;
enum Type { enum Type {
TEX_1D = 0, TEX_1D = 0,
@ -272,35 +249,68 @@ public:
NUM_CUBE_FACES, // Not a valid vace index NUM_CUBE_FACES, // Not a valid vace index
}; };
class Storage { class Storage {
public: public:
Storage() {} Storage() {}
virtual ~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; } Texture::Type getType() const { return _type; }
Stamp getStamp() const { return _stamp; } Stamp getStamp() const { return _stamp; }
Stamp bumpStamp() { 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. virtual void assignTexture(Texture* tex); // Texture storage is pointing to ONE corrresponding Texture.
const Texture* getTexture() const { return _texture; } const Texture* getTexture() const { return _texture; }
friend class 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* 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* 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()); 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 // 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 // Manually allocate the mips down until the specified maxMip
// this is just allocating the sysmem version of it // this is just allocating the sysmem version of it
// in case autoGen is on, this doesn't allocate // in case autoGen is on, this doesn't allocate
// Explicitely assign mip data for a certain level // Explicitely assign mip data for a certain level
// If Bytes is NULL then simply allocate the space so mip sysmem can be accessed // 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 // Access the the sub mips
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); }

View file

@ -129,10 +129,11 @@ Texture* Texture::unserialize(Usage usage, TextureUsageType usageType, const ktx
tex->setUsage(usage); tex->setUsage(usage);
// Assing the mips availables // Assing the mips availables
tex->setStoredMipFormat(mipFormat);
uint16_t level = 0; uint16_t level = 0;
for (auto& image : srcData->_images) { for (auto& image : srcData->_images) {
for (uint32_t face = 0; face < image._numFaces; face++) { for (uint32_t face = 0; face < image._numFaces; face++) {
tex->assignStoredMipFace(level, mipFormat, image._faceSize, image._faceBytes[face], face); tex->assignStoredMipFace(level, face, image._faceSize, image._faceBytes[face]);
} }
level++; 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 = 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; return _permutationNormalTexture;
} }
@ -122,7 +123,8 @@ const gpu::TexturePointer& TextureCache::getWhiteTexture() {
if (!_whiteTexture) { if (!_whiteTexture) {
_whiteTexture = gpu::TexturePointer(gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1)); _whiteTexture = gpu::TexturePointer(gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1));
_whiteTexture->setSource("TextureCache::_whiteTexture"); _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; return _whiteTexture;
} }
@ -131,7 +133,8 @@ const gpu::TexturePointer& TextureCache::getGrayTexture() {
if (!_grayTexture) { if (!_grayTexture) {
_grayTexture = gpu::TexturePointer(gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1)); _grayTexture = gpu::TexturePointer(gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1));
_grayTexture->setSource("TextureCache::_grayTexture"); _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; return _grayTexture;
} }
@ -140,7 +143,8 @@ const gpu::TexturePointer& TextureCache::getBlueTexture() {
if (!_blueTexture) { if (!_blueTexture) {
_blueTexture = gpu::TexturePointer(gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1)); _blueTexture = gpu::TexturePointer(gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1));
_blueTexture->setSource("TextureCache::_blueTexture"); _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; return _blueTexture;
} }
@ -149,7 +153,8 @@ const gpu::TexturePointer& TextureCache::getBlackTexture() {
if (!_blackTexture) { if (!_blackTexture) {
_blackTexture = gpu::TexturePointer(gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1)); _blackTexture = gpu::TexturePointer(gpu::Texture::createStrict(gpu::Element::COLOR_RGBA_32, 1, 1));
_blackTexture->setSource("TextureCache::_blackTexture"); _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; return _blackTexture;
} }

View file

@ -96,7 +96,7 @@ gpu::Texture* cacheTexture(const std::string& name, gpu::Texture* srcTexture, bo
// Prepare cache directory // Prepare cache directory
QString path("hifi_ktx/"); QString path("hifi_ktx/");
QFileInfo originalFileInfo(path); QFileInfo originalFileInfo(path);
QString docsLocation = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); QString docsLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
path = docsLocation + "/" + path; path = docsLocation + "/" + path;
QFileInfo info(path); QFileInfo info(path);
if (!info.absoluteDir().exists()) { if (!info.absoluteDir().exists()) {
@ -272,7 +272,7 @@ const QImage& image, bool isLinear, bool doCompress) {
#define CPU_MIPMAPS 1 #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 #if CPU_MIPMAPS
PROFILE_RANGE(resource_parse, "generateMips"); PROFILE_RANGE(resource_parse, "generateMips");
auto numMips = texture->evalNumMips(); auto numMips = texture->evalNumMips();
@ -280,10 +280,10 @@ void generateMips(gpu::Texture* texture, QImage& image, gpu::Element formatMip,
QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level)); QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level));
if (fastResize) { if (fastResize) {
image = image.scaled(mipSize); image = image.scaled(mipSize);
texture->assignStoredMip(level, formatMip, image.byteCount(), image.constBits()); texture->assignStoredMip(level, image.byteCount(), image.constBits());
} else { } else {
QImage mipImage = image.scaled(mipSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); 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 #else
@ -291,14 +291,14 @@ void generateMips(gpu::Texture* texture, QImage& image, gpu::Element formatMip,
#endif #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 #if CPU_MIPMAPS
PROFILE_RANGE(resource_parse, "generateFaceMips"); PROFILE_RANGE(resource_parse, "generateFaceMips");
auto numMips = texture->evalNumMips(); auto numMips = texture->evalNumMips();
for (uint16 level = 1; level < numMips; ++level) { for (uint16 level = 1; level < numMips; ++level) {
QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level)); QSize mipSize(texture->evalMipWidth(level), texture->evalMipHeight(level));
QImage mipImage = image.scaled(mipSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); 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 #else
texture->autoGenerateMips(-1); texture->autoGenerateMips(-1);
@ -332,11 +332,11 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag
} }
} }
theTexture->setUsage(usage.build()); theTexture->setUsage(usage.build());
theTexture->setStoredMipFormat(formatMip);
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
if (generateMips) { if (generateMips) {
::generateMips(theTexture, image, formatMip, false); ::generateMips(theTexture, image, false);
} }
theTexture->setSource(srcImageName); theTexture->setSource(srcImageName);
theTexture = cacheTexture(theTexture->source(), theTexture); theTexture = cacheTexture(theTexture->source(), theTexture);
@ -383,8 +383,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 = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
theTexture->setSource(srcImageName); theTexture->setSource(srcImageName);
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); theTexture->setStoredMipFormat(formatMip);
generateMips(theTexture, image, formatMip, true); theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
generateMips(theTexture, image, true);
theTexture->setSource(srcImageName); theTexture->setSource(srcImageName);
theTexture = cacheTexture(theTexture->source(), theTexture); theTexture = cacheTexture(theTexture->source(), theTexture);
@ -472,8 +473,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 = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
theTexture->setSource(srcImageName); theTexture->setSource(srcImageName);
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); theTexture->setStoredMipFormat(formatMip);
generateMips(theTexture, image, formatMip, true); theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
generateMips(theTexture, image, true);
theTexture->setSource(srcImageName); theTexture->setSource(srcImageName);
theTexture = cacheTexture(theTexture->source(), theTexture); theTexture = cacheTexture(theTexture->source(), theTexture);
@ -508,8 +510,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 = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
theTexture->setSource(srcImageName); theTexture->setSource(srcImageName);
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); theTexture->setStoredMipFormat(formatMip);
generateMips(theTexture, image, formatMip, true); theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
generateMips(theTexture, image, true);
theTexture->setSource(srcImageName); theTexture->setSource(srcImageName);
theTexture = cacheTexture(theTexture->source(), theTexture); theTexture = cacheTexture(theTexture->source(), theTexture);
@ -548,8 +551,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 = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
theTexture->setSource(srcImageName); theTexture->setSource(srcImageName);
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); theTexture->setStoredMipFormat(formatMip);
generateMips(theTexture, image, formatMip, true); theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
generateMips(theTexture, image, true);
theTexture->setSource(srcImageName); theTexture->setSource(srcImageName);
theTexture = cacheTexture(theTexture->source(), theTexture); theTexture = cacheTexture(theTexture->source(), theTexture);
@ -585,8 +589,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 = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
theTexture->setSource(srcImageName); theTexture->setSource(srcImageName);
theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); theTexture->setStoredMipFormat(formatMip);
generateMips(theTexture, image, formatMip, true); theTexture->assignStoredMip(0, image.byteCount(), image.constBits());
generateMips(theTexture, image, true);
theTexture->setSource(srcImageName); theTexture->setSource(srcImageName);
theTexture = cacheTexture(theTexture->source(), theTexture); theTexture = cacheTexture(theTexture->source(), theTexture);
@ -901,11 +906,12 @@ gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcIm
if (faces.size() == gpu::Texture::NUM_FACES_PER_TYPE[gpu::Texture::TEX_CUBE]) { 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 = gpu::Texture::createCube(formatGPU, faces[0].width(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR, gpu::Sampler::WRAP_CLAMP));
theTexture->setSource(srcImageName); theTexture->setSource(srcImageName);
theTexture->setStoredMipFormat(formatMip);
int f = 0; int f = 0;
for (auto& face : faces) { for (auto& face : faces) {
theTexture->assignStoredMipFace(0, formatMip, face.byteCount(), face.constBits(), f); theTexture->assignStoredMipFace(0, f, face.byteCount(), face.constBits());
if (generateMips) { if (generateMips) {
generateFaceMips(theTexture, face, formatMip, f); generateFaceMips(theTexture, face, f);
} }
f++; f++;
} }

View file

@ -209,7 +209,8 @@ void Font::read(QIODevice& in) {
} }
_texture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height(), _texture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height(),
gpu::Sampler(gpu::Sampler::FILTER_MIN_POINT_MAG_LINEAR))); 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() { void Font::setupGPU() {

View file

@ -14,10 +14,13 @@ using namespace storage;
ViewStoragePointer Storage::createView(size_t viewSize, size_t offset) const { ViewStoragePointer Storage::createView(size_t viewSize, size_t offset) const {
auto selfSize = size(); auto selfSize = size();
if ((viewSize + offset) > selfSize) { if (0 == viewSize) {
throw std::runtime_error("Unable to map file"); 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 { MemoryStoragePointer Storage::toMemoryStorage() const {

View file

@ -18,22 +18,27 @@
namespace storage { namespace storage {
class Storage; class Storage;
using StoragePointer = std::unique_ptr<Storage>; using StoragePointer = std::shared_ptr<const Storage>;
class MemoryStorage; class MemoryStorage;
using MemoryStoragePointer = std::unique_ptr<MemoryStorage>; using MemoryStoragePointer = std::shared_ptr<const MemoryStorage>;
class FileStorage; class FileStorage;
using FileStoragePointer = std::unique_ptr<FileStorage>; using FileStoragePointer = std::shared_ptr<const FileStorage>;
class ViewStorage; 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: public:
virtual ~Storage() {} virtual ~Storage() {}
virtual const uint8_t* data() const = 0; virtual const uint8_t* data() const = 0;
virtual size_t size() 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; FileStoragePointer toFileStorage(const QString& filename) const;
MemoryStoragePointer toMemoryStorage() 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 { class MemoryStorage : public Storage {
@ -63,10 +68,11 @@ namespace storage {
class ViewStorage : public Storage { class ViewStorage : public Storage {
public: 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; } const uint8_t* data() const override { return _data; }
size_t size() const override { return _size; } size_t size() const override { return _size; }
private: private:
const storage::StoragePointer _owner;
const size_t _size; const size_t _size;
const uint8_t* _data; 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/") set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/")
# link in the shared libraries # 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() package_libraries_for_deployment()