Add object labels to GL objects and add ktx min mip kv

This commit is contained in:
Ryan Huffman 2017-04-13 15:54:25 -07:00 committed by Atlante45
parent aca7ad27c6
commit cf3dc12542
9 changed files with 72 additions and 19 deletions

View file

@ -109,6 +109,8 @@ GL45Texture::GL45Texture(const std::weak_ptr<GLBackend>& backend, const Texture&
GLuint GL45Texture::allocate(const Texture& texture) {
GLuint result;
glCreateTextures(getGLTextureType(texture), 1, &result);
auto source = texture.source();
glObjectLabel(GL_TEXTURE, result, source.length(), source.data());
return result;
}

View file

@ -41,16 +41,25 @@ GL45VariableAllocationTexture::~GL45VariableAllocationTexture() {
using GL45ResourceTexture = GL45Backend::GL45ResourceTexture;
GL45ResourceTexture::GL45ResourceTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture) : GL45VariableAllocationTexture(backend, texture) {
if (texture.source().find_first_of("box.ktx") != std::string::npos) {
qDebug() << "In box.ktx ctor";
}
auto mipLevels = texture.getNumMips();
_allocatedMip = mipLevels;
_maxAllocatedMip = _populatedMip = mipLevels;
uvec3 mipDimensions;
for (uint16_t mip = 0; mip < mipLevels; ++mip) {
if (glm::all(glm::lessThanEqual(texture.evalMipDimensions(mip), INITIAL_MIP_TRANSFER_DIMENSIONS))) {
if (glm::all(glm::lessThanEqual(texture.evalMipDimensions(mip), INITIAL_MIP_TRANSFER_DIMENSIONS))
&& texture.isStoredMipFaceAvailable(mip)) {
_maxAllocatedMip = _populatedMip = mip;
break;
}
}
//_maxAllocatedMip = _populatedMip = mipLevels;
//glObjectLabel(GL_TEXTURE, _id, _source.length(), _source.data());
uint16_t allocatedMip = _populatedMip - std::min<uint16_t>(_populatedMip, 2);
allocateStorage(allocatedMip);
copyMipsFromTexture();
@ -87,6 +96,10 @@ void GL45ResourceTexture::copyMipsFromTexture() {
void GL45ResourceTexture::syncSampler() const {
Parent::syncSampler();
qDebug() << "glTextureParameteri " << QString::fromStdString(_source) << _populatedMip << _populatedMip - _allocatedMip;
if (_source == "test" && _populatedMip == 0) {
qDebug() << "here";
}
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, _populatedMip - _allocatedMip);
}
@ -97,6 +110,7 @@ void GL45ResourceTexture::promote() {
auto oldSize = _size;
// create new texture
const_cast<GLuint&>(_id) = allocate(_gpuObject);
//glObjectLabel(GL_TEXTURE, _id, _source.length(), _source.data());
uint16_t oldAllocatedMip = _allocatedMip;
// allocate storage for new level
allocateStorage(_allocatedMip - std::min<uint16_t>(_allocatedMip, 2));
@ -130,6 +144,7 @@ void GL45ResourceTexture::demote() {
auto oldId = _id;
auto oldSize = _size;
const_cast<GLuint&>(_id) = allocate(_gpuObject);
//glObjectLabel(GL_TEXTURE, _id, _source.length(), _source.data());
allocateStorage(_allocatedMip + 1);
_populatedMip = std::max(_populatedMip, _allocatedMip);
uint16_t mips = _gpuObject.getNumMips();
@ -166,20 +181,24 @@ void GL45ResourceTexture::populateTransferQueue() {
const uint8_t maxFace = GLTexture::getFaceCount(_target);
uint16_t sourceMip = _populatedMip;
qDebug() << "populateTransferQueue info : " << _populatedMip << " " << _maxAllocatedMip << " " << _allocatedMip;
do {
--sourceMip;
auto targetMip = sourceMip - _allocatedMip;
auto mipDimensions = _gpuObject.evalMipDimensions(sourceMip);
bool transferQueued = false;
qDebug() << "populateTransferQueue " << QString::fromStdString(_gpuObject.source()) << sourceMip << " " << targetMip;
for (uint8_t face = 0; face < maxFace; ++face) {
qDebug() << "populateTransferQueue " << QString::fromStdString(_gpuObject.source()) << sourceMip << " " << targetMip;
if (!_gpuObject.isStoredMipFaceAvailable(sourceMip, face)) {
continue;
}
// If the mip is less than the max transfer size, then just do it in one transfer
if (glm::all(glm::lessThanEqual(mipDimensions, MAX_TRANSFER_DIMENSIONS))) {
qDebug() << "mip is less than max transfer size";
// Can the mip be transferred in one go
_pendingTransfers.emplace(new TransferJob(*this, sourceMip, targetMip, face));
transferQueued = true;
continue;
}
@ -191,18 +210,22 @@ void GL45ResourceTexture::populateTransferQueue() {
Q_ASSERT(0 == (mipSize % lines));
uint32_t linesPerTransfer = (uint32_t)(MAX_TRANSFER_SIZE / bytesPerLine);
uint32_t lineOffset = 0;
qDebug() << "queing up single line transfers " << linesPerTransfer << " " << lineOffset;
while (lineOffset < lines) {
uint32_t linesToCopy = std::min<uint32_t>(lines - lineOffset, linesPerTransfer);
_pendingTransfers.emplace(new TransferJob(*this, sourceMip, targetMip, face, linesToCopy, lineOffset));
lineOffset += linesToCopy;
transferQueued = true;
}
}
// queue up the sampler and populated mip change for after the transfer has completed
_pendingTransfers.emplace(new TransferJob(*this, [=] {
_populatedMip = sourceMip;
syncSampler();
}));
if (transferQueued) {
_pendingTransfers.emplace(new TransferJob(*this, [=] {
_populatedMip = sourceMip;
syncSampler();
}));
}
} while (sourceMip != _allocatedMip);
}

View file

@ -321,6 +321,7 @@ public:
protected:
std::string _filename;
uint8_t _minMipLevelAvailable;
//storage::FileStorage _cacheFile;
ktx::KTXDescriptorPointer _ktxDescriptor;
friend class Texture;

View file

@ -30,7 +30,7 @@ struct GPUKTXPayload {
}
static bool findInKeyValues(const ktx::KeyValues& keyValues, GPUKTXPayload& payload) {
auto found = std::find_if(keyValues.begin(), keyValues.end(), isGPUKTX);
auto found = std::find_if(keyValues.begin(), keyValues.end(), isGPUKTX);
if (found != keyValues.end()) {
if ((*found)._value.size() == sizeof(GPUKTXPayload)) {
memcpy(&payload, (*found)._value.data(), sizeof(GPUKTXPayload));
@ -41,14 +41,23 @@ struct GPUKTXPayload {
}
};
std::string GPUKTXPayload::KEY { "hifi.gpu" };
std::string GPUKTXPayload::KEY{ "hifi.gpu" };
KtxStorage::KtxStorage(const std::string& filename) : _filename(filename) {
{
// We are doing a lot of work here just to get descriptor data
ktx::StoragePointer storage { new storage::FileStorage(_filename.c_str()) };
ktx::StoragePointer storage{ new storage::FileStorage(_filename.c_str()) };
auto ktxPointer = ktx::KTX::create(storage);
_ktxDescriptor.reset(new ktx::KTXDescriptor(ktxPointer->toDescriptor()));
auto& keyValues = _ktxDescriptor->keyValues;
auto found = std::find_if(keyValues.begin(), keyValues.end(), [](const ktx::KeyValue& val) -> bool {
return val._key.compare(ktx::HIFI_MIN_POPULATED_MIP_KEY) == 0;
});
if (found != keyValues.end()) {
_minMipLevelAvailable = found->_value[0];
} else {
_minMipLevelAvailable = 4;// _ktxDescriptor->header.numberOfMipmapLevels;
}
}
// now that we know the ktx, let's get the header info to configure this Texture::Storage:
@ -76,12 +85,11 @@ Size KtxStorage::getMipFaceSize(uint16 level, uint8 face) const {
bool KtxStorage::isMipAvailable(uint16 level, uint8 face) const {
auto numLevels = _ktxDescriptor->header.numberOfMipmapLevels;
auto minLevel = 7 > numLevels ? 0 : numLevels - 10;
auto minLevel = _minMipLevelAvailable;
auto avail = level >= minLevel;
qDebug() << "isMipAvailable: " << QString::fromStdString(_filename) << ": " << level << " " << face << avail << minLevel << " " << _ktxDescriptor->header.numberOfMipmapLevels;
//return true;
return level > _ktxDescriptor->header.numberOfMipmapLevels - 7;
return avail;
}
void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& storage) {

View file

@ -70,6 +70,9 @@ end
namespace ktx {
const std::string HIFI_MIN_POPULATED_MIP_KEY = "hifiMinMip";
const uint32_t PACKING_SIZE { sizeof(uint32_t) };
using Byte = uint8_t;

View file

@ -43,12 +43,19 @@ namespace ktx {
std::unique_ptr<KTX> KTX::createBare(const Header& header, const KeyValues& keyValues) {
auto descriptors = header.generateImageDescriptors();
auto newHeader = header;
Byte minMip = header.numberOfMipmapLevels - 6;
auto newKeyValues = keyValues;
//newKeyValues.emplace_back(KeyValue(HIFI_MIN_POPULATED_MIP_KEY, sizeof(Byte), &minMip));
//newHeader.bytesOfKeyValueData = KeyValue::serializedKeyValuesByteSize(newKeyValues);
StoragePointer storagePointer;
{
auto storageSize = ktx::KTX::evalStorageSize(header, descriptors, keyValues);
auto storageSize = ktx::KTX::evalStorageSize(header, descriptors, newKeyValues);
auto memoryStorage = new storage::MemoryStorage(storageSize);
qDebug() << "Memory storage size is: " << storageSize;
ktx::KTX::writeWithoutImages(memoryStorage->data(), memoryStorage->size(), header, descriptors, keyValues);
ktx::KTX::writeWithoutImages(memoryStorage->data(), memoryStorage->size(), header, descriptors, newKeyValues);
storagePointer.reset(memoryStorage);
}
return create(storagePointer);
@ -132,6 +139,7 @@ namespace ktx {
memcpy(currentDestPtr, &header, sizeof(Header));
currentDestPtr += sizeof(Header);
// KeyValues
if (!keyValues.empty()) {
destHeader->bytesOfKeyValueData = (uint32_t) writeKeyValues(currentDestPtr, destByteSize - sizeof(Header), keyValues);
@ -145,9 +153,11 @@ namespace ktx {
auto ptr = reinterpret_cast<uint32_t*>(currentDestPtr);
*ptr = descriptors[i]._imageSize;
ptr++;
#ifdef DEBUG
for (size_t k = 0; k < descriptors[i]._imageSize/4; k++) {
*(ptr + k) = 0xFFFF0000;
*(ptr + k) = 0xFFFF00FF;
}
#endif
currentDestPtr += descriptors[i]._imageSize + sizeof(uint32_t);
}

View file

@ -425,7 +425,7 @@ void NetworkTexture::ktxMipRequestFinished() {
_ktxHighMipData = _ktxMipRequest->getData();
maybeCreateKTX();
} else {
handleFailedRequest(_ktxHeaderRequest->getResult());
handleFailedRequest(_ktxMipRequest->getResult());
}
_ktxMipRequest->deleteLater();
_ktxMipRequest = nullptr;
@ -433,7 +433,6 @@ void NetworkTexture::ktxMipRequestFinished() {
// This is called when the header or top mips have been loaded
void NetworkTexture::maybeCreateKTX() {
qDebug() << "Maybe create ktx...";
if (_ktxHeaderData.size() > 0 && _ktxHighMipData.size() > 0) {
// create ktx...
auto header = reinterpret_cast<const ktx::Header*>(_ktxHeaderData.data());
@ -478,6 +477,7 @@ void NetworkTexture::maybeCreateKTX() {
gpu::TexturePointer texture;
texture.reset(gpu::Texture::unserialize(_file->getFilepath(), *_ktxDescriptor));
texture->setKtxBacking(file->getFilepath());
texture->setSource(filename);
// We replace the texture with the one stored in the cache. This deals with the possible race condition of two different
// images with the same hash being loaded concurrently. Only one of them will make it into the cache by hash first and will

View file

@ -103,6 +103,11 @@ private:
ResourceRequest* _ktxMipRequest { nullptr };
QByteArray _ktxHeaderData;
QByteArray _ktxHighMipData;
// This is a copy of the original KTX descriptor from the source url.
// We need this because the KTX that will be cached will likely include extra data
// in its key/value data, and so will not match up with the original, causing
// mip offsets to change.
ktx::KTXDescriptorPointer _ktxDescriptor;

View file

@ -63,10 +63,11 @@ void HTTPResourceRequest::doSend() {
if (_byteRange.isSet()) {
QString byteRange;
if (_byteRange.fromInclusive < 0) {
auto byteRange = QString("bytes=%1").arg(_byteRange.fromInclusive);
byteRange = QString("bytes=%1").arg(_byteRange.fromInclusive);
} else {
auto byteRange = QString("bytes=%1-%2").arg(_byteRange.fromInclusive).arg(_byteRange.toExclusive);
byteRange = QString("bytes=%1-%2").arg(_byteRange.fromInclusive).arg(_byteRange.toExclusive);
}
qDebug() << "Setting http range to " << byteRange;
networkRequest.setRawHeader("Range", byteRange.toLatin1());
}
networkRequest.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);