gsdx-ogl: protect PBO with fence

Safer and doesn't impact perf too much.
This commit is contained in:
Gregory Hainaut 2015-05-15 18:32:47 +02:00
parent a5e424512c
commit 6166c95325
3 changed files with 42 additions and 17 deletions

View File

@ -28,6 +28,9 @@
extern uint64 g_real_texture_upload_byte;
#endif
// FIXME find the optimal number of PBO
#define PBO_POOL_SIZE 8
// FIXME OGL4: investigate, only 1 unpack buffer always bound
namespace PboPool {
@ -37,8 +40,9 @@ namespace PboPool {
uint32 m_current_pbo = 0;
uint32 m_size;
bool m_texture_storage;
const uint32 m_pbo_size = 4*1024*1024;
uint8* m_gpu_texture;
GLsync m_fence[PBO_POOL_SIZE];
const uint32 m_pbo_size = 4*1024*1024;
// Option for buffer storage
// XXX: actually does I really need coherent and barrier???
@ -66,6 +70,7 @@ namespace PboPool {
if (m_texture_storage) {
gl_BufferStorage(GL_PIXEL_UNPACK_BUFFER, m_pbo_size, NULL, create_flags);
m_map[m_current_pbo] = (char*)gl_MapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, m_pbo_size, map_flags);
m_fence[m_current_pbo] = 0;
} else {
gl_BufferData(GL_PIXEL_UNPACK_BUFFER, m_pbo_size, NULL, GL_STREAM_COPY);
m_map[m_current_pbo] = NULL;
@ -88,7 +93,8 @@ namespace PboPool {
if (m_texture_storage) {
if (m_offset[m_current_pbo] + m_size >= m_pbo_size) {
NextPbo();
//NextPbo(); // For test purpose
NextPboWithSync();
}
// Note: texsubimage will access currently bound buffer
@ -117,14 +123,6 @@ namespace PboPool {
return map;
}
// Used to unmap the buffer when context was detached.
void UnmapAll() {
for (size_t i = 0; i < countof(m_pool); i++) {
m_map[i] = NULL;
m_offset[m_current_pbo] = 0;
}
}
void Unmap() {
if (m_texture_storage) {
gl_FlushMappedBufferRange(GL_PIXEL_UNPACK_BUFFER, m_offset[m_current_pbo], m_size);
@ -138,8 +136,18 @@ namespace PboPool {
}
void Destroy() {
if (m_texture_storage)
UnmapAll();
if (m_texture_storage) {
for (size_t i = 0; i < countof(m_pool); i++) {
m_map[i] = NULL;
m_offset[i] = 0;
gl_DeleteSync(m_fence[i]);
// Don't know if we must do it
gl_BindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pool[0]);
gl_UnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
}
gl_BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
gl_DeleteBuffers(countof(m_pool), m_pool);
_aligned_free(m_gpu_texture);
@ -155,6 +163,26 @@ namespace PboPool {
m_offset[m_current_pbo] = 0;
}
void NextPboWithSync() {
m_fence[m_current_pbo] = gl_FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
NextPbo();
if (m_fence[m_current_pbo]) {
#ifdef ENABLE_OGL_DEBUG_FENCE
GLenum status = gl_ClientWaitSync(m_fence[m_current_pbo], GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
#else
gl_ClientWaitSync(m_fence[m_current_pbo], GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
#endif
gl_DeleteSync(m_fence[m_current_pbo]);
m_fence[m_current_pbo] = 0;
#ifdef ENABLE_OGL_DEBUG_FENCE
if (status != GL_ALREADY_SIGNALED) {
fprintf(stderr, "GL_PIXEL_UNPACK_BUFFER: Sync Sync! Buffer too small\n");
}
#endif
}
}
void UnbindPbo() {
gl_BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}

View File

@ -23,18 +23,14 @@
#include "GSTexture.h"
// FIXME find the optimal number of PBO
#define PBO_POOL_SIZE 8
namespace PboPool {
void BindPbo();
void UnbindPbo();
void NextPbo();
void NextPboWithSync();
char* Map(uint32 size);
void MapAll();
void Unmap();
void UnmapAll();
uint32 Offset();
void EndTransfer();

View File

@ -89,6 +89,7 @@ class GSBufferOGL {
for (size_t i = 0; i < 5; i++) {
gl_DeleteSync(m_fence[i]);
}
// Don't know if we must do it
bind();
gl_UnmapBuffer(m_target);
}