GLES: Defrag using deleter off render thread.

Moving it to the render thread was a bit more complex because of
localMemory.  Fixes #10859.
This commit is contained in:
Unknown W. Brackets 2018-04-08 19:00:24 -07:00
parent 330bb8158c
commit 32eb483932
2 changed files with 27 additions and 7 deletions

View File

@ -13,6 +13,11 @@
#define VLOG(...)
#endif
static std::thread::id renderThreadId;
static bool OnRenderThread() {
return std::this_thread::get_id() == renderThreadId;
}
// Runs on the GPU thread.
void GLDeleter::Perform(GLRenderManager *renderManager) {
for (auto pushBuffer : pushBuffers) {
@ -65,6 +70,7 @@ GLRenderManager::~GLRenderManager() {
void GLRenderManager::ThreadStart() {
queueRunner_.CreateDeviceObjects();
threadFrame_ = threadInitFrame_;
renderThreadId = std::this_thread::get_id();
bool mapBuffers = (gl_extensions.bugs & BUG_ANY_MAP_BUFFER_RANGE_SLOW) == 0;
bool hasBufferStorage = gl_extensions.ARB_buffer_storage || gl_extensions.EXT_buffer_storage;
@ -574,7 +580,7 @@ GLPushBuffer::GLPushBuffer(GLRenderManager *render, GLuint target, size_t size)
}
GLPushBuffer::~GLPushBuffer() {
Destroy();
Destroy(true);
}
void GLPushBuffer::Map() {
@ -606,6 +612,8 @@ void GLPushBuffer::Unmap() {
void GLPushBuffer::Flush() {
// Must be called from the render thread.
_dbg_assert_(G3D, OnRenderThread());
buffers_[buf_].flushOffset = offset_;
if (!buffers_[buf_].deviceMemory && writePtr_) {
auto &info = buffers_[buf_];
@ -647,12 +655,18 @@ bool GLPushBuffer::AddBuffer() {
}
// Executed on the render thread!
void GLPushBuffer::Destroy() {
void GLPushBuffer::Destroy(bool onRenderThread) {
for (BufInfo &info : buffers_) {
// This will automatically unmap device memory, if needed.
// NOTE: We immediately delete the buffer, don't go through the deleter, since we're on the render thread.
// render_->DeleteBuffer(info.buffer);
delete info.buffer;
// NOTE: We immediately delete the buffer, don't go through the deleter, if we're on the render thread.
if (onRenderThread) {
_dbg_assert_(G3D, OnRenderThread());
delete info.buffer;
} else {
_dbg_assert_(G3D, !OnRenderThread());
render_->DeleteBuffer(info.buffer);
}
FreeAlignedMemory(info.localMemory);
}
buffers_.clear();
@ -684,6 +698,8 @@ void GLPushBuffer::NextBuffer(size_t minSize) {
}
void GLPushBuffer::Defragment() {
_dbg_assert_(G3D, std::this_thread::get_id() != renderThreadId);
if (buffers_.size() <= 1) {
// Let's take this chance to jetison localMemory we don't need.
for (auto &info : buffers_) {
@ -698,7 +714,7 @@ void GLPushBuffer::Defragment() {
// Okay, we have more than one. Destroy them all and start over with a larger one.
size_t newSize = size_ * buffers_.size();
Destroy();
Destroy(false);
size_ = newSize;
bool res = AddBuffer();
@ -714,6 +730,8 @@ size_t GLPushBuffer::GetTotalSize() const {
}
void GLPushBuffer::MapDevice(GLBufferStrategy strategy) {
_dbg_assert_(G3D, OnRenderThread());
strategy_ = strategy;
if (strategy_ == GLBufferStrategy::SUBDATA) {
return;
@ -746,6 +764,8 @@ void GLPushBuffer::MapDevice(GLBufferStrategy strategy) {
}
void GLPushBuffer::UnmapDevice() {
_dbg_assert_(G3D, OnRenderThread());
for (auto &info : buffers_) {
if (info.deviceMemory) {
// TODO: Technically this can return false?

View File

@ -288,7 +288,7 @@ private:
bool AddBuffer();
void NextBuffer(size_t minSize);
void Defragment();
void Destroy();
void Destroy(bool onRenderThread);
GLRenderManager *render_;
std::vector<BufInfo> buffers_;