gsdx-ogl: found_GL_ARB_buffer_storage is now mandatory

This commit is contained in:
Gregory Hainaut 2016-04-07 22:17:22 +02:00
parent 52e3c3516d
commit a62019a3fd
5 changed files with 41 additions and 117 deletions

View File

@ -475,7 +475,7 @@ namespace GLLoader {
// GL4.3 // GL4.3
status &= status_and_override(found_GL_ARB_copy_image, "GL_ARB_copy_image"); status &= status_and_override(found_GL_ARB_copy_image, "GL_ARB_copy_image");
// GL4.4 // GL4.4
status &= status_and_override(found_GL_ARB_buffer_storage,"GL_ARB_buffer_storage"); status &= status_and_override(found_GL_ARB_buffer_storage,"GL_ARB_buffer_storage", true);
status &= status_and_override(found_GL_ARB_clear_texture,"GL_ARB_clear_texture"); status &= status_and_override(found_GL_ARB_clear_texture,"GL_ARB_clear_texture");
// GL4.5 // GL4.5
status &= status_and_override(found_GL_ARB_clip_control, "GL_ARB_clip_control", true); status &= status_and_override(found_GL_ARB_clip_control, "GL_ARB_clip_control", true);

View File

@ -352,7 +352,6 @@ namespace GLLoader {
extern bool found_GL_ARB_gpu_shader5; extern bool found_GL_ARB_gpu_shader5;
extern bool found_GL_ARB_shader_image_load_store; extern bool found_GL_ARB_shader_image_load_store;
extern bool found_GL_ARB_clear_texture; extern bool found_GL_ARB_clear_texture;
extern bool found_GL_ARB_buffer_storage;
extern bool found_GL_ARB_direct_state_access; extern bool found_GL_ARB_direct_state_access;
extern bool found_GL_EXT_texture_filter_anisotropic; extern bool found_GL_EXT_texture_filter_anisotropic;
} }

View File

@ -40,7 +40,6 @@ namespace PboPool {
char* m_map[PBO_POOL_SIZE]; char* m_map[PBO_POOL_SIZE];
uint32 m_current_pbo = 0; uint32 m_current_pbo = 0;
uint32 m_size; uint32 m_size;
bool m_texture_storage;
GLsync m_fence[PBO_POOL_SIZE]; GLsync m_fence[PBO_POOL_SIZE];
const uint32 m_pbo_size = 8*1024*1024; const uint32 m_pbo_size = 8*1024*1024;
@ -62,19 +61,13 @@ namespace PboPool {
// will use DMA CACHED memory as the source for buffer object operations // will use DMA CACHED memory as the source for buffer object operations
void Init() { void Init() {
glGenBuffers(countof(m_pool), m_pool); glGenBuffers(countof(m_pool), m_pool);
m_texture_storage = GLLoader::found_GL_ARB_buffer_storage;
for (size_t i = 0; i < countof(m_pool); i++) { for (size_t i = 0; i < countof(m_pool); i++) {
BindPbo(); BindPbo();
if (m_texture_storage) { glBufferStorage(GL_PIXEL_UNPACK_BUFFER, m_pbo_size, NULL, create_flags);
glBufferStorage(GL_PIXEL_UNPACK_BUFFER, m_pbo_size, NULL, create_flags); m_map[m_current_pbo] = (char*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, m_pbo_size, map_flags);
m_map[m_current_pbo] = (char*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, m_pbo_size, map_flags); m_fence[m_current_pbo] = 0;
m_fence[m_current_pbo] = 0;
} else {
glBufferData(GL_PIXEL_UNPACK_BUFFER, m_pbo_size, NULL, GL_STREAM_COPY);
m_map[m_current_pbo] = NULL;
}
NextPbo(); NextPbo();
} }
@ -89,44 +82,22 @@ namespace PboPool {
fprintf(stderr, "BUG: PBO too small %d but need %d\n", m_pbo_size, m_size); fprintf(stderr, "BUG: PBO too small %d but need %d\n", m_pbo_size, m_size);
} }
if (m_texture_storage) { if (m_offset[m_current_pbo] + m_size >= m_pbo_size) {
if (m_offset[m_current_pbo] + m_size >= m_pbo_size) { //NextPbo(); // For test purpose
//NextPbo(); // For test purpose NextPboWithSync();
NextPboWithSync();
}
// Note: texsubimage will access currently bound buffer
// Pbo ready let's get a pointer
BindPbo();
map = m_map[m_current_pbo] + m_offset[m_current_pbo];
} else {
GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
if (m_offset[m_current_pbo] + m_size >= m_pbo_size) {
NextPbo();
flags &= ~GL_MAP_INVALIDATE_RANGE_BIT;
flags |= GL_MAP_INVALIDATE_BUFFER_BIT;
}
// Pbo ready let's get a pointer
BindPbo();
// Be sure the map is aligned
map = (char*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, m_offset[m_current_pbo], m_size, flags);
} }
// Note: texsubimage will access currently bound buffer
// Pbo ready let's get a pointer
BindPbo();
map = m_map[m_current_pbo] + m_offset[m_current_pbo];
return map; return map;
} }
void Unmap() { void Unmap() {
if (m_texture_storage) { glFlushMappedBufferRange(GL_PIXEL_UNPACK_BUFFER, m_offset[m_current_pbo], m_size);
glFlushMappedBufferRange(GL_PIXEL_UNPACK_BUFFER, m_offset[m_current_pbo], m_size);
} else {
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
}
} }
uptr Offset() { uptr Offset() {
@ -134,18 +105,16 @@ namespace PboPool {
} }
void Destroy() { void Destroy() {
if (m_texture_storage) { for (size_t i = 0; i < countof(m_pool); i++) {
for (size_t i = 0; i < countof(m_pool); i++) { m_map[i] = NULL;
m_map[i] = NULL; m_offset[i] = 0;
m_offset[i] = 0; glDeleteSync(m_fence[i]);
glDeleteSync(m_fence[i]);
// Don't know if we must do it // Don't know if we must do it
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pool[i]); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pool[i]);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
}
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
} }
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glDeleteBuffers(countof(m_pool), m_pool); glDeleteBuffers(countof(m_pool), m_pool);
} }

View File

@ -43,7 +43,6 @@ class GSBufferOGL {
const GLenum m_target; const GLenum m_target;
GLuint m_buffer_name; GLuint m_buffer_name;
uint8* m_buffer_ptr; uint8* m_buffer_ptr;
const bool m_buffer_storage;
GLsync m_fence[5]; GLsync m_fence[5];
public: public:
@ -52,7 +51,6 @@ class GSBufferOGL {
, m_count(0) , m_count(0)
, m_limit(0) , m_limit(0)
, m_target(target) , m_target(target)
, m_buffer_storage(GLLoader::found_GL_ARB_buffer_storage)
{ {
glGenBuffers(1, &m_buffer_name); glGenBuffers(1, &m_buffer_name);
// Opengl works best with 1-4MB buffer. // Opengl works best with 1-4MB buffer.
@ -63,73 +61,37 @@ class GSBufferOGL {
m_fence[i] = 0; m_fence[i] = 0;
} }
if (m_buffer_storage) { // TODO: if we do manually the synchronization, I'm not sure size is important. It worths to investigate it.
// TODO: if we do manually the synchronization, I'm not sure size is important. It worths to investigate it. // => bigger buffer => less sync
// => bigger buffer => less sync bind();
bind(); // coherency will be done by flushing
// coherency will be done by flushing const GLbitfield common_flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT;
const GLbitfield common_flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT; const GLbitfield map_flags = common_flags | GL_MAP_FLUSH_EXPLICIT_BIT;
const GLbitfield map_flags = common_flags | GL_MAP_FLUSH_EXPLICIT_BIT; const GLbitfield create_flags = common_flags | GL_CLIENT_STORAGE_BIT;
const GLbitfield create_flags = common_flags | GL_CLIENT_STORAGE_BIT;
glBufferStorage(m_target, STRIDE * m_limit, NULL, create_flags ); glBufferStorage(m_target, STRIDE * m_limit, NULL, create_flags );
m_buffer_ptr = (uint8*) glMapBufferRange(m_target, 0, STRIDE * m_limit, map_flags); m_buffer_ptr = (uint8*) glMapBufferRange(m_target, 0, STRIDE * m_limit, map_flags);
if (!m_buffer_ptr) { if (!m_buffer_ptr) {
fprintf(stderr, "Failed to map buffer\n"); fprintf(stderr, "Failed to map buffer\n");
throw GSDXError(); throw GSDXError();
}
} else {
m_buffer_ptr = NULL;
} }
} }
~GSBufferOGL() { ~GSBufferOGL() {
if (m_buffer_storage) { for (size_t i = 0; i < 5; i++) {
for (size_t i = 0; i < 5; i++) { glDeleteSync(m_fence[i]);
glDeleteSync(m_fence[i]);
}
// Don't know if we must do it
bind();
glUnmapBuffer(m_target);
} }
// Don't know if we must do it
bind();
glUnmapBuffer(m_target);
glDeleteBuffers(1, &m_buffer_name); glDeleteBuffers(1, &m_buffer_name);
} }
void allocate() { allocate(m_limit); }
void allocate(size_t new_limit)
{
if (!m_buffer_storage) {
m_start = 0;
m_limit = new_limit;
glBufferData(m_target, m_limit * STRIDE, NULL, GL_STREAM_DRAW);
}
}
void bind() void bind()
{ {
glBindBuffer(m_target, m_buffer_name); glBindBuffer(m_target, m_buffer_name);
} }
void subdata_upload(const void* src)
{
// Current GPU buffer is really too small need to allocate a new one
if (m_count > m_limit) {
//fprintf(stderr, "Allocate a new buffer\n %d", STRIDE);
allocate(std::max<int>(m_count * 3 / 2, m_limit));
} else if (m_count > (m_limit - m_start) ) {
//fprintf(stderr, "Orphan the buffer %d\n", STRIDE);
// Not enough left free room. Just go back at the beginning
m_start = 0;
// Orphan the buffer to avoid synchronization
allocate(m_limit);
}
glBufferSubData(m_target, STRIDE * m_start, STRIDE * m_count, src);
}
void map_upload(const void* src) void map_upload(const void* src)
{ {
ASSERT(m_count < m_limit); ASSERT(m_count < m_limit);
@ -207,11 +169,7 @@ class GSBufferOGL {
m_count = count; m_count = count;
if (m_buffer_storage) { map_upload(src);
map_upload(src);
} else {
subdata_upload(src);
}
} }
void EndScene() void EndScene()
@ -267,8 +225,6 @@ public:
m_vb->bind(); m_vb->bind();
m_ib->bind(); m_ib->bind();
m_vb->allocate();
m_ib->allocate();
set_internal_format(layout, layout_nbr); set_internal_format(layout, layout_nbr);
} }

View File

@ -128,7 +128,7 @@ void GSWndGL::PopulateGlFunction()
GL_EXT_LOAD_OPT(glDebugMessageControl); GL_EXT_LOAD_OPT(glDebugMessageControl);
// GL4.4 // GL4.4
GL_EXT_LOAD_OPT(glClearTexImage); GL_EXT_LOAD_OPT(glClearTexImage);
GL_EXT_LOAD_OPT(glBufferStorage); GL_EXT_LOAD(glBufferStorage);
// GL4.5 // GL4.5
GL_EXT_LOAD_OPT(glCreateTextures); GL_EXT_LOAD_OPT(glCreateTextures);