Merge pull request #2357 from degasus/ogl_efb_poke_merge
ogl: efb poke merge
This commit is contained in:
commit
dad5d8e13d
|
@ -35,6 +35,10 @@ GLuint FramebufferManager::m_resolvedDepthTexture;
|
|||
// reinterpret pixel format
|
||||
SHADER FramebufferManager::m_pixel_format_shaders[2];
|
||||
|
||||
// EFB pokes
|
||||
GLuint FramebufferManager::m_EfbColorPokes_VBO;
|
||||
GLuint FramebufferManager::m_EfbColorPokes_VAO;
|
||||
SHADER FramebufferManager::m_EfbColorPokes;
|
||||
|
||||
FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples)
|
||||
{
|
||||
|
@ -318,6 +322,51 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
|
|||
|
||||
ProgramShaderCache::CompileShader(m_pixel_format_shaders[0], vs, ps_rgb8_to_rgba6.c_str(), (m_EFBLayers > 1) ? gs.c_str() : nullptr);
|
||||
ProgramShaderCache::CompileShader(m_pixel_format_shaders[1], vs, ps_rgba6_to_rgb8.c_str(), (m_EFBLayers > 1) ? gs.c_str() : nullptr);
|
||||
|
||||
ProgramShaderCache::CompileShader(m_EfbColorPokes,
|
||||
StringFromFormat(
|
||||
"in vec2 rawpos;\n"
|
||||
"in vec4 color0;\n"
|
||||
"out vec4 v_c;\n"
|
||||
"void main(void) {\n"
|
||||
" gl_Position = vec4(((rawpos + 0.5) / vec2(640.0, 528.0) * 2.0 - 1.0) * vec2(1.0, -1.0), 0.0, 1.0);\n"
|
||||
" gl_PointSize = %d.0 / 640.0;\n"
|
||||
" v_c = color0;\n"
|
||||
"}\n", m_targetWidth).c_str(),
|
||||
|
||||
StringFromFormat(
|
||||
"in vec4 %s_c;\n"
|
||||
"out vec4 ocol0;\n"
|
||||
"void main(void) {\n"
|
||||
" ocol0 = %s_c.bgra;\n"
|
||||
"}\n", m_EFBLayers > 1 ? "g" : "v", m_EFBLayers > 1 ? "g" : "v").c_str(),
|
||||
|
||||
m_EFBLayers > 1 ? StringFromFormat(
|
||||
"layout(points) in;\n"
|
||||
"layout(points, max_vertices = %d) out;\n"
|
||||
"in vec4 v_c[1];\n"
|
||||
"out vec4 g_c;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" for (int j = 0; j < %d; ++j) {\n"
|
||||
" gl_Layer = j;\n"
|
||||
" gl_Position = gl_in[0].gl_Position;\n"
|
||||
" gl_PointSize = %d.0 / 640.0;\n"
|
||||
" g_c = v_c[0];\n"
|
||||
" EmitVertex();\n"
|
||||
" EndPrimitive();\n"
|
||||
" }\n"
|
||||
"}\n", m_EFBLayers, m_EFBLayers, m_targetWidth).c_str() : nullptr);
|
||||
glGenBuffers(1, &m_EfbColorPokes_VBO);
|
||||
glGenVertexArrays(1, &m_EfbColorPokes_VAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_EfbColorPokes_VBO);
|
||||
glBindVertexArray(m_EfbColorPokes_VAO );
|
||||
glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
|
||||
glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_UNSIGNED_SHORT, 0, sizeof(EfbPokeData), (void*)offsetof(EfbPokeData, x));
|
||||
glEnableVertexAttribArray(SHADER_COLOR0_ATTRIB);
|
||||
glVertexAttribPointer(SHADER_COLOR0_ATTRIB, 4, GL_UNSIGNED_BYTE, 1, sizeof(EfbPokeData), (void*)offsetof(EfbPokeData, data));
|
||||
|
||||
glEnable(GL_PROGRAM_POINT_SIZE);
|
||||
}
|
||||
|
||||
FramebufferManager::~FramebufferManager()
|
||||
|
@ -355,6 +404,13 @@ FramebufferManager::~FramebufferManager()
|
|||
// reinterpret pixel format
|
||||
m_pixel_format_shaders[0].Destroy();
|
||||
m_pixel_format_shaders[1].Destroy();
|
||||
|
||||
// EFB pokes
|
||||
glDeleteBuffers(1, &m_EfbColorPokes_VBO);
|
||||
glDeleteVertexArrays(1, &m_EfbColorPokes_VAO);
|
||||
m_EfbColorPokes_VBO = 0;
|
||||
m_EfbColorPokes_VAO = 0;
|
||||
m_EfbColorPokes.Destroy();
|
||||
}
|
||||
|
||||
GLuint FramebufferManager::GetEFBColorTexture(const EFBRectangle& sourceRc)
|
||||
|
@ -551,4 +607,31 @@ void FramebufferManager::GetTargetSize(unsigned int *width, unsigned int *height
|
|||
*height = m_targetHeight;
|
||||
}
|
||||
|
||||
void FramebufferManager::PokeEFB(EFBAccessType type, const std::vector<EfbPokeData>& data)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case POKE_COLOR:
|
||||
{
|
||||
g_renderer->ResetAPIState();
|
||||
|
||||
glBindVertexArray(m_EfbColorPokes_VAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_EfbColorPokes_VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(EfbPokeData) * data.size(), data.data(), GL_STREAM_DRAW);
|
||||
m_EfbColorPokes.Bind();
|
||||
glViewport(0, 0, m_targetWidth, m_targetHeight);
|
||||
glDrawArrays(GL_POINTS, 0, (GLsizei)data.size());
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
|
||||
// TODO: Could just update the EFB cache with the new value
|
||||
ClearEFBCache();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OGL
|
||||
|
|
|
@ -91,6 +91,8 @@ public:
|
|||
// convtype=0 -> rgb8->rgba6, convtype=2 -> rgba6->rgb8
|
||||
static void ReinterpretPixelData(unsigned int convtype);
|
||||
|
||||
static void PokeEFB(EFBAccessType type, const std::vector<EfbPokeData>& data);
|
||||
|
||||
private:
|
||||
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height, unsigned int layers) override;
|
||||
void GetTargetSize(unsigned int *width, unsigned int *height) override;
|
||||
|
@ -115,6 +117,11 @@ private:
|
|||
|
||||
// For pixel format draw
|
||||
static SHADER m_pixel_format_shaders[2];
|
||||
|
||||
// For EFB pokes
|
||||
static GLuint m_EfbColorPokes_VBO;
|
||||
static GLuint m_EfbColorPokes_VAO;
|
||||
static SHADER m_EfbColorPokes;
|
||||
};
|
||||
|
||||
} // namespace OGL
|
||||
|
|
|
@ -1108,23 +1108,13 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
|||
|
||||
case POKE_COLOR:
|
||||
{
|
||||
ResetAPIState();
|
||||
|
||||
glClearColor(float((poke_data >> 16) & 0xFF) / 255.0f,
|
||||
float((poke_data >> 8) & 0xFF) / 255.0f,
|
||||
float((poke_data >> 0) & 0xFF) / 255.0f,
|
||||
float((poke_data >> 24) & 0xFF) / 255.0f);
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(targetPixelRc.left, targetPixelRc.bottom, targetPixelRc.GetWidth(), targetPixelRc.GetHeight());
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
RestoreAPIState();
|
||||
|
||||
// TODO: Could just update the EFB cache with the new value
|
||||
ClearEFBCache();
|
||||
|
||||
std::vector<EfbPokeData> vector;
|
||||
EfbPokeData d;
|
||||
d.x = x;
|
||||
d.y = y;
|
||||
d.data = poke_data;
|
||||
vector.push_back(d);
|
||||
PokeEFB(type, vector);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1155,6 +1145,22 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Renderer::PokeEFB(EFBAccessType type, const std::vector<EfbPokeData>& data)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case POKE_COLOR:
|
||||
{
|
||||
FramebufferManager::PokeEFB(type, data);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
::Renderer::PokeEFB(type, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u16 Renderer::BBoxRead(int index)
|
||||
{
|
||||
int swapped_index = index;
|
||||
|
|
|
@ -75,6 +75,7 @@ public:
|
|||
void FlipImageData(u8 *data, int w, int h, int pixel_width = 3);
|
||||
|
||||
u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override;
|
||||
void PokeEFB(EFBAccessType type, const std::vector<EfbPokeData>& data) override;
|
||||
|
||||
u16 BBoxRead(int index) override;
|
||||
void BBoxWrite(int index, u16 value) override;
|
||||
|
|
|
@ -20,7 +20,34 @@ void AsyncRequests::PullEventsInternal()
|
|||
|
||||
while (!m_queue.empty())
|
||||
{
|
||||
const Event& e = m_queue.front();
|
||||
Event e = m_queue.front();
|
||||
|
||||
// try to merge as many efb pokes as possible
|
||||
// it's a bit hacky, but some games render a complete frame in this way
|
||||
if ((e.type == Event::EFB_POKE_COLOR || e.type == Event::EFB_POKE_Z))
|
||||
{
|
||||
m_merged_efb_pokes.clear();
|
||||
Event first_event = m_queue.front();
|
||||
EFBAccessType t = first_event.type == Event::EFB_POKE_COLOR ? POKE_COLOR : POKE_Z;
|
||||
|
||||
do
|
||||
{
|
||||
e = m_queue.front();
|
||||
|
||||
EfbPokeData d;
|
||||
d.data = e.efb_poke.data;
|
||||
d.x = e.efb_poke.x;
|
||||
d.y = e.efb_poke.y;
|
||||
m_merged_efb_pokes.push_back(d);
|
||||
|
||||
m_queue.pop();
|
||||
} while(!m_queue.empty() && m_queue.front().type == first_event.type);
|
||||
|
||||
lock.unlock();
|
||||
g_renderer->PokeEFB(t, m_merged_efb_pokes);
|
||||
lock.lock();
|
||||
continue;
|
||||
}
|
||||
|
||||
lock.unlock();
|
||||
HandleEvent(e);
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
struct EfbPokeData;
|
||||
|
||||
class AsyncRequests
|
||||
{
|
||||
public:
|
||||
|
@ -91,4 +93,6 @@ private:
|
|||
bool m_wake_me_up_again;
|
||||
bool m_enable;
|
||||
bool m_passthrough;
|
||||
|
||||
std::vector<EfbPokeData> m_merged_efb_pokes;
|
||||
};
|
||||
|
|
|
@ -599,3 +599,11 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const
|
|||
Core::Callback_VideoCopiedToXFB(XFBWrited || (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB));
|
||||
XFBWrited = false;
|
||||
}
|
||||
|
||||
void Renderer::PokeEFB(EFBAccessType type, const std::vector<EfbPokeData>& data)
|
||||
{
|
||||
for (EfbPokeData poke : data)
|
||||
{
|
||||
AccessEFB(type, poke.x, poke.y, poke.data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,12 @@
|
|||
|
||||
class PostProcessingShaderImplementation;
|
||||
|
||||
struct EfbPokeData
|
||||
{
|
||||
u16 x,y;
|
||||
u32 data;
|
||||
};
|
||||
|
||||
// TODO: Move these out of here.
|
||||
extern int frameCount;
|
||||
extern int OSDChoice;
|
||||
|
@ -104,6 +110,7 @@ public:
|
|||
static void RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbWidth, u32 fbHeight, float Gamma = 1.0f);
|
||||
|
||||
virtual u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) = 0;
|
||||
virtual void PokeEFB(EFBAccessType type, const std::vector<EfbPokeData>& data);
|
||||
|
||||
virtual u16 BBoxRead(int index) = 0;
|
||||
virtual void BBoxWrite(int index, u16 value) = 0;
|
||||
|
|
Loading…
Reference in New Issue