Commit 1ce09ace by Jamie Madill Committed by Commit Bot

D3D11: Free buffer staging storage when idle.

Using the same policy as for system memory storage, we release the staging buffer if it has been unmodified for several uses. We could further extend this technique to other storage buffers using a nearly identical policy. We might need to mitigate the cost of iterating over all the storages of all the buffers. BUG=angleproject:516 Change-Id: Ib24ef03cf4184ef6f0c24f83347538df82de5f58 Reviewed-on: https://chromium-review.googlesource.com/387200Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 596018ce
...@@ -254,11 +254,11 @@ Buffer11::Buffer11(Renderer11 *renderer) ...@@ -254,11 +254,11 @@ Buffer11::Buffer11(Renderer11 *renderer)
mRenderer(renderer), mRenderer(renderer),
mSize(0), mSize(0),
mMappedStorage(nullptr), mMappedStorage(nullptr),
mBufferStorages(BUFFER_USAGE_COUNT, nullptr), mBufferStorages({}),
mDeallocThresholds({}),
mIdleness({}),
mConstantBufferStorageAdditionalSize(0), mConstantBufferStorageAdditionalSize(0),
mMaxConstantBufferLruCount(0), mMaxConstantBufferLruCount(0)
mReadUsageCount(0),
mSystemMemoryDeallocThreshold(0)
{ {
} }
...@@ -289,8 +289,6 @@ gl::Error Buffer11::getData(const uint8_t **outData) ...@@ -289,8 +289,6 @@ gl::Error Buffer11::getData(const uint8_t **outData)
SystemMemoryStorage *systemMemoryStorage = nullptr; SystemMemoryStorage *systemMemoryStorage = nullptr;
ANGLE_TRY_RESULT(getSystemMemoryStorage(), systemMemoryStorage); ANGLE_TRY_RESULT(getSystemMemoryStorage(), systemMemoryStorage);
mReadUsageCount = 0;
ASSERT(systemMemoryStorage->getSize() >= mSize); ASSERT(systemMemoryStorage->getSize() >= mSize);
*outData = systemMemoryStorage->getSystemCopy()->data(); *outData = systemMemoryStorage->getSystemCopy()->data();
...@@ -484,50 +482,65 @@ gl::Error Buffer11::markTransformFeedbackUsage() ...@@ -484,50 +482,65 @@ gl::Error Buffer11::markTransformFeedbackUsage()
return gl::NoError(); return gl::NoError();
} }
void Buffer11::updateSystemMemoryDeallocThreshold() void Buffer11::updateDeallocThreshold(BufferUsage usage)
{ {
// The following strategy was tuned on the Oort online benchmark (http://oortonline.gl/) // The following strategy was tuned on the Oort online benchmark (http://oortonline.gl/)
// as well as a custom microbenchmark (IndexConversionPerfTest.Run/index_range_d3d11) // as well as a custom microbenchmark (IndexConversionPerfTest.Run/index_range_d3d11)
// First readback: 8 unmodified uses before we free system memory. // First readback: 8 unmodified uses before we free buffer memory.
// After that, double the threshold each time until we reach the max. // After that, double the threshold each time until we reach the max.
if (mSystemMemoryDeallocThreshold == 0) if (mDeallocThresholds[usage] == 0)
{ {
mSystemMemoryDeallocThreshold = 8; mDeallocThresholds[usage] = 8;
} }
else if (mSystemMemoryDeallocThreshold < std::numeric_limits<unsigned int>::max() / 2u) else if (mDeallocThresholds[usage] < std::numeric_limits<unsigned int>::max() / 2u)
{ {
mSystemMemoryDeallocThreshold *= 2u; mDeallocThresholds[usage] *= 2u;
} }
else else
{ {
mSystemMemoryDeallocThreshold = std::numeric_limits<unsigned int>::max(); mDeallocThresholds[usage] = std::numeric_limits<unsigned int>::max();
} }
} }
gl::Error Buffer11::markBufferUsage() // Free the storage if we decide it isn't being used very often.
gl::Error Buffer11::checkForDeallocation(BufferUsage usage)
{ {
mReadUsageCount++; mIdleness[usage]++;
// Free the system memory storage if we decide it isn't being used very often. BufferStorage *&storage = mBufferStorages[usage];
BufferStorage *&sysMemStorage = mBufferStorages[BUFFER_USAGE_SYSTEM_MEMORY]; if (storage != nullptr && mIdleness[usage] > mDeallocThresholds[usage])
if (sysMemStorage != nullptr && mReadUsageCount > mSystemMemoryDeallocThreshold)
{ {
BufferStorage *latestStorage = nullptr; BufferStorage *latestStorage = nullptr;
ANGLE_TRY_RESULT(getLatestBufferStorage(), latestStorage); ANGLE_TRY_RESULT(getLatestBufferStorage(), latestStorage);
if (latestStorage != sysMemStorage) if (latestStorage != storage)
{ {
SafeDelete(sysMemStorage); SafeDelete(storage);
} }
} }
return gl::NoError(); return gl::NoError();
} }
gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getBuffer(BufferUsage usage) gl::Error Buffer11::markBufferUsage(BufferUsage usage)
{ {
ANGLE_TRY(markBufferUsage()); mIdleness[usage] = 0;
if (usage != BUFFER_USAGE_SYSTEM_MEMORY)
{
ANGLE_TRY(checkForDeallocation(BUFFER_USAGE_SYSTEM_MEMORY));
}
if (usage != BUFFER_USAGE_STAGING)
{
ANGLE_TRY(checkForDeallocation(BUFFER_USAGE_STAGING));
}
return gl::NoError();
}
gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getBuffer(BufferUsage usage)
{
BufferStorage *storage = nullptr; BufferStorage *storage = nullptr;
ANGLE_TRY_RESULT(getBufferStorage(usage), storage); ANGLE_TRY_RESULT(getBufferStorage(usage), storage);
return GetAs<NativeStorage>(storage)->getNativeStorage(); return GetAs<NativeStorage>(storage)->getNativeStorage();
...@@ -540,8 +553,6 @@ gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getEmulatedIndexedBuffer( ...@@ -540,8 +553,6 @@ gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getEmulatedIndexedBuffer(
{ {
ASSERT(indexInfo); ASSERT(indexInfo);
ANGLE_TRY(markBufferUsage());
BufferStorage *untypedStorage = nullptr; BufferStorage *untypedStorage = nullptr;
ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_EMULATED_INDEXED_VERTEX), untypedStorage); ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_EMULATED_INDEXED_VERTEX), untypedStorage);
...@@ -556,8 +567,6 @@ gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getEmulatedIndexedBuffer( ...@@ -556,8 +567,6 @@ gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getEmulatedIndexedBuffer(
gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getConstantBufferRange(GLintptr offset, GLsizeiptr size) gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getConstantBufferRange(GLintptr offset, GLsizeiptr size)
{ {
ANGLE_TRY(markBufferUsage());
BufferStorage *bufferStorage = nullptr; BufferStorage *bufferStorage = nullptr;
if (offset == 0 || mRenderer->getRenderer11DeviceCaps().supportsConstantBufferOffsets) if (offset == 0 || mRenderer->getRenderer11DeviceCaps().supportsConstantBufferOffsets)
...@@ -626,21 +635,20 @@ gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getBufferStorage(BufferUs ...@@ -626,21 +635,20 @@ gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getBufferStorage(BufferUs
} }
ANGLE_TRY(updateBufferStorage(newStorage, 0, mSize)); ANGLE_TRY(updateBufferStorage(newStorage, 0, mSize));
ANGLE_TRY(markBufferUsage(usage));
return newStorage; return newStorage;
} }
Buffer11::BufferStorage *Buffer11::allocateStorage(BufferUsage usage) Buffer11::BufferStorage *Buffer11::allocateStorage(BufferUsage usage)
{ {
updateDeallocThreshold(usage);
switch (usage) switch (usage)
{ {
case BUFFER_USAGE_PIXEL_PACK: case BUFFER_USAGE_PIXEL_PACK:
return new PackStorage(mRenderer); return new PackStorage(mRenderer);
case BUFFER_USAGE_SYSTEM_MEMORY: case BUFFER_USAGE_SYSTEM_MEMORY:
{
updateSystemMemoryDeallocThreshold();
return new SystemMemoryStorage(mRenderer); return new SystemMemoryStorage(mRenderer);
}
case BUFFER_USAGE_EMULATED_INDEXED_VERTEX: case BUFFER_USAGE_EMULATED_INDEXED_VERTEX:
return new EmulatedIndexedStorage(mRenderer); return new EmulatedIndexedStorage(mRenderer);
case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
...@@ -705,6 +713,7 @@ gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getConstantBufferRangeSto ...@@ -705,6 +713,7 @@ gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getConstantBufferRangeSto
} }
ANGLE_TRY(updateBufferStorage(newStorage, offset, size)); ANGLE_TRY(updateBufferStorage(newStorage, offset, size));
ANGLE_TRY(markBufferUsage(BUFFER_USAGE_UNIFORM));
return newStorage; return newStorage;
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#ifndef LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ #ifndef LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
#define LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
#include <array>
#include <map> #include <map>
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
...@@ -100,7 +101,7 @@ class Buffer11 : public BufferD3D ...@@ -100,7 +101,7 @@ class Buffer11 : public BufferD3D
unsigned int lruCount; unsigned int lruCount;
}; };
gl::Error markBufferUsage(); gl::Error markBufferUsage(BufferUsage usage);
gl::ErrorOrResult<NativeStorage *> getStagingStorage(); gl::ErrorOrResult<NativeStorage *> getStagingStorage();
gl::ErrorOrResult<PackStorage *> getPackStorage(); gl::ErrorOrResult<PackStorage *> getPackStorage();
gl::ErrorOrResult<SystemMemoryStorage *> getSystemMemoryStorage(); gl::ErrorOrResult<SystemMemoryStorage *> getSystemMemoryStorage();
...@@ -113,14 +114,21 @@ class Buffer11 : public BufferD3D ...@@ -113,14 +114,21 @@ class Buffer11 : public BufferD3D
GLsizeiptr size); GLsizeiptr size);
BufferStorage *allocateStorage(BufferUsage usage); BufferStorage *allocateStorage(BufferUsage usage);
void updateSystemMemoryDeallocThreshold(); void updateDeallocThreshold(BufferUsage usage);
// Free the storage if we decide it isn't being used very often.
gl::Error checkForDeallocation(BufferUsage usage);
Renderer11 *mRenderer; Renderer11 *mRenderer;
size_t mSize; size_t mSize;
BufferStorage *mMappedStorage; BufferStorage *mMappedStorage;
std::vector<BufferStorage *> mBufferStorages; std::array<BufferStorage *, BUFFER_USAGE_COUNT> mBufferStorages;
// These two arrays are used to track when to free unused storage.
std::array<unsigned int, BUFFER_USAGE_COUNT> mDeallocThresholds;
std::array<unsigned int, BUFFER_USAGE_COUNT> mIdleness;
// Cache of D3D11 constant buffer for specific ranges of buffer data. // Cache of D3D11 constant buffer for specific ranges of buffer data.
// This is used to emulate UBO ranges on 11.0 devices. // This is used to emulate UBO ranges on 11.0 devices.
...@@ -130,9 +138,6 @@ class Buffer11 : public BufferD3D ...@@ -130,9 +138,6 @@ class Buffer11 : public BufferD3D
size_t mConstantBufferStorageAdditionalSize; size_t mConstantBufferStorageAdditionalSize;
unsigned int mMaxConstantBufferLruCount; unsigned int mMaxConstantBufferLruCount;
unsigned int mReadUsageCount;
unsigned int mSystemMemoryDeallocThreshold;
angle::BroadcastChannel mStaticBroadcastChannel; angle::BroadcastChannel mStaticBroadcastChannel;
angle::BroadcastChannel mDirectBroadcastChannel; angle::BroadcastChannel mDirectBroadcastChannel;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment