1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-07 03:13:49 +00:00

Allow triple buffering in async copy mode

This commit is contained in:
Logan McNaughton 2018-02-20 23:29:10 -07:00 committed by Sergey Lipskiy
parent 892290b304
commit d2d0e9aafc
9 changed files with 37 additions and 28 deletions

View File

@ -54,7 +54,7 @@ void Config::resetToDefaults()
frameBufferEmulation.copyDepthToRDRAM = cdSoftwareRender; frameBufferEmulation.copyDepthToRDRAM = cdSoftwareRender;
frameBufferEmulation.copyFromRDRAM = 0; frameBufferEmulation.copyFromRDRAM = 0;
frameBufferEmulation.copyAuxToRDRAM = 0; frameBufferEmulation.copyAuxToRDRAM = 0;
frameBufferEmulation.copyToRDRAM = ctAsync; frameBufferEmulation.copyToRDRAM = ctDoubleBuffer;
frameBufferEmulation.N64DepthCompare = 0; frameBufferEmulation.N64DepthCompare = 0;
frameBufferEmulation.aspect = a43; frameBufferEmulation.aspect = a43;
frameBufferEmulation.bufferSwapMode = bsOnVerticalInterrupt; frameBufferEmulation.bufferSwapMode = bsOnVerticalInterrupt;

View File

@ -78,8 +78,9 @@ struct Config
enum CopyToRDRAM { enum CopyToRDRAM {
ctDisable = 0, ctDisable = 0,
ctSync, ctSync = 1,
ctAsync ctDoubleBuffer = 2,
ctTripleBuffer = 3
}; };
enum BufferSwapMode { enum BufferSwapMode {

View File

@ -1,3 +1,4 @@
#include <Config.h>
#include <Graphics/Context.h> #include <Graphics/Context.h>
#include "opengl_ColorBufferReaderWithBufferStorage.h" #include "opengl_ColorBufferReaderWithBufferStorage.h"
@ -18,12 +19,16 @@ ColorBufferReaderWithBufferStorage::~ColorBufferReaderWithBufferStorage()
void ColorBufferReaderWithBufferStorage::_initBuffers() void ColorBufferReaderWithBufferStorage::_initBuffers()
{ {
m_numPBO = config.frameBufferEmulation.copyToRDRAM;
if (m_numPBO > _maxPBO)
m_numPBO = _maxPBO;
// Generate Pixel Buffer Objects // Generate Pixel Buffer Objects
glGenBuffers(_numPBO, m_PBO); glGenBuffers(m_numPBO, m_PBO);
m_curIndex = 0; m_curIndex = 0;
// Initialize Pixel Buffer Objects // Initialize Pixel Buffer Objects
for (int index = 0; index < _numPBO; ++index) { for (int index = 0; index < m_numPBO; ++index) {
m_bindBuffer->bind(Parameter(GL_PIXEL_PACK_BUFFER), ObjectHandle(m_PBO[index])); m_bindBuffer->bind(Parameter(GL_PIXEL_PACK_BUFFER), ObjectHandle(m_PBO[index]));
m_fence[index] = 0; m_fence[index] = 0;
glBufferStorage(GL_PIXEL_PACK_BUFFER, m_pTexture->textureBytes, nullptr, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); glBufferStorage(GL_PIXEL_PACK_BUFFER, m_pTexture->textureBytes, nullptr, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
@ -35,9 +40,9 @@ void ColorBufferReaderWithBufferStorage::_initBuffers()
void ColorBufferReaderWithBufferStorage::_destroyBuffers() void ColorBufferReaderWithBufferStorage::_destroyBuffers()
{ {
glDeleteBuffers(_numPBO, m_PBO); glDeleteBuffers(m_numPBO, m_PBO);
for (int index = 0; index < _numPBO; ++index) { for (int index = 0; index < m_numPBO; ++index) {
m_PBO[index] = 0; m_PBO[index] = 0;
glDeleteSync(m_fence[index]); glDeleteSync(m_fence[index]);
} }
@ -55,7 +60,7 @@ const u8 * ColorBufferReaderWithBufferStorage::_readPixels(const ReadColorBuffer
if (!_params.sync) { if (!_params.sync) {
//Setup a fence sync object so that we know when glReadPixels completes //Setup a fence sync object so that we know when glReadPixels completes
m_fence[m_curIndex] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); m_fence[m_curIndex] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
m_curIndex = (m_curIndex + 1) % _numPBO; m_curIndex = (m_curIndex + 1) % m_numPBO;
//Wait for glReadPixels to complete for the currently selected PBO //Wait for glReadPixels to complete for the currently selected PBO
if (m_fence[m_curIndex] != 0) { if (m_fence[m_curIndex] != 0) {
glClientWaitSync(m_fence[m_curIndex], 0, 100000000); glClientWaitSync(m_fence[m_curIndex], 0, 100000000);

View File

@ -24,11 +24,12 @@ namespace opengl {
CachedBindBuffer * m_bindBuffer; CachedBindBuffer * m_bindBuffer;
static const int _numPBO = 2; static const int _maxPBO = 3;
GLuint m_PBO[_numPBO]; u32 m_numPBO;
void* m_PBOData[_numPBO]; GLuint m_PBO[_maxPBO];
void* m_PBOData[_maxPBO];
u32 m_curIndex; u32 m_curIndex;
GLsync m_fence[_numPBO]; GLsync m_fence[_maxPBO];
}; };
} }

View File

@ -1,3 +1,4 @@
#include <Config.h>
#include <Graphics/Context.h> #include <Graphics/Context.h>
#include "opengl_ColorBufferReaderWithPixelBuffer.h" #include "opengl_ColorBufferReaderWithPixelBuffer.h"
@ -19,20 +20,24 @@ ColorBufferReaderWithPixelBuffer::~ColorBufferReaderWithPixelBuffer()
void ColorBufferReaderWithPixelBuffer::_destroyBuffers() void ColorBufferReaderWithPixelBuffer::_destroyBuffers()
{ {
glDeleteBuffers(_numPBO, m_PBO); glDeleteBuffers(m_numPBO, m_PBO);
for(int index = 0; index < _numPBO; ++index) for(int index = 0; index < m_numPBO; ++index)
m_PBO[index] = 0; m_PBO[index] = 0;
} }
void ColorBufferReaderWithPixelBuffer::_initBuffers() void ColorBufferReaderWithPixelBuffer::_initBuffers()
{ {
m_numPBO = config.frameBufferEmulation.copyToRDRAM;
if (m_numPBO > _maxPBO)
m_numPBO = _maxPBO;
// Generate Pixel Buffer Objects // Generate Pixel Buffer Objects
glGenBuffers(_numPBO, m_PBO); glGenBuffers(m_numPBO, m_PBO);
m_curIndex = 0; m_curIndex = 0;
// Initialize Pixel Buffer Objects // Initialize Pixel Buffer Objects
for (u32 i = 0; i < _numPBO; ++i) { for (u32 i = 0; i < m_numPBO; ++i) {
m_bindBuffer->bind(Parameter(GL_PIXEL_PACK_BUFFER), ObjectHandle(m_PBO[i])); m_bindBuffer->bind(Parameter(GL_PIXEL_PACK_BUFFER), ObjectHandle(m_PBO[i]));
glBufferData(GL_PIXEL_PACK_BUFFER, m_pTexture->textureBytes, nullptr, GL_DYNAMIC_READ); glBufferData(GL_PIXEL_PACK_BUFFER, m_pTexture->textureBytes, nullptr, GL_DYNAMIC_READ);
} }
@ -45,17 +50,13 @@ const u8 * ColorBufferReaderWithPixelBuffer::_readPixels(const ReadColorBufferPa
GLenum format = GLenum(_params.colorFormat); GLenum format = GLenum(_params.colorFormat);
GLenum type = GLenum(_params.colorType); GLenum type = GLenum(_params.colorType);
m_bindBuffer->bind(Parameter(GL_PIXEL_PACK_BUFFER), ObjectHandle(m_PBO[m_curIndex]));
glReadPixels(_params.x0, _params.y0, m_pTexture->realWidth, _params.height, format, type, 0);
// If Sync, read pixels from the buffer, copy them to RDRAM. // If Sync, read pixels from the buffer, copy them to RDRAM.
// If not Sync, read pixels from the buffer, copy pixels from the previous buffer to RDRAM. // If not Sync, read pixels from the buffer, copy pixels from the previous buffer to RDRAM.
if (!_params.sync) { if (!_params.sync) {
m_curIndex ^= 1; m_curIndex = (m_curIndex + 1) % m_numPBO;
const u32 nextIndex = m_curIndex ^ 1;
m_bindBuffer->bind(Parameter(GL_PIXEL_PACK_BUFFER), ObjectHandle(m_PBO[m_curIndex])); m_bindBuffer->bind(Parameter(GL_PIXEL_PACK_BUFFER), ObjectHandle(m_PBO[m_curIndex]));
glReadPixels(_params.x0, _params.y0, m_pTexture->realWidth, _params.height, format, type, 0);
m_bindBuffer->bind(Parameter(GL_PIXEL_PACK_BUFFER), ObjectHandle(m_PBO[nextIndex]));
} else {
m_bindBuffer->bind(Parameter(GL_PIXEL_PACK_BUFFER), ObjectHandle(m_PBO[_numPBO -1]));
glReadPixels(_params.x0, _params.y0, m_pTexture->realWidth, _params.height, format, type, 0);
} }
_heightOffset = 0; _heightOffset = 0;

View File

@ -21,8 +21,9 @@ private:
CachedBindBuffer * m_bindBuffer; CachedBindBuffer * m_bindBuffer;
static const int _numPBO = 3; u32 m_numPBO;
GLuint m_PBO[_numPBO]; static const int _maxPBO = 3;
GLuint m_PBO[_maxPBO];
u32 m_curIndex; u32 m_curIndex;
}; };

View File

@ -305,7 +305,7 @@ graphics::ColorBufferReader * ContextImpl::createColorBufferReader(CachedTexture
return new ColorBufferReaderWithPixelBuffer(_pTexture, m_cachedFunctions->getCachedBindBuffer()); return new ColorBufferReaderWithPixelBuffer(_pTexture, m_cachedFunctions->getCachedBindBuffer());
#if defined(EGL) && defined(OS_ANDROID) #if defined(EGL) && defined(OS_ANDROID)
if(config.frameBufferEmulation.copyToRDRAM == Config::ctAsync) if(config.frameBufferEmulation.copyToRDRAM > Config::ctSync)
return new ColorBufferReaderWithEGLImage(_pTexture, m_cachedFunctions->getCachedBindTexture()); return new ColorBufferReaderWithEGLImage(_pTexture, m_cachedFunctions->getCachedBindTexture());
#endif #endif

View File

@ -79,7 +79,7 @@ void GLInfo::init() {
} }
} }
#ifndef OS_ANDROID #ifndef OS_ANDROID
if (isGLES2 && config.frameBufferEmulation.copyToRDRAM == Config::ctAsync) { if (isGLES2 && config.frameBufferEmulation.copyToRDRAM > Config::ctSync) {
config.frameBufferEmulation.copyToRDRAM = Config::ctDisable; config.frameBufferEmulation.copyToRDRAM = Config::ctDisable;
LOG(LOG_WARNING, "Async color buffer copies are not supported on GLES2\n"); LOG(LOG_WARNING, "Async color buffer copies are not supported on GLES2\n");
} }

View File

@ -108,7 +108,7 @@ bool Config_SetDefault()
assert(res == M64ERR_SUCCESS); assert(res == M64ERR_SUCCESS);
res = ConfigSetDefaultBool(g_configVideoGliden64, "FBInfoReadDepthChunk", config.frameBufferEmulation.fbInfoReadDepthChunk, "Read depth buffer by 4kb chunks (strict follow to FBRead specification)"); res = ConfigSetDefaultBool(g_configVideoGliden64, "FBInfoReadDepthChunk", config.frameBufferEmulation.fbInfoReadDepthChunk, "Read depth buffer by 4kb chunks (strict follow to FBRead specification)");
assert(res == M64ERR_SUCCESS); assert(res == M64ERR_SUCCESS);
res = ConfigSetDefaultInt(g_configVideoGliden64, "EnableCopyColorToRDRAM", config.frameBufferEmulation.copyToRDRAM, "Enable color buffer copy to RDRAM (0=do not copy, 1=copy in sync mode, 2=copy in async mode)"); res = ConfigSetDefaultInt(g_configVideoGliden64, "EnableCopyColorToRDRAM", config.frameBufferEmulation.copyToRDRAM, "Enable color buffer copy to RDRAM (0=do not copy, 1=copy in sync mode, 2=Double Buffer, 3=Triple Buffer)");
assert(res == M64ERR_SUCCESS); assert(res == M64ERR_SUCCESS);
res = ConfigSetDefaultInt(g_configVideoGliden64, "EnableCopyDepthToRDRAM", config.frameBufferEmulation.copyDepthToRDRAM, "Enable depth buffer copy to RDRAM (0=do not copy, 1=copy from video memory, 2=use software render)"); res = ConfigSetDefaultInt(g_configVideoGliden64, "EnableCopyDepthToRDRAM", config.frameBufferEmulation.copyDepthToRDRAM, "Enable depth buffer copy to RDRAM (0=do not copy, 1=copy from video memory, 2=use software render)");
assert(res == M64ERR_SUCCESS); assert(res == M64ERR_SUCCESS);