mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 16:19:28 +01:00
implement emulate efb format changes on ogl backend
This commit is contained in:
parent
a963c621dc
commit
c6ae08fc39
@ -29,6 +29,12 @@ GLuint FramebufferManager::m_resolvedDepthTexture;
|
|||||||
|
|
||||||
GLuint FramebufferManager::m_xfbFramebuffer;
|
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)
|
FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples)
|
||||||
{
|
{
|
||||||
m_efbFramebuffer = 0;
|
m_efbFramebuffer = 0;
|
||||||
@ -65,10 +71,11 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
|
|||||||
{
|
{
|
||||||
// EFB targets will be textures in non-MSAA mode.
|
// EFB targets will be textures in non-MSAA mode.
|
||||||
|
|
||||||
GLuint glObj[2];
|
GLuint glObj[3];
|
||||||
glGenTextures(2, glObj);
|
glGenTextures(3, glObj);
|
||||||
m_efbColor = glObj[0];
|
m_efbColor = glObj[0];
|
||||||
m_efbDepth = glObj[1];
|
m_efbDepth = glObj[1];
|
||||||
|
m_resolvedColorTexture = glObj[2]; // needed for pixel format convertion
|
||||||
|
|
||||||
glBindTexture(getFbType(), m_efbColor);
|
glBindTexture(getFbType(), m_efbColor);
|
||||||
glTexParameteri(getFbType(), GL_TEXTURE_MAX_LEVEL, 0);
|
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);
|
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);
|
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.
|
// Bind target textures to the EFB framebuffer.
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer);
|
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);
|
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||||
glClearDepthf(1.0f);
|
glClearDepthf(1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
|
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()
|
FramebufferManager::~FramebufferManager()
|
||||||
@ -195,6 +260,12 @@ FramebufferManager::~FramebufferManager()
|
|||||||
glDeleteRenderbuffers(2, glObj);
|
glDeleteRenderbuffers(2, glObj);
|
||||||
m_efbColor = 0;
|
m_efbColor = 0;
|
||||||
m_efbDepth = 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)
|
GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
|
||||||
@ -286,6 +357,49 @@ GLuint FramebufferManager::ResolveAndGetDepthTarget(const EFBRectangle &source_r
|
|||||||
return GetEFBDepthTexture(source_rect);
|
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()
|
XFBSource::~XFBSource()
|
||||||
{
|
{
|
||||||
glDeleteRenderbuffers(1, &renderbuf);
|
glDeleteRenderbuffers(1, &renderbuf);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "GLUtil.h"
|
#include "GLUtil.h"
|
||||||
#include "FramebufferManagerBase.h"
|
#include "FramebufferManagerBase.h"
|
||||||
|
#include "ProgramShaderCache.h"
|
||||||
#include "Render.h"
|
#include "Render.h"
|
||||||
|
|
||||||
// On the GameCube, the game sends a request for the graphics processor to
|
// 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.
|
// After calling this, before you render anything else, you MUST bind the framebuffer you want to draw to.
|
||||||
static GLuint ResolveAndGetDepthTarget(const EFBRectangle &rect);
|
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:
|
private:
|
||||||
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
|
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
|
||||||
void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc);
|
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_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
|
||||||
static GLuint m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
|
static GLuint m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
|
||||||
|
|
||||||
// Only used in MSAA mode.
|
// Only used in MSAA mode and to convert pixel format
|
||||||
static GLuint m_resolvedFramebuffer;
|
static GLuint m_resolvedFramebuffer; // will be hot swapped with m_efbColor on non-msaa pixel format change
|
||||||
static GLuint m_resolvedColorTexture;
|
static GLuint m_resolvedColorTexture;
|
||||||
static GLuint m_resolvedDepthTexture;
|
static GLuint m_resolvedDepthTexture;
|
||||||
|
|
||||||
static GLuint m_xfbFramebuffer; // Only used in MSAA mode
|
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
|
} // namespace OGL
|
||||||
|
@ -547,13 +547,6 @@ Renderer::Renderer()
|
|||||||
// options while running
|
// options while running
|
||||||
g_Config.bRunning = true;
|
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)
|
if (GL_REPORT_ERROR() != GL_NO_ERROR)
|
||||||
bSuccess = false;
|
bSuccess = false;
|
||||||
|
|
||||||
@ -601,12 +594,12 @@ Renderer::~Renderer()
|
|||||||
if (scrshotThread.joinable())
|
if (scrshotThread.joinable())
|
||||||
scrshotThread.join();
|
scrshotThread.join();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
delete g_framebuffer_manager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::Shutdown()
|
void Renderer::Shutdown()
|
||||||
{
|
{
|
||||||
|
delete g_framebuffer_manager;
|
||||||
|
|
||||||
g_Config.bRunning = false;
|
g_Config.bRunning = false;
|
||||||
UpdateActiveConfig();
|
UpdateActiveConfig();
|
||||||
|
|
||||||
@ -621,6 +614,10 @@ void Renderer::Shutdown()
|
|||||||
|
|
||||||
void Renderer::Init()
|
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();
|
s_pfont = new RasterFont();
|
||||||
|
|
||||||
ProgramShaderCache::CompileShader(s_ShowEFBCopyRegions,
|
ProgramShaderCache::CompileShader(s_ShowEFBCopyRegions,
|
||||||
@ -1123,7 +1120,14 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE
|
|||||||
|
|
||||||
void Renderer::ReinterpretPixelData(unsigned int convtype)
|
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)
|
void Renderer::SetBlendMode(bool forceUpdate)
|
||||||
|
@ -130,7 +130,7 @@ void InitBackendInfo()
|
|||||||
g_Config.backend_info.bUseMinimalMipCount = false;
|
g_Config.backend_info.bUseMinimalMipCount = false;
|
||||||
g_Config.backend_info.bSupports3DVision = 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.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.bSupportsPixelLighting = true;
|
||||||
//g_Config.backend_info.bSupportsEarlyZ = true; // is gpu dependent and must be set in renderer
|
//g_Config.backend_info.bSupportsEarlyZ = true; // is gpu dependent and must be set in renderer
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user