gsdx-ogl: fix read back of render target

Initial code use a PBO to do asynchronous transfer. It is silly because
GSdx doesn't use this free time. So let's use a sync read. Same speed but
no PBO to manage.
This commit is contained in:
Gregory Hainaut 2015-05-01 01:26:44 +02:00
parent de52ce956a
commit c76e66f8d2
2 changed files with 21 additions and 39 deletions

View File

@ -39,6 +39,7 @@ namespace PboPool {
uint32 m_size; uint32 m_size;
bool m_texture_storage; bool m_texture_storage;
const uint32 m_pbo_size = 4*1024*1024; const uint32 m_pbo_size = 4*1024*1024;
uint8* m_gpu_texture;
#ifndef ENABLE_GLES #ifndef ENABLE_GLES
// Option for buffer storage // Option for buffer storage
@ -71,6 +72,8 @@ namespace PboPool {
NextPbo(); NextPbo();
} }
UnbindPbo(); UnbindPbo();
m_gpu_texture = (uint8*)_aligned_malloc(1024 * 1024 * 4, 32);
} }
char* Map(uint32 size) { char* Map(uint32 size) {
@ -138,6 +141,8 @@ namespace PboPool {
if (m_texture_storage) if (m_texture_storage)
UnmapAll(); UnmapAll();
gl_DeleteBuffers(countof(m_pool), m_pool); gl_DeleteBuffers(countof(m_pool), m_pool);
_aligned_free(m_gpu_texture);
} }
void BindPbo() { void BindPbo() {
@ -165,7 +170,7 @@ namespace PboPool {
// glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
GSTextureOGL::GSTextureOGL(int type, int w, int h, int format, GLuint fbo_read) GSTextureOGL::GSTextureOGL(int type, int w, int h, int format, GLuint fbo_read)
: m_pbo_id(0), m_pbo_size(0), m_dirty(false) : m_pbo_size(0), m_dirty(false)
{ {
// m_size.x = w; // m_size.x = w;
// m_size.y = h; // m_size.y = h;
@ -236,16 +241,6 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, int format, GLuint fbo_read)
// Allocate the buffer // Allocate the buffer
switch (m_type) { switch (m_type) {
case GSTexture::Offscreen: case GSTexture::Offscreen:
// Extra buffer to handle various pixel transfer
gl_GenBuffers(1, &m_pbo_id);
// Allocate a pbo with the texture
m_pbo_size = (m_size.x * m_size.y) << m_int_shift;
gl_BindBuffer(GL_PIXEL_PACK_BUFFER, m_pbo_id);
gl_BufferData(GL_PIXEL_PACK_BUFFER, m_pbo_size, NULL, GL_STREAM_READ);
gl_BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
case GSTexture::DepthStencil: case GSTexture::DepthStencil:
case GSTexture::RenderTarget: case GSTexture::RenderTarget:
case GSTexture::Texture: case GSTexture::Texture:
@ -268,7 +263,6 @@ GSTextureOGL::~GSTextureOGL()
GLState::tex_unit[i] = 0; GLState::tex_unit[i] = 0;
} }
gl_DeleteBuffers(1, &m_pbo_id);
glDeleteTextures(1, &m_texture_id); glDeleteTextures(1, &m_texture_id);
} }
@ -364,37 +358,31 @@ bool GSTextureOGL::Map(GSMap& m, const GSVector4i* r)
// LOTS OF CRAP CODE!!!! PLEASE FIX ME !!! // LOTS OF CRAP CODE!!!! PLEASE FIX ME !!!
if (m_type != GSTexture::Offscreen) return false; if (m_type != GSTexture::Offscreen) return false;
// The function allow to modify the texture from the CPU // The fastest way will be to use a PBO to read the data asynchronously. Unfortunately GSdx
// Set m.bits <- pointer to the data // architecture is waiting the data right now.
// Set m.pitch <- size of a row
// I think in opengl we need to copy back the data to the RAM: glReadPixels — read a block of pixels from the frame buffer #if 0
// // Maybe it is as good as the code below. I don't know
// gl_MapBuffer — map a buffer object's data store
// Can be used on GL_PIXEL_UNPACK_BUFFER or GL_TEXTURE_BUFFER gl_GetTextureImage(m_texture_id, GL_TEX_LEVEL_0, m_int_format, m_int_type, 1024*1024*16, PboPool::m_gpu_texture);
#else
// Bind the texture to the read framebuffer to avoid any disturbance // Bind the texture to the read framebuffer to avoid any disturbance
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read); gl_BindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0); gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0);
glReadBuffer(GL_COLOR_ATTACHMENT0); glReadBuffer(GL_COLOR_ATTACHMENT0);
// FIXME It might be possible to only read a subrange of the texture based on r object
// Load the PBO with the data
gl_BindBuffer(GL_PIXEL_PACK_BUFFER, m_pbo_id);
glPixelStorei(GL_PACK_ALIGNMENT, m_int_alignment); glPixelStorei(GL_PACK_ALIGNMENT, m_int_alignment);
glReadPixels(0, 0, m_size.x, m_size.y, m_int_format, m_int_type, 0); glReadPixels(0, 0, m_size.x, m_size.y, m_int_format, m_int_type, PboPool::m_gpu_texture);
m.pitch = m_size.x << m_int_shift;
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, 0); gl_BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
// Give access from the CPU #endif
m.bits = (uint8*) gl_MapBufferRange(GL_PIXEL_PACK_BUFFER, 0, m_pbo_size, GL_MAP_READ_BIT);
if ( m.bits ) { m.bits = PboPool::m_gpu_texture;
return true; m.pitch = m_size.x << m_int_shift;
} else {
fprintf(stderr, "bad mapping of the pbo\n"); return true;
gl_BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
return false;
}
#if 0 #if 0
if(m_texture && m_desc.Usage == D3D11_USAGE_STAGING) if(m_texture && m_desc.Usage == D3D11_USAGE_STAGING)
@ -416,11 +404,6 @@ bool GSTextureOGL::Map(GSMap& m, const GSVector4i* r)
void GSTextureOGL::Unmap() void GSTextureOGL::Unmap()
{ {
if (m_type == GSTexture::Offscreen) {
gl_UnmapBuffer(GL_PIXEL_PACK_BUFFER);
gl_BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}
} }
#ifndef _WINDOWS #ifndef _WINDOWS

View File

@ -46,7 +46,6 @@ class GSTextureOGL : public GSTexture
{ {
private: private:
GLuint m_texture_id; // the texture id GLuint m_texture_id; // the texture id
uint32 m_pbo_id;
int m_pbo_size; int m_pbo_size;
GLuint m_fbo_read; GLuint m_fbo_read;
bool m_dirty; bool m_dirty;