From 9d1f91fa19da870952f556778a1fffde8a0ee571 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 31 Mar 2016 19:27:35 -0700 Subject: [PATCH] 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(); }