From 93b0364f73827c877ff1254efb322ba489c3baf5 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 14 Sep 2016 10:17:20 -0700 Subject: [PATCH] Working on sparse stability --- libraries/gpu-gl/src/gpu/gl/GLTexture.cpp | 38 --------- libraries/gpu-gl/src/gpu/gl/GLTexture.h | 2 - .../src/gpu/gl45/GL45BackendTexture.cpp | 82 ++++++++----------- tests/render-perf/src/main.cpp | 34 -------- 4 files changed, 34 insertions(+), 122 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp b/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp index d5a68bd99b..a04ae13b05 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp @@ -17,8 +17,6 @@ using namespace gpu; using namespace gpu::gl; std::shared_ptr GLTexture::_textureTransferHelper; -static std::map _textureCountByMips; -static uint16 _currentMaxMipCount { 0 }; // FIXME placeholder for texture memory over-use #define DEFAULT_MAX_MEMORY_MB 256 @@ -131,34 +129,12 @@ GLTexture::GLTexture(const std::weak_ptr& backend, const Texture& tex { auto strongBackend = _backend.lock(); strongBackend->recycle(); - if (_transferrable) { - uint16 mipCount = usedMipLevels(); - _currentMaxMipCount = std::max(_currentMaxMipCount, mipCount); - if (!_textureCountByMips.count(mipCount)) { - _textureCountByMips[mipCount] = 1; - } else { - ++_textureCountByMips[mipCount]; - } - } Backend::incrementTextureGPUCount(); Backend::updateTextureGPUVirtualMemoryUsage(0, _virtualSize); Backend::setGPUObject(texture, this); } GLTexture::~GLTexture() { - if (_transferrable) { - uint16 mipCount = usedMipLevels(); - Q_ASSERT(_textureCountByMips.count(mipCount)); - auto& numTexturesForMipCount = _textureCountByMips[mipCount]; - --numTexturesForMipCount; - if (0 == numTexturesForMipCount) { - _textureCountByMips.erase(mipCount); - if (mipCount == _currentMaxMipCount) { - _currentMaxMipCount = (_textureCountByMips.empty() ? 0 : _textureCountByMips.rbegin()->first); - } - } - } - if (_id) { auto backend = _backend.lock(); if (backend) { @@ -213,20 +189,6 @@ bool GLTexture::isOutdated() const { return GLSyncState::Idle == _syncState && _contentStamp < _gpuObject.getDataStamp(); } -bool GLTexture::isOverMaxMemory() const { - // FIXME switch to using the max mip count used from the previous frame - if (usedMipLevels() < _currentMaxMipCount) { - return false; - } - Q_ASSERT(usedMipLevels() == _currentMaxMipCount); - - if (getMemoryPressure() < 1.0f) { - return false; - } - - return true; -} - bool GLTexture::isReady() const { // If we have an invalid texture, we're never ready if (isInvalid()) { diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexture.h b/libraries/gpu-gl/src/gpu/gl/GLTexture.h index e3bee4e103..a54e45989d 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexture.h +++ b/libraries/gpu-gl/src/gpu/gl/GLTexture.h @@ -134,8 +134,6 @@ public: // Execute any post-move operations that must occur only on the main thread virtual void postTransfer(); - bool isOverMaxMemory() const; - uint16 usedMipLevels() const { return (_maxMip - _minMip) + 1; } static const size_t CUBE_NUM_FACES = 6; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index a1c9129887..889229c1aa 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -17,6 +17,7 @@ #include #include +#include #include "../gl/GLTexelFormat.h" @@ -24,11 +25,8 @@ using namespace gpu; using namespace gpu::gl; using namespace gpu::gl45; -#ifdef THREADED_TEXTURE_TRANSFER -#define SPARSE_TEXTURES 1 -#else -#define SPARSE_TEXTURES 0 -#endif +static const QString DEBUG_FLAG("HIFI_ENABLE_SPARSE_TEXTURES"); +static bool enableSparseTextures = true; // QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG); // Allocate 1 MB of buffer space for paged transfers #define DEFAULT_PAGE_BUFFER_SIZE (1024*1024) @@ -36,6 +34,7 @@ using namespace gpu::gl45; using GL45Texture = GL45Backend::GL45Texture; static std::map> texturesByMipCounts; +static Mutex texturesByMipCountsMutex; GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texture, bool transfer) { return GL45Texture::sync(*this, texture, transfer); @@ -179,9 +178,9 @@ GLuint GL45Backend::getTextureID(const TexturePointer& texture, bool transfer) { GL45Texture::GL45Texture(const std::weak_ptr& backend, const Texture& texture, bool transferrable) : GLTexture(backend, texture, allocate(texture), transferrable), _sparseInfo(*this), _transferState(*this) { -#if SPARSE_TEXTURES - _sparse = _transferrable; -#endif + + _sparse = _transferrable && (_target != GL_TEXTURE_CUBE_MAP); + if (_sparse) { glTextureParameteri(_id, GL_TEXTURE_SPARSE_ARB, GL_TRUE); } @@ -190,11 +189,15 @@ GL45Texture::GL45Texture(const std::weak_ptr& backend, const Texture& GL45Texture::~GL45Texture() { if (_sparse) { auto mipLevels = usedMipLevels(); - if (texturesByMipCounts.count(mipLevels)) { - auto& textures = texturesByMipCounts[mipLevels]; - textures.erase(this); - if (textures.empty()) { - texturesByMipCounts.erase(mipLevels); + + { + Lock lock(texturesByMipCountsMutex); + if (texturesByMipCounts.count(mipLevels)) { + auto& textures = texturesByMipCounts[mipLevels]; + textures.erase(this); + if (textures.empty()) { + texturesByMipCounts.erase(mipLevels); + } } } @@ -271,10 +274,10 @@ bool GL45Texture::continueTransfer() { if (_allocatedPages > _sparseInfo._maxPages) { qDebug() << "Exceeded max page allocation!"; } - glBindTexture(_target, _id); + //glBindTexture(_target, _id); // FIXME we should be using glTexturePageCommitmentEXT, but for some reason it causes out of memory errors. // Either I'm not understanding how it should work or there's a driver bug. - glTexPageCommitmentARB(_target, _transferState._mipLevel, + glTexturePageCommitmentEXT(_id, _transferState._mipLevel, offset.x, offset.y, _transferState._face, pageSize.x, pageSize.y, pageSize.z, GL_TRUE); @@ -303,7 +306,7 @@ bool GL45Texture::continueTransfer() { serverWait(); auto currentMip = _transferState._mipLevel; auto result = _transferState.increment(); - if (_transferState._mipLevel != currentMip && currentMip <= _sparseInfo._maxSparseLevel) { + if (_sparse && _transferState._mipLevel != currentMip && currentMip <= _sparseInfo._maxSparseLevel) { auto mipDimensions = _gpuObject.evalMipDimensions(currentMip); auto mipExpectedPages = _sparseInfo.getPageCount(mipDimensions); auto newPages = _allocatedPages - _lastMipAllocatedPages; @@ -346,10 +349,10 @@ void GL45Texture::syncSampler() const { void GL45Texture::postTransfer() { Parent::postTransfer(); - if (_transferrable) { + if (_sparse) { auto mipLevels = usedMipLevels(); if (mipLevels > 1 && _minMip < _sparseInfo._maxSparseLevel) { - auto& textureMap = texturesByMipCounts; + Lock lock(texturesByMipCountsMutex); texturesByMipCounts[mipLevels].insert(this); } } @@ -371,32 +374,16 @@ void GL45Texture::stripToMip(uint16_t newMinMip) { } auto mipLevels = usedMipLevels(); - assert(0 != texturesByMipCounts.count(mipLevels)); - assert(0 != texturesByMipCounts[mipLevels].count(this)); - texturesByMipCounts[mipLevels].erase(this); - if (texturesByMipCounts[mipLevels].empty()) { - texturesByMipCounts.erase(mipLevels); + { + Lock lock(texturesByMipCountsMutex); + assert(0 != texturesByMipCounts.count(mipLevels)); + assert(0 != texturesByMipCounts[mipLevels].count(this)); + texturesByMipCounts[mipLevels].erase(this); + if (texturesByMipCounts[mipLevels].empty()) { + texturesByMipCounts.erase(mipLevels); + } } - // FIXME this shouldn't be necessary should it? -#if 1 - glGenerateTextureMipmap(_id); -#else - static GLuint framebuffers[2] = { 0, 0 }; - static std::once_flag initFramebuffers; - std::call_once(initFramebuffers, [&] { - glCreateFramebuffers(2, framebuffers); - }); - auto readSize = _gpuObject.evalMipDimensions(_minMip); - auto drawSize = _gpuObject.evalMipDimensions(newMinMip); - glNamedFramebufferTexture(framebuffers[0], GL_COLOR_ATTACHMENT0, _id, _minMip); - glNamedFramebufferTexture(framebuffers[1], GL_COLOR_ATTACHMENT0, _id, newMinMip); - glBlitNamedFramebuffer(framebuffers[0], framebuffers[1], - 0, 0, readSize.x, readSize.y, - 0, 0, drawSize.x, drawSize.y, - GL_COLOR_BUFFER_BIT, GL_LINEAR); -#endif - uint8_t maxFace = (uint8_t)((_target == GL_TEXTURE_CUBE_MAP) ? GLTexture::CUBE_NUM_FACES : 1); for (uint16_t mip = _minMip; mip < newMinMip; ++mip) { auto mipDimensions = _gpuObject.evalMipDimensions(mip); @@ -425,8 +412,8 @@ void GL45Texture::stripToMip(uint16_t newMinMip) { // Re-insert into the texture-by-mips map if appropriate mipLevels = usedMipLevels(); - if (mipLevels > 1 && _minMip < _sparseInfo._maxSparseLevel) { - auto& textureMap = texturesByMipCounts; + if (_sparse && mipLevels > 1 && _minMip < _sparseInfo._maxSparseLevel) { + Lock lock(texturesByMipCountsMutex); texturesByMipCounts[mipLevels].insert(this); } } @@ -443,9 +430,7 @@ void GL45Texture::updateMips() { } void GL45Texture::derez() { - if (!_sparse) { - return; - } + assert(_sparse); assert(_minMip < _sparseInfo._maxSparseLevel); assert(_minMip < _maxMip); assert(_transferrable); @@ -459,6 +444,7 @@ void GL45Backend::derezTextures() const { qDebug() << "Allowed texture memory " << Texture::getAllowedGPUMemoryUsage(); qDebug() << "Used texture memory " << Context::getTextureGPUMemoryUsage(); + Lock lock(texturesByMipCountsMutex); if (texturesByMipCounts.empty()) { qDebug() << "No available textures to derez"; return; @@ -479,7 +465,7 @@ void GL45Backend::derezTextures() const { assert(!textures.empty()); targetTexture = *textures.begin(); } + lock.unlock(); targetTexture->derez(); - qDebug() << "New Used texture memory " << Context::getTextureGPUMemoryUsage(); } diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index 267d192c7f..bbe1c33bb1 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -286,10 +286,6 @@ public: } _context.makeCurrent(); - glewExperimental = true; - glewInit(); - glGetError(); - _frameTimes.resize(FRAME_TIME_BUFFER_SIZE, 0); { auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS(); @@ -552,36 +548,6 @@ public: _renderThread.initialize(this, _initContext); _initContext.makeCurrent(); -#if 0 - glfwInit(); - glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5); - glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - resizeWindow(QSize(800, 600)); - _window = glfwCreateWindow(_size.width(), _size.height(), "Window Title", NULL, NULL); - if (!_window) { - throw std::runtime_error("Could not create window"); - } - - glfwSetWindowUserPointer(_window, this); - glfwSetKeyCallback(_window, KeyboardHandler); - glfwSetMouseButtonCallback(_window, MouseHandler); - glfwSetCursorPosCallback(_window, MouseMoveHandler); - glfwSetWindowCloseCallback(_window, CloseHandler); - glfwSetFramebufferSizeCallback(_window, FramebufferSizeHandler); - glfwSetScrollCallback(_window, MouseScrollHandler); - - - glfwMakeContextCurrent(_window); - GLDebug::setupLogger(this); -#endif - -#ifdef Q_OS_WIN - //wglSwapIntervalEXT(0); -#endif - // FIXME use a wait condition QThread::msleep(1000); _renderThread.submitFrame(gpu::FramePointer());