// Perf impact (test was only done on a gs dump): // Normal (fast): Message:Buffer detailed info: Buffer object 9 (bound to // GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_STREAM_COPY) will use VIDEO // memory as the source for buffer object operations. // // Persistent (slower): Message:Buffer detailed info: Buffer object 8 // (bound to GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_DYNAMIC_DRAW) // will use DMA CACHED memory as the source for buffer object operations void Init() { glGenBuffers(countof(m_pool), m_pool); for (size_t i = 0; i < countof(m_pool); i++) { BindPbo(); 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_fence[m_current_pbo] = 0; NextPbo(); } UnbindPbo(); }
void NextPboWithSync() { m_fence[m_current_pbo] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); NextPbo(); if (m_fence[m_current_pbo]) { #ifdef ENABLE_OGL_DEBUG_FENCE GLenum status = glClientWaitSync(m_fence[m_current_pbo], GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED); #else glClientWaitSync(m_fence[m_current_pbo], GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED); #endif glDeleteSync(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 } }
// Perf impact (test was only done on a gs dump): // Normal (fast): Message:Buffer detailed info: Buffer object 9 (bound to // GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_STREAM_COPY) will use VIDEO // memory as the source for buffer object operations. // // Persistent (slower): Message:Buffer detailed info: Buffer object 8 // (bound to GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_DYNAMIC_DRAW) // will use DMA CACHED memory as the source for buffer object operations void Init() { 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++) { BindPbo(); if (m_texture_storage) { 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_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(); } UnbindPbo(); }
char* Map(uint32 size) { char* map; m_size = size; if (m_size > m_pbo_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) { //NextPbo(); // For test purpose 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); } return map; }
// Perf impact (test was only done on a gs dump): // Normal (fast): Message:Buffer detailed info: Buffer object 9 (bound to // GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_STREAM_COPY) will use VIDEO // memory as the source for buffer object operations. // // Persistent (slower): Message:Buffer detailed info: Buffer object 8 // (bound to GL_PIXEL_UNPACK_BUFFER_ARB, usage hint is GL_DYNAMIC_DRAW) // will use DMA CACHED memory as the source for buffer object operations void Init() { glGenBuffers(countof(m_pool), m_pool); m_texture_storage = GLLoader::found_GL_ARB_buffer_storage; // Code is really faster on MT driver. So far only nvidia support it if (!GLLoader::nvidia_buggy_driver) m_texture_storage &= (theApp.GetConfig("ogl_texture_storage", 0) == 1); for (size_t i = 0; i < countof(m_pool); i++) { BindPbo(); if (m_texture_storage) { 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_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(); } UnbindPbo(); }