implement emulate efb format changes on ogl backend

This commit is contained in:
degasus 2013-07-22 15:41:10 +02:00
parent a963c621dc
commit c6ae08fc39
4 changed files with 143 additions and 15 deletions

View File

@ -29,6 +29,12 @@ GLuint FramebufferManager::m_resolvedDepthTexture;
GLuint FramebufferManager::m_xfbFramebuffer;
// reinterpret pixel format
GLuint FramebufferManager::m_pixel_format_vao;
GLuint FramebufferManager::m_pixel_format_vbo;
SHADER FramebufferManager::m_pixel_format_shaders[2];
FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples)
{
m_efbFramebuffer = 0;
@ -65,10 +71,11 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
{
// EFB targets will be textures in non-MSAA mode.
GLuint glObj[2];
glGenTextures(2, glObj);
GLuint glObj[3];
glGenTextures(3, glObj);
m_efbColor = glObj[0];
m_efbDepth = glObj[1];
m_resolvedColorTexture = glObj[2]; // needed for pixel format convertion
glBindTexture(getFbType(), m_efbColor);
glTexParameteri(getFbType(), GL_TEXTURE_MAX_LEVEL, 0);
@ -78,6 +85,10 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
glTexParameteri(getFbType(), GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(getFbType(), 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
glBindTexture(getFbType(), m_resolvedColorTexture);
glTexParameteri(getFbType(), GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(getFbType(), 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
// Bind target textures to the EFB framebuffer.
glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
@ -164,6 +175,60 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
glClearColor(0.f, 0.f, 0.f, 1.f);
glClearDepthf(1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// reinterpret pixel format
glGenBuffers(1, &m_pixel_format_vbo);
glGenVertexArrays(1, &m_pixel_format_vao);
glBindVertexArray(m_pixel_format_vao);
glBindBuffer(GL_ARRAY_BUFFER, m_pixel_format_vbo);
glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*2, NULL);
float vertices[] = {
-1.0, -1.0,
1.0, -1.0,
-1.0, 1.0,
1.0, 1.0,
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
char vs[] =
"ATTRIN vec2 rawpos;\n"
"void main(void) {\n"
" gl_Position = vec4(rawpos,0,1);\n"
"}\n";
char ps_rgba6_to_rgb8[] =
"uniform sampler2DRect samp9;\n"
"COLOROUT(ocol0)\n"
"void main()\n"
"{\n"
" ivec4 src6 = ivec4(round(texture2DRect(samp9, gl_FragCoord.xy) * 63.f));\n"
" ivec4 dst8;\n"
" dst8.r = (src6.r << 2) | (src6.g >> 4);\n"
" dst8.g = ((src6.g & 0xF) << 4) | (src6.b >> 2);\n"
" dst8.b = ((src6.b & 0x3) << 6) | src6.a;\n"
" dst8.a = 255;\n"
" ocol0 = float4(dst8) / 255.f;\n"
"}";
char ps_rgb8_to_rgba6[] =
"uniform sampler2DRect samp9;\n"
"COLOROUT(ocol0)\n"
"void main()\n"
"{\n"
" ivec4 src8 = ivec4(round(texture2DRect(samp9, gl_FragCoord.xy) * 255.f));\n"
" ivec4 dst6;\n"
" dst6.r = src8.r >> 2;\n"
" dst6.g = ((src8.r & 0x3) << 4) | (src8.g >> 4);\n"
" dst6.b = ((src8.g & 0xF) << 2) | (src8.b >> 6);\n"
" dst6.a = src8.b & 0x3F;\n"
" ocol0 = float4(dst6) / 63.f;\n"
"}";
ProgramShaderCache::CompileShader(m_pixel_format_shaders[0], vs, ps_rgb8_to_rgba6);
ProgramShaderCache::CompileShader(m_pixel_format_shaders[1], vs, ps_rgba6_to_rgb8);
}
FramebufferManager::~FramebufferManager()
@ -195,6 +260,12 @@ FramebufferManager::~FramebufferManager()
glDeleteRenderbuffers(2, glObj);
m_efbColor = 0;
m_efbDepth = 0;
// reinterpret pixel format
glDeleteVertexArrays(1, &m_pixel_format_vao);
glDeleteBuffers(1, &m_pixel_format_vbo);
m_pixel_format_shaders[0].Destroy();
m_pixel_format_shaders[1].Destroy();
}
GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
@ -286,6 +357,49 @@ GLuint FramebufferManager::ResolveAndGetDepthTarget(const EFBRectangle &source_r
return GetEFBDepthTexture(source_rect);
}
void FramebufferManager::ReinterpretPixelData(unsigned int convtype)
{
g_renderer->ResetAPIState();
GLuint src_texture = 0;
if(m_msaaSamples > 1)
{
// MSAA mode, so resolve first
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_efbFramebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolvedFramebuffer);
glBlitFramebuffer(
0, 0, m_targetWidth, m_targetHeight,
0, 0, m_targetWidth, m_targetHeight,
GL_COLOR_BUFFER_BIT, GL_NEAREST
);
// Return to EFB.
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_efbFramebuffer);
src_texture = m_resolvedColorTexture;
}
else
{
// non-MSAA mode, so switch textures
src_texture = m_efbColor;
m_efbColor = m_resolvedColorTexture;
m_resolvedColorTexture = src_texture;
// also switch them on fbo
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, getFbType(), m_efbColor, 0);
}
glViewport(0,0, m_targetWidth, m_targetHeight);
glActiveTexture(GL_TEXTURE0 + 9);
glBindTexture(getFbType(), src_texture);
m_pixel_format_shaders[convtype ? 1 : 0].Bind();
glBindVertexArray(m_pixel_format_vao);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
g_renderer->RestoreAPIState();
}
XFBSource::~XFBSource()
{
glDeleteRenderbuffers(1, &renderbuf);

View File

@ -7,6 +7,7 @@
#include "GLUtil.h"
#include "FramebufferManagerBase.h"
#include "ProgramShaderCache.h"
#include "Render.h"
// On the GameCube, the game sends a request for the graphics processor to
@ -96,6 +97,10 @@ public:
// After calling this, before you render anything else, you MUST bind the framebuffer you want to draw to.
static GLuint ResolveAndGetDepthTarget(const EFBRectangle &rect);
// Convert EFB content on pixel format change.
// convtype=0 -> rgb8->rgba6, convtype=2 -> rgba6->rgb8
static void ReinterpretPixelData(unsigned int convtype);
private:
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc);
@ -111,12 +116,17 @@ private:
static GLuint m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
static GLuint m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
// Only used in MSAA mode.
static GLuint m_resolvedFramebuffer;
// Only used in MSAA mode and to convert pixel format
static GLuint m_resolvedFramebuffer; // will be hot swapped with m_efbColor on non-msaa pixel format change
static GLuint m_resolvedColorTexture;
static GLuint m_resolvedDepthTexture;
static GLuint m_xfbFramebuffer; // Only used in MSAA mode
// For pixel format draw
static GLuint m_pixel_format_vbo;
static GLuint m_pixel_format_vao;
static SHADER m_pixel_format_shaders[2];
};
} // namespace OGL

View File

@ -547,13 +547,6 @@ Renderer::Renderer()
// options while running
g_Config.bRunning = true;
if (GL_REPORT_ERROR() != GL_NO_ERROR)
bSuccess = false;
// Initialize the FramebufferManager
g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height,
s_MSAASamples, s_MSAACoverageSamples);
if (GL_REPORT_ERROR() != GL_NO_ERROR)
bSuccess = false;
@ -601,12 +594,12 @@ Renderer::~Renderer()
if (scrshotThread.joinable())
scrshotThread.join();
#endif
delete g_framebuffer_manager;
}
void Renderer::Shutdown()
{
delete g_framebuffer_manager;
g_Config.bRunning = false;
UpdateActiveConfig();
@ -621,6 +614,10 @@ void Renderer::Shutdown()
void Renderer::Init()
{
// Initialize the FramebufferManager
g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height,
s_MSAASamples, s_MSAACoverageSamples);
s_pfont = new RasterFont();
ProgramShaderCache::CompileShader(s_ShowEFBCopyRegions,
@ -1123,7 +1120,14 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE
void Renderer::ReinterpretPixelData(unsigned int convtype)
{
// TODO
if (convtype == 0 || convtype == 2)
{
FramebufferManager::ReinterpretPixelData(convtype);
}
else
{
ERROR_LOG(VIDEO, "Trying to reinterpret pixel data with unsupported conversion type %d", convtype);
}
}
void Renderer::SetBlendMode(bool forceUpdate)

View File

@ -130,7 +130,7 @@ void InitBackendInfo()
g_Config.backend_info.bUseMinimalMipCount = false;
g_Config.backend_info.bSupports3DVision = false;
//g_Config.backend_info.bSupportsDualSourceBlend = true; // is gpu dependent and must be set in renderer
g_Config.backend_info.bSupportsFormatReinterpretation = false;
g_Config.backend_info.bSupportsFormatReinterpretation = true;
g_Config.backend_info.bSupportsPixelLighting = true;
//g_Config.backend_info.bSupportsEarlyZ = true; // is gpu dependent and must be set in renderer