Skip to content

Commit

Permalink
Use BufferStorage extension for faster glReadPixels.
Browse files Browse the repository at this point in the history
  • Loading branch information
fzurita authored and gonetz committed Nov 24, 2016
1 parent bc00985 commit 313741d
Show file tree
Hide file tree
Showing 20 changed files with 15,078 additions and 12,227 deletions.
3 changes: 3 additions & 0 deletions projects/msvc12/GLideN64.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@
<ItemGroup>
<ClCompile Include="..\..\src\3DMath.cpp" />
<ClCompile Include="..\..\src\BufferCopy\ColorBufferToRDRAM.cpp" />
<ClCompile Include="..\..\src\BufferCopy\ColorBufferToRDRAM_BufferStorageExt.cpp" />
<ClCompile Include="..\..\src\BufferCopy\ColorBufferToRDRAM_GL.cpp" />
<ClCompile Include="..\..\src\BufferCopy\DepthBufferToRDRAM.cpp" />
<ClCompile Include="..\..\src\BufferCopy\RDRAMtoColorBuffer.cpp" />
Expand Down Expand Up @@ -380,6 +381,8 @@
<ItemGroup>
<ClInclude Include="..\..\src\3DMath.h" />
<ClInclude Include="..\..\src\BufferCopy\ColorBufferToRDRAM.h" />
<ClInclude Include="..\..\src\BufferCopy\ColorBufferToRDRAM_BufferStorageExt.h" />
<ClInclude Include="..\..\src\BufferCopy\ColorBufferToRDRAM_GL.h" />
<ClInclude Include="..\..\src\BufferCopy\DepthBufferToRDRAM.h" />
<ClInclude Include="..\..\src\BufferCopy\RDRAMtoColorBuffer.h" />
<ClInclude Include="..\..\src\BufferCopy\WriteToRDRAM.h" />
Expand Down
9 changes: 9 additions & 0 deletions projects/msvc12/GLideN64.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,9 @@
<ClCompile Include="..\..\src\Log.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\BufferCopy\ColorBufferToRDRAM_BufferStorageExt.cpp">
<Filter>Source Files\BufferCopy</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\3DMath.h">
Expand Down Expand Up @@ -454,5 +457,11 @@
<ClInclude Include="..\..\src\common\GLFunctions.h">
<Filter>Header Files\common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\BufferCopy\ColorBufferToRDRAM_BufferStorageExt.h">
<Filter>Header Files\BufferCopy</Filter>
</ClInclude>
<ClInclude Include="..\..\src\BufferCopy\ColorBufferToRDRAM_GL.h">
<Filter>Header Files\BufferCopy</Filter>
</ClInclude>
</ItemGroup>
</Project>
36 changes: 34 additions & 2 deletions src/BufferCopy/ColorBufferToRDRAM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,18 @@

#include <FBOTextureFormats.h>
#include <FrameBuffer.h>
#include <Textures.h>
#include <Config.h>
#include <N64.h>
#include <VI.h>
#include <Log.h>
#include "Log.h"
#ifndef GLES2
#include "ColorBufferToRDRAM_GL.h"
#include "ColorBufferToRDRAM_BufferStorageExt.h"
#elif defined(ANDROID) && defined (GLES2)
#include "ColorBufferToRDRAM_GLES.h"
#else
#include "ColorBufferToRDRAMStub.h"
#endif

ColorBufferToRDRAM::ColorBufferToRDRAM()
: m_FBO(0)
Expand Down Expand Up @@ -264,6 +271,31 @@ void ColorBufferToRDRAM::copyChunkToRDRAM(u32 _address)
_copy(_address, _address + 0x1000, true);
}


ColorBufferToRDRAM & ColorBufferToRDRAM::get()
{
#ifndef GLES2

static bool supportsBufferStorage = OGLVideo::isExtensionSupported("GL_EXT_buffer_storage") ||
OGLVideo::isExtensionSupported("GL_ARB_buffer_storage");

if (supportsBufferStorage) {
static ColorBufferToRDRAM_BufferStorageExt cbCopy;
return cbCopy;
} else {
static ColorBufferToRDRAM_GL cbCopy;
return cbCopy;
}

#elif defined(ANDROID) && defined (GLES2)
static ColorBufferToRDRAM_GLES cbCopy;
return cbCopy;
#else
static ColorBufferToRDRAMStub cbCopy;
return cbCopy;
#endif
}

void copyWhiteToRDRAM(FrameBuffer * _pBuffer)
{
if (_pBuffer->m_size == G_IM_SIZ_32b) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,3 @@ class ColorBufferToRDRAMStub : public ColorBufferToRDRAM
bool _readPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync) override {}
void _cleanUp() override {}
};

ColorBufferToRDRAM & ColorBufferToRDRAM::get()
{
static ColorBufferToRDRAMStub cbCopy;
return cbCopy;
}
104 changes: 104 additions & 0 deletions src/BufferCopy/ColorBufferToRDRAM_BufferStorageExt.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#include <OpenGL.h>
#include <Textures.h>
#include <FBOTextureFormats.h>

#if defined(EGL) || defined(GLESX)
#include <inc/ARB_buffer_storage.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#endif

#include "ColorBufferToRDRAM_BufferStorageExt.h"

ColorBufferToRDRAM_BufferStorageExt::ColorBufferToRDRAM_BufferStorageExt()
: ColorBufferToRDRAM(), m_curIndex(0)
{
#ifdef GLESX
glBufferStorage = (PFNGLBUFFERSTORAGEPROC)eglGetProcAddress("glBufferStorageEXT");
#endif
}

void ColorBufferToRDRAM_BufferStorageExt::_init()
{
// Generate Pixel Buffer Objects
glGenBuffers(_numPBO, m_PBO);
}

void ColorBufferToRDRAM_BufferStorageExt::_destroy()
{
for (int index = 0; index < _numPBO; ++index) {
if (m_PBOData[index] != nullptr) {
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO[index]);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
}
}

glDeleteBuffers(_numPBO, m_PBO);

for (int index = 0; index < _numPBO; ++index) {
m_PBO[index] = 0;
}
}

void ColorBufferToRDRAM_BufferStorageExt::_initBuffers(void)
{
// Initialize Pixel Buffer Objects
for (int index = 0; index < _numPBO; ++index) {
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO[index]);
m_fence[index] = 0;
glBufferStorage(GL_PIXEL_PACK_BUFFER, m_pTexture->textureBytes, nullptr, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT);
m_PBOData[index] = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, m_pTexture->textureBytes, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT );
}

glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}

bool ColorBufferToRDRAM_BufferStorageExt::_readPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync)
{
GLenum colorFormat, colorType, colorFormatBytes;
if (_size > G_IM_SIZ_8b) {
colorFormat = fboFormats.colorFormat;
colorType = fboFormats.colorType;
colorFormatBytes = fboFormats.colorFormatBytes;
} else {
colorFormat = fboFormats.monochromeFormat;
colorType = fboFormats.monochromeType;
colorFormatBytes = fboFormats.monochromeFormatBytes;
}

glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO[m_curIndex]);
glReadPixels(_x0, _y0, m_pTexture->realWidth, _height, colorFormat, colorType, 0);

//Setup a fence sync object so that we know when glReadPixels completes
glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
m_fence[m_curIndex] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);

if (!_sync) {
m_curIndex = (m_curIndex+1)%_numPBO;
}

//Wait for glReadPixels to complete for the currently selected PBO
if (m_fence[m_curIndex] != 0) {
glClientWaitSync(m_fence[m_curIndex], 0, 1e8);
glDeleteSync(m_fence[m_curIndex]);
}

GLubyte* pixelData = reinterpret_cast<GLubyte*>(m_PBOData[m_curIndex]);
if (pixelData == nullptr)
return false;

int widthBytes = _width * colorFormatBytes;
int strideBytes = m_pTexture->realWidth * colorFormatBytes;

GLubyte* pixelDataAlloc = m_pixelData.data();
for (unsigned int lnIndex = 0; lnIndex < _height; ++lnIndex) {
memcpy(pixelDataAlloc + lnIndex*widthBytes, pixelData + (lnIndex*strideBytes), widthBytes);
}

return true;
}

void ColorBufferToRDRAM_BufferStorageExt::_cleanUp()
{
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}
26 changes: 26 additions & 0 deletions src/BufferCopy/ColorBufferToRDRAM_BufferStorageExt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "ColorBufferToRDRAM.h"

#include "inc/ARB_buffer_storage.h"


class ColorBufferToRDRAM_BufferStorageExt : public ColorBufferToRDRAM
{
public:
ColorBufferToRDRAM_BufferStorageExt();
~ColorBufferToRDRAM_BufferStorageExt() = default;

private:
void _init() override;
void _destroy() override;
bool _readPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync) override;
void _cleanUp() override;
void _initBuffers(void) override;
static const int _numPBO = 2;
GLuint m_PBO[_numPBO];
void* m_PBOData[_numPBO];
u32 m_curIndex;
GLsync m_fence[_numPBO];
#ifdef GLESX
PFNGLBUFFERSTORAGEPROC glBufferStorage;
#endif
};
28 changes: 2 additions & 26 deletions src/BufferCopy/ColorBufferToRDRAM_GL.cpp
Original file line number Diff line number Diff line change
@@ -1,30 +1,6 @@
#include "ColorBufferToRDRAM.h"

#include <Textures.h>
#include <FBOTextureFormats.h>

class ColorBufferToRDRAM_GL : public ColorBufferToRDRAM
{
public:
ColorBufferToRDRAM_GL();
~ColorBufferToRDRAM_GL() {};

private:
void _init() override;
void _destroy() override;
bool _readPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync) override;
void _cleanUp() override;
void _initBuffers(void) override;
static const int _numPBO = 3;
GLuint m_PBO[_numPBO];
u32 m_curIndex;
};

ColorBufferToRDRAM & ColorBufferToRDRAM::get()
{
static ColorBufferToRDRAM_GL cbCopy;
return cbCopy;
}
#include "ColorBufferToRDRAM_GL.h"

ColorBufferToRDRAM_GL::ColorBufferToRDRAM_GL()
: ColorBufferToRDRAM()
Expand Down Expand Up @@ -81,7 +57,7 @@ bool ColorBufferToRDRAM_GL::_readPixels(GLint _x0, GLint _y0, GLsizei _width, GL
glReadPixels(_x0, _y0, m_pTexture->realWidth, _height, colorFormat, colorType, 0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO[nextIndex]);
} else {
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO[2]);
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO[_numPBO - 1]);
glReadPixels(_x0, _y0, m_pTexture->realWidth, _height, colorFormat, colorType, 0);
}

Expand Down
21 changes: 21 additions & 0 deletions src/BufferCopy/ColorBufferToRDRAM_GL.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "ColorBufferToRDRAM.h"

#include <Textures.h>
#include <FBOTextureFormats.h>

class ColorBufferToRDRAM_GL : public ColorBufferToRDRAM
{
public:
ColorBufferToRDRAM_GL();
~ColorBufferToRDRAM_GL() {};

private:
void _init() override;
void _destroy() override;
bool _readPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync) override;
void _cleanUp() override;
void _initBuffers(void) override;
static const int _numPBO = 3;
GLuint m_PBO[_numPBO];
u32 m_curIndex;
};
38 changes: 5 additions & 33 deletions src/BufferCopy/ColorBufferToRDRAM_GLES.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <algorithm>
#include "ColorBufferToRDRAM.h"
#include "ColorBufferToRDRAM_GLES.h"

#include <Textures.h>
#include <FBOTextureFormats.h>
Expand All @@ -9,39 +10,10 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>

typedef void (GL_APIENTRY* PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, EGLImageKHR image);
typedef void (GL_APIENTRY* PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, EGLImageKHR image);

using namespace android;

class ColorBufferToRDRAM_GLES : public ColorBufferToRDRAM
{
public:
ColorBufferToRDRAM_GLES();
~ColorBufferToRDRAM_GLES() {};

private:
void _init() override;
void _destroy() override;
bool _readPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync) override;
void _cleanUp() override;
void _initBuffers(void) override;

GraphicBuffer* m_window;
EGLImageKHR m_image;
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC m_glEGLImageTargetTexture2DOES;
};

ColorBufferToRDRAM & ColorBufferToRDRAM::get()
{
static ColorBufferToRDRAM_GLES cbCopy;
return cbCopy;
}

ColorBufferToRDRAM_GLES::ColorBufferToRDRAM_GLES()
: ColorBufferToRDRAM(),
m_window(nullptr),
m_image(0)
ColorBufferToRDRAM_GLES::ColorBufferToRDRAM_GLES()
: ColorBufferToRDRAM(),
m_window(nullptr),
m_image(0)
{
}

Expand Down
33 changes: 33 additions & 0 deletions src/BufferCopy/ColorBufferToRDRAM_GLES.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include <algorithm>
#include "ColorBufferToRDRAM.h"

#include <Textures.h>
#include <FBOTextureFormats.h>

#include <ui/GraphicBuffer.h>
#include <android/native_window.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>

typedef void (GL_APIENTRY* PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, EGLImageKHR image);
typedef void (GL_APIENTRY* PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, EGLImageKHR image);

using namespace android;

class ColorBufferToRDRAM_GLES : public ColorBufferToRDRAM
{
public:
ColorBufferToRDRAM_GLES();
~ColorBufferToRDRAM_GLES() = default;

private:
void _init() override;
void _destroy() override;
bool _readPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync) override;
void _cleanUp() override;
void _initBuffers(void) override;

GraphicBuffer* m_window;
EGLImageKHR m_image;
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC m_glEGLImageTargetTexture2DOES;
};
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,6 @@ if(GLES2)
)
list(APPEND GLideN64_SOURCES
GLES2/GLSLCombiner_gles2.cpp
BufferCopy/ColorBufferToRDRAMStub.cpp
)
SET(OPENGL_LIBRARIES -lGLESv2 -lEGL)
else(GLES2)
Expand All @@ -255,6 +254,7 @@ else(GLES2)
list(APPEND GLideN64_SOURCES
OGL3X/GLSLCombiner_ogl3x.cpp
BufferCopy/ColorBufferToRDRAM_GL.cpp
BufferCopy/ColorBufferToRDRAM_BufferStorageExt.cpp
)
endif(GLES2)

Expand Down
Loading

0 comments on commit 313741d

Please sign in to comment.