From 35a6359d5976b61fab4f21f17188872a6e6122b5 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 10 Feb 2017 10:56:01 -0800 Subject: [PATCH] Fixing transfer logic, adding stats display & profile ranges --- interface/resources/qml/Stats.qml | 11 +-- interface/src/ui/Stats.cpp | 3 + interface/src/ui/Stats.h | 2 + libraries/gpu-gl/src/gpu/gl45/GL45Backend.h | 7 +- .../src/gpu/gl45/GL45BackendTexture.cpp | 3 - .../gpu/gl45/GL45BackendVariableTexture.cpp | 70 ++++++++++++++++--- 6 files changed, 72 insertions(+), 24 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index faf37d5366..4cba41f6cc 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -241,7 +241,7 @@ Item { text: "GPU Textures: "; } StatText { - text: " Sparse Enabled: " + (0 == root.gpuSparseTextureEnabled ? "false" : "true"); + text: " Pressure State: " + root.gpuTextureMemoryPressureState; } StatText { text: " Count: " + root.gpuTextures; @@ -253,14 +253,7 @@ Item { text: " Decimated: " + root.decimatedTextureCount; } StatText { - text: " Sparse Count: " + root.gpuTexturesSparse; - visible: 0 != root.gpuSparseTextureEnabled; - } - StatText { - text: " Virtual Memory: " + root.gpuTextureVirtualMemory + " MB"; - } - StatText { - text: " Commited Memory: " + root.gpuTextureMemory + " MB"; + text: " Resource Memory: " + root.gpuTextureMemory + " MB"; } StatText { text: " Framebuffer Memory: " + root.gpuTextureFramebufferMemory + " MB"; diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index e82f99bed2..7af454b702 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -38,6 +38,8 @@ using namespace std; static Stats* INSTANCE{ nullptr }; +QString getTextureMemoryPressureModeString(); + Stats* Stats::getInstance() { if (!INSTANCE) { Stats::registerType(); @@ -323,6 +325,7 @@ void Stats::updateStats(bool force) { STAT_UPDATE(gpuTextureVirtualMemory, (int)BYTES_TO_MB(gpu::Texture::getTextureGPUVirtualMemoryUsage())); STAT_UPDATE(gpuTextureFramebufferMemory, (int)BYTES_TO_MB(gpu::Texture::getTextureGPUFramebufferMemoryUsage())); STAT_UPDATE(gpuTextureSparseMemory, (int)BYTES_TO_MB(gpu::Texture::getTextureGPUSparseMemoryUsage())); + STAT_UPDATE(gpuTextureMemoryPressureState, getTextureMemoryPressureModeString()); STAT_UPDATE(gpuSparseTextureEnabled, gpuContext->getBackend()->isTextureManagementSparseEnabled() ? 1 : 0); STAT_UPDATE(gpuFreeMemory, (int)BYTES_TO_MB(gpu::Context::getFreeGPUMemory())); STAT_UPDATE(rectifiedTextureCount, (int)RECTIFIED_TEXTURE_COUNT.load()); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index f501f4b09a..069429d639 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -110,6 +110,7 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, gpuTextureFramebufferMemory, 0) STATS_PROPERTY(int, gpuTextureSparseMemory, 0) STATS_PROPERTY(int, gpuSparseTextureEnabled, 0) + STATS_PROPERTY(QString, gpuTextureMemoryPressureState, QString()) STATS_PROPERTY(int, gpuFreeMemory, 0) STATS_PROPERTY(float, gpuFrameTime, 0) STATS_PROPERTY(float, batchFrameTime, 0) @@ -217,6 +218,7 @@ signals: void gpuTextureVirtualMemoryChanged(); void gpuTextureFramebufferMemoryChanged(); void gpuTextureSparseMemoryChanged(); + void gpuTextureMemoryPressureStateChanged(); void gpuSparseTextureEnabledChanged(); void gpuFreeMemoryChanged(); void gpuFrameTimeChanged(); diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h index e6a61e9498..1983088ca5 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h +++ b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h @@ -103,11 +103,13 @@ public: }; using WorkQueue = std::priority_queue, QueuePairLess>; + static MemoryPressureState _memoryPressureState; protected: static std::atomic _memoryPressureStateStale; - static MemoryPressureState _memoryPressureState; static std::list _memoryManagedTextures; - static WorkQueue _workQueue; + static WorkQueue _transferQueue; + static WorkQueue _promoteQueue; + static WorkQueue _demoteQueue; static const uvec3 INITIAL_MIP_TRANSFER_DIMENSIONS; @@ -115,6 +117,7 @@ public: static void processWorkQueues(); static void addMemoryManagedTexture(const TexturePointer& texturePointer); static void addToWorkQueue(const TexturePointer& texture); + static WorkQueue& getActiveWorkQueue(); static void manageMemory(); diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 87eb5228a4..c344b453a9 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -35,9 +35,6 @@ GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texturePointer) { } const Texture& texture = *texturePointer; - if (std::string("cursor texture") == texture.source()) { - qDebug() << "Loading cursor texture"; - } if (TextureUsageType::EXTERNAL == texture.getUsageType()) { return Parent::syncGPUObject(texturePointer); } diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendVariableTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendVariableTexture.cpp index 0f14c9cc43..282ec2161c 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendVariableTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendVariableTexture.cpp @@ -36,7 +36,9 @@ std::list GL45VariableAllocationTexture::_memoryManagedTextu MemoryPressureState GL45VariableAllocationTexture::_memoryPressureState = MemoryPressureState::Idle; std::atomic GL45VariableAllocationTexture::_memoryPressureStateStale { false }; const uvec3 GL45VariableAllocationTexture::INITIAL_MIP_TRANSFER_DIMENSIONS { 64, 64, 1 }; -WorkQueue GL45VariableAllocationTexture::_workQueue; +WorkQueue GL45VariableAllocationTexture::_transferQueue; +WorkQueue GL45VariableAllocationTexture::_promoteQueue; +WorkQueue GL45VariableAllocationTexture::_demoteQueue; #define OVERSUBSCRIBED_PRESSURE_VALUE 0.95f #define UNDERSUBSCRIBED_PRESSURE_VALUE 0.85f @@ -54,19 +56,19 @@ void GL45VariableAllocationTexture::addToWorkQueue(const TexturePointer& texture switch (_memoryPressureState) { case MemoryPressureState::Oversubscribed: if (object->canDemote()) { - _workQueue.push({ texturePointer, (float) object->size() }); + _demoteQueue.push({ texturePointer, (float)object->size() }); } break; case MemoryPressureState::Undersubscribed: if (object->canPromote()) { - _workQueue.push({ texturePointer, 1.0f / (float)object->size() }); + _promoteQueue.push({ texturePointer, 1.0f / (float)object->size() }); } break; case MemoryPressureState::Transfer: if (object->hasPendingTransfers()) { - _workQueue.push({ texturePointer, 1.0f / (float)object->_gpuObject.evalMipSize(object->_populatedMip) }); + _transferQueue.push({ texturePointer, 1.0f / (float)object->_gpuObject.evalMipSize(object->_populatedMip) }); } break; @@ -78,6 +80,44 @@ void GL45VariableAllocationTexture::addToWorkQueue(const TexturePointer& texture } } +WorkQueue& GL45VariableAllocationTexture::getActiveWorkQueue() { + static WorkQueue empty; + switch (_memoryPressureState) { + case MemoryPressureState::Oversubscribed: + return _demoteQueue; + + case MemoryPressureState::Undersubscribed: + return _promoteQueue; + + case MemoryPressureState::Transfer: + return _transferQueue; + + default: + break; + } + Q_UNREACHABLE(); + return empty; +} + +// FIXME hack for stats display +QString getTextureMemoryPressureModeString() { + switch (GL45VariableAllocationTexture::_memoryPressureState) { + case MemoryPressureState::Oversubscribed: + return "Oversubscribed"; + + case MemoryPressureState::Undersubscribed: + return "Undersubscribed"; + + case MemoryPressureState::Transfer: + return "Transfer"; + + case MemoryPressureState::Idle: + return "Idle"; + } + Q_UNREACHABLE(); + return "Unknown"; +} + void GL45VariableAllocationTexture::updateMemoryPressure() { static size_t lastAllowedMemoryAllocation = gpu::Texture::getAllowedGPUMemoryUsage(); @@ -97,6 +137,8 @@ void GL45VariableAllocationTexture::updateMemoryPressure() { return; } + PROFILE_RANGE(render_gpu_gl, __FUNCTION__); + // Clear any defunct textures (weak pointers that no longer have a valid texture) _memoryManagedTextures.remove_if([&](const TextureWeakPointer& weakPointer) { return weakPointer.expired(); @@ -147,7 +189,9 @@ void GL45VariableAllocationTexture::updateMemoryPressure() { if (newState != _memoryPressureState) { _memoryPressureState = newState; // Clear the existing queue - _workQueue = WorkQueue(); + _transferQueue = WorkQueue(); + _promoteQueue = WorkQueue(); + _demoteQueue = WorkQueue(); // Populate the existing textures into the queue for (const auto& texture : strongTextures) { addToWorkQueue(texture); @@ -160,9 +204,11 @@ void GL45VariableAllocationTexture::processWorkQueues() { return; } - while (!_workQueue.empty()) { - auto workTarget = _workQueue.top(); - _workQueue.pop(); + auto& workQueue = getActiveWorkQueue(); + PROFILE_RANGE(render_gpu_gl, __FUNCTION__); + while (!workQueue.empty()) { + auto workTarget = workQueue.top(); + workQueue.pop(); auto texture = workTarget.first.lock(); if (!texture) { continue; @@ -197,7 +243,7 @@ void GL45VariableAllocationTexture::processWorkQueues() { break; } - if (_workQueue.empty()) { + if (workQueue.empty()) { _memoryPressureState = MemoryPressureState::Idle; } } @@ -208,6 +254,7 @@ void GL45VariableAllocationTexture::manageMemory() { auto interval = now - lastProcessTime; if (interval > (USECS_PER_MSEC * 20)) { lastProcessTime = now; + PROFILE_RANGE(render_gpu_gl, __FUNCTION__); updateMemoryPressure(); processWorkQueues(); } @@ -283,6 +330,7 @@ void GL45ResourceTexture::syncSampler() const { } void GL45ResourceTexture::promote() { + PROFILE_RANGE(render_gpu_gl, __FUNCTION__); Q_ASSERT(_allocatedMip > 0); GLuint oldId = _id; uint32_t oldSize = _size; @@ -317,6 +365,7 @@ void GL45ResourceTexture::promote() { } void GL45ResourceTexture::demote() { + PROFILE_RANGE(render_gpu_gl, __FUNCTION__); Q_ASSERT(_allocatedMip < _maxAllocatedMip); auto oldId = _id; auto oldSize = _size; @@ -349,6 +398,7 @@ void GL45ResourceTexture::demote() { } void GL45ResourceTexture::populateTransferQueue() { + PROFILE_RANGE(render_gpu_gl, __FUNCTION__); _pendingTransfers = std::queue(); if (_populatedMip <= _allocatedMip) { return; @@ -401,7 +451,7 @@ void GL45ResourceTexture::populateTransferQueue() { // queue up the sampler and populated mip change for after the transfer has completed _pendingTransfers.push([=] { - _populatedMip = targetMip; + _populatedMip = sourceMip; syncSampler(); }); } while (sourceMip != _allocatedMip);