mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-12 04:02:35 +02:00
Add object labels to GL objects and add ktx min mip kv
This commit is contained in:
parent
aca7ad27c6
commit
cf3dc12542
9 changed files with 72 additions and 19 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -321,6 +321,7 @@ public:
|
|||
|
||||
protected:
|
||||
std::string _filename;
|
||||
uint8_t _minMipLevelAvailable;
|
||||
//storage::FileStorage _cacheFile;
|
||||
ktx::KTXDescriptorPointer _ktxDescriptor;
|
||||
friend class Texture;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue