From 882a0272c08dc8fd0cccdff3b824136f3279cd11 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 31 Mar 2016 09:54:30 -0700 Subject: [PATCH 01/27] add simple cleanup of unmapped assets on start --- assignment-client/src/assets/AssetServer.cpp | 30 ++++++++++++++++++++ assignment-client/src/assets/AssetServer.h | 3 ++ 2 files changed, 33 insertions(+) diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index fad8ece7bf..33ae631b77 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -136,6 +136,8 @@ void AssetServer::completeSetup() { performMappingMigration(); + cleanupUnmappedFiles(); + nodeList->addNodeTypeToInterestSet(NodeType::Agent); } @@ -189,6 +191,34 @@ void AssetServer::performMappingMigration() { } } +void AssetServer::cleanupUnmappedFiles() { + QRegExp hashFileRegex { "^[a-f0-9]{" + QString::number(SHA256_HASH_HEX_LENGTH) + "}" }; + + auto files = _filesDirectory.entryInfoList(QDir::Files); + + // grab the currently mapped hashes + auto mappedHashes = _fileMappings.values(); + + qDebug() << "Performing unmapped asset cleanup."; + + for (const auto& fileInfo : files) { + if (hashFileRegex.exactMatch(fileInfo.fileName())) { + if (mappedHashes.contains(fileInfo.fileName())) { + qDebug() << "\tLeaving" << fileInfo.fileName() << "in asset files directory since it is mapped"; + } else { + // remove the unmapped file + QFile removeableFile { fileInfo.absoluteFilePath() }; + + if (removeableFile.remove()) { + qDebug() << "\tDeleted" << fileInfo.fileName() << "from asset files directory since it is unmapped."; + } else { + qDebug() << "\tAttempt to delete unmapped file" << fileInfo.fileName() << "failed"; + } + } + } + } +} + void AssetServer::handleAssetMappingOperation(QSharedPointer message, SharedNodePointer senderNode) { MessageID messageID; message->readPrimitive(&messageID); diff --git a/assignment-client/src/assets/AssetServer.h b/assignment-client/src/assets/AssetServer.h index 1a8ebed50b..7e7c3c8b69 100644 --- a/assignment-client/src/assets/AssetServer.h +++ b/assignment-client/src/assets/AssetServer.h @@ -62,6 +62,9 @@ private: void performMappingMigration(); + // deletes any unmapped files from the local asset directory + void cleanupUnmappedFiles(); + Mappings _fileMappings; QDir _resourcesDirectory; From 9d1f91fa19da870952f556778a1fffde8a0ee571 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 31 Mar 2016 19:27:35 -0700 Subject: [PATCH 02/27] First pass at using compressed format when uploading textures --- examples/utilities/render/stats.qml | 13 +++++- libraries/gpu/src/gpu/Context.cpp | 17 +++++++ libraries/gpu/src/gpu/Context.h | 5 ++ libraries/gpu/src/gpu/Format.h | 7 +++ libraries/gpu/src/gpu/GLBackend.h | 10 +++- libraries/gpu/src/gpu/GLBackendPipeline.cpp | 2 + libraries/gpu/src/gpu/GLBackendTexture.cpp | 52 ++++++++++++++++++--- libraries/gpu/src/gpu/Texture.cpp | 7 ++- libraries/gpu/src/gpu/Texture.h | 1 + libraries/model/src/model/TextureMap.cpp | 18 +++---- libraries/render/src/render/EngineStats.cpp | 2 + libraries/render/src/render/EngineStats.h | 5 +- 12 files changed, 118 insertions(+), 21 deletions(-) diff --git a/examples/utilities/render/stats.qml b/examples/utilities/render/stats.qml index 0e51cb8834..d236d80dde 100644 --- a/examples/utilities/render/stats.qml +++ b/examples/utilities/render/stats.qml @@ -108,7 +108,18 @@ Item { prop: "textureGPUMemoryUsage", label: "GPU", color: "#1AC567" + }, + { + prop: "textureGPUVirtualMemoryUsage", + label: "GPU Virtual", + color: "#9495FF" + }, + { + prop: "frameTextureMemoryUsage", + label: "Frame", + color: "#E2334D" } + ] } @@ -186,7 +197,7 @@ Item { object: Render.getConfig("DrawLight"), prop: "numDrawn", label: "Lights", - color: "#E2334D" + color: "#FED959" } ] } diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index b14c461bc5..99ecf80e39 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -114,6 +114,7 @@ std::atomic Context::_bufferGPUMemoryUsage{ 0 }; std::atomic Context::_textureGPUCount{ 0 }; std::atomic Context::_textureGPUMemoryUsage{ 0 }; +std::atomic Context::_textureGPUVirtualMemoryUsage{ 0 }; void Context::incrementBufferGPUCount() { _bufferGPUCount++; @@ -149,6 +150,17 @@ void Context::updateTextureGPUMemoryUsage(Size prevObjectSize, Size newObjectSiz } } +void Context::updateTextureGPUVirtualMemoryUsage(Size prevObjectSize, Size newObjectSize) { + if (prevObjectSize == newObjectSize) { + return; + } + if (newObjectSize > prevObjectSize) { + _textureGPUVirtualMemoryUsage.fetch_add(newObjectSize - prevObjectSize); + } else { + _textureGPUVirtualMemoryUsage.fetch_sub(prevObjectSize - newObjectSize); + } +} + uint32_t Context::getBufferGPUCount() { return _bufferGPUCount.load(); } @@ -165,10 +177,15 @@ Context::Size Context::getTextureGPUMemoryUsage() { return _textureGPUMemoryUsage.load(); } +Context::Size Context::getTextureGPUVirtualMemoryUsage() { + return _textureGPUVirtualMemoryUsage.load(); +} + void Backend::incrementBufferGPUCount() { Context::incrementBufferGPUCount(); } void Backend::decrementBufferGPUCount() { Context::decrementBufferGPUCount(); } void Backend::updateBufferGPUMemoryUsage(Resource::Size prevObjectSize, Resource::Size newObjectSize) { Context::updateBufferGPUMemoryUsage(prevObjectSize, newObjectSize); } void Backend::incrementTextureGPUCount() { Context::incrementTextureGPUCount(); } void Backend::decrementTextureGPUCount() { Context::decrementTextureGPUCount(); } void Backend::updateTextureGPUMemoryUsage(Resource::Size prevObjectSize, Resource::Size newObjectSize) { Context::updateTextureGPUMemoryUsage(prevObjectSize, newObjectSize); } +void Backend::updateTextureGPUVirtualMemoryUsage(Resource::Size prevObjectSize, Resource::Size newObjectSize) { Context::updateTextureGPUVirtualMemoryUsage(prevObjectSize, newObjectSize); } diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 7f442895a5..1dbe92ab38 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -34,6 +34,7 @@ public: int _ISNumIndexBufferChanges = 0; int _RSNumTextureBounded = 0; + int _RSAmountTextureMemoryBounded = 0; int _DSNumAPIDrawcalls = 0; int _DSNumDrawcalls = 0; @@ -128,6 +129,7 @@ public: static void incrementTextureGPUCount(); static void decrementTextureGPUCount(); static void updateTextureGPUMemoryUsage(Resource::Size prevObjectSize, Resource::Size newObjectSize); + static void updateTextureGPUVirtualMemoryUsage(Resource::Size prevObjectSize, Resource::Size newObjectSize); protected: StereoState _stereo; @@ -177,6 +179,7 @@ public: static uint32_t getTextureGPUCount(); static Size getTextureGPUMemoryUsage(); + static Size getTextureGPUVirtualMemoryUsage(); protected: Context(const Context& context); @@ -202,6 +205,7 @@ protected: static void incrementTextureGPUCount(); static void decrementTextureGPUCount(); static void updateTextureGPUMemoryUsage(Size prevObjectSize, Size newObjectSize); + static void updateTextureGPUVirtualMemoryUsage(Size prevObjectSize, Size newObjectSize); // Buffer and Texture Counters static std::atomic _bufferGPUCount; @@ -209,6 +213,7 @@ protected: static std::atomic _textureGPUCount; static std::atomic _textureGPUMemoryUsage; + static std::atomic _textureGPUVirtualMemoryUsage; friend class Backend; }; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 625ca6cec3..16de9caa28 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -192,6 +192,13 @@ enum Semantic { SRGBA, SBGRA, + COMPRESSED_R, + COMPRESSED_RGB, + COMPRESSED_RGBA, + + COMPRESSED_SRGB, + COMPRESSED_SRGBA, + R11G11B10, UNIFORM, diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index f5abacd279..77cb96ba9a 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -83,11 +83,17 @@ public: GLTexture(); ~GLTexture(); - void setSize(GLuint size); GLuint size() const { return _size; } + GLuint virtualSize() const { return _virtualSize; } + + void updateSize(GLuint virtualSize); private: - GLuint _size; + void setSize(GLuint size); + void setVirtualSize(GLuint size); + + GLuint _size; // true size as reported by the gl api + GLuint _virtualSize; // theorical size as expected }; static GLTexture* syncGPUObject(const Texture& texture); static GLuint getTextureID(const TexturePointer& texture, bool sync = true); diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 046f1ff0e5..4fe083909a 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -266,6 +266,8 @@ void GLBackend::do_setResourceTexture(Batch& batch, size_t paramOffset) { _resource._textures[slot] = resourceTexture; + _stats._RSAmountTextureMemoryBounded += object->size(); + } else { releaseResourceTexture(slot); return; diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 3fc7906285..600786eb3e 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -18,7 +18,8 @@ GLBackend::GLTexture::GLTexture() : _contentStamp(0), _texture(0), _target(GL_TEXTURE_2D), - _size(0) + _size(0), + _virtualSize(0) { Backend::incrementTextureGPUCount(); } @@ -28,6 +29,7 @@ GLBackend::GLTexture::~GLTexture() { glDeleteTextures(1, &_texture); } Backend::updateTextureGPUMemoryUsage(_size, 0); + Backend::updateTextureGPUVirtualMemoryUsage(_virtualSize, 0); Backend::decrementTextureGPUCount(); } @@ -36,6 +38,25 @@ void GLBackend::GLTexture::setSize(GLuint size) { _size = size; } +void GLBackend::GLTexture::setVirtualSize(GLuint size) { + Backend::updateTextureGPUVirtualMemoryUsage(_virtualSize, size); + _virtualSize = size; +} + +void GLBackend::GLTexture::updateSize(GLuint virtualSize) { + setVirtualSize(virtualSize); + + GLint gpuSize{ 0 }; + glGetTexLevelParameteriv(_target, 0, GL_TEXTURE_COMPRESSED, &gpuSize); + if (gpuSize) { + glGetTexLevelParameteriv(_target, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &gpuSize); + setSize(gpuSize); + } else { + setSize(virtualSize); + } +} + + class GLTexelFormat { public: GLenum internalFormat; @@ -56,6 +77,11 @@ public: case gpu::RGBA: texel.internalFormat = GL_RED; break; + + case gpu::COMPRESSED_R: + texel.internalFormat = GL_COMPRESSED_RED_RGTC1; + break; + case gpu::DEPTH: texel.internalFormat = GL_DEPTH_COMPONENT; break; @@ -96,6 +122,12 @@ public: case gpu::RGBA: texel.internalFormat = GL_RGB; break; + case gpu::COMPRESSED_RGB: + texel.internalFormat = GL_COMPRESSED_RGB; + break; + case gpu::COMPRESSED_SRGB: + texel.internalFormat = GL_COMPRESSED_SRGB; + break; default: qCDebug(gpulogging) << "Unknown combination of texel format"; } @@ -133,6 +165,13 @@ public: case gpu::SRGBA: texel.internalFormat = GL_SRGB_ALPHA; break; + + case gpu::COMPRESSED_RGBA: + texel.internalFormat = GL_COMPRESSED_RGBA; + break; + case gpu::COMPRESSED_SRGBA: + texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA; + break; default: qCDebug(gpulogging) << "Unknown combination of texel format"; } @@ -452,15 +491,15 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } - object->_target = GL_TEXTURE_2D; - - syncSampler(texture.getSampler(), texture.getType(), object); + object->_target = GL_TEXTURE_2D; + syncSampler(texture.getSampler(), texture.getType(), object); // At this point the mip piels have been loaded, we can notify texture.notifyMipFaceGPULoaded(0, 0); object->_contentStamp = texture.getDataStamp(); + object->updateSize((GLuint)texture.evalTotalSize()); } } else { const GLvoid* bytes = 0; @@ -493,7 +532,7 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { object->_storageStamp = texture.getStamp(); object->_contentStamp = texture.getDataStamp(); - object->setSize((GLuint)texture.getSize()); + object->updateSize((GLuint)texture.evalTotalSize()); } glBindTexture(GL_TEXTURE_2D, boundTex); @@ -539,6 +578,7 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { object->_contentStamp = texture.getDataStamp(); + object->updateSize((GLuint)texture.evalTotalSize()); } else { glBindTexture(GL_TEXTURE_CUBE_MAP, object->_texture); @@ -571,7 +611,7 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { object->_storageStamp = texture.getStamp(); object->_contentStamp = texture.getDataStamp(); - object->setSize((GLuint)texture.getSize()); + object->updateSize((GLuint)texture.evalTotalSize()); } glBindTexture(GL_TEXTURE_CUBE_MAP, boundTex); diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index af740ddb65..d94b6a4b93 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -46,10 +46,13 @@ uint32_t Texture::getTextureGPUCount() { Texture::Size Texture::getTextureGPUMemoryUsage() { return Context::getTextureGPUMemoryUsage(); - } -uint8 Texture::NUM_FACES_PER_TYPE[NUM_TYPES] = {1, 1, 1, 6}; +Texture::Size Texture::getTextureGPUVirtualMemoryUsage() { + return Context::getTextureGPUVirtualMemoryUsage(); +} + +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), diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 80fbc867e3..fc965f3251 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -146,6 +146,7 @@ public: static Size getTextureCPUMemoryUsage(); static uint32_t getTextureGPUCount(); static Size getTextureGPUMemoryUsage(); + static Size getTextureGPUVirtualMemoryUsage(); class Usage { public: diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 5173af438c..cc44ddef4c 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -94,10 +94,10 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con // bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); bool isLinearRGB = false; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::COMPRESSED_SRGB)); gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); + formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::COMPRESSED_SRGBA)); formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); } @@ -264,7 +264,7 @@ gpu::Texture* TextureUsage::createRoughnessTextureFromImage(const QImage& srcIma gpu::Texture* theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { - gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); + gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::COMPRESSED_R); gpu::Element formatMip = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); @@ -297,7 +297,7 @@ gpu::Texture* TextureUsage::createRoughnessTextureFromGlossImage(const QImage& s gpu::Texture* theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { - gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); + gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::COMPRESSED_R); gpu::Element formatMip = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); @@ -327,7 +327,7 @@ gpu::Texture* TextureUsage::createMetallicTextureFromImage(const QImage& srcImag gpu::Texture* theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { - gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); + gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::COMPRESSED_R); gpu::Element formatMip = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); @@ -446,10 +446,10 @@ gpu::Texture* TextureUsage::createCubeTextureFromImage(const QImage& srcImage, c // bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); bool isLinearRGB = false; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::COMPRESSED_SRGB)); gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); + formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::COMPRESSED_SRGBA)); formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); } @@ -669,10 +669,10 @@ gpu::Texture* TextureUsage::createLightmapTextureFromImage(const QImage& srcImag // bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::COMPRESSED_SRGB)); gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); + formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::COMPRESSED_SRGBA)); formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); } diff --git a/libraries/render/src/render/EngineStats.cpp b/libraries/render/src/render/EngineStats.cpp index 794f278fcf..4fc21acc5b 100644 --- a/libraries/render/src/render/EngineStats.cpp +++ b/libraries/render/src/render/EngineStats.cpp @@ -32,6 +32,7 @@ void EngineStats::run(const SceneContextPointer& sceneContext, const RenderConte config->textureGPUCount = gpu::Texture::getTextureGPUCount(); config->textureCPUMemoryUsage = gpu::Texture::getTextureCPUMemoryUsage(); config->textureGPUMemoryUsage = gpu::Texture::getTextureGPUMemoryUsage(); + config->textureGPUVirtualMemoryUsage = gpu::Texture::getTextureGPUVirtualMemoryUsage(); gpu::ContextStats gpuStats(_gpuStats); renderContext->args->_context->getStats(_gpuStats); @@ -45,6 +46,7 @@ void EngineStats::run(const SceneContextPointer& sceneContext, const RenderConte config->frameTextureCount = _gpuStats._RSNumTextureBounded - gpuStats._RSNumTextureBounded; config->frameTextureRate = config->frameTextureCount * frequency; + config->frameTextureMemoryUsage = _gpuStats._RSAmountTextureMemoryBounded - gpuStats._RSAmountTextureMemoryBounded; config->emitDirty(); } diff --git a/libraries/render/src/render/EngineStats.h b/libraries/render/src/render/EngineStats.h index 4a57724644..a5f1643d3f 100644 --- a/libraries/render/src/render/EngineStats.h +++ b/libraries/render/src/render/EngineStats.h @@ -33,6 +33,7 @@ namespace render { Q_PROPERTY(quint32 textureGPUCount MEMBER textureGPUCount NOTIFY dirty) Q_PROPERTY(qint64 textureCPUMemoryUsage MEMBER textureCPUMemoryUsage NOTIFY dirty) Q_PROPERTY(qint64 textureGPUMemoryUsage MEMBER textureGPUMemoryUsage NOTIFY dirty) + Q_PROPERTY(qint64 textureGPUVirtualMemoryUsage MEMBER textureGPUVirtualMemoryUsage NOTIFY dirty) Q_PROPERTY(quint32 frameAPIDrawcallCount MEMBER frameAPIDrawcallCount NOTIFY dirty) Q_PROPERTY(quint32 frameDrawcallCount MEMBER frameDrawcallCount NOTIFY dirty) @@ -43,7 +44,7 @@ namespace render { Q_PROPERTY(quint32 frameTextureCount MEMBER frameTextureCount NOTIFY dirty) Q_PROPERTY(quint32 frameTextureRate MEMBER frameTextureRate NOTIFY dirty) - + Q_PROPERTY(quint32 frameTextureMemoryUsage MEMBER frameTextureMemoryUsage NOTIFY dirty) public: EngineStatsConfig() : Job::Config(true) {} @@ -57,6 +58,7 @@ namespace render { quint32 textureGPUCount{ 0 }; qint64 textureCPUMemoryUsage{ 0 }; qint64 textureGPUMemoryUsage{ 0 }; + qint64 textureGPUVirtualMemoryUsage{ 0 }; quint32 frameAPIDrawcallCount{ 0 }; quint32 frameDrawcallCount{ 0 }; @@ -67,6 +69,7 @@ namespace render { quint32 frameTextureCount{ 0 }; quint32 frameTextureRate{ 0 }; + qint64 frameTextureMemoryUsage{ 0 }; void emitDirty() { emit dirty(); } From 582a6b7db308f9bd2ea9b0022254d475deffa101 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 1 Apr 2016 01:34:33 -0700 Subject: [PATCH 03/27] Adding the correct mip evaluation --- libraries/gpu/src/gpu/GLBackendTexture.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 600786eb3e..8690b78503 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -49,7 +49,19 @@ void GLBackend::GLTexture::updateSize(GLuint virtualSize) { GLint gpuSize{ 0 }; glGetTexLevelParameteriv(_target, 0, GL_TEXTURE_COMPRESSED, &gpuSize); if (gpuSize) { - glGetTexLevelParameteriv(_target, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &gpuSize); + GLint baseLevel; + GLint maxLevel; + glGetTexParameteriv(_target, GL_TEXTURE_BASE_LEVEL, &baseLevel); + glGetTexParameteriv(_target, GL_TEXTURE_MAX_LEVEL, &maxLevel); + + for (GLint level = baseLevel; level < maxLevel; level++) { + GLint levelSize{ 0 }; + glGetTexLevelParameteriv(_target, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &levelSize); + if (levelSize <= 0) { + break; + } + gpuSize += levelSize; + } setSize(gpuSize); } else { setSize(virtualSize); From 1ca87fa06962ae3d8645a8665f316492f6926d1f Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 1 Apr 2016 11:44:57 -0700 Subject: [PATCH 04/27] Refactoring a bit the texture loaders to factorize work --- .../src/model-networking/ModelCache.cpp | 6 +- .../src/model-networking/TextureCache.cpp | 13 +- .../src/model-networking/TextureCache.h | 1 + libraries/model/src/model/TextureMap.cpp | 171 +++++++----------- libraries/model/src/model/TextureMap.h | 4 + 5 files changed, 88 insertions(+), 107 deletions(-) diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 4120062308..ef78c83d76 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -400,7 +400,7 @@ NetworkMaterial::NetworkMaterial(const FBXMaterial& material, const QUrl& textur { _textures = Textures(MapChannel::NUM_MAP_CHANNELS); if (!material.albedoTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.albedoTexture, DEFAULT_TEXTURE, MapChannel::ALBEDO_MAP); + auto map = fetchTextureMap(textureBaseUrl, material.albedoTexture, ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); _albedoTransform = material.albedoTexture.transform; map->setTextureTransform(_albedoTransform); @@ -471,7 +471,7 @@ void NetworkMaterial::setTextures(const QVariantMap& textureMap) { if (!albedoName.isEmpty()) { auto url = textureMap.contains(albedoName) ? textureMap[albedoName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, DEFAULT_TEXTURE, MapChannel::ALBEDO_MAP); + auto map = fetchTextureMap(url, ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); map->setTextureTransform(_albedoTransform); // when reassigning the albedo texture we also check for the alpha channel used as opacity map->setUseAlphaChannel(true); @@ -480,7 +480,7 @@ void NetworkMaterial::setTextures(const QVariantMap& textureMap) { if (!normalName.isEmpty()) { auto url = textureMap.contains(normalName) ? textureMap[normalName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, DEFAULT_TEXTURE, MapChannel::NORMAL_MAP); + auto map = fetchTextureMap(url, NORMAL_TEXTURE, MapChannel::NORMAL_MAP); setTextureMap(MapChannel::NORMAL_MAP, map); } diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 3ba36dc2da..b6c87ca386 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -199,6 +199,18 @@ NetworkTexture::NetworkTexture(const QUrl& url, const TextureLoaderFunc& texture NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const { switch (_type) { + case ALBEDO_TEXTURE: { + return TextureLoaderFunc(model::TextureUsage::createAlbedoTextureFromImage); + break; + } + case EMISSIVE_TEXTURE: { + return TextureLoaderFunc(model::TextureUsage::createEmissiveTextureFromImage); + break; + } + case LIGHTMAP_TEXTURE: { + return TextureLoaderFunc(model::TextureUsage::createLightmapTextureFromImage); + break; + } case CUBE_TEXTURE: { return TextureLoaderFunc(model::TextureUsage::createCubeTextureFromImage); break; @@ -228,7 +240,6 @@ NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const { break; } case DEFAULT_TEXTURE: - case EMISSIVE_TEXTURE: default: { return TextureLoaderFunc(model::TextureUsage::create2DTextureFromImage); break; diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 858a40de36..4fe9a89460 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -31,6 +31,7 @@ typedef QSharedPointer NetworkTexturePointer; enum TextureType { DEFAULT_TEXTURE, + ALBEDO_TEXTURE, NORMAL_TEXTURE, BUMP_TEXTURE, SPECULAR_TEXTURE, diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index cc44ddef4c..56cc88bfc8 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -49,9 +49,7 @@ void TextureMap::setLightmapOffsetScale(float offset, float scale) { _lightmapOffsetScale.y = scale; } - -// FIXME why is this in the model library? Move to GPU or GPU_GL -gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { +gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImage, bool isLinear, bool doCompress, bool generateMips) { QImage image = srcImage; bool validAlpha = false; bool alphaAsMask = true; @@ -63,7 +61,7 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con if (image.format() != QImage::Format_ARGB32) { image = image.convertToFormat(QImage::Format_ARGB32); } - + // Actual alpha channel? create the histogram for (int y = 0; y < image.height(); ++y) { const QRgb* data = reinterpret_cast(image.constScanLine(y)); @@ -83,22 +81,58 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con alphaAsMask = ((numTranslucents / (double)totalNumPixels) < 0.05); } - } - + } + if (!validAlpha && image.format() != QImage::Format_RGB888) { image = image.convertToFormat(QImage::Format_RGB888); } - + gpu::Texture* theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { - // bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - bool isLinearRGB = false; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::COMPRESSED_SRGB)); - gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); + gpu::Element formatGPU; + gpu::Element formatMip; + if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::COMPRESSED_SRGBA)); - formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); + gpu::Semantic gpuSemantic; + gpu::Semantic mipSemantic; + if (isLinear) { + mipSemantic = gpu::SBGRA; + if (doCompress) { + gpuSemantic = gpu::COMPRESSED_SRGBA; + } else { + gpuSemantic = gpu::SRGBA; + } + } else { + mipSemantic = gpu::BGRA; + if (doCompress) { + gpuSemantic = gpu::COMPRESSED_RGBA; + } else { + gpuSemantic = gpu::RGBA; + } + } + formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpuSemantic); + formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, mipSemantic); + } else { + gpu::Semantic gpuSemantic; + gpu::Semantic mipSemantic; + if (isLinear) { + mipSemantic = gpu::SRGB; + if (doCompress) { + gpuSemantic = gpu::COMPRESSED_SRGB; + } else { + gpuSemantic = gpu::SRGB; + } + } else { + mipSemantic = gpu::RGB; + if (doCompress) { + gpuSemantic = gpu::COMPRESSED_RGB; + } else { + gpuSemantic = gpu::RGB; + } + } + formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, gpuSemantic); + formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, mipSemantic); } theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); @@ -113,15 +147,32 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con theTexture->setUsage(usage.build()); theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); - theTexture->autoGenerateMips(-1); - - // FIXME queue for transfer to GPU and block on completion + if (generateMips) { + theTexture->autoGenerateMips(-1); + } } - + return theTexture; } +gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, true, false, true); +} + + +gpu::Texture* TextureUsage::createAlbedoTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, true, true, true); +} + +gpu::Texture* TextureUsage::createEmissiveTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, true, true, true); +} + +gpu::Texture* TextureUsage::createLightmapTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return process2DTextureColorFromImage(srcImage, true, true, true); +} + gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& srcImage, const std::string& srcImageName) { QImage image = srcImage; @@ -598,89 +649,3 @@ gpu::Texture* TextureUsage::createCubeTextureFromImage(const QImage& srcImage, c return theTexture; } - - -gpu::Texture* TextureUsage::createLightmapTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - QImage image = srcImage; - - int imageArea = image.width() * image.height(); - - int opaquePixels = 0; - int translucentPixels = 0; - //bool isTransparent = false; - int redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0; - const int EIGHT_BIT_MAXIMUM = 255; - QColor averageColor(EIGHT_BIT_MAXIMUM, EIGHT_BIT_MAXIMUM, EIGHT_BIT_MAXIMUM); - - if (!image.hasAlphaChannel()) { - if (image.format() != QImage::Format_RGB888) { - image = image.convertToFormat(QImage::Format_RGB888); - } - // int redTotal = 0, greenTotal = 0, blueTotal = 0; - for (int y = 0; y < image.height(); y++) { - for (int x = 0; x < image.width(); x++) { - QRgb rgb = image.pixel(x, y); - redTotal += qRed(rgb); - greenTotal += qGreen(rgb); - blueTotal += qBlue(rgb); - } - } - if (imageArea > 0) { - averageColor.setRgb(redTotal / imageArea, greenTotal / imageArea, blueTotal / imageArea); - } - } else { - if (image.format() != QImage::Format_ARGB32) { - image = image.convertToFormat(QImage::Format_ARGB32); - } - - // check for translucency/false transparency - // int opaquePixels = 0; - // int translucentPixels = 0; - // int redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0; - for (int y = 0; y < image.height(); y++) { - for (int x = 0; x < image.width(); x++) { - QRgb rgb = image.pixel(x, y); - redTotal += qRed(rgb); - greenTotal += qGreen(rgb); - blueTotal += qBlue(rgb); - int alpha = qAlpha(rgb); - alphaTotal += alpha; - if (alpha == EIGHT_BIT_MAXIMUM) { - opaquePixels++; - } else if (alpha != 0) { - translucentPixels++; - } - } - } - if (opaquePixels == imageArea) { - qCDebug(modelLog) << "Image with alpha channel is completely opaque:" << QString(srcImageName.c_str()); - image = image.convertToFormat(QImage::Format_RGB888); - } - - averageColor = QColor(redTotal / imageArea, - greenTotal / imageArea, blueTotal / imageArea, alphaTotal / imageArea); - - //isTransparent = (translucentPixels >= imageArea / 2); - } - - gpu::Texture* theTexture = nullptr; - if ((image.width() > 0) && (image.height() > 0)) { - - // bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::COMPRESSED_SRGB)); - gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); - if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::COMPRESSED_SRGBA)); - formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); - } - - - theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); - theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); - theTexture->autoGenerateMips(-1); - } - - return theTexture; -} diff --git a/libraries/model/src/model/TextureMap.h b/libraries/model/src/model/TextureMap.h index e845aebb81..fa0eea55cb 100755 --- a/libraries/model/src/model/TextureMap.h +++ b/libraries/model/src/model/TextureMap.h @@ -32,6 +32,8 @@ public: int _environmentUsage = 0; static gpu::Texture* create2DTextureFromImage(const QImage& image, const std::string& srcImageName); + static gpu::Texture* createAlbedoTextureFromImage(const QImage& image, const std::string& srcImageName); + static gpu::Texture* createEmissiveTextureFromImage(const QImage& image, const std::string& srcImageName); static gpu::Texture* createNormalTextureFromNormalImage(const QImage& image, const std::string& srcImageName); static gpu::Texture* createNormalTextureFromBumpImage(const QImage& image, const std::string& srcImageName); static gpu::Texture* createRoughnessTextureFromImage(const QImage& image, const std::string& srcImageName); @@ -40,6 +42,8 @@ public: static gpu::Texture* createCubeTextureFromImage(const QImage& image, const std::string& srcImageName); static gpu::Texture* createLightmapTextureFromImage(const QImage& image, const std::string& srcImageName); + + static gpu::Texture* process2DTextureColorFromImage(const QImage& imageSrc, bool isLinear, bool doCompress, bool generateMips); }; From be38de32398aac789757b21347ec1479590d744b Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 1 Apr 2016 17:16:22 -0700 Subject: [PATCH 05/27] Cleaning up the TextureMap loaders and cleaning for pr --- libraries/gpu/src/gpu/Format.h | 11 ++++++++++- libraries/gpu/src/gpu/GLBackendTexture.cpp | 18 ++++++++++++++++++ libraries/model/src/model/TextureMap.cpp | 13 ++++--------- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 16de9caa28..60a90840c6 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -192,13 +192,22 @@ enum Semantic { SRGBA, SBGRA, + // These are generic compression format smeantic for images COMPRESSED_R, - COMPRESSED_RGB, + + COMPRESSED_RGB, COMPRESSED_RGBA, COMPRESSED_SRGB, COMPRESSED_SRGBA, + // FIXME: Will have to be supported later: + /*COMPRESSED_BC3_RGBA, // RGBA_S3TC_DXT5_EXT, + COMPRESSED_BC3_SRGBA, // SRGB_ALPHA_S3TC_DXT5_EXT + + COMPRESSED_BC7_RGBA, + COMPRESSED_BC7_SRGBA, */ + R11G11B10, UNIFORM, diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 8690b78503..82e6d12054 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -184,6 +184,24 @@ public: case gpu::COMPRESSED_SRGBA: texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA; break; + + // FIXME: WE will want to support this later + /* + case gpu::COMPRESSED_BC3_RGBA: + texel.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + break; + case gpu::COMPRESSED_BC3_SRGBA: + texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; + break; + + case gpu::COMPRESSED_BC7_RGBA: + texel.internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB; + break; + case gpu::COMPRESSED_BC7_SRGBA: + texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; + break; + */ + default: qCDebug(gpulogging) << "Unknown combination of texel format"; } diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 56cc88bfc8..bd09955fd1 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -182,9 +182,7 @@ gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& src image = image.convertToFormat(QImage::Format_RGB888); } } else { - if (image.format() != QImage::Format_ARGB32) { - image = image.convertToFormat(QImage::Format_ARGB32); - } + image = image.convertToFormat(QImage::Format_RGB888); } gpu::Texture* theTexture = nullptr; @@ -192,12 +190,9 @@ gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& src bool isLinearRGB = true; - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); - gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); - if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); - formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); - } + gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB); + gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB); + theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); From d9bc06d92d934968e39585aa4759bd629de1297c Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 5 Apr 2016 19:13:24 -0700 Subject: [PATCH 06/27] Trying to ge5t the proper behavior for the Compression texture and textures in genral... --- libraries/gpu/src/gpu/GLBackendShared.h | 2 + .../gpu/src/gpu/GLBackendTexelFormat.cpp | 24 +++++++++ libraries/gpu/src/gpu/GLBackendTexture.cpp | 49 +++++++++++++------ 3 files changed, 61 insertions(+), 14 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackendShared.h b/libraries/gpu/src/gpu/GLBackendShared.h index d6aab6034d..aef670e6b0 100644 --- a/libraries/gpu/src/gpu/GLBackendShared.h +++ b/libraries/gpu/src/gpu/GLBackendShared.h @@ -54,6 +54,8 @@ public: static GLTexelFormat evalGLTexelFormat(const gpu::Element& dstFormat) { return evalGLTexelFormat(dstFormat, dstFormat); } + static GLTexelFormat evalGLTexelFormatInternal(const gpu::Element& dstFormat); + static GLTexelFormat evalGLTexelFormat(const gpu::Element& dstFormat, const gpu::Element& srcFormat); }; diff --git a/libraries/gpu/src/gpu/GLBackendTexelFormat.cpp b/libraries/gpu/src/gpu/GLBackendTexelFormat.cpp index 3f64f373d6..1a7b969e13 100644 --- a/libraries/gpu/src/gpu/GLBackendTexelFormat.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexelFormat.cpp @@ -10,6 +10,11 @@ using namespace gpu; +GLTexelFormat GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) { + GLTexelFormat texel = { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE }; + return texel; +} + GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const Element& srcFormat) { if (dstFormat != srcFormat) { GLTexelFormat texel = { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE }; @@ -118,6 +123,7 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E break; case gpu::COMPRESSED_SRGBA: texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA; + break; // FIXME: WE will want to support this later @@ -156,6 +162,10 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E texel.type = _elementTypeToGLType[dstFormat.getType()]; switch (dstFormat.getSemantic()) { + case gpu::COMPRESSED_R: { + texel.internalFormat = GL_COMPRESSED_RED_RGTC1; + break; + } case gpu::RGB: case gpu::RGBA: case gpu::SRGB: @@ -312,6 +322,12 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E case gpu::SRGBA: texel.internalFormat = GL_SRGB8; // standard 2.2 gamma correction color break; + case gpu::COMPRESSED_RGB: + texel.internalFormat = GL_COMPRESSED_RGB; + break; + case gpu::COMPRESSED_SRGB: + texel.internalFormat = GL_COMPRESSED_SRGB; + break; default: qCDebug(gpulogging) << "Unknown combination of texel format"; } @@ -383,11 +399,19 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E } break; case gpu::SRGB: + texel.format = GL_RGB; texel.internalFormat = GL_SRGB8; break; case gpu::SRGBA: + texel.format = GL_RGBA; texel.internalFormat = GL_SRGB8_ALPHA8; // standard 2.2 gamma correction color break; + case gpu::COMPRESSED_RGBA: + texel.internalFormat = GL_COMPRESSED_RGBA; + break; + case gpu::COMPRESSED_SRGBA: + texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA; + break; default: qCDebug(gpulogging) << "Unknown combination of texel format"; } diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 35c8666292..1e68dd1453 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -72,20 +72,41 @@ GLBackend::GLTexture::GLTexture(const Texture& texture) : } GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat()); - withPreservedTexture(_target, [&] { - glBindTexture(_target, _texture); - (void)CHECK_GL_ERROR(); - // GO through the process of allocating the correct storage - if (GLEW_VERSION_4_2) { - glTexStorage2D(_target, levels, texelFormat.internalFormat, width, height); - } else { - glTexImage2D(_target, 0, texelFormat.internalFormat, width, height, 0, texelFormat.format, texelFormat.type, 0); - } - (void)CHECK_GL_ERROR(); - syncSampler(texture.getSampler(), texture.getType(), this); - (void)CHECK_GL_ERROR(); - updateSize((GLuint)texture.evalTotalSize()); - }); + + GLint boundTex = -1; + switch (_target) { + case GL_TEXTURE_2D: + glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTex); + break; + + case GL_TEXTURE_CUBE_MAP: + glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP, &boundTex); + break; + + default: + qFatal("Unsupported texture type"); + } + (void)CHECK_GL_ERROR(); + + glBindTexture(_target, _texture); + + (void)CHECK_GL_ERROR(); + // GO through the process of allocating the correct storage + if (GLEW_VERSION_4_2) { + glTexStorage2D(_target, levels, texelFormat.internalFormat, width, height); + } else { + glTexImage2D(_target, 0, texelFormat.internalFormat, width, height, 0, texelFormat.format, texelFormat.type, 0); + } + (void)CHECK_GL_ERROR(); + + syncSampler(texture.getSampler(), texture.getType(), this); + (void)CHECK_GL_ERROR(); + + updateSize((GLuint)texture.evalTotalSize()); + (void)CHECK_GL_ERROR(); + + glBindTexture(_target, boundTex); + (void)CHECK_GL_ERROR(); } GLBackend::GLTexture::~GLTexture() { From 16174df0f319f7cda70ee2ec28fb87057f006a60 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 6 Apr 2016 16:33:45 -0700 Subject: [PATCH 07/27] POlishing the size evaluation and trying to debug the compression scheme --- libraries/gpu/src/gpu/Format.h | 4 ++ libraries/gpu/src/gpu/GLBackend.h | 3 +- libraries/gpu/src/gpu/GLBackendOutput.cpp | 4 +- libraries/gpu/src/gpu/GLBackendTexture.cpp | 70 +++++++++++++++------- libraries/model/src/model/TextureMap.cpp | 6 +- 5 files changed, 58 insertions(+), 29 deletions(-) diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 60a90840c6..b9e46b700a 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -193,6 +193,7 @@ enum Semantic { SBGRA, // These are generic compression format smeantic for images + _FIRST_COMPRESSED, COMPRESSED_R, COMPRESSED_RGB, @@ -208,6 +209,8 @@ enum Semantic { COMPRESSED_BC7_RGBA, COMPRESSED_BC7_SRGBA, */ + _LAST_COMPRESSED, + R11G11B10, UNIFORM, @@ -240,6 +243,7 @@ public: Dimension getDimension() const { return (Dimension)_dimension; } + bool isCompressed() const { return (getSemantic() - _FIRST_COMPRESSED <= _LAST_COMPRESSED - _FIRST_COMPRESSED); } Type getType() const { return (Type)_type; } bool isNormalized() const { return (getType() >= NORMALIZED_START); } diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 0f64f6d199..f59e154bb9 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -130,6 +130,7 @@ public: GLuint _size; // true size as reported by the gl api GLuint _virtualSize; // theorical size as expected + GLuint _numLevels{ 0 }; void transferMip(GLenum target, const Texture::PixelsPointer& mip) const; @@ -137,7 +138,7 @@ public: const Texture& _gpuTexture; std::atomic _syncState { SyncState::Idle }; }; - static GLTexture* syncGPUObject(const TexturePointer& texture); + static GLTexture* syncGPUObject(const TexturePointer& texture, bool needTransfer = true); static GLuint getTextureID(const TexturePointer& texture, bool sync = true); // very specific for now diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index 4f714fb53d..545d0a8cdb 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -83,7 +83,7 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe for (auto& b : framebuffer.getRenderBuffers()) { surface = b._texture; if (surface) { - gltexture = GLBackend::syncGPUObject(surface); + gltexture = GLBackend::syncGPUObject(surface, false); // Grab the gltexture and don't transfer } else { gltexture = nullptr; } @@ -123,7 +123,7 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe if (framebuffer.getDepthStamp() != object->_depthStamp) { auto surface = framebuffer.getDepthStencilBuffer(); if (framebuffer.hasDepthStencil() && surface) { - gltexture = GLBackend::syncGPUObject(surface); + gltexture = GLBackend::syncGPUObject(surface, false); // Grab the gltexture and don't transfer } if (gltexture) { diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 1e68dd1453..c4889fe6f7 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -53,6 +53,8 @@ GLBackend::GLTexture::GLTexture(const Texture& texture) : _target(gpuToGLTextureType(texture)), _size(0), _virtualSize(0), + // _numLevels(std::max((uint16)1, texture.maxMip())), + _numLevels(texture.maxMip() + 1), _gpuTexture(texture) { Backend::incrementTextureGPUCount(); @@ -61,15 +63,6 @@ GLBackend::GLTexture::GLTexture(const Texture& texture) : GLsizei width = texture.getWidth(); GLsizei height = texture.getHeight(); - GLsizei levels = 1; - if (texture.maxMip() > 0) { - if (texture.isAutogenerateMips()) { - while ((width | height) >> levels) { - ++levels; - } - } - levels = std::max(1, std::min(texture.maxMip() + 1, levels)); - } GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat()); @@ -92,12 +85,26 @@ GLBackend::GLTexture::GLTexture(const Texture& texture) : (void)CHECK_GL_ERROR(); // GO through the process of allocating the correct storage - if (GLEW_VERSION_4_2) { - glTexStorage2D(_target, levels, texelFormat.internalFormat, width, height); + if (GLEW_VERSION_4_2 && !texture.getTexelFormat().isCompressed()) { + glTexStorage2D(_target, _numLevels, texelFormat.internalFormat, width, height); + (void)CHECK_GL_ERROR(); } else { - glTexImage2D(_target, 0, texelFormat.internalFormat, width, height, 0, texelFormat.format, texelFormat.type, 0); + glTexParameteri(_target, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(_target, GL_TEXTURE_MAX_LEVEL, _numLevels - 1); + + for (int l = 0; l < _numLevels; l++) { + if (texture.getType() == gpu::Texture::TEX_CUBE) { + for (int face = 0; face < CUBE_NUM_FACES; face++) { + glTexImage2D(CUBE_FACE_LAYOUT[face], l, texelFormat.internalFormat, width, height, 0, texelFormat.format, texelFormat.type, NULL); + } + } else { + glTexImage2D(_target, l, texelFormat.internalFormat, width, height, 0, texelFormat.format, texelFormat.type, NULL); + } + width = std::max(1, (width / 2)); + height = std::max(1, (height / 2)); + } + (void)CHECK_GL_ERROR(); } - (void)CHECK_GL_ERROR(); syncSampler(texture.getSampler(), texture.getType(), this); (void)CHECK_GL_ERROR(); @@ -118,9 +125,6 @@ GLBackend::GLTexture::~GLTexture() { Backend::decrementTextureGPUCount(); } -bool GLBackend::GLTexture::isInvalid() const { - return _storageStamp < _gpuTexture.getStamp(); -} void GLBackend::GLTexture::setSize(GLuint size) { Backend::updateTextureGPUMemoryUsage(_size, size); @@ -136,16 +140,30 @@ void GLBackend::GLTexture::updateSize(GLuint virtualSize) { setVirtualSize(virtualSize); GLint gpuSize{ 0 }; - glGetTexLevelParameteriv(_target, 0, GL_TEXTURE_COMPRESSED, &gpuSize); + if (_target == GL_TEXTURE_CUBE_MAP) { + glGetTexLevelParameteriv(CUBE_FACE_LAYOUT[0], 0, GL_TEXTURE_COMPRESSED, &gpuSize); + } else { + glGetTexLevelParameteriv(_target, 0, GL_TEXTURE_COMPRESSED, &gpuSize); + } + (void)CHECK_GL_ERROR(); + if (gpuSize) { GLint baseLevel; GLint maxLevel; glGetTexParameteriv(_target, GL_TEXTURE_BASE_LEVEL, &baseLevel); glGetTexParameteriv(_target, GL_TEXTURE_MAX_LEVEL, &maxLevel); - for (GLint level = baseLevel; level < maxLevel; level++) { + for (GLint level = baseLevel; level <= maxLevel; level++) { GLint levelSize{ 0 }; - glGetTexLevelParameteriv(_target, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &levelSize); + if (_target == GL_TEXTURE_CUBE_MAP) { + for (int face = 0; face < CUBE_NUM_FACES; face++) { + GLint faceSize{ 0 }; + glGetTexLevelParameteriv(CUBE_FACE_LAYOUT[face], level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &faceSize); + levelSize += faceSize; + } + } else { + glGetTexLevelParameteriv(_target, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &levelSize); + } if (levelSize <= 0) { break; } @@ -158,6 +176,10 @@ void GLBackend::GLTexture::updateSize(GLuint virtualSize) { } +bool GLBackend::GLTexture::isInvalid() const { + return _storageStamp < _gpuTexture.getStamp(); +} + bool GLBackend::GLTexture::isOutdated() const { return _contentStamp < _gpuTexture.getDataStamp(); } @@ -247,7 +269,7 @@ void GLBackend::GLTexture::postTransfer() { } } -GLBackend::GLTexture* GLBackend::syncGPUObject(const TexturePointer& texturePointer) { +GLBackend::GLTexture* GLBackend::syncGPUObject(const TexturePointer& texturePointer, bool needTransfer) { const Texture& texture = *texturePointer; if (!texture.isDefined()) { // NO texture definition yet so let's avoid thinking @@ -269,8 +291,9 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const TexturePointer& texturePoin object = new GLTexture(texture); } - // need to have a gpu object? - if (texture.getNumSlices() != 1) { + // Object maybe doens't neet to be tranasferred after creation + if (!needTransfer) { + object->_contentStamp = texturePointer->getDataStamp(); return object; } @@ -383,7 +406,8 @@ void GLBackend::do_generateTextureMips(Batch& batch, size_t paramOffset) { return; } - GLTexture* object = GLBackend::syncGPUObject(resourceTexture); + // DO not transfer the texture, this call is expected for rendering texture + GLTexture* object = GLBackend::syncGPUObject(resourceTexture, false); if (!object) { return; } diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index ce6d46fcdb..9a145ffbec 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -162,15 +162,15 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con gpu::Texture* TextureUsage::createAlbedoTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, true, true, true); + return process2DTextureColorFromImage(srcImage, true, false, true); } gpu::Texture* TextureUsage::createEmissiveTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, true, true, true); + return process2DTextureColorFromImage(srcImage, true, false, true); } gpu::Texture* TextureUsage::createLightmapTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, true, true, true); + return process2DTextureColorFromImage(srcImage, true, false, true); } From a6bac7ad927789932f532a546ae27680fe626f99 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 6 Apr 2016 18:30:18 -0700 Subject: [PATCH 08/27] Experimenting with a hidden gltexture object while beeing transfered --- libraries/gpu/src/gpu/GLBackend.h | 3 ++- libraries/gpu/src/gpu/GLBackendTexture.cpp | 26 ++++++++++++++-------- libraries/model/src/model/TextureMap.cpp | 12 ++++------ 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index f59e154bb9..c8df1f809f 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -78,7 +78,8 @@ public: public: const Stamp _storageStamp; Stamp _contentStamp { 0 }; - const GLuint _texture; + const GLuint _secretTexture; + GLuint _texture{ 0 }; const GLenum _target; GLTexture(const gpu::Texture& gpuTexture); diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index c4889fe6f7..de1dd9ce2f 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -49,7 +49,7 @@ const GLenum GLBackend::GLTexture::CUBE_FACE_LAYOUT[6] = { // Create the texture and allocate storage GLBackend::GLTexture::GLTexture(const Texture& texture) : _storageStamp(texture.getStamp()), - _texture(allocateSingleTexture()), + _secretTexture(allocateSingleTexture()), _target(gpuToGLTextureType(texture)), _size(0), _virtualSize(0), @@ -81,18 +81,19 @@ GLBackend::GLTexture::GLTexture(const Texture& texture) : } (void)CHECK_GL_ERROR(); - glBindTexture(_target, _texture); + glBindTexture(_target, _secretTexture); (void)CHECK_GL_ERROR(); // GO through the process of allocating the correct storage - if (GLEW_VERSION_4_2 && !texture.getTexelFormat().isCompressed()) { + /* if (GLEW_VERSION_4_2 && !texture.getTexelFormat().isCompressed()) { glTexStorage2D(_target, _numLevels, texelFormat.internalFormat, width, height); (void)CHECK_GL_ERROR(); - } else { + } else*/ { glTexParameteri(_target, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(_target, GL_TEXTURE_MAX_LEVEL, _numLevels - 1); - for (int l = 0; l < _numLevels; l++) { + // for (int l = 0; l < _numLevels; l++) { + { int l = 0; if (texture.getType() == gpu::Texture::TEX_CUBE) { for (int face = 0; face < CUBE_NUM_FACES; face++) { glTexImage2D(CUBE_FACE_LAYOUT[face], l, texelFormat.internalFormat, width, height, 0, texelFormat.format, texelFormat.type, NULL); @@ -117,9 +118,12 @@ GLBackend::GLTexture::GLTexture(const Texture& texture) : } GLBackend::GLTexture::~GLTexture() { - if (_texture != 0) { - glDeleteTextures(1, &_texture); + if (_secretTexture != 0) { + glDeleteTextures(1, &_secretTexture); } + /*if (_texture != 0) { + glDeleteTextures(1, &_texture); + }*/ Backend::updateTextureGPUMemoryUsage(_size, 0); Backend::updateTextureGPUVirtualMemoryUsage(_virtualSize, 0); Backend::decrementTextureGPUCount(); @@ -213,13 +217,15 @@ void GLBackend::GLTexture::transferMip(GLenum target, const Texture::PixelsPoint // Move content bits from the CPU to the GPU void GLBackend::GLTexture::transfer() const { PROFILE_RANGE(__FUNCTION__); - qDebug() << "Transferring texture: " << _texture; + qDebug() << "Transferring texture: " << _secretTexture; // Need to update the content of the GPU object from the source sysmem of the texture if (_contentStamp >= _gpuTexture.getDataStamp()) { return; } - glBindTexture(_target, _texture); + //_secretTexture + glBindTexture(_target, _secretTexture); + // glBindTexture(_target, _texture); // GO through the process of allocating the correct storage and/or update the content switch (_gpuTexture.getType()) { case Texture::TEX_2D: @@ -251,6 +257,7 @@ void GLBackend::GLTexture::transfer() const { // Do any post-transfer operations that might be required on the main context / rendering thread void GLBackend::GLTexture::postTransfer() { setSyncState(GLTexture::Idle); + _texture = _secretTexture; // At this point the mip pixels have been loaded, we can notify the gpu texture to abandon it's memory switch (_gpuTexture.getType()) { case Texture::TEX_2D: @@ -294,6 +301,7 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const TexturePointer& texturePoin // Object maybe doens't neet to be tranasferred after creation if (!needTransfer) { object->_contentStamp = texturePointer->getDataStamp(); + object->postTransfer(); return object; } diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 9a145ffbec..2906fe7abf 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -162,26 +162,22 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con gpu::Texture* TextureUsage::createAlbedoTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, true, false, true); + return process2DTextureColorFromImage(srcImage, true, true, true); } gpu::Texture* TextureUsage::createEmissiveTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, true, false, true); + return process2DTextureColorFromImage(srcImage, true, true, true); } gpu::Texture* TextureUsage::createLightmapTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - return process2DTextureColorFromImage(srcImage, true, false, true); + return process2DTextureColorFromImage(srcImage, true, true, true); } gpu::Texture* TextureUsage::createNormalTextureFromNormalImage(const QImage& srcImage, const std::string& srcImageName) { QImage image = srcImage; - if (!image.hasAlphaChannel()) { - if (image.format() != QImage::Format_RGB888) { - image = image.convertToFormat(QImage::Format_RGB888); - } - } else { + if (image.format() != QImage::Format_RGB888) { image = image.convertToFormat(QImage::Format_RGB888); } From cf983e627dd341b683ed3cb8a58c834233572c4a Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 6 Apr 2016 19:36:52 -0700 Subject: [PATCH 09/27] fixing the warnings --- libraries/gpu/src/gpu/GLBackend.h | 2 +- libraries/gpu/src/gpu/GLBackendTexture.cpp | 15 ++++++++++----- .../gpu/src/gpu/GLBackendTextureTransfer.cpp | 6 +++--- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index c8df1f809f..ed72a7ad30 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -88,7 +88,7 @@ public: GLuint size() const { return _size; } GLuint virtualSize() const { return _virtualSize; } - void updateSize(GLuint virtualSize); + void updateSize(); enum SyncState { // The texture is currently undergoing no processing, although it's content diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index de1dd9ce2f..0252bd0ea4 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -95,7 +95,7 @@ GLBackend::GLTexture::GLTexture(const Texture& texture) : // for (int l = 0; l < _numLevels; l++) { { int l = 0; if (texture.getType() == gpu::Texture::TEX_CUBE) { - for (int face = 0; face < CUBE_NUM_FACES; face++) { + for (size_t face = 0; face < CUBE_NUM_FACES; face++) { glTexImage2D(CUBE_FACE_LAYOUT[face], l, texelFormat.internalFormat, width, height, 0, texelFormat.format, texelFormat.type, NULL); } } else { @@ -110,7 +110,9 @@ GLBackend::GLTexture::GLTexture(const Texture& texture) : syncSampler(texture.getSampler(), texture.getType(), this); (void)CHECK_GL_ERROR(); - updateSize((GLuint)texture.evalTotalSize()); + GLuint virtualSize = _gpuTexture.evalTotalSize(); + setVirtualSize(virtualSize); + setSize(virtualSize); (void)CHECK_GL_ERROR(); glBindTexture(_target, boundTex); @@ -140,9 +142,12 @@ void GLBackend::GLTexture::setVirtualSize(GLuint size) { _virtualSize = size; } -void GLBackend::GLTexture::updateSize(GLuint virtualSize) { +void GLBackend::GLTexture::updateSize() { + GLuint virtualSize = _gpuTexture.evalTotalSize(); setVirtualSize(virtualSize); - + if (!_texture) { + setSize(virtualSize); + } GLint gpuSize{ 0 }; if (_target == GL_TEXTURE_CUBE_MAP) { glGetTexLevelParameteriv(CUBE_FACE_LAYOUT[0], 0, GL_TEXTURE_COMPRESSED, &gpuSize); @@ -160,7 +165,7 @@ void GLBackend::GLTexture::updateSize(GLuint virtualSize) { for (GLint level = baseLevel; level <= maxLevel; level++) { GLint levelSize{ 0 }; if (_target == GL_TEXTURE_CUBE_MAP) { - for (int face = 0; face < CUBE_NUM_FACES; face++) { + for (size_t face = 0; face < CUBE_NUM_FACES; face++) { GLint faceSize{ 0 }; glGetTexLevelParameteriv(CUBE_FACE_LAYOUT[face], level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &faceSize); levelSize += faceSize; diff --git a/libraries/gpu/src/gpu/GLBackendTextureTransfer.cpp b/libraries/gpu/src/gpu/GLBackendTextureTransfer.cpp index 1ad18c8c2f..657712490c 100644 --- a/libraries/gpu/src/gpu/GLBackendTextureTransfer.cpp +++ b/libraries/gpu/src/gpu/GLBackendTextureTransfer.cpp @@ -63,10 +63,10 @@ bool GLTextureTransferHelper::processQueueItems(const Queue& messages) { GLBackend::GLTexture* object = Backend::getGPUObject(*texturePointer); object->transfer(); - - - glBindTexture(object->_target, 0); auto writeSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + + object->updateSize(); + glBindTexture(object->_target, 0); glClientWaitSync(writeSync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED); glDeleteSync(writeSync); object->_contentStamp = texturePointer->getDataStamp(); From 76dd7405787754c1a9c11ab702a52151fd95eb81 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 7 Apr 2016 20:05:05 -0700 Subject: [PATCH 10/27] Cleaning up to test before merge, not solved the stuttering happening when using compressed textures. cleaned up a bit of the TextureMap doanload callbacks --- libraries/gpu/src/gpu/Format.h | 2 +- libraries/gpu/src/gpu/GLBackend.h | 6 +- libraries/gpu/src/gpu/GLBackendTexture.cpp | 139 ++--- .../gpu/src/gpu/GLBackendTextureTransfer.cpp | 12 +- libraries/model/src/model/TextureMap.cpp | 498 +++++++++--------- libraries/model/src/model/TextureMap.h | 7 +- 6 files changed, 332 insertions(+), 332 deletions(-) diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index b9e46b700a..940b0eb85b 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -243,7 +243,7 @@ public: Dimension getDimension() const { return (Dimension)_dimension; } - bool isCompressed() const { return (getSemantic() - _FIRST_COMPRESSED <= _LAST_COMPRESSED - _FIRST_COMPRESSED); } + bool isCompressed() const { return uint8(getSemantic() - _FIRST_COMPRESSED) <= uint8(_LAST_COMPRESSED - _FIRST_COMPRESSED); } Type getType() const { return (Type)_type; } bool isNormalized() const { return (getType() >= NORMALIZED_START); } diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index ed72a7ad30..29256a322f 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -78,13 +78,14 @@ public: public: const Stamp _storageStamp; Stamp _contentStamp { 0 }; - const GLuint _secretTexture; GLuint _texture{ 0 }; const GLenum _target; GLTexture(const gpu::Texture& gpuTexture); ~GLTexture(); + void createTexture(); + GLuint size() const { return _size; } GLuint virtualSize() const { return _virtualSize; } @@ -125,6 +126,9 @@ public: static const GLenum CUBE_FACE_LAYOUT[6]; private: + // at creation the true texture is created in GL + // it becomes public only when ready. + GLuint _privateTexture; void setSize(GLuint size); void setVirtualSize(GLuint size); diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 0252bd0ea4..54d7fb27bb 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -49,22 +49,30 @@ const GLenum GLBackend::GLTexture::CUBE_FACE_LAYOUT[6] = { // Create the texture and allocate storage GLBackend::GLTexture::GLTexture(const Texture& texture) : _storageStamp(texture.getStamp()), - _secretTexture(allocateSingleTexture()), + _privateTexture(allocateSingleTexture()), _target(gpuToGLTextureType(texture)), _size(0), _virtualSize(0), - // _numLevels(std::max((uint16)1, texture.maxMip())), _numLevels(texture.maxMip() + 1), _gpuTexture(texture) { Backend::incrementTextureGPUCount(); - Backend::updateTextureGPUMemoryUsage(0, _size); Backend::setGPUObject(texture, this); - GLsizei width = texture.getWidth(); - GLsizei height = texture.getHeight(); - GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat()); + // updateSize(); + GLuint virtualSize = _gpuTexture.evalTotalSize(); + setVirtualSize(virtualSize); + setSize(virtualSize); +} + +void GLBackend::GLTexture::createTexture() { + _privateTexture = allocateSingleTexture(); + + GLsizei width = _gpuTexture.getWidth(); + GLsizei height = _gpuTexture.getHeight(); + + GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuTexture.getTexelFormat()); GLint boundTex = -1; switch (_target) { @@ -81,51 +89,47 @@ GLBackend::GLTexture::GLTexture(const Texture& texture) : } (void)CHECK_GL_ERROR(); - glBindTexture(_target, _secretTexture); + glBindTexture(_target, _privateTexture); (void)CHECK_GL_ERROR(); + // Fixme: this usage of TexStorage doesn;t work wtih compressed texture, altuogh it should. // GO through the process of allocating the correct storage - /* if (GLEW_VERSION_4_2 && !texture.getTexelFormat().isCompressed()) { - glTexStorage2D(_target, _numLevels, texelFormat.internalFormat, width, height); - (void)CHECK_GL_ERROR(); - } else*/ { + /* if (GLEW_VERSION_4_2 && !texture.getTexelFormat().isCompressed()) { + glTexStorage2D(_target, _numLevels, texelFormat.internalFormat, width, height); + (void)CHECK_GL_ERROR(); + } else*/ + { glTexParameteri(_target, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(_target, GL_TEXTURE_MAX_LEVEL, _numLevels - 1); - // for (int l = 0; l < _numLevels; l++) { + // for (int l = 0; l < _numLevels; l++) { { int l = 0; - if (texture.getType() == gpu::Texture::TEX_CUBE) { - for (size_t face = 0; face < CUBE_NUM_FACES; face++) { - glTexImage2D(CUBE_FACE_LAYOUT[face], l, texelFormat.internalFormat, width, height, 0, texelFormat.format, texelFormat.type, NULL); - } - } else { - glTexImage2D(_target, l, texelFormat.internalFormat, width, height, 0, texelFormat.format, texelFormat.type, NULL); + if (_gpuTexture.getType() == gpu::Texture::TEX_CUBE) { + for (size_t face = 0; face < CUBE_NUM_FACES; face++) { + glTexImage2D(CUBE_FACE_LAYOUT[face], l, texelFormat.internalFormat, width, height, 0, texelFormat.format, texelFormat.type, NULL); } - width = std::max(1, (width / 2)); - height = std::max(1, (height / 2)); + } else { + glTexImage2D(_target, l, texelFormat.internalFormat, width, height, 0, texelFormat.format, texelFormat.type, NULL); + } + width = std::max(1, (width / 2)); + height = std::max(1, (height / 2)); } (void)CHECK_GL_ERROR(); } - syncSampler(texture.getSampler(), texture.getType(), this); + syncSampler(_gpuTexture.getSampler(), _gpuTexture.getType(), this); (void)CHECK_GL_ERROR(); - GLuint virtualSize = _gpuTexture.evalTotalSize(); - setVirtualSize(virtualSize); - setSize(virtualSize); - (void)CHECK_GL_ERROR(); glBindTexture(_target, boundTex); (void)CHECK_GL_ERROR(); } GLBackend::GLTexture::~GLTexture() { - if (_secretTexture != 0) { - glDeleteTextures(1, &_secretTexture); + if (_privateTexture != 0) { + glDeleteTextures(1, &_privateTexture); } - /*if (_texture != 0) { - glDeleteTextures(1, &_texture); - }*/ + Backend::updateTextureGPUMemoryUsage(_size, 0); Backend::updateTextureGPUVirtualMemoryUsage(_virtualSize, 0); Backend::decrementTextureGPUCount(); @@ -148,37 +152,36 @@ void GLBackend::GLTexture::updateSize() { if (!_texture) { setSize(virtualSize); } - GLint gpuSize{ 0 }; - if (_target == GL_TEXTURE_CUBE_MAP) { - glGetTexLevelParameteriv(CUBE_FACE_LAYOUT[0], 0, GL_TEXTURE_COMPRESSED, &gpuSize); - } else { - glGetTexLevelParameteriv(_target, 0, GL_TEXTURE_COMPRESSED, &gpuSize); - } - (void)CHECK_GL_ERROR(); - if (gpuSize) { - GLint baseLevel; - GLint maxLevel; - glGetTexParameteriv(_target, GL_TEXTURE_BASE_LEVEL, &baseLevel); - glGetTexParameteriv(_target, GL_TEXTURE_MAX_LEVEL, &maxLevel); - - for (GLint level = baseLevel; level <= maxLevel; level++) { - GLint levelSize{ 0 }; - if (_target == GL_TEXTURE_CUBE_MAP) { - for (size_t face = 0; face < CUBE_NUM_FACES; face++) { - GLint faceSize{ 0 }; - glGetTexLevelParameteriv(CUBE_FACE_LAYOUT[face], level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &faceSize); - levelSize += faceSize; - } - } else { - glGetTexLevelParameteriv(_target, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &levelSize); - } - if (levelSize <= 0) { - break; - } - gpuSize += levelSize; + if (_gpuTexture.getTexelFormat().isCompressed()) { + GLenum proxyType = GL_TEXTURE_2D; + GLuint numFaces = 1; + if (_gpuTexture.getType() == gpu::Texture::TEX_CUBE) { + proxyType = CUBE_FACE_LAYOUT[0]; + numFaces = CUBE_NUM_FACES; } - setSize(gpuSize); + GLint gpuSize{ 0 }; + glGetTexLevelParameteriv(proxyType, 0, GL_TEXTURE_COMPRESSED, &gpuSize); + (void)CHECK_GL_ERROR(); + + if (gpuSize) { + for (GLint level = 0; level < _numLevels; level++) { + GLint levelSize{ 0 }; + glGetTexLevelParameteriv(proxyType, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &levelSize); + levelSize *= numFaces; + + if (levelSize <= 0) { + break; + } + gpuSize += levelSize; + } + (void)CHECK_GL_ERROR(); + + setSize(gpuSize); + } else { + setSize(virtualSize); + } + } else { setSize(virtualSize); } @@ -210,27 +213,25 @@ bool GLBackend::GLTexture::isReady() const { return Idle == syncState; } - // Move content bits from the CPU to the GPU for a given mip / face void GLBackend::GLTexture::transferMip(GLenum target, const Texture::PixelsPointer& mip) const { GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuTexture.getTexelFormat(), mip->getFormat()); - - glTexSubImage2D(target, 0, 0, 0, _gpuTexture.getWidth(), _gpuTexture.getHeight(), texelFormat.format, texelFormat.type, mip->readData()); + glTexSubImage2D(target, 0, 0, 0, _gpuTexture.getWidth(), _gpuTexture.getHeight(), texelFormat.format, texelFormat.type, mip->readData()); glTexSubImage2D(target, 0, 0, 0, _gpuTexture.getWidth(), _gpuTexture.getHeight(), texelFormat.format, texelFormat.type, mip->readData()); (void)CHECK_GL_ERROR(); } // Move content bits from the CPU to the GPU void GLBackend::GLTexture::transfer() const { PROFILE_RANGE(__FUNCTION__); - qDebug() << "Transferring texture: " << _secretTexture; + //qDebug() << "Transferring texture: " << _privateTexture; // Need to update the content of the GPU object from the source sysmem of the texture if (_contentStamp >= _gpuTexture.getDataStamp()) { return; } //_secretTexture - glBindTexture(_target, _secretTexture); - // glBindTexture(_target, _texture); + glBindTexture(_target, _privateTexture); + // glBindTexture(_target, _texture); // GO through the process of allocating the correct storage and/or update the content switch (_gpuTexture.getType()) { case Texture::TEX_2D: @@ -262,7 +263,10 @@ void GLBackend::GLTexture::transfer() const { // Do any post-transfer operations that might be required on the main context / rendering thread void GLBackend::GLTexture::postTransfer() { setSyncState(GLTexture::Idle); - _texture = _secretTexture; + + // The public gltexture becaomes available + _texture = _privateTexture; + // At this point the mip pixels have been loaded, we can notify the gpu texture to abandon it's memory switch (_gpuTexture.getType()) { case Texture::TEX_2D: @@ -295,7 +299,7 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const TexturePointer& texturePoin } // Object isn't ready, check what we need to do... - + // Create the texture if need be (force re-creation if the storage stamp changes // for easier use of immutable storage) if (!object || object->isInvalid()) { @@ -305,6 +309,7 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const TexturePointer& texturePoin // Object maybe doens't neet to be tranasferred after creation if (!needTransfer) { + object->createTexture(); object->_contentStamp = texturePointer->getDataStamp(); object->postTransfer(); return object; diff --git a/libraries/gpu/src/gpu/GLBackendTextureTransfer.cpp b/libraries/gpu/src/gpu/GLBackendTextureTransfer.cpp index 657712490c..24aa9a9c4a 100644 --- a/libraries/gpu/src/gpu/GLBackendTextureTransfer.cpp +++ b/libraries/gpu/src/gpu/GLBackendTextureTransfer.cpp @@ -15,6 +15,7 @@ #include #include + #endif using namespace gpu; @@ -35,8 +36,7 @@ GLTextureTransferHelper::GLTextureTransferHelper() { void GLTextureTransferHelper::transferTexture(const gpu::TexturePointer& texturePointer) { GLBackend::GLTexture* object = Backend::getGPUObject(*texturePointer); #ifdef THREADED_TEXTURE_TRANSFER - TextureTransferPackage package { texturePointer, glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0) }; - glFlush(); + TextureTransferPackage package{ texturePointer, 0}; object->setSyncState(GLBackend::GLTexture::Pending); queueItem(package); #else @@ -53,8 +53,6 @@ void GLTextureTransferHelper::setup() { bool GLTextureTransferHelper::processQueueItems(const Queue& messages) { for (auto package : messages) { - glWaitSync(package.fence, 0, GL_TIMEOUT_IGNORED); - glDeleteSync(package.fence); TexturePointer texturePointer = package.texture.lock(); // Texture no longer exists, move on to the next if (!texturePointer) { @@ -62,13 +60,17 @@ bool GLTextureTransferHelper::processQueueItems(const Queue& messages) { } GLBackend::GLTexture* object = Backend::getGPUObject(*texturePointer); + object->createTexture(); + object->transfer(); - auto writeSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); object->updateSize(); + glBindTexture(object->_target, 0); + auto writeSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); glClientWaitSync(writeSync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED); glDeleteSync(writeSync); + object->_contentStamp = texturePointer->getDataStamp(); object->setSyncState(GLBackend::GLTexture::Transferred); } diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 2906fe7abf..4d6ea82845 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -19,6 +19,9 @@ using namespace model; using namespace gpu; +// FIXME: Turn that define off to prevent compression +#define COMPRESS_TEXTURES + void TextureMap::setTextureSource(TextureSourcePointer& textureSource) { _textureSource = textureSource; @@ -49,10 +52,10 @@ void TextureMap::setLightmapOffsetScale(float offset, float scale) { _lightmapOffsetScale.y = scale; } -gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImage, bool isLinear, bool doCompress, bool generateMips) { +const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& validAlpha, bool& alphaAsMask) { QImage image = srcImage; - bool validAlpha = false; - bool alphaAsMask = true; + validAlpha = false; + alphaAsMask = true; const uint8 OPAQUE_ALPHA = 255; const uint8 TRANSPARENT_ALPHA = 0; if (image.hasAlphaChannel()) { @@ -87,53 +90,71 @@ gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImag image = image.convertToFormat(QImage::Format_RGB888); } + return image; +} + +void TextureUsage::defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element& formatMip, +const QImage& image, bool isLinear, bool doCompress) { + +#ifdef COMPRESS_TEXTURES +#else + doCompress = false; +#endif + + if (image.hasAlphaChannel()) { + gpu::Semantic gpuSemantic; + gpu::Semantic mipSemantic; + if (isLinear) { + mipSemantic = gpu::SBGRA; + if (doCompress) { + gpuSemantic = gpu::COMPRESSED_SRGBA; + } else { + gpuSemantic = gpu::SRGBA; + } + } else { + mipSemantic = gpu::BGRA; + if (doCompress) { + gpuSemantic = gpu::COMPRESSED_RGBA; + } else { + gpuSemantic = gpu::RGBA; + } + } + formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpuSemantic); + formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, mipSemantic); + } else { + gpu::Semantic gpuSemantic; + gpu::Semantic mipSemantic; + if (isLinear) { + mipSemantic = gpu::SRGB; + if (doCompress) { + gpuSemantic = gpu::COMPRESSED_SRGB; + } else { + gpuSemantic = gpu::SRGB; + } + } else { + mipSemantic = gpu::RGB; + if (doCompress) { + gpuSemantic = gpu::COMPRESSED_RGB; + } else { + gpuSemantic = gpu::RGB; + } + } + formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, gpuSemantic); + formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, mipSemantic); + } +} + +gpu::Texture* TextureUsage::process2DTextureColorFromImage(const QImage& srcImage, bool isLinear, bool doCompress, bool generateMips) { + bool validAlpha = false; + bool alphaAsMask = true; + QImage image = process2DImageColor(srcImage, validAlpha, alphaAsMask); + gpu::Texture* theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { gpu::Element formatGPU; gpu::Element formatMip; - - if (image.hasAlphaChannel()) { - gpu::Semantic gpuSemantic; - gpu::Semantic mipSemantic; - if (isLinear) { - mipSemantic = gpu::SBGRA; - if (doCompress) { - gpuSemantic = gpu::COMPRESSED_SRGBA; - } else { - gpuSemantic = gpu::SRGBA; - } - } else { - mipSemantic = gpu::BGRA; - if (doCompress) { - gpuSemantic = gpu::COMPRESSED_RGBA; - } else { - gpuSemantic = gpu::RGBA; - } - } - formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpuSemantic); - formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, mipSemantic); - } else { - gpu::Semantic gpuSemantic; - gpu::Semantic mipSemantic; - if (isLinear) { - mipSemantic = gpu::SRGB; - if (doCompress) { - gpuSemantic = gpu::COMPRESSED_SRGB; - } else { - gpuSemantic = gpu::SRGB; - } - } else { - mipSemantic = gpu::RGB; - if (doCompress) { - gpuSemantic = gpu::COMPRESSED_RGB; - } else { - gpuSemantic = gpu::RGB; - } - } - formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, gpuSemantic); - formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, mipSemantic); - } + defineColorTexelFormats(formatGPU, formatMip, image, isLinear, doCompress); theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); @@ -296,8 +317,11 @@ gpu::Texture* TextureUsage::createRoughnessTextureFromImage(const QImage& srcIma gpu::Texture* theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { - +#ifdef COMPRESS_TEXTURES gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::COMPRESSED_R); +#else + gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); +#endif gpu::Element formatMip = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); @@ -330,9 +354,13 @@ gpu::Texture* TextureUsage::createRoughnessTextureFromGlossImage(const QImage& s gpu::Texture* theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { +#ifdef COMPRESS_TEXTURES gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::COMPRESSED_R); +#else + gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); +#endif gpu::Element formatMip = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); - + theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); theTexture->autoGenerateMips(-1); @@ -360,7 +388,11 @@ gpu::Texture* TextureUsage::createMetallicTextureFromImage(const QImage& srcImag gpu::Texture* theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { +#ifdef COMPRESS_TEXTURES gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::COMPRESSED_R); +#else + gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); +#endif gpu::Element formatMip = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); @@ -405,229 +437,181 @@ public: _faceYNeg(fYN), _faceZPos(fZP), _faceZNeg(fZN) {} + + + static const CubeLayout CUBEMAP_LAYOUTS[]; + static const int NUM_CUBEMAP_LAYOUTS; + + static int findLayout(int width, int height) { + // Find the layout of the cubemap in the 2D image + int foundLayout = -1; + for (int i = 0; i < NUM_CUBEMAP_LAYOUTS; i++) { + if ((height * CUBEMAP_LAYOUTS[i]._widthRatio) == (width * CUBEMAP_LAYOUTS[i]._heightRatio)) { + foundLayout = i; + break; + } + } + return foundLayout; + } }; -gpu::Texture* TextureUsage::createCubeTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { - QImage image = srcImage; - - int imageArea = image.width() * image.height(); - - - qCDebug(modelLog) << "Cube map size:" << QString(srcImageName.c_str()) << image.width() << image.height(); - - int opaquePixels = 0; - int translucentPixels = 0; - //bool isTransparent = false; - int redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0; - const int EIGHT_BIT_MAXIMUM = 255; - QColor averageColor(EIGHT_BIT_MAXIMUM, EIGHT_BIT_MAXIMUM, EIGHT_BIT_MAXIMUM); - - if (!image.hasAlphaChannel()) { - if (image.format() != QImage::Format_RGB888) { - image = image.convertToFormat(QImage::Format_RGB888); - } - // int redTotal = 0, greenTotal = 0, blueTotal = 0; - for (int y = 0; y < image.height(); y++) { - for (int x = 0; x < image.width(); x++) { - QRgb rgb = image.pixel(x, y); - redTotal += qRed(rgb); - greenTotal += qGreen(rgb); - blueTotal += qBlue(rgb); - } - } - if (imageArea > 0) { - averageColor.setRgb(redTotal / imageArea, greenTotal / imageArea, blueTotal / imageArea); - } - } else { - if (image.format() != QImage::Format_ARGB32) { - image = image.convertToFormat(QImage::Format_ARGB32); - } - - // check for translucency/false transparency - // int opaquePixels = 0; - // int translucentPixels = 0; - // int redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0; - for (int y = 0; y < image.height(); y++) { - for (int x = 0; x < image.width(); x++) { - QRgb rgb = image.pixel(x, y); - redTotal += qRed(rgb); - greenTotal += qGreen(rgb); - blueTotal += qBlue(rgb); - int alpha = qAlpha(rgb); - alphaTotal += alpha; - if (alpha == EIGHT_BIT_MAXIMUM) { - opaquePixels++; - } else if (alpha != 0) { - translucentPixels++; - } - } - } - if (opaquePixels == imageArea) { - qCDebug(modelLog) << "Image with alpha channel is completely opaque:" << QString(srcImageName.c_str()); - image = image.convertToFormat(QImage::Format_RGB888); - } - - averageColor = QColor(redTotal / imageArea, - greenTotal / imageArea, blueTotal / imageArea, alphaTotal / imageArea); - - //isTransparent = (translucentPixels >= imageArea / 2); +const CubeLayout CubeLayout::CUBEMAP_LAYOUTS[] = { + // Here is the expected layout for the faces in an image with the 1/6 aspect ratio: + // + // WIDTH + // <------> + // ^ +------+ + // | | | + // | | +X | + // | | | + // H +------+ + // E | | + // I | -X | + // G | | + // H +------+ + // T | | + // | | +Y | + // | | | + // | +------+ + // | | | + // | | -Y | + // | | | + // H +------+ + // E | | + // I | +Z | + // G | | + // H +------+ + // T | | + // | | -Z | + // | | | + // V +------+ + // + // FaceWidth = width = height / 6 + { 1, 6, + { 0, 0, true, false }, + { 0, 1, true, false }, + { 0, 2, false, true }, + { 0, 3, false, true }, + { 0, 4, true, false }, + { 0, 5, true, false } + }, + + // Here is the expected layout for the faces in an image with the 3/4 aspect ratio: + // + // <-----------WIDTH-----------> + // ^ +------+------+------+------+ + // | | | | | | + // | | | +Y | | | + // | | | | | | + // H +------+------+------+------+ + // E | | | | | + // I | -X | -Z | +X | +Z | + // G | | | | | + // H +------+------+------+------+ + // T | | | | | + // | | | -Y | | | + // | | | | | | + // V +------+------+------+------+ + // + // FaceWidth = width / 4 = height / 3 + { 4, 3, + { 2, 1, true, false }, + { 0, 1, true, false }, + { 1, 0, false, true }, + { 1, 2, false, true }, + { 3, 1, true, false }, + { 1, 1, true, false } + }, + + // Here is the expected layout for the faces in an image with the 4/3 aspect ratio: + // + // <-------WIDTH--------> + // ^ +------+------+------+ + // | | | | | + // | | | +Y | | + // | | | | | + // H +------+------+------+ + // E | | | | + // I | -X | -Z | +X | + // G | | | | + // H +------+------+------+ + // T | | | | + // | | | -Y | | + // | | | | | + // | +------+------+------+ + // | | | | | + // | | | +Z! | | <+Z is upside down! + // | | | | | + // V +------+------+------+ + // + // FaceWidth = width / 3 = height / 4 + { 3, 4, + { 2, 1, true, false }, + { 0, 1, true, false }, + { 1, 0, false, true }, + { 1, 2, false, true }, + { 1, 3, false, true }, + { 1, 1, true, false } } - +}; +const int CubeLayout::NUM_CUBEMAP_LAYOUTS = sizeof(CubeLayout::CUBEMAP_LAYOUTS) / sizeof(CubeLayout); + +gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool generateIrradiance) { + + bool validAlpha = false; + bool alphaAsMask = true; + QImage image = process2DImageColor(srcImage, validAlpha, alphaAsMask); + gpu::Texture* theTexture = nullptr; if ((image.width() > 0) && (image.height() > 0)) { + + gpu::Element formatGPU; + gpu::Element formatMip; + defineColorTexelFormats(formatGPU, formatMip, image, isLinear, doCompress); + + // Find the layout of the cubemap in the 2D image + int foundLayout = CubeLayout::findLayout(image.width(), image.height()); - // bool isLinearRGB = true; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - bool isLinearRGB = false; //(_type == NORMAL_TEXTURE) || (_type == EMISSIVE_TEXTURE); - - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::COMPRESSED_SRGB)); - gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::NUINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); - if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::RGBA : gpu::COMPRESSED_SRGBA)); - formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, (isLinearRGB ? gpu::BGRA : gpu::SBGRA)); + std::vector faces; + // If found, go extract the faces as separate images + if (foundLayout >= 0) { + auto& layout = CubeLayout::CUBEMAP_LAYOUTS[foundLayout]; + int faceWidth = image.width() / layout._widthRatio; + + faces.push_back(image.copy(QRect(layout._faceXPos._x * faceWidth, layout._faceXPos._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceXPos._horizontalMirror, layout._faceXPos._verticalMirror)); + faces.push_back(image.copy(QRect(layout._faceXNeg._x * faceWidth, layout._faceXNeg._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceXNeg._horizontalMirror, layout._faceXNeg._verticalMirror)); + faces.push_back(image.copy(QRect(layout._faceYPos._x * faceWidth, layout._faceYPos._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceYPos._horizontalMirror, layout._faceYPos._verticalMirror)); + faces.push_back(image.copy(QRect(layout._faceYNeg._x * faceWidth, layout._faceYNeg._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceYNeg._horizontalMirror, layout._faceYNeg._verticalMirror)); + faces.push_back(image.copy(QRect(layout._faceZPos._x * faceWidth, layout._faceZPos._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceZPos._horizontalMirror, layout._faceZPos._verticalMirror)); + faces.push_back(image.copy(QRect(layout._faceZNeg._x * faceWidth, layout._faceZNeg._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceZNeg._horizontalMirror, layout._faceZNeg._verticalMirror)); + } else { + qCDebug(modelLog) << "Failed to find a known cube map layout from this image:" << QString(srcImageName.c_str()); + return nullptr; } - - const CubeLayout CUBEMAP_LAYOUTS[] = { - // Here is the expected layout for the faces in an image with the 1/6 aspect ratio: - // - // WIDTH - // <------> - // ^ +------+ - // | | | - // | | +X | - // | | | - // H +------+ - // E | | - // I | -X | - // G | | - // H +------+ - // T | | - // | | +Y | - // | | | - // | +------+ - // | | | - // | | -Y | - // | | | - // H +------+ - // E | | - // I | +Z | - // G | | - // H +------+ - // T | | - // | | -Z | - // | | | - // V +------+ - // - // FaceWidth = width = height / 6 - { 1, 6, - {0, 0, true, false}, - {0, 1, true, false}, - {0, 2, false, true}, - {0, 3, false, true}, - {0, 4, true, false}, - {0, 5, true, false} - }, - - // Here is the expected layout for the faces in an image with the 3/4 aspect ratio: - // - // <-----------WIDTH-----------> - // ^ +------+------+------+------+ - // | | | | | | - // | | | +Y | | | - // | | | | | | - // H +------+------+------+------+ - // E | | | | | - // I | -X | -Z | +X | +Z | - // G | | | | | - // H +------+------+------+------+ - // T | | | | | - // | | | -Y | | | - // | | | | | | - // V +------+------+------+------+ - // - // FaceWidth = width / 4 = height / 3 - { 4, 3, - {2, 1, true, false}, - {0, 1, true, false}, - {1, 0, false, true}, - {1, 2, false, true}, - {3, 1, true, false}, - {1, 1, true, false} - }, - - // Here is the expected layout for the faces in an image with the 4/3 aspect ratio: - // - // <-------WIDTH--------> - // ^ +------+------+------+ - // | | | | | - // | | | +Y | | - // | | | | | - // H +------+------+------+ - // E | | | | - // I | -X | -Z | +X | - // G | | | | - // H +------+------+------+ - // T | | | | - // | | | -Y | | - // | | | | | - // | +------+------+------+ - // | | | | | - // | | | +Z! | | <+Z is upside down! - // | | | | | - // V +------+------+------+ - // - // FaceWidth = width / 3 = height / 4 - { 3, 4, - {2, 1, true, false}, - {0, 1, true, false}, - {1, 0, false, true}, - {1, 2, false, true}, - {1, 3, false, true}, - {1, 1, true, false} - } - }; - const int NUM_CUBEMAP_LAYOUTS = sizeof(CUBEMAP_LAYOUTS) / sizeof(CubeLayout); - - // Find the layout of the cubemap in the 2D image - int foundLayout = -1; - for (int i = 0; i < NUM_CUBEMAP_LAYOUTS; i++) { - if ((image.height() * CUBEMAP_LAYOUTS[i]._widthRatio) == (image.width() * CUBEMAP_LAYOUTS[i]._heightRatio)) { - foundLayout = i; - break; - } + // If the 6 faces have been created go on and define the true Texture + 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)); + int f = 0; + for (auto& face : faces) { + theTexture->assignStoredMipFace(0, formatMip, face.byteCount(), face.constBits(), f); + f++; } - - std::vector faces; - // If found, go extract the faces as separate images - if (foundLayout >= 0) { - auto& layout = CUBEMAP_LAYOUTS[foundLayout]; - int faceWidth = image.width() / layout._widthRatio; - - faces.push_back(image.copy(QRect(layout._faceXPos._x * faceWidth, layout._faceXPos._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceXPos._horizontalMirror, layout._faceXPos._verticalMirror)); - faces.push_back(image.copy(QRect(layout._faceXNeg._x * faceWidth, layout._faceXNeg._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceXNeg._horizontalMirror, layout._faceXNeg._verticalMirror)); - faces.push_back(image.copy(QRect(layout._faceYPos._x * faceWidth, layout._faceYPos._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceYPos._horizontalMirror, layout._faceYPos._verticalMirror)); - faces.push_back(image.copy(QRect(layout._faceYNeg._x * faceWidth, layout._faceYNeg._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceYNeg._horizontalMirror, layout._faceYNeg._verticalMirror)); - faces.push_back(image.copy(QRect(layout._faceZPos._x * faceWidth, layout._faceZPos._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceZPos._horizontalMirror, layout._faceZPos._verticalMirror)); - faces.push_back(image.copy(QRect(layout._faceZNeg._x * faceWidth, layout._faceZNeg._y * faceWidth, faceWidth, faceWidth)).mirrored(layout._faceZNeg._horizontalMirror, layout._faceZNeg._verticalMirror)); - } else { - qCDebug(modelLog) << "Failed to find a known cube map layout from this image:" << QString(srcImageName.c_str()); - return nullptr; - } - - // If the 6 faces have been created go on and define the true Texture - 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)); + + if (generateMips) { theTexture->autoGenerateMips(-1); - int f = 0; - for (auto& face : faces) { - theTexture->assignStoredMipFace(0, formatMip, face.byteCount(), face.constBits(), f); - f++; - } + } - // Generate irradiance while we are at it + // Generate irradiance while we are at it + if (generateIrradiance) { theTexture->generateIrradiance(); } + } } - + return theTexture; } + +gpu::Texture* TextureUsage::createCubeTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + return processCubeTextureColorFromImage(srcImage, srcImageName, false, true, true, true); +} diff --git a/libraries/model/src/model/TextureMap.h b/libraries/model/src/model/TextureMap.h index fa0eea55cb..daa4b0d7bb 100755 --- a/libraries/model/src/model/TextureMap.h +++ b/libraries/model/src/model/TextureMap.h @@ -43,7 +43,12 @@ public: static gpu::Texture* createLightmapTextureFromImage(const QImage& image, const std::string& srcImageName); - static gpu::Texture* process2DTextureColorFromImage(const QImage& imageSrc, bool isLinear, bool doCompress, bool generateMips); + static const QImage process2DImageColor(const QImage& srcImage, bool& validAlpha, bool& alphaAsMask); + static void defineColorTexelFormats(gpu::Element& formatGPU, gpu::Element& formatMip, + const QImage& srcImage, bool isLinear, bool doCompress); + static gpu::Texture* process2DTextureColorFromImage(const QImage& srcImage, bool isLinear, bool doCompress, bool generateMips); + static gpu::Texture* processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool generateIrradiance); + }; From 04e71df3bcc3d09b338fd81681d2a4e00c4a1f87 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 7 Apr 2016 23:05:50 -0700 Subject: [PATCH 11/27] fixing a stupid code and a warning --- libraries/gpu/src/gpu/GLBackendTexture.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 54d7fb27bb..b0b68c6a2c 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -49,7 +49,7 @@ const GLenum GLBackend::GLTexture::CUBE_FACE_LAYOUT[6] = { // Create the texture and allocate storage GLBackend::GLTexture::GLTexture(const Texture& texture) : _storageStamp(texture.getStamp()), - _privateTexture(allocateSingleTexture()), + _privateTexture(0), _target(gpuToGLTextureType(texture)), _size(0), _virtualSize(0), @@ -165,7 +165,7 @@ void GLBackend::GLTexture::updateSize() { (void)CHECK_GL_ERROR(); if (gpuSize) { - for (GLint level = 0; level < _numLevels; level++) { + for (GLuint level = 0; level < _numLevels; level++) { GLint levelSize{ 0 }; glGetTexLevelParameteriv(proxyType, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &levelSize); levelSize *= numFaces; From be178e9e0988a81076bc091bf38a45ee9a53ccf7 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 7 Apr 2016 23:44:28 -0700 Subject: [PATCH 12/27] fixing warnings --- libraries/gpu/src/gpu/GLBackend.h | 8 +++++--- libraries/gpu/src/gpu/GLBackendTexture.cpp | 1 - 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 29256a322f..aabd84fbfb 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -76,9 +76,11 @@ public: class GLTexture : public GPUObject { public: + // The public gl texture object + GLuint _texture{ 0 }; + const Stamp _storageStamp; Stamp _contentStamp { 0 }; - GLuint _texture{ 0 }; const GLenum _target; GLTexture(const gpu::Texture& gpuTexture); @@ -124,11 +126,11 @@ public: static const size_t CUBE_NUM_FACES = 6; static const GLenum CUBE_FACE_LAYOUT[6]; - + private: // at creation the true texture is created in GL // it becomes public only when ready. - GLuint _privateTexture; + GLuint _privateTexture{ 0 }; void setSize(GLuint size); void setVirtualSize(GLuint size); diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index b0b68c6a2c..8da6b6d300 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -49,7 +49,6 @@ const GLenum GLBackend::GLTexture::CUBE_FACE_LAYOUT[6] = { // Create the texture and allocate storage GLBackend::GLTexture::GLTexture(const Texture& texture) : _storageStamp(texture.getStamp()), - _privateTexture(0), _target(gpuToGLTextureType(texture)), _size(0), _virtualSize(0), From 4374bd26ae210b448b3763f87038e6e950c252d4 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 8 Apr 2016 01:37:27 -0700 Subject: [PATCH 13/27] Disabling COmpression --- libraries/model/src/model/TextureMap.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 4d6ea82845..014431619c 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -19,8 +19,8 @@ using namespace model; using namespace gpu; -// FIXME: Turn that define off to prevent compression -#define COMPRESS_TEXTURES +// FIXME: Declare this to enable compression +//#define COMPRESS_TEXTURES void TextureMap::setTextureSource(TextureSourcePointer& textureSource) { From 1df0dce971d066dc3b6b42d021b616753ae71c01 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 8 Apr 2016 14:38:26 -0700 Subject: [PATCH 14/27] use ResourceRequest in Agent to handle ATP scripts --- assignment-client/src/Agent.cpp | 53 +++++++++++--------- assignment-client/src/Agent.h | 2 +- libraries/networking/src/ResourceRequest.cpp | 1 + 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 740f456595..dc35885f8d 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -164,52 +164,57 @@ void Agent::requestScript() { scriptURL = QUrl(_payload); } - // setup a network access manager and - QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + // make sure this is not a script request for the file scheme + if (scriptURL.scheme() == URL_SCHEME_FILE) { + qWarning() << "Cannot load script for Agent from local filesystem."; + scriptRequestFinished(); + return; + } - QNetworkDiskCache* cache = new QNetworkDiskCache(); - QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation); - cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "agentCache"); - networkAccessManager.setCache(cache); + auto request = ResourceManager::createResourceRequest(this, scriptURL); - QNetworkRequest networkRequest = QNetworkRequest(scriptURL); - networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); + if (!request) { + qWarning() << "Could not create ResourceRequest for Agent script at" << scriptURL.toString(); + scriptRequestFinished(); + return; + } // setup a timeout for script request static const int SCRIPT_TIMEOUT_MS = 10000; - _scriptRequestTimeout = new QTimer(this); - connect(_scriptRequestTimeout, &QTimer::timeout, this, &Agent::scriptRequestFinished); - _scriptRequestTimeout->start(SCRIPT_TIMEOUT_MS); + connect(&_scriptRequestTimeout, &QTimer::timeout, this, &Agent::scriptRequestFinished); + _scriptRequestTimeout.start(SCRIPT_TIMEOUT_MS); + + connect(request, &ResourceRequest::finished, this, &Agent::scriptRequestFinished); - qDebug() << "Downloading script at" << scriptURL.toString(); - QNetworkReply* reply = networkAccessManager.get(networkRequest); - connect(reply, &QNetworkReply::finished, this, &Agent::scriptRequestFinished); + qInfo() << "Requesting script at URL" << qPrintable(request->getUrl().toString()); + + request->send(); } void Agent::scriptRequestFinished() { - auto reply = qobject_cast(sender()); + auto request = qobject_cast(sender()); - _scriptRequestTimeout->stop(); + _scriptRequestTimeout.stop(); - if (reply && reply->error() == QNetworkReply::NoError) { - _scriptContents = reply->readAll(); - qDebug() << "Downloaded script:" << _scriptContents; + if (request && request->getResult() == ResourceRequest::Success) { + _scriptContents = request->getData(); + qInfo() << "Downloaded script:" << _scriptContents; // we could just call executeScript directly - we use a QueuedConnection to allow scriptRequestFinished // to return before calling executeScript QMetaObject::invokeMethod(this, "executeScript", Qt::QueuedConnection); } else { - if (reply) { - qDebug() << "Failed to download script at" << reply->url().toString() << " - bailing on assignment."; - qDebug() << "QNetworkReply error was" << reply->errorString(); + if (request) { + qWarning() << "Failed to download script at" << request->getUrl().toString() << " - bailing on assignment."; + qWarning() << "ResourceRequest error was" << request->getResult(); } else { - qDebug() << "Failed to download script - request timed out. Bailing on assignment."; + qWarning() << "Failed to download script - request timed out. Bailing on assignment."; } setFinished(true); } - reply->deleteLater(); + request->deleteLater(); } void Agent::executeScript() { diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index d86b99db33..8fb6c10f0b 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -83,7 +83,7 @@ private: void sendAvatarBillboardPacket(); QString _scriptContents; - QTimer* _scriptRequestTimeout { nullptr }; + QTimer _scriptRequestTimeout; bool _isListeningToAudioStream = false; SharedSoundPointer _avatarSound; int _numAvatarSoundSentBytes = 0; diff --git a/libraries/networking/src/ResourceRequest.cpp b/libraries/networking/src/ResourceRequest.cpp index e6402d6b25..bce6af7091 100644 --- a/libraries/networking/src/ResourceRequest.cpp +++ b/libraries/networking/src/ResourceRequest.cpp @@ -20,6 +20,7 @@ void ResourceRequest::send() { QMetaObject::invokeMethod(this, "send", Qt::QueuedConnection); return; } + Q_ASSERT(_state == NotStarted); _state = InProgress; From bf3324fc6bad5e0cbfac6a6a4803b8766a1ba485 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 8 Apr 2016 15:28:12 -0700 Subject: [PATCH 15/27] hold download of ATP script if Asset Server isn't ready --- assignment-client/src/Agent.cpp | 39 +++++++++++++++++++++++++++++---- assignment-client/src/Agent.h | 5 ++++- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index dc35885f8d..3305beae35 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -144,6 +144,9 @@ void Agent::run() { connect(messagesThread, &QThread::started, messagesClient.data(), &MessagesClient::init); messagesThread->start(); + // make sure we hear about connected nodes so we can grab an ATP script if a request is pending + connect(nodeList.data(), &LimitedNodeList::nodeActivated, this, &Agent::nodeActivated); + nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::AudioMixer, NodeType::AvatarMixer, NodeType::EntityServer, NodeType::MessagesMixer, NodeType::AssetServer }); @@ -181,20 +184,48 @@ void Agent::requestScript() { // setup a timeout for script request static const int SCRIPT_TIMEOUT_MS = 10000; - connect(&_scriptRequestTimeout, &QTimer::timeout, this, &Agent::scriptRequestFinished); - _scriptRequestTimeout.start(SCRIPT_TIMEOUT_MS); - + _scriptRequestTimeout = new QTimer; + connect(_scriptRequestTimeout, &QTimer::timeout, this, &Agent::scriptRequestFinished); + _scriptRequestTimeout->start(SCRIPT_TIMEOUT_MS); + connect(request, &ResourceRequest::finished, this, &Agent::scriptRequestFinished); + if (scriptURL.scheme() == URL_SCHEME_ATP) { + // we have an ATP URL for the script - if we're not currently connected to the AssetServer + // then wait for the nodeConnected signal to fire off the request + + auto assetServer = nodeList->soloNodeOfType(NodeType::AssetServer); + if (!assetServer || assetServer->getActiveSocket()) { + qDebug() << "Waiting to connect to Asset Server for ATP script download."; + _pendingScriptRequest = request; + + return; + } + } + qInfo() << "Requesting script at URL" << qPrintable(request->getUrl().toString()); request->send(); } +void Agent::nodeActivated(SharedNodePointer activatedNode) { + if (_pendingScriptRequest) { + qInfo() << "Requesting script at URL" << qPrintable(_pendingScriptRequest->getUrl().toString()); + + _pendingScriptRequest->send(); + + _pendingScriptRequest = nullptr; + } +} + void Agent::scriptRequestFinished() { auto request = qobject_cast(sender()); - _scriptRequestTimeout.stop(); + // stop the script request timeout, if it's running + if (_scriptRequestTimeout) { + QMetaObject::invokeMethod(_scriptRequestTimeout, "stop"); + _scriptRequestTimeout->deleteLater(); + } if (request && request->getResult() == ResourceRequest::Success) { _scriptContents = request->getData(); diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 8fb6c10f0b..2b0d22385d 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -69,6 +69,8 @@ private slots: void processAgentAvatarAndAudio(float deltaTime); + void nodeActivated(SharedNodePointer activatedNode); + private: std::unique_ptr _scriptEngine; EntityEditPacketSender _entityEditSender; @@ -83,7 +85,8 @@ private: void sendAvatarBillboardPacket(); QString _scriptContents; - QTimer _scriptRequestTimeout; + QTimer* _scriptRequestTimeout { nullptr }; + ResourceRequest* _pendingScriptRequest { nullptr }; bool _isListeningToAudioStream = false; SharedSoundPointer _avatarSound; int _numAvatarSoundSentBytes = 0; From 4d0976f7306756a9a82806634beae2ed5c444d34 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Apr 2016 08:41:39 -0700 Subject: [PATCH 16/27] remove migration code for pre-mapping migrations --- assignment-client/src/assets/AssetServer.cpp | 52 -------------------- assignment-client/src/assets/AssetServer.h | 2 - 2 files changed, 54 deletions(-) diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index 33ae631b77..d9af9f1019 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -134,63 +134,11 @@ void AssetServer::completeSetup() { qInfo() << "There are" << hashedFiles.size() << "asset files in the asset directory."; - performMappingMigration(); - cleanupUnmappedFiles(); nodeList->addNodeTypeToInterestSet(NodeType::Agent); } -void AssetServer::performMappingMigration() { - QRegExp hashFileRegex { "^[a-f0-9]{" + QString::number(SHA256_HASH_HEX_LENGTH) + "}(\\.[\\w]+)+$" }; - - auto files = _resourcesDirectory.entryInfoList(QDir::Files); - - for (const auto& fileInfo : files) { - if (hashFileRegex.exactMatch(fileInfo.fileName())) { - // we have a pre-mapping file that we should migrate to the new mapping system - qDebug() << "Migrating pre-mapping file" << fileInfo.fileName(); - - // rename the file to the same name with no extension - QFile oldFile { fileInfo.absoluteFilePath() }; - - auto oldAbsolutePath = fileInfo.absoluteFilePath(); - auto oldFilename = fileInfo.fileName(); - auto hash = oldFilename.left(SHA256_HASH_HEX_LENGTH); - auto fullExtension = oldFilename.mid(oldFilename.indexOf('.')); - - qDebug() << "\tMoving" << oldAbsolutePath << "to" << oldAbsolutePath.replace(fullExtension, ""); - - bool renamed = oldFile.copy(_filesDirectory.filePath(hash)); - if (!renamed) { - qWarning() << "\tCould not migrate pre-mapping file" << fileInfo.fileName(); - } else { - qDebug() << "\tRenamed pre-mapping file" << fileInfo.fileName(); - - // add a new mapping with the old extension and a truncated version of the hash - const int TRUNCATED_HASH_NUM_CHAR = 16; - auto fakeFileName = "/" + hash.left(TRUNCATED_HASH_NUM_CHAR) + fullExtension; - - qDebug() << "\tAdding a migration mapping from" << fakeFileName << "to" << hash; - - auto it = _fileMappings.find(fakeFileName); - if (it == _fileMappings.end()) { - _fileMappings[fakeFileName] = hash; - - if (writeMappingsToFile()) { - // mapping added and persisted, we can remove the migrated file - oldFile.remove(); - qDebug() << "\tMigration completed for" << oldFilename; - } - } else { - qDebug() << "\tCould not add migration mapping for" << hash << "since a mapping for" << fakeFileName - << "already exists."; - } - } - } - } -} - void AssetServer::cleanupUnmappedFiles() { QRegExp hashFileRegex { "^[a-f0-9]{" + QString::number(SHA256_HASH_HEX_LENGTH) + "}" }; diff --git a/assignment-client/src/assets/AssetServer.h b/assignment-client/src/assets/AssetServer.h index 7e7c3c8b69..a0a85f8fd5 100644 --- a/assignment-client/src/assets/AssetServer.h +++ b/assignment-client/src/assets/AssetServer.h @@ -60,8 +60,6 @@ private: /// Rename mapping from `oldPath` to `newPath`. Returns true if successful bool renameMapping(AssetPath oldPath, AssetPath newPath); - void performMappingMigration(); - // deletes any unmapped files from the local asset directory void cleanupUnmappedFiles(); From fae9b061a3e4036a5afb039bb1e0b3d899e15943 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Apr 2016 08:42:52 -0700 Subject: [PATCH 17/27] promote a debug to info --- assignment-client/src/assets/AssetServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index d9af9f1019..0542da45d7 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -147,7 +147,7 @@ void AssetServer::cleanupUnmappedFiles() { // grab the currently mapped hashes auto mappedHashes = _fileMappings.values(); - qDebug() << "Performing unmapped asset cleanup."; + qInfo() << "Performing unmapped asset cleanup."; for (const auto& fileInfo : files) { if (hashFileRegex.exactMatch(fileInfo.fileName())) { From 775898893bf54700118db301a915a600a3b81c43 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Apr 2016 08:57:07 -0700 Subject: [PATCH 18/27] add deletion of unmapped files during delete op --- assignment-client/src/assets/AssetServer.cpp | 29 ++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index 0542da45d7..00fbdf7ab7 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -544,6 +544,8 @@ bool AssetServer::deleteMappings(AssetPathList& paths) { // take a copy of the current mappings in case persistence of these deletes fails auto oldMappings = _fileMappings; + QSet hashesToCheck; + // enumerate the paths to delete and remove them all for (auto& path : paths) { @@ -557,6 +559,9 @@ bool AssetServer::deleteMappings(AssetPathList& paths) { while (it != _fileMappings.end()) { if (it.key().startsWith(path)) { + // add this hash to the list we need to check for asset removal from the server + hashesToCheck << it.value().toString(); + it = _fileMappings.erase(it); } else { ++it; @@ -583,6 +588,30 @@ bool AssetServer::deleteMappings(AssetPathList& paths) { // deleted the old mappings, attempt to persist to file if (writeMappingsToFile()) { // persistence succeeded we are good to go + + // grab the current mapped hashes + auto mappedHashes = _fileMappings.values(); + + // enumerate the mapped hashes and clear the list of hashes to check for anything that's present + for (auto& hashVariant : mappedHashes) { + auto it = hashesToCheck.find(hashVariant.toString()); + if (it != hashesToCheck.end()) { + hashesToCheck.erase(it); + } + } + + // we now have a set of hashes that are unmapped - we will delete those asset files + for (auto& hash : hashesToCheck) { + // remove the unmapped file + QFile removeableFile { _filesDirectory.absoluteFilePath(hash) }; + + if (removeableFile.remove()) { + qDebug() << "\tDeleted" << hash << "from asset files directory since it is now unmapped."; + } else { + qDebug() << "\tAttempt to delete unmapped file" << hash << "failed"; + } + } + return true; } else { qWarning() << "Failed to persist deleted mappings, rolling back"; From 334dc3cb6c1a25cbf9394ef73fac98a2fa690991 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Apr 2016 09:05:11 -0700 Subject: [PATCH 19/27] cleanup left file debug, add check for deleted mapping --- assignment-client/src/assets/AssetServer.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index 00fbdf7ab7..a06163c396 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -151,9 +151,7 @@ void AssetServer::cleanupUnmappedFiles() { for (const auto& fileInfo : files) { if (hashFileRegex.exactMatch(fileInfo.fileName())) { - if (mappedHashes.contains(fileInfo.fileName())) { - qDebug() << "\tLeaving" << fileInfo.fileName() << "in asset files directory since it is mapped"; - } else { + if (!mappedHashes.contains(fileInfo.fileName())) { // remove the unmapped file QFile removeableFile { fileInfo.absoluteFilePath() }; @@ -578,6 +576,9 @@ bool AssetServer::deleteMappings(AssetPathList& paths) { } else { auto oldMapping = _fileMappings.take(path); if (!oldMapping.isNull()) { + // add this hash to the list we need to check for asset removal from server + hashesToCheck << oldMapping.toString(); + qDebug() << "Deleted a mapping:" << path << "=>" << oldMapping.toString(); } else { qDebug() << "Unable to delete a mapping that was not found:" << path; From 470aac3acf91ff22eb9374aa9998f33b5f4213d8 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 11 Apr 2016 11:52:33 -0700 Subject: [PATCH 20/27] Rename CPUID to CPUIdent to fix XCode 7.2 builds --- libraries/shared/src/{CPUID.cpp => CPUIdent.cpp} | 6 +++--- libraries/shared/src/{CPUID.h => CPUIdent.h} | 8 ++++---- libraries/shared/src/SharedUtil.cpp | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) rename libraries/shared/src/{CPUID.cpp => CPUIdent.cpp} (98%) rename libraries/shared/src/{CPUID.h => CPUIdent.h} (98%) diff --git a/libraries/shared/src/CPUID.cpp b/libraries/shared/src/CPUIdent.cpp similarity index 98% rename from libraries/shared/src/CPUID.cpp rename to libraries/shared/src/CPUIdent.cpp index e0eae248f3..2a367513b5 100644 --- a/libraries/shared/src/CPUID.cpp +++ b/libraries/shared/src/CPUIdent.cpp @@ -1,5 +1,5 @@ // -// CPUID.cpp +// CPUIdent.cpp // // Created by Ryan Huffman on 3/25/16. // Copyright 2016 High Fidelity, Inc. @@ -8,7 +8,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "CPUID.h" +#include "CPUIdent.h" #ifdef Q_OS_WIN @@ -72,4 +72,4 @@ std::vector CPUID::getAllFeatures() { return features; }; -#endif \ No newline at end of file +#endif diff --git a/libraries/shared/src/CPUID.h b/libraries/shared/src/CPUIdent.h similarity index 98% rename from libraries/shared/src/CPUID.h rename to libraries/shared/src/CPUIdent.h index a8b8921d19..b8d39ac7b9 100644 --- a/libraries/shared/src/CPUID.h +++ b/libraries/shared/src/CPUIdent.h @@ -1,5 +1,5 @@ // -// CPUID.h +// CPUIdent.h // // Adapted from Microsoft's example for using the cpuid intrinsic, // found at https://msdn.microsoft.com/en-us/library/hskdteyh.aspx @@ -15,8 +15,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_CPUID_h -#define hifi_CPUID_h +#ifndef hifi_CPUIdent_h +#define hifi_CPUIdent_h #include @@ -209,4 +209,4 @@ private: #endif -#endif // hifi_CPUID_h +#endif // hifi_CPUIdent_h diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 30d4726bcc..bdc5d4c60d 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -24,7 +24,7 @@ #endif #ifdef Q_OS_WIN -#include "CPUID.h" +#include "CPUIdent.h" #endif @@ -758,10 +758,10 @@ void printSystemInformation() { qDebug() << "CPUID"; - qDebug() << "\tCPU Vendor: " << CPUID::Vendor().c_str(); - qDebug() << "\tCPU Brand: " << CPUID::Brand().c_str(); + qDebug() << "\tCPU Vendor: " << CPUIdent::Vendor().c_str(); + qDebug() << "\tCPU Brand: " << CPUIdent::Brand().c_str(); - for (auto& feature : CPUID::getAllFeatures()) { + for (auto& feature : CPUIdent::getAllFeatures()) { qDebug().nospace().noquote() << "\t[" << (feature.supported ? "x" : " ") << "] " << feature.name.c_str(); } #endif @@ -777,4 +777,4 @@ void printSystemInformation() { qDebug().noquote().nospace() << "\t" << (envVariables.contains(env) ? " = " + envVariables.value(env) : " NOT FOUND"); } -} \ No newline at end of file +} From aad98cc25d60f9ad3d36d1986ced7a48f5d35ea3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Apr 2016 11:56:47 -0700 Subject: [PATCH 21/27] make sure password setting is set before checking length --- domain-server/resources/web/settings/js/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/resources/web/settings/js/settings.js b/domain-server/resources/web/settings/js/settings.js index dfdfeded04..e17a886e10 100644 --- a/domain-server/resources/web/settings/js/settings.js +++ b/domain-server/resources/web/settings/js/settings.js @@ -870,7 +870,7 @@ function saveSettings() { // check if we've set the basic http password - if so convert it to base64 if (formJSON["security"]) { var password = formJSON["security"]["http_password"]; - if (password.length > 0) { + if (password && password.length > 0) { formJSON["security"]["http_password"] = sha256_digest(password); } } From 026f58c8666a6b44d625ba68825652b254e68a4b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Apr 2016 17:14:31 -0700 Subject: [PATCH 22/27] don't perform asset cleanup if mapping file load fails --- assignment-client/src/assets/AssetServer.cpp | 34 ++++++++++++-------- assignment-client/src/assets/AssetServer.h | 2 +- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index a06163c396..b522890b61 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -122,21 +122,27 @@ void AssetServer::completeSetup() { } // load whatever mappings we currently have from the local file - loadMappingsFromFile(); + if (loadMappingsFromFile()) { + qInfo() << "Serving files from: " << _filesDirectory.path(); - qInfo() << "Serving files from: " << _filesDirectory.path(); + // Check the asset directory to output some information about what we have + auto files = _filesDirectory.entryList(QDir::Files); - // Check the asset directory to output some information about what we have - auto files = _filesDirectory.entryList(QDir::Files); + QRegExp hashFileRegex { ASSET_HASH_REGEX_STRING }; + auto hashedFiles = files.filter(hashFileRegex); - QRegExp hashFileRegex { ASSET_HASH_REGEX_STRING }; - auto hashedFiles = files.filter(hashFileRegex); + qInfo() << "There are" << hashedFiles.size() << "asset files in the asset directory."; - qInfo() << "There are" << hashedFiles.size() << "asset files in the asset directory."; + if (_fileMappings.count() > 0) { + cleanupUnmappedFiles(); + } - cleanupUnmappedFiles(); + nodeList->addNodeTypeToInterestSet(NodeType::Agent); + } else { + qCritical() << "Asset Server assignment will not continue because mapping file could not be loaded."; + setFinished(true); + } - nodeList->addNodeTypeToInterestSet(NodeType::Agent); } void AssetServer::cleanupUnmappedFiles() { @@ -427,7 +433,7 @@ void AssetServer::sendStatsPacket() { static const QString MAP_FILE_NAME = "map.json"; -void AssetServer::loadMappingsFromFile() { +bool AssetServer::loadMappingsFromFile() { auto mapFilePath = _resourcesDirectory.absoluteFilePath(MAP_FILE_NAME); @@ -464,15 +470,17 @@ void AssetServer::loadMappingsFromFile() { } qInfo() << "Loaded" << _fileMappings.count() << "mappings from map file at" << mapFilePath; - return; + return true; } } - qCritical() << "Failed to read mapping file at" << mapFilePath << "- assignment will not continue."; - setFinished(true); + qCritical() << "Failed to read mapping file at" << mapFilePath; + return false; } else { qInfo() << "No existing mappings loaded from file since no file was found at" << mapFilePath; } + + return true; } bool AssetServer::writeMappingsToFile() { diff --git a/assignment-client/src/assets/AssetServer.h b/assignment-client/src/assets/AssetServer.h index a0a85f8fd5..07ff0a92b3 100644 --- a/assignment-client/src/assets/AssetServer.h +++ b/assignment-client/src/assets/AssetServer.h @@ -48,7 +48,7 @@ private: void handleRenameMappingOperation(ReceivedMessage& message, SharedNodePointer senderNode, NLPacketList& replyPacket); // Mapping file operations must be called from main assignment thread only - void loadMappingsFromFile(); + bool loadMappingsFromFile(); bool writeMappingsToFile(); /// Set the mapping for path to hash From 190d11e0bf68a6facac1b4cfe1086893eddd1b9a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Apr 2016 17:16:52 -0700 Subject: [PATCH 23/27] rename the set of hashes to check for deletion --- assignment-client/src/assets/AssetServer.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index b522890b61..5a5f51eb58 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -550,7 +550,7 @@ bool AssetServer::deleteMappings(AssetPathList& paths) { // take a copy of the current mappings in case persistence of these deletes fails auto oldMappings = _fileMappings; - QSet hashesToCheck; + QSet hashesToCheckForDeletion; // enumerate the paths to delete and remove them all for (auto& path : paths) { @@ -566,7 +566,7 @@ bool AssetServer::deleteMappings(AssetPathList& paths) { while (it != _fileMappings.end()) { if (it.key().startsWith(path)) { // add this hash to the list we need to check for asset removal from the server - hashesToCheck << it.value().toString(); + hashesToCheckForDeletion << it.value().toString(); it = _fileMappings.erase(it); } else { @@ -585,7 +585,7 @@ bool AssetServer::deleteMappings(AssetPathList& paths) { auto oldMapping = _fileMappings.take(path); if (!oldMapping.isNull()) { // add this hash to the list we need to check for asset removal from server - hashesToCheck << oldMapping.toString(); + hashesToCheckForDeletion << oldMapping.toString(); qDebug() << "Deleted a mapping:" << path << "=>" << oldMapping.toString(); } else { @@ -603,14 +603,14 @@ bool AssetServer::deleteMappings(AssetPathList& paths) { // enumerate the mapped hashes and clear the list of hashes to check for anything that's present for (auto& hashVariant : mappedHashes) { - auto it = hashesToCheck.find(hashVariant.toString()); - if (it != hashesToCheck.end()) { - hashesToCheck.erase(it); + auto it = hashesToCheckForDeletion.find(hashVariant.toString()); + if (it != hashesToCheckForDeletion.end()) { + hashesToCheckForDeletion.erase(it); } } // we now have a set of hashes that are unmapped - we will delete those asset files - for (auto& hash : hashesToCheck) { + for (auto& hash : hashesToCheckForDeletion) { // remove the unmapped file QFile removeableFile { _filesDirectory.absoluteFilePath(hash) }; From 76af3efe73eb29a8601d44329b10477d65d3b8b3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 11 Apr 2016 17:59:27 -0700 Subject: [PATCH 24/27] fix for active socket check on ATP script download --- assignment-client/src/Agent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 3305beae35..d0433b5d60 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -195,7 +195,7 @@ void Agent::requestScript() { // then wait for the nodeConnected signal to fire off the request auto assetServer = nodeList->soloNodeOfType(NodeType::AssetServer); - if (!assetServer || assetServer->getActiveSocket()) { + if (!assetServer || !assetServer->getActiveSocket()) { qDebug() << "Waiting to connect to Asset Server for ATP script download."; _pendingScriptRequest = request; From 455d2d50480b0e3fda9436e1a1265fd93322cb62 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 12 Apr 2016 09:37:26 -0700 Subject: [PATCH 25/27] allow for an empty password with a username --- domain-server/src/DomainServer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 4ff3564e72..16928f3dee 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1678,10 +1678,12 @@ bool DomainServer::isAuthenticatedRequest(HTTPConnection* connection, const QUrl // we've pulled a username and password - now check if there is a match in our basic auth hash QString settingsUsername = valueForKeyPath(settingsMap, BASIC_AUTH_USERNAME_KEY_PATH)->toString(); const QVariant* settingsPasswordVariant = valueForKeyPath(settingsMap, BASIC_AUTH_PASSWORD_KEY_PATH); + QString settingsPassword = settingsPasswordVariant ? settingsPasswordVariant->toString() : ""; QString hexHeaderPassword = QCryptographicHash::hash(headerPassword.toUtf8(), QCryptographicHash::Sha256).toHex(); - if (settingsUsername == headerUsername && hexHeaderPassword == settingsPassword) { + if (settingsUsername == headerUsername + && (settingsPassword.isEmpty() || hexHeaderPassword == settingsPassword)) { return true; } } From 32ccc1d68e6c1e1d45bb4e21cf2330aedff84884 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 12 Apr 2016 10:53:04 -0700 Subject: [PATCH 26/27] Windows build fixes --- libraries/shared/src/CPUIdent.cpp | 108 +++++++++++++++--------------- libraries/shared/src/CPUIdent.h | 10 +-- 2 files changed, 59 insertions(+), 59 deletions(-) diff --git a/libraries/shared/src/CPUIdent.cpp b/libraries/shared/src/CPUIdent.cpp index 2a367513b5..718b01b196 100644 --- a/libraries/shared/src/CPUIdent.cpp +++ b/libraries/shared/src/CPUIdent.cpp @@ -12,62 +12,62 @@ #ifdef Q_OS_WIN -const CPUID::CPUID_Internal CPUID::CPU_Rep; +const CPUIdent::CPUIdent_Internal CPUIdent::CPU_Rep; -std::vector CPUID::getAllFeatures() { - std::vector features; +std::vector CPUIdent::getAllFeatures() { + std::vector features; - features.push_back({ "3DNOW", CPUID::_3DNOW() }); - features.push_back({ "3DNOWEXT", CPUID::_3DNOWEXT() }); - features.push_back({ "ABM", CPUID::ABM() }); - features.push_back({ "ADX", CPUID::ADX() }); - features.push_back({ "AES", CPUID::AES() }); - features.push_back({ "AVX", CPUID::AVX() }); - features.push_back({ "AVX2", CPUID::AVX2() }); - features.push_back({ "AVX512CD", CPUID::AVX512CD() }); - features.push_back({ "AVX512ER", CPUID::AVX512ER() }); - features.push_back({ "AVX512F", CPUID::AVX512F() }); - features.push_back({ "AVX512PF", CPUID::AVX512PF() }); - features.push_back({ "BMI1", CPUID::BMI1() }); - features.push_back({ "BMI2", CPUID::BMI2() }); - features.push_back({ "CLFSH", CPUID::CLFSH() }); - features.push_back({ "CMPXCHG16B", CPUID::CMPXCHG16B() }); - features.push_back({ "CX8", CPUID::CX8() }); - features.push_back({ "ERMS", CPUID::ERMS() }); - features.push_back({ "F16C", CPUID::F16C() }); - features.push_back({ "FMA", CPUID::FMA() }); - features.push_back({ "FSGSBASE", CPUID::FSGSBASE() }); - features.push_back({ "FXSR", CPUID::FXSR() }); - features.push_back({ "HLE", CPUID::HLE() }); - features.push_back({ "INVPCID", CPUID::INVPCID() }); - features.push_back({ "LAHF", CPUID::LAHF() }); - features.push_back({ "LZCNT", CPUID::LZCNT() }); - features.push_back({ "MMX", CPUID::MMX() }); - features.push_back({ "MMXEXT", CPUID::MMXEXT() }); - features.push_back({ "MONITOR", CPUID::MONITOR() }); - features.push_back({ "MOVBE", CPUID::MOVBE() }); - features.push_back({ "MSR", CPUID::MSR() }); - features.push_back({ "OSXSAVE", CPUID::OSXSAVE() }); - features.push_back({ "PCLMULQDQ", CPUID::PCLMULQDQ() }); - features.push_back({ "POPCNT", CPUID::POPCNT() }); - features.push_back({ "PREFETCHWT1", CPUID::PREFETCHWT1() }); - features.push_back({ "RDRAND", CPUID::RDRAND() }); - features.push_back({ "RDSEED", CPUID::RDSEED() }); - features.push_back({ "RDTSCP", CPUID::RDTSCP() }); - features.push_back({ "RTM", CPUID::RTM() }); - features.push_back({ "SEP", CPUID::SEP() }); - features.push_back({ "SHA", CPUID::SHA() }); - features.push_back({ "SSE", CPUID::SSE() }); - features.push_back({ "SSE2", CPUID::SSE2() }); - features.push_back({ "SSE3", CPUID::SSE3() }); - features.push_back({ "SSE4.1", CPUID::SSE41() }); - features.push_back({ "SSE4.2", CPUID::SSE42() }); - features.push_back({ "SSE4a", CPUID::SSE4a() }); - features.push_back({ "SSSE3", CPUID::SSSE3() }); - features.push_back({ "SYSCALL", CPUID::SYSCALL() }); - features.push_back({ "TBM", CPUID::TBM() }); - features.push_back({ "XOP", CPUID::XOP() }); - features.push_back({ "XSAVE", CPUID::XSAVE() }); + features.push_back({ "3DNOW", CPUIdent::_3DNOW() }); + features.push_back({ "3DNOWEXT", CPUIdent::_3DNOWEXT() }); + features.push_back({ "ABM", CPUIdent::ABM() }); + features.push_back({ "ADX", CPUIdent::ADX() }); + features.push_back({ "AES", CPUIdent::AES() }); + features.push_back({ "AVX", CPUIdent::AVX() }); + features.push_back({ "AVX2", CPUIdent::AVX2() }); + features.push_back({ "AVX512CD", CPUIdent::AVX512CD() }); + features.push_back({ "AVX512ER", CPUIdent::AVX512ER() }); + features.push_back({ "AVX512F", CPUIdent::AVX512F() }); + features.push_back({ "AVX512PF", CPUIdent::AVX512PF() }); + features.push_back({ "BMI1", CPUIdent::BMI1() }); + features.push_back({ "BMI2", CPUIdent::BMI2() }); + features.push_back({ "CLFSH", CPUIdent::CLFSH() }); + features.push_back({ "CMPXCHG16B", CPUIdent::CMPXCHG16B() }); + features.push_back({ "CX8", CPUIdent::CX8() }); + features.push_back({ "ERMS", CPUIdent::ERMS() }); + features.push_back({ "F16C", CPUIdent::F16C() }); + features.push_back({ "FMA", CPUIdent::FMA() }); + features.push_back({ "FSGSBASE", CPUIdent::FSGSBASE() }); + features.push_back({ "FXSR", CPUIdent::FXSR() }); + features.push_back({ "HLE", CPUIdent::HLE() }); + features.push_back({ "INVPCID", CPUIdent::INVPCID() }); + features.push_back({ "LAHF", CPUIdent::LAHF() }); + features.push_back({ "LZCNT", CPUIdent::LZCNT() }); + features.push_back({ "MMX", CPUIdent::MMX() }); + features.push_back({ "MMXEXT", CPUIdent::MMXEXT() }); + features.push_back({ "MONITOR", CPUIdent::MONITOR() }); + features.push_back({ "MOVBE", CPUIdent::MOVBE() }); + features.push_back({ "MSR", CPUIdent::MSR() }); + features.push_back({ "OSXSAVE", CPUIdent::OSXSAVE() }); + features.push_back({ "PCLMULQDQ", CPUIdent::PCLMULQDQ() }); + features.push_back({ "POPCNT", CPUIdent::POPCNT() }); + features.push_back({ "PREFETCHWT1", CPUIdent::PREFETCHWT1() }); + features.push_back({ "RDRAND", CPUIdent::RDRAND() }); + features.push_back({ "RDSEED", CPUIdent::RDSEED() }); + features.push_back({ "RDTSCP", CPUIdent::RDTSCP() }); + features.push_back({ "RTM", CPUIdent::RTM() }); + features.push_back({ "SEP", CPUIdent::SEP() }); + features.push_back({ "SHA", CPUIdent::SHA() }); + features.push_back({ "SSE", CPUIdent::SSE() }); + features.push_back({ "SSE2", CPUIdent::SSE2() }); + features.push_back({ "SSE3", CPUIdent::SSE3() }); + features.push_back({ "SSE4.1", CPUIdent::SSE41() }); + features.push_back({ "SSE4.2", CPUIdent::SSE42() }); + features.push_back({ "SSE4a", CPUIdent::SSE4a() }); + features.push_back({ "SSSE3", CPUIdent::SSSE3() }); + features.push_back({ "SYSCALL", CPUIdent::SYSCALL() }); + features.push_back({ "TBM", CPUIdent::TBM() }); + features.push_back({ "XOP", CPUIdent::XOP() }); + features.push_back({ "XSAVE", CPUIdent::XSAVE() }); return features; }; diff --git a/libraries/shared/src/CPUIdent.h b/libraries/shared/src/CPUIdent.h index b8d39ac7b9..32668149f4 100644 --- a/libraries/shared/src/CPUIdent.h +++ b/libraries/shared/src/CPUIdent.h @@ -29,10 +29,10 @@ #include -class CPUID +class CPUIdent { // forward declarations - class CPUID_Internal; + class CPUIdent_Internal; public: struct Feature { @@ -104,12 +104,12 @@ public: static bool _3DNOW(void) { return CPU_Rep.isAMD_ && CPU_Rep.f_81_EDX_[31]; } private: - static const CPUID_Internal CPU_Rep; + static const CPUIdent_Internal CPU_Rep; - class CPUID_Internal + class CPUIdent_Internal { public: - CPUID_Internal() + CPUIdent_Internal() : nIds_ { 0 }, nExIds_ { 0 }, isIntel_ { false }, From 9f2eabe6ce147f6ab6a77a1c9e89c44b40e045c7 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 12 Apr 2016 14:11:56 -0700 Subject: [PATCH 27/27] Fixing rate counter --- libraries/shared/src/shared/RateCounter.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/shared/src/shared/RateCounter.h b/libraries/shared/src/shared/RateCounter.h index a160adadcf..754439ec15 100644 --- a/libraries/shared/src/shared/RateCounter.h +++ b/libraries/shared/src/shared/RateCounter.h @@ -27,6 +27,8 @@ public: float currentCount = _count; float intervalSeconds = (float)currentIntervalMs / (float)MSECS_PER_SECOND; _rate = roundf(currentCount / intervalSeconds * _scale) / _scale; + _start = now; + _count = 0; }; _count += count; }