Fixing transfer logic, adding stats display & profile ranges

This commit is contained in:
Brad Davis 2017-02-10 10:56:01 -08:00
parent 283ff01038
commit 35a6359d59
6 changed files with 72 additions and 24 deletions

View file

@ -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";

View file

@ -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());

View file

@ -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();

View file

@ -103,11 +103,13 @@ public:
};
using WorkQueue = std::priority_queue<QueuePair, std::vector<QueuePair>, QueuePairLess>;
static MemoryPressureState _memoryPressureState;
protected:
static std::atomic<bool> _memoryPressureStateStale;
static MemoryPressureState _memoryPressureState;
static std::list<TextureWeakPointer> _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();

View file

@ -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);
}

View file

@ -36,7 +36,9 @@ std::list<TextureWeakPointer> GL45VariableAllocationTexture::_memoryManagedTextu
MemoryPressureState GL45VariableAllocationTexture::_memoryPressureState = MemoryPressureState::Idle;
std::atomic<bool> 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<PromoteLambda>();
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);