From 2a7c65c0195ceee222dadefaa0443dbb3bd0104e Mon Sep 17 00:00:00 2001 From: vlj Date: Sat, 16 May 2015 01:10:27 +0200 Subject: [PATCH] GL: Use pipeline cache --- rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp | 21 ++-- rpcs3/Emu/RSX/GL/GLFragmentProgram.h | 1 + rpcs3/Emu/RSX/GL/GLGSRender.cpp | 109 +++++--------------- rpcs3/Emu/RSX/GL/GLGSRender.h | 17 ++-- rpcs3/Emu/RSX/GL/GLProgram.cpp | 4 +- rpcs3/Emu/RSX/GL/GLProgramBuffer.cpp | 131 +------------------------ rpcs3/Emu/RSX/GL/GLProgramBuffer.h | 79 +++++++++++---- rpcs3/Emu/RSX/GL/GLVertexProgram.cpp | 2 +- 8 files changed, 115 insertions(+), 249 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp index ae1ea0b308..317ac55aba 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp @@ -105,10 +105,10 @@ std::string GLFragmentDecompilerThread::AddConst() auto data = vm::ptr::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) + ")"); @@ -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() @@ -672,7 +672,7 @@ void GLFragmentProgram::DecompileAsync(RSXFragmentProgram& prog) void GLFragmentProgram::Compile() { - if (id) + if (id) { glDeleteShader(id); } @@ -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() diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.h b/rpcs3/Emu/RSX/GL/GLFragmentProgram.h index aa7acdad9f..3430e85a39 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.h +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.h @@ -65,6 +65,7 @@ public: GLParamArray parr; u32 id; std::string shader; + std::vector FragmentConstantOffsetCache; /** * Decompile a fragment shader located in the PS3's Memory. This function operates synchronously. diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 317613183a..c723cd4e0d 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -1089,6 +1089,28 @@ void GLGSRender::InitFragmentData() return; } + // Get constant from fragment program + const std::vector &fragmentOffset = m_prog_buffer.getFragmentConstantOffsetsCache(m_cur_fragment_prog); + for (size_t offsetInFP : fragmentOffset) + { + auto data = vm::ptr::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; @@ -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, ""); } @@ -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; } @@ -1477,7 +1421,6 @@ void GLGSRender::OnExitThread() m_fbo.Delete(); m_vbo.Delete(); m_vao.Delete(); - m_prog_buffer.Clear(); } void GLGSRender::OnReset() diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 409f9ae124..495f940172 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -1,16 +1,13 @@ #pragma once #include "Emu/RSX/GSRender.h" #include "GLBuffers.h" -#include "GLProgramBuffer.h" - -#pragma comment(lib, "opengl32.lib") #define RSX_DEBUG 1 -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); + +#include "GLProgramBuffer.h" + +#pragma comment(lib, "opengl32.lib") #if RSX_DEBUG #define checkForGlError(sit) if((g_last_gl_error = glGetError()) != GL_NO_ERROR) printGlError(g_last_gl_error, sit) @@ -18,6 +15,12 @@ u32 LinearToSwizzleAddress(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height, #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); + + class GLTexture { u32 m_id; diff --git a/rpcs3/Emu/RSX/GL/GLProgram.cpp b/rpcs3/Emu/RSX/GL/GLProgram.cpp index da5f7e6952..6f03a91043 100644 --- a/rpcs3/Emu/RSX/GL/GLProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLProgram.cpp @@ -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); diff --git a/rpcs3/Emu/RSX/GL/GLProgramBuffer.cpp b/rpcs3/Emu/RSX/GL/GLProgramBuffer.cpp index f3a358940d..3df737bd0c 100644 --- a/rpcs3/Emu/RSX/GL/GLProgramBuffer.cpp +++ b/rpcs3/Emu/RSX/GL/GLProgramBuffer.cpp @@ -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(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(rsx_fp.addr), vm::get_ptr(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" \ No newline at end of file diff --git a/rpcs3/Emu/RSX/GL/GLProgramBuffer.h b/rpcs3/Emu/RSX/GL/GLProgramBuffer.h index 5299313e6f..6e7ff05fd6 100644 --- a/rpcs3/Emu/RSX/GL/GLProgramBuffer.h +++ b/rpcs3/Emu/RSX/GL/GLProgramBuffer.h @@ -1,29 +1,66 @@ #pragma once #include "GLProgram.h" +#include "../Common/ProgramStateCache.h" +#include "Utilities/File.h" -struct GLBufferInfo +struct GLTraits { - u32 prog_id; - u32 fp_id; - u32 vp_id; - std::vector fp_data; - std::vector vp_data; - std::string fp_shader; - std::string vp_shader; + typedef GLVertexProgram VertexProgramData; + typedef GLFragmentProgram FragmentProgramData; + typedef GLProgram PipelineData; + typedef void* PipelineProperties; + typedef void* ExtraData; + + static + void RecompileFragmentProgram(RSXFragmentProgram *RSXFP, FragmentProgramData& fragmentProgramData, size_t ID) + { + fragmentProgramData.Decompile(*RSXFP); + fragmentProgramData.Compile(); + GLuint res = glGetError(); + //checkForGlError("m_fragment_prog.Compile"); + + // TODO: This shouldn't use current dir + fs::file("./FragmentProgram.txt", o_write | o_create | o_trunc).write(fragmentProgramData.shader.c_str(), fragmentProgramData.shader.size()); + } + + static + void RecompileVertexProgram(RSXVertexProgram *RSXVP, VertexProgramData& vertexProgramData, size_t ID) + { + vertexProgramData.Decompile(*RSXVP); + vertexProgramData.Compile(); + GLuint res = glGetError(); + //checkForGlError("m_vertex_prog.Compile"); + + // TODO: This shouldn't use current dir + fs::file("./VertexProgram.txt", o_write | o_create | o_trunc).write(vertexProgramData.shader.c_str(), vertexProgramData.shader.size()); + } + + static + PipelineData *BuildProgram(VertexProgramData &vertexProgramData, FragmentProgramData &fragmentProgramData, const PipelineProperties &pipelineProperties, const ExtraData& extraData) + { + GLProgram *result = new GLProgram(); + result->Create(vertexProgramData.id, fragmentProgramData.id); + GLuint res = glGetError(); + //checkForGlError("m_program.Create"); + result->Use(); + + LOG_NOTICE(RSX, "*** prog id = %d", result->id); + LOG_NOTICE(RSX, "*** vp id = %d", vertexProgramData.id); + LOG_NOTICE(RSX, "*** fp id = %d", fragmentProgramData.id); + + LOG_NOTICE(RSX, "*** vp shader = \n%s", vertexProgramData.shader.c_str()); + LOG_NOTICE(RSX, "*** fp shader = \n%s", fragmentProgramData.shader.c_str()); + + return result; + } + + static + void DeleteProgram(PipelineData *ptr) + { + ptr->Delete(); + } }; -struct GLProgramBuffer +class GLProgramBuffer : public ProgramStateCache { - std::vector m_buf; - - int SearchFp(const RSXFragmentProgram& rsx_fp, GLFragmentProgram& gl_fp); - int SearchVp(const RSXVertexProgram& rsx_vp, GLVertexProgram& gl_vp); - - bool CmpVP(const u32 a, const u32 b) const; - bool CmpFP(const u32 a, const u32 b) const; - - u32 GetProg(u32 fp, u32 vp) const; - - void Add(GLProgram& prog, GLFragmentProgram& gl_fp, RSXFragmentProgram& rsx_fp, GLVertexProgram& gl_vp, RSXVertexProgram& rsx_vp); - void Clear(); }; diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index ecada28746..291fc4d6e7 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -822,7 +822,7 @@ void GLVertexProgram::DecompileAsync(RSXVertexProgram& prog) void GLVertexProgram::Compile() { - if (id) + if (id) { glDeleteShader(id); }