From 4a55ba30672175174523beaad38044a5ebbaf1d2 Mon Sep 17 00:00:00 2001 From: DH Date: Wed, 14 Oct 2015 03:15:23 +0300 Subject: [PATCH 1/2] OpenGL renderer improvements Flush program cache at thread exit Use cached locations --- rpcs3/Emu/RSX/Common/ProgramStateCache.h | 9 ++++++ rpcs3/Emu/RSX/GL/GLGSRender.cpp | 39 ++++++++++++------------ rpcs3/Emu/RSX/GL/GLGSRender.h | 3 +- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/ProgramStateCache.h b/rpcs3/Emu/RSX/Common/ProgramStateCache.h index 3c1f85bae..46513fb62 100644 --- a/rpcs3/Emu/RSX/Common/ProgramStateCache.h +++ b/rpcs3/Emu/RSX/Common/ProgramStateCache.h @@ -290,11 +290,20 @@ private: public: ProgramStateCache() : m_currentShaderId(0) {} ~ProgramStateCache() + { + clear(); + } + + void clear() { for (auto pair : m_cachePSO) BackendTraits::DeleteProgram(pair.second); + m_cachePSO.clear(); + for (auto pair : m_cacheFS) free(pair.first); + + m_cacheFS.clear(); } typename BackendTraits::PipelineData *getGraphicPipelineState( diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index b2e956936..3276ce7e3 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -840,10 +840,10 @@ void GLGSRender::end() return; } - LOG_NOTICE(Log::RSX, "draw()"); + //LOG_NOTICE(Log::RSX, "draw()"); draw_fbo.bind(); - m_program.use(); + m_program->use(); //setup textures for (int i = 0; i < rsx::limits::textures_count; ++i) @@ -852,10 +852,10 @@ void GLGSRender::end() continue; int location; - if (m_program.uniforms.has_location("tex" + std::to_string(i), &location)) + if (m_program->uniforms.has_location("tex" + std::to_string(i), &location)) { __glcheck m_gl_textures[i].init(textures[i]); - __glcheck m_program.uniforms.texture(location, i, gl::texture_view(gl::texture::target::texture2D, m_gl_textures[i].id())); + __glcheck m_program->uniforms.texture(location, i, gl::texture_view(gl::texture::target::texture2D, m_gl_textures[i].id())); } } @@ -997,11 +997,11 @@ void GLGSRender::end() "in_tc4", "in_tc5", "in_tc6", "in_tc7" }; - int location = m_program.attribs.location(reg_table[index]); + int location = m_program->attribs.location(reg_table[index]); if (vertex_info.array) { - __glcheck m_program.attribs[location] = + __glcheck m_program->attribs[location] = (m_vao + vertex_arrays_offsets[index]) .config(gl_types[vertex_info.type], vertex_info.size, gl_normalized[vertex_info.type]); } @@ -1014,10 +1014,10 @@ void GLGSRender::end() case CELL_GCM_VERTEX_F: switch (vertex_info.size) { - case 1: apply_attrib_array(m_program, location, vertex_data); break; - case 2: apply_attrib_array(m_program, location, vertex_data); break; - case 3: apply_attrib_array(m_program, location, vertex_data); break; - case 4: apply_attrib_array(m_program, location, vertex_data); break; + case 1: apply_attrib_array(*m_program, location, vertex_data); break; + case 2: apply_attrib_array(*m_program, location, vertex_data); break; + case 3: apply_attrib_array(*m_program, location, vertex_data); break; + case 4: apply_attrib_array(*m_program, location, vertex_data); break; } break; @@ -1095,11 +1095,13 @@ void GLGSRender::onexit_thread() if (m_vao) m_vao.remove(); + + m_prog_buffer.clear(); } void nv4097_clear_surface(u32 arg, GLGSRender* renderer) { - LOG_NOTICE(Log::RSX, "nv4097_clear_surface(0x%x)", arg); + //LOG_NOTICE(Log::RSX, "nv4097_clear_surface(0x%x)", arg); if ((arg & 0xf3) == 0) { @@ -1214,11 +1216,8 @@ bool GLGSRender::load_program() fragment_program.addr = rsx::get_address(fragment_program.offset, (shader_program & 0x3) - 1); fragment_program.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL]; - gl::glsl::program *result; - __glcheck result = m_prog_buffer.getGraphicPipelineState(&vertex_program, &fragment_program, nullptr, nullptr); - __glcheck result->use(); - - m_program.set_id(result->id()); + __glcheck m_program = m_prog_buffer.getGraphicPipelineState(&vertex_program, &fragment_program, nullptr, nullptr); + __glcheck m_program->use(); #else std::vector vertex_program; @@ -1287,12 +1286,12 @@ bool GLGSRender::load_program() scaleOffsetMat[1][3] = viewport_offset_y * 2.f / viewport_h - 1.f; scaleOffsetMat[2][3] = viewport_offset_z - .5f; - __glcheck m_program.uniforms["scaleOffsetMat"] = scaleOffsetMat; + __glcheck m_program->uniforms["scaleOffsetMat"] = scaleOffsetMat; for (auto &constant : transform_constants) { //LOG_WARNING(RSX, "vc[%u] = (%f, %f, %f, %f)", constant.first, constant.second.r, constant.second.g, constant.second.b, constant.second.a); - __glcheck m_program.uniforms["vc[" + std::to_string(constant.first) + "]"] = constant.second; + __glcheck m_program->uniforms["vc[" + std::to_string(constant.first) + "]"] = constant.second; } for (u32 constant_offset : m_prog_buffer.getFragmentConstantOffsetsCache(&fragment_program)) @@ -1304,7 +1303,7 @@ bool GLGSRender::load_program() u32 c2 = (data[2] >> 16 | data[2] << 16); u32 c3 = (data[3] >> 16 | data[3] << 16); - m_program.uniforms["fc" + std::to_string(constant_offset)] = color4f{ (f32&)c0, (f32&)c1, (f32&)c2, (f32&)c3 }; + m_program->uniforms["fc" + std::to_string(constant_offset)] = color4f{ (f32&)c0, (f32&)c1, (f32&)c2, (f32&)c3 }; } return true; @@ -1714,7 +1713,7 @@ void GLGSRender::write_buffers() void GLGSRender::flip(int buffer) { - LOG_NOTICE(Log::RSX, "flip(%d)", buffer); + //LOG_NOTICE(Log::RSX, "flip(%d)", buffer); u32 buffer_width = gcm_buffers[buffer].width; u32 buffer_height = gcm_buffers[buffer].height; u32 buffer_pitch = gcm_buffers[buffer].pitch; diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index e388598e8..71f0c08ac 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -57,8 +57,7 @@ private: GLTexture m_gl_textures[rsx::limits::textures_count]; GLTexture m_gl_vertex_textures[rsx::limits::vertex_textures_count]; - //TODO: program cache - gl::glsl::program m_program; + gl::glsl::program *m_program; rsx::surface_info m_surface; From a443682aafc82426000ebb3770f9ad942e1b6c27 Mon Sep 17 00:00:00 2001 From: DH Date: Wed, 14 Oct 2015 14:34:55 +0300 Subject: [PATCH 2/2] OpenGL renderer fixes Fixed attributes loading Fixed scale-offset matrix Fixed attribute debug option --- Utilities/File.cpp | 5 ++++ Utilities/File.h | 1 + rpcs3/Emu/RSX/GL/GLGSRender.cpp | 50 ++++++++++++++++++--------------- rpcs3/Emu/RSX/GL/gl_helpers.h | 27 ++++++++++++++++++ rpcs3/Emu/RSX/RSXThread.cpp | 4 --- 5 files changed, 60 insertions(+), 27 deletions(-) diff --git a/Utilities/File.cpp b/Utilities/File.cpp index 8baf514b2..02e61f502 100644 --- a/Utilities/File.cpp +++ b/Utilities/File.cpp @@ -598,6 +598,11 @@ u64 fs::file::write(const void* buffer, u64 count) const #endif } +u64 fs::file::write(const std::string &string) const +{ + return write(string.data(), string.size()); +} + u64 fs::file::seek(s64 offset, fsm seek_mode) const { g_tls_error = fse::ok; diff --git a/Utilities/File.h b/Utilities/File.h index dd21db379..38c7bf414 100644 --- a/Utilities/File.h +++ b/Utilities/File.h @@ -94,6 +94,7 @@ namespace fs u64 read(void* buffer, u64 count) const; u64 write(const void* buffer, u64 count) const; + u64 write(const std::string &string) const; u64 seek(s64 offset, fsm seek_mode = fsm::begin) const; u64 size() const; }; diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 3276ce7e3..a059d6fdb 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -587,11 +587,11 @@ void GLGSRender::begin() __glcheck glDepthMask(rsx::method_registers[NV4097_SET_DEPTH_MASK]); __glcheck glStencilMask(rsx::method_registers[NV4097_SET_STENCIL_MASK]); - int viewport_x = int(rsx::method_registers[NV4097_SET_VIEWPORT_HORIZONTAL] & 0xffff); - int viewport_y = int(rsx::method_registers[NV4097_SET_VIEWPORT_VERTICAL] & 0xffff); - int viewport_w = int(rsx::method_registers[NV4097_SET_VIEWPORT_HORIZONTAL] >> 16); - int viewport_h = int(rsx::method_registers[NV4097_SET_VIEWPORT_VERTICAL] >> 16); - glViewport(viewport_x, viewport_y, viewport_w, viewport_h); + //int viewport_x = int(rsx::method_registers[NV4097_SET_VIEWPORT_HORIZONTAL] & 0xffff); + //int viewport_y = int(rsx::method_registers[NV4097_SET_VIEWPORT_VERTICAL] & 0xffff); + //int viewport_w = int(rsx::method_registers[NV4097_SET_VIEWPORT_HORIZONTAL] >> 16); + //int viewport_h = int(rsx::method_registers[NV4097_SET_VIEWPORT_VERTICAL] >> 16); + //glViewport(viewport_x, viewport_y, viewport_w, viewport_h); //scissor test is always enabled glEnable(GL_SCISSOR_TEST); @@ -672,15 +672,15 @@ void GLGSRender::begin() rsx::method_registers[NV4097_SET_STENCIL_FUNC_MASK]); __glcheck glStencilOp(rsx::method_registers[NV4097_SET_STENCIL_OP_FAIL], rsx::method_registers[NV4097_SET_STENCIL_OP_ZFAIL], rsx::method_registers[NV4097_SET_STENCIL_OP_ZPASS]); + } - if (__glcheck enable(rsx::method_registers[NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE], GL_STENCIL_TEST_TWO_SIDE_EXT)) - { - __glcheck glStencilMaskSeparate(GL_BACK, rsx::method_registers[NV4097_SET_BACK_STENCIL_MASK]); - __glcheck glStencilFuncSeparate(GL_BACK, rsx::method_registers[NV4097_SET_BACK_STENCIL_FUNC], - rsx::method_registers[NV4097_SET_BACK_STENCIL_FUNC_REF], rsx::method_registers[NV4097_SET_BACK_STENCIL_FUNC_MASK]); - __glcheck glStencilOpSeparate(GL_BACK, rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_FAIL], - rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_ZFAIL], rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_ZPASS]); - } + if (__glcheck enable(rsx::method_registers[NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE], GL_STENCIL_TEST_TWO_SIDE_EXT)) + { + __glcheck glStencilMaskSeparate(GL_BACK, rsx::method_registers[NV4097_SET_BACK_STENCIL_MASK]); + __glcheck glStencilFuncSeparate(GL_BACK, rsx::method_registers[NV4097_SET_BACK_STENCIL_FUNC], + rsx::method_registers[NV4097_SET_BACK_STENCIL_FUNC_REF], rsx::method_registers[NV4097_SET_BACK_STENCIL_FUNC_MASK]); + __glcheck glStencilOpSeparate(GL_BACK, rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_FAIL], + rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_ZFAIL], rsx::method_registers[NV4097_SET_BACK_STENCIL_OP_ZPASS]); } __glcheck glShadeModel(rsx::method_registers[NV4097_SET_SHADE_MODE]); @@ -924,7 +924,7 @@ void GLGSRender::end() case CELL_GCM_VERTEX_F: for (u32 j = 0; j < vertex_arrays[index].size(); j += 4) { - dump.write(fmt::Format("%.01f\n", *(float*)&vertex_arrays[index][j])); + dump.write(fmt::format("%.01f\n", *(float*)&vertex_arrays[index][j])); if (!(((j + 4) / 4) % vertex_info.size)) dump.write("\n"); } break; @@ -932,7 +932,7 @@ void GLGSRender::end() case CELL_GCM_VERTEX_SF: for (u32 j = 0; j < vertex_arrays[index].size(); j += 2) { - dump.write(fmt::Format("%.01f\n", *(float*)&vertex_arrays[index][j])); + dump.write(fmt::format("%.01f\n", *(float*)&vertex_arrays[index][j])); if (!(((j + 2) / 2) % vertex_info.size)) dump.write("\n"); } break; @@ -940,7 +940,7 @@ void GLGSRender::end() case CELL_GCM_VERTEX_UB: for (u32 j = 0; j < vertex_arrays[index].size(); ++j) { - dump.write(fmt::Format("%d\n", vertex_arrays[index][j])); + dump.write(fmt::format("%d\n", vertex_arrays[index][j])); if (!((j + 1) % vertex_info.size)) dump.write("\n"); } break; @@ -948,7 +948,7 @@ void GLGSRender::end() case CELL_GCM_VERTEX_S32K: for (u32 j = 0; j < vertex_arrays[index].size(); j += 2) { - dump.write(fmt::Format("%d\n", *(u16*)&vertex_arrays[index][j])); + dump.write(fmt::format("%d\n", *(u16*)&vertex_arrays[index][j])); if (!(((j + 2) / 2) % vertex_info.size)) dump.write("\n"); } break; @@ -958,7 +958,7 @@ void GLGSRender::end() case CELL_GCM_VERTEX_UB256: for (u32 j = 0; j < vertex_arrays[index].size(); ++j) { - dump.write(fmt::Format("%d\n", vertex_arrays[index][j])); + dump.write(fmt::format("%d\n", vertex_arrays[index][j])); if (!((j + 1) % vertex_info.size)) dump.write("\n"); } break; @@ -997,7 +997,11 @@ void GLGSRender::end() "in_tc4", "in_tc5", "in_tc6", "in_tc7" }; - int location = m_program->attribs.location(reg_table[index]); + int location; + + //TODO: use attrib input mask register + if (!m_program->attribs.has_location(reg_table[index], &location)) + continue; if (vertex_info.array) { @@ -1277,13 +1281,13 @@ bool GLGSRender::load_program() glm::mat4 scaleOffsetMat(1.f); //Scale - scaleOffsetMat[0][0] = viewport_scale_x * 2.f / viewport_w; - scaleOffsetMat[1][1] = viewport_scale_y * 2.f / viewport_h; + scaleOffsetMat[0][0] = viewport_scale_x * 2.f / width; + scaleOffsetMat[1][1] = viewport_scale_y * 2.f / height; scaleOffsetMat[2][2] = viewport_scale_z; // Offset - scaleOffsetMat[0][3] = viewport_offset_x * 2.f / viewport_w - 1.f; - scaleOffsetMat[1][3] = viewport_offset_y * 2.f / viewport_h - 1.f; + scaleOffsetMat[0][3] = viewport_offset_x * 2.f / width - 1.f; + scaleOffsetMat[1][3] = viewport_offset_y * 2.f / height - 1.f; scaleOffsetMat[2][3] = viewport_offset_z - .5f; __glcheck m_program->uniforms["scaleOffsetMat"] = scaleOffsetMat; diff --git a/rpcs3/Emu/RSX/GL/gl_helpers.h b/rpcs3/Emu/RSX/GL/gl_helpers.h index 025b636ae..08116fb32 100644 --- a/rpcs3/Emu/RSX/GL/gl_helpers.h +++ b/rpcs3/Emu/RSX/GL/gl_helpers.h @@ -1942,6 +1942,9 @@ namespace gl if (finded != m_locations.end()) { + if (finded->second < 0) + throw not_found_exception(name); + return finded->second; } @@ -1955,6 +1958,30 @@ namespace gl return result; } + bool has_location(const std::string &name, int *location_ = nullptr) + { + auto finded = m_locations.find(name); + + if (finded != m_locations.end()) + { + if (finded->second < 0) + return false; + + *location_ = finded->second; + return true; + } + + int loc = glGetAttribLocation(m_program.id(), name.c_str()); + + m_locations[name] = loc; + + if (loc < 0) + return false; + + *location_ = loc; + return true; + } + attrib_t operator[](GLint location) { return{ m_program.id(), location }; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 66dd14ed0..6524e6274 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -916,10 +916,6 @@ namespace rsx for (auto &vertex_array : vertex_arrays) vertex_array.clear(); - //disable all vertex data - for (auto &vertex_info : vertex_arrays_info) - vertex_info.size = 0; - transform_constants.clear(); }