Skip to content

Commit

Permalink
GL: Use pipeline cache
Browse files Browse the repository at this point in the history
  • Loading branch information
vlj authored and Vincent Lejeune committed May 19, 2015
1 parent 145f411 commit 2a7c65c
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 246 deletions.
21 changes: 15 additions & 6 deletions rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ std::string GLFragmentDecompilerThread::AddConst()
auto data = vm::ptr<u32>::make(m_addr + m_size + 4 * sizeof(u32));

m_offset = 2 * 4 * sizeof(u32);
u32 x = GetData(data[0]);
u32 y = GetData(data[1]);
u32 z = GetData(data[2]);
u32 w = GetData(data[3]);
u32 x = 0;//GetData(data[0]);
u32 y = 0;//GetData(data[1]);
u32 z = 0;//GetData(data[2]);
u32 w = 0;//GetData(data[3]);
return m_parr.AddParam(PARAM_UNIFORM, "vec4", name,
std::string("vec4(") + std::to_string((float&)x) + ", " + std::to_string((float&)y)
+ ", " + std::to_string((float&)z) + ", " + std::to_string((float&)w) + ")");
Expand Down Expand Up @@ -612,7 +612,7 @@ void GLFragmentDecompilerThread::Task()
m_code_level = 1;
m_shader = BuildCode();
main.clear();
m_parr.params.clear();
// m_parr.params.clear();
}

GLFragmentProgram::GLFragmentProgram()
Expand Down Expand Up @@ -672,7 +672,7 @@ void GLFragmentProgram::DecompileAsync(RSXFragmentProgram& prog)

void GLFragmentProgram::Compile()
{
if (id)
if (id)
{
glDeleteShader(id);
}
Expand Down Expand Up @@ -706,6 +706,15 @@ void GLFragmentProgram::Compile()
LOG_NOTICE(RSX, shader.c_str()); // Log the text of the shader that failed to compile
Emu.Pause(); // Pause the emulator, we can't really continue from here
}
for (const GLParamType& PT : parr.params)
{
if (PT.flag != PARAM_UNIFORM) continue;
for (const GLParamItem PI : PT.items)
{
size_t offset = atoi(PI.name.c_str() + 2);
FragmentConstantOffsetCache.push_back(offset);
}
}
}

void GLFragmentProgram::Delete()
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/RSX/GL/GLFragmentProgram.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class GLFragmentProgram
GLParamArray parr;
u32 id;
std::string shader;
std::vector<size_t> FragmentConstantOffsetCache;

/**
* Decompile a fragment shader located in the PS3's Memory. This function operates synchronously.
Expand Down
109 changes: 26 additions & 83 deletions rpcs3/Emu/RSX/GL/GLGSRender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,28 @@ void GLGSRender::InitFragmentData()
return;
}

// Get constant from fragment program
const std::vector<size_t> &fragmentOffset = m_prog_buffer.getFragmentConstantOffsetsCache(m_cur_fragment_prog);
for (size_t offsetInFP : fragmentOffset)
{
auto data = vm::ptr<u32>::make(m_cur_fragment_prog->addr + (u32)offsetInFP);

u32 c0 = (data[0] >> 16 | data[0] << 16);
u32 c1 = (data[1] >> 16 | data[1] << 16);
u32 c2 = (data[2] >> 16 | data[2] << 16);
u32 c3 = (data[3] >> 16 | data[3] << 16);
const std::string name = fmt::Format("fc%u", offsetInFP);
const int l = m_program.GetLocation(name);
checkForGlError("glGetUniformLocation " + name);

float f0 = (float&)c0;
float f1 = (float&)c1;
float f2 = (float&)c2;
float f3 = (float&)c3;
glUniform4f(l, f0, f1, f2, f3);
checkForGlError("glUniform4f " + name + fmt::Format(" %u [%f %f %f %f]", l, f0, f1, f2, f3));
}

for (const RSXTransformConstant& c : m_fragment_constants)
{
u32 id = c.id - m_cur_fragment_prog->offset;
Expand All @@ -1103,6 +1125,7 @@ void GLGSRender::InitFragmentData()
checkForGlError("glUniform4f " + name + fmt::Format(" %u [%f %f %f %f]", l, c.x, c.y, c.z, c.w));
}


//if (m_fragment_constants.GetCount())
// LOG_NOTICE(HLE, "");
}
Expand All @@ -1123,88 +1146,9 @@ bool GLGSRender::LoadProgram()
return false;
}

m_fp_buf_num = m_prog_buffer.SearchFp(*m_cur_fragment_prog, m_fragment_prog);
m_vp_buf_num = m_prog_buffer.SearchVp(*m_cur_vertex_prog, m_vertex_prog);

if (m_fp_buf_num == -1)
{
LOG_WARNING(RSX, "FP not found in buffer!");
m_fragment_prog.Decompile(*m_cur_fragment_prog);
m_fragment_prog.Compile();
checkForGlError("m_fragment_prog.Compile");

// TODO: This shouldn't use current dir
fs::file("./FragmentProgram.txt", o_write | o_create | o_trunc).write(m_fragment_prog.shader.c_str(), m_fragment_prog.shader.size());
}

if (m_vp_buf_num == -1)
{
LOG_WARNING(RSX, "VP not found in buffer!");
m_vertex_prog.Decompile(*m_cur_vertex_prog);
m_vertex_prog.Compile();
checkForGlError("m_vertex_prog.Compile");

// TODO: This shouldn't use current dir
fs::file("./VertexProgram.txt", o_write | o_create | o_trunc).write(m_vertex_prog.shader.c_str(), m_vertex_prog.shader.size());
}

if (m_fp_buf_num != -1 && m_vp_buf_num != -1)
{
m_program.id = m_prog_buffer.GetProg(m_fp_buf_num, m_vp_buf_num);
}

if (m_program.id)
{
// RSX Debugger: Check if this program was modified and update it
if (Ini.GSLogPrograms.GetValue())
{
for (auto& program : m_debug_programs)
{
if (program.id == m_program.id && program.modified)
{
// TODO: This isn't working perfectly. Is there any better/shorter way to update the program
m_vertex_prog.shader = program.vp_shader;
m_fragment_prog.shader = program.fp_shader;
m_vertex_prog.Wait();
m_vertex_prog.Compile();
checkForGlError("m_vertex_prog.Compile");
m_fragment_prog.Wait();
m_fragment_prog.Compile();
checkForGlError("m_fragment_prog.Compile");
glAttachShader(m_program.id, m_vertex_prog.id);
glAttachShader(m_program.id, m_fragment_prog.id);
glLinkProgram(m_program.id);
checkForGlError("glLinkProgram");
glDetachShader(m_program.id, m_vertex_prog.id);
glDetachShader(m_program.id, m_fragment_prog.id);
program.vp_id = m_vertex_prog.id;
program.fp_id = m_fragment_prog.id;
program.modified = false;
}
}
}
m_program.Use();
}
else
{
m_program.Create(m_vertex_prog.id, m_fragment_prog.id);
checkForGlError("m_program.Create");
m_prog_buffer.Add(m_program, m_fragment_prog, *m_cur_fragment_prog, m_vertex_prog, *m_cur_vertex_prog);
checkForGlError("m_prog_buffer.Add");
m_program.Use();

// RSX Debugger
if (Ini.GSLogPrograms.GetValue())
{
RSXDebuggerProgram program;
program.id = m_program.id;
program.vp_id = m_vertex_prog.id;
program.fp_id = m_fragment_prog.id;
program.vp_shader = m_vertex_prog.shader;
program.fp_shader = m_fragment_prog.shader;
m_debug_programs.push_back(program);
}
}
GLProgram *result = m_prog_buffer.getGraphicPipelineState(m_cur_vertex_prog, m_cur_fragment_prog, nullptr, nullptr);
m_program.id = result->id;
m_program.Use();

return true;
}
Expand Down Expand Up @@ -1477,7 +1421,6 @@ void GLGSRender::OnExitThread()
m_fbo.Delete();
m_vbo.Delete();
m_vao.Delete();
m_prog_buffer.Clear();
}

void GLGSRender::OnReset()
Expand Down
15 changes: 9 additions & 6 deletions rpcs3/Emu/RSX/GL/GLGSRender.h
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
#pragma once
#include "Emu/RSX/GSRender.h"
#include "GLBuffers.h"

#define RSX_DEBUG 1


#include "GLProgramBuffer.h"

#pragma comment(lib, "opengl32.lib")

#define RSX_DEBUG 1
#if RSX_DEBUG
#define checkForGlError(sit) if((g_last_gl_error = glGetError()) != GL_NO_ERROR) printGlError(g_last_gl_error, sit)
#else
#define checkForGlError(sit)
#endif

extern GLenum g_last_gl_error;
void printGlError(GLenum err, const char* situation);
void printGlError(GLenum err, const std::string& situation);
u32 LinearToSwizzleAddress(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height, u32 log2_depth);

#if RSX_DEBUG
#define checkForGlError(sit) if((g_last_gl_error = glGetError()) != GL_NO_ERROR) printGlError(g_last_gl_error, sit)
#else
#define checkForGlError(sit)
#endif

class GLTexture
{
Expand Down
4 changes: 3 additions & 1 deletion rpcs3/Emu/RSX/GL/GLProgram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ void GLProgram::Create(const u32 vp, const u32 fp)
Delete();

id = glCreateProgram();

GLuint res = glGetError();
glAttachShader(id, vp);
res = glGetError();
glAttachShader(id, fp);
res = glGetError();

glLinkProgram(id);

Expand Down
131 changes: 1 addition & 130 deletions rpcs3/Emu/RSX/GL/GLProgramBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,133 +2,4 @@
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"

#include "GLProgramBuffer.h"

int GLProgramBuffer::SearchFp(const RSXFragmentProgram& rsx_fp, GLFragmentProgram& gl_fp)
{
for(u32 i=0; i<m_buf.size(); ++i)
{
if(memcmp(&m_buf[i].fp_data[0], vm::get_ptr<void>(rsx_fp.addr), m_buf[i].fp_data.size()) != 0) continue;

gl_fp.id = m_buf[i].fp_id;
gl_fp.shader = m_buf[i].fp_shader.c_str();

return i;
}

return -1;
}

int GLProgramBuffer::SearchVp(const RSXVertexProgram& rsx_vp, GLVertexProgram& gl_vp)
{
for(u32 i=0; i<m_buf.size(); ++i)
{
if(m_buf[i].vp_data.size() != rsx_vp.data.size()) continue;
if(memcmp(m_buf[i].vp_data.data(), rsx_vp.data.data(), rsx_vp.data.size() * 4) != 0) continue;

gl_vp.id = m_buf[i].vp_id;
gl_vp.shader = m_buf[i].vp_shader.c_str();

return i;
}

return -1;
}

bool GLProgramBuffer::CmpVP(const u32 a, const u32 b) const
{
if(m_buf[a].vp_data.size() != m_buf[b].vp_data.size()) return false;
return memcmp(m_buf[a].vp_data.data(), m_buf[b].vp_data.data(), m_buf[a].vp_data.size() * 4) == 0;
}

bool GLProgramBuffer::CmpFP(const u32 a, const u32 b) const
{
if(m_buf[a].fp_data.size() != m_buf[b].fp_data.size()) return false;
return memcmp(m_buf[a].fp_data.data(), m_buf[b].fp_data.data(), m_buf[a].fp_data.size()) == 0;
}

u32 GLProgramBuffer::GetProg(u32 fp, u32 vp) const
{
if(fp == vp)
{
/*
LOG_NOTICE(RSX, "Get program (%d):", fp);
LOG_NOTICE(RSX, "*** prog id = %d", m_buf[fp].prog_id);
LOG_NOTICE(RSX, "*** vp id = %d", m_buf[fp].vp_id);
LOG_NOTICE(RSX, "*** fp id = %d", m_buf[fp].fp_id);
LOG_NOTICE(RSX, "*** vp shader = \n%s", m_buf[fp].vp_shader.wx_str());
LOG_NOTICE(RSX, "*** fp shader = \n%s", m_buf[fp].fp_shader.wx_str());
*/
return m_buf[fp].prog_id;
}

for(u32 i=0; i<m_buf.size(); ++i)
{
if(i == fp || i == vp) continue;

if(CmpVP(vp, i) && CmpFP(fp, i))
{
/*
LOG_NOTICE(RSX, "Get program (%d):", i);
LOG_NOTICE(RSX, "*** prog id = %d", m_buf[i].prog_id);
LOG_NOTICE(RSX, "*** vp id = %d", m_buf[i].vp_id);
LOG_NOTICE(RSX, "*** fp id = %d", m_buf[i].fp_id);
LOG_NOTICE(RSX, "*** vp shader = \n%s", m_buf[i].vp_shader.wx_str());
LOG_NOTICE(RSX, "*** fp shader = \n%s", m_buf[i].fp_shader.wx_str());
*/
return m_buf[i].prog_id;
}
}

return 0;
}

void GLProgramBuffer::Add(GLProgram& prog, GLFragmentProgram& gl_fp, RSXFragmentProgram& rsx_fp, GLVertexProgram& gl_vp, RSXVertexProgram& rsx_vp)
{
GLBufferInfo new_buf;

LOG_NOTICE(RSX, "Add program (%d):", m_buf.size());
LOG_NOTICE(RSX, "*** prog id = %d", prog.id);
LOG_NOTICE(RSX, "*** vp id = %d", gl_vp.id);
LOG_NOTICE(RSX, "*** fp id = %d", gl_fp.id);
LOG_NOTICE(RSX, "*** vp data size = %d", rsx_vp.data.size() * 4);
LOG_NOTICE(RSX, "*** fp data size = %d", rsx_fp.size);

LOG_NOTICE(RSX, "*** vp shader = \n%s", gl_vp.shader.c_str());
LOG_NOTICE(RSX, "*** fp shader = \n%s", gl_fp.shader.c_str());


new_buf.prog_id = prog.id;
new_buf.vp_id = gl_vp.id;
new_buf.fp_id = gl_fp.id;

new_buf.fp_data.insert(new_buf.fp_data.end(), vm::get_ptr<u8>(rsx_fp.addr), vm::get_ptr<u8>(rsx_fp.addr + rsx_fp.size));
new_buf.vp_data = rsx_vp.data;

new_buf.vp_shader = gl_vp.shader;
new_buf.fp_shader = gl_fp.shader;

m_buf.push_back(new_buf);
}

void GLProgramBuffer::Clear()
{
for (u32 i = 0; i < m_buf.size(); ++i)
{
glDetachShader(m_buf[i].prog_id, m_buf[i].fp_id);
glDetachShader(m_buf[i].prog_id, m_buf[i].vp_id);
glDeleteShader(m_buf[i].fp_id);
glDeleteShader(m_buf[i].vp_id);
glDeleteProgram(m_buf[i].prog_id);

m_buf[i].fp_data.clear();
m_buf[i].vp_data.clear();

m_buf[i].vp_shader.clear();
m_buf[i].fp_shader.clear();
}

m_buf.clear();
}
//#include "GLProgramBuffer.h"
Loading

0 comments on commit 2a7c65c

Please sign in to comment.