From 6ae54ae27b048ce260d9067b09d08bcbbfdf1a68 Mon Sep 17 00:00:00 2001 From: DH Date: Sun, 26 Jun 2016 21:28:19 +0300 Subject: [PATCH] RSX: Added legacy non-array vertex attributes support (if count of elements > 1) Fixed ps1ght games --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 98 ++++++++++++++---------------- rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp | 19 ++++-- rpcs3/Emu/RSX/GL/vertex_buffer.cpp | 9 +-- rpcs3/Emu/RSX/RSXThread.cpp | 15 ++++- rpcs3/Emu/RSX/RSXThread.h | 1 + rpcs3/Emu/RSX/rsx_methods.cpp | 42 +++++++++++-- rsx_program_decompiler | 2 +- 7 files changed, 112 insertions(+), 74 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 341ebcc1fb..8ee4141f78 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -64,12 +64,6 @@ void GLGSRender::begin() { rsx::thread::begin(); - if (!load_program()) - { - //no program - no drawing - return; - } - init_buffers(); std::chrono::time_point then = std::chrono::system_clock::now(); @@ -207,51 +201,6 @@ void GLGSRender::begin() //NV4097_SET_FLAT_SHADE_OP //NV4097_SET_EDGE_FLAG - u32 clip_plane_control = rsx::method_registers[NV4097_SET_USER_CLIP_PLANE_CONTROL]; - u8 clip_plane_0 = clip_plane_control & 0xf; - u8 clip_plane_1 = (clip_plane_control >> 4) & 0xf; - u8 clip_plane_2 = (clip_plane_control >> 8) & 0xf; - u8 clip_plane_3 = (clip_plane_control >> 12) & 0xf; - u8 clip_plane_4 = (clip_plane_control >> 16) & 0xf; - u8 clip_plane_5 = (clip_plane_control >> 20) & 0xf; - - auto set_clip_plane_control = [&](int index, u8 control) - { - int value = 0; - int location; - if (m_program->uniforms.has_location("uc_m" + std::to_string(index), &location)) - { - switch (control) - { - default: - LOG_ERROR(RSX, "bad clip plane control (0x%x)", control); - - case CELL_GCM_USER_CLIP_PLANE_DISABLE: - value = 0; - break; - - case CELL_GCM_USER_CLIP_PLANE_ENABLE_GE: - value = 1; - break; - - case CELL_GCM_USER_CLIP_PLANE_ENABLE_LT: - value = -1; - break; - } - - __glcheck m_program->uniforms[location] = value; - } - - __glcheck enable(value, GL_CLIP_DISTANCE0 + index); - }; - - set_clip_plane_control(0, clip_plane_0); - set_clip_plane_control(1, clip_plane_1); - set_clip_plane_control(2, clip_plane_2); - set_clip_plane_control(3, clip_plane_3); - set_clip_plane_control(4, clip_plane_4); - set_clip_plane_control(5, clip_plane_5); - __glcheck enable(rsx::method_registers[NV4097_SET_POLY_OFFSET_FILL_ENABLE], GL_POLYGON_OFFSET_FILL); if (__glcheck enable(rsx::method_registers[NV4097_SET_CULL_FACE_ENABLE], GL_CULL_FACE)) @@ -296,12 +245,57 @@ namespace void GLGSRender::end() { - if (!draw_fbo) + if (!draw_fbo || !load_program()) { rsx::thread::end(); return; } + u32 clip_plane_control = rsx::method_registers[NV4097_SET_USER_CLIP_PLANE_CONTROL]; + u8 clip_plane_0 = clip_plane_control & 0xf; + u8 clip_plane_1 = (clip_plane_control >> 4) & 0xf; + u8 clip_plane_2 = (clip_plane_control >> 8) & 0xf; + u8 clip_plane_3 = (clip_plane_control >> 12) & 0xf; + u8 clip_plane_4 = (clip_plane_control >> 16) & 0xf; + u8 clip_plane_5 = (clip_plane_control >> 20) & 0xf; + + auto set_clip_plane_control = [&](int index, u8 control) + { + int value = 0; + int location; + if (m_program->uniforms.has_location("uc_m" + std::to_string(index), &location)) + { + switch (control) + { + default: + LOG_ERROR(RSX, "bad clip plane control (0x%x)", control); + + case CELL_GCM_USER_CLIP_PLANE_DISABLE: + value = 0; + break; + + case CELL_GCM_USER_CLIP_PLANE_ENABLE_GE: + value = 1; + break; + + case CELL_GCM_USER_CLIP_PLANE_ENABLE_LT: + value = -1; + break; + } + + __glcheck m_program->uniforms[location] = value; + } + + __glcheck enable(value, GL_CLIP_DISTANCE0 + index); + }; + + set_clip_plane_control(0, clip_plane_0); + set_clip_plane_control(1, clip_plane_1); + set_clip_plane_control(2, clip_plane_2); + set_clip_plane_control(3, clip_plane_3); + set_clip_plane_control(4, clip_plane_4); + set_clip_plane_control(5, clip_plane_5); + draw_fbo.bind(); m_program->use(); diff --git a/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp b/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp index 042b186080..391ffcd808 100644 --- a/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp +++ b/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp @@ -463,11 +463,22 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, std::string vertex_id; - if (state.is_array & (1 << index)) + if (state.frequency[index] == 1) + { + if (state.divider_op & (1 << index)) + { + vertex_id += "0"; + } + else + { + vertex_id += "gl_VertexID"; + } + } + else { vertex_id = "gl_VertexID"; - if (state.frequency[index] > 1) + if (state.frequency[index]) { if (state.divider_op & (1 << index)) { @@ -481,10 +492,6 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, vertex_id += std::to_string(state.frequency[index]); } } - else - { - vertex_id = "0"; - } prepare += '\t' + attrib_name + " = texelFetch(" + attrib_name + "_buffer, " + vertex_id + ");\n"; } diff --git a/rpcs3/Emu/RSX/GL/vertex_buffer.cpp b/rpcs3/Emu/RSX/GL/vertex_buffer.cpp index a485b0d479..eaa958469a 100644 --- a/rpcs3/Emu/RSX/GL/vertex_buffer.cpp +++ b/rpcs3/Emu/RSX/GL/vertex_buffer.cpp @@ -176,12 +176,10 @@ u32 GLGSRender::set_vertex_buffer() for (u8 index = 0; index < rsx::limits::vertex_count; ++index) { - if (vertex_arrays_info[index].size == 0) + if (vertex_arrays_info[index].size || register_vertex_info[index].size) { - continue; + max_vertex_attrib_size += 16; } - - max_vertex_attrib_size += 16; } if (draw_command == rsx::draw_command::indexed) @@ -292,7 +290,7 @@ u32 GLGSRender::set_vertex_buffer() if (draw_command == rsx::draw_command::array || draw_command == rsx::draw_command::indexed) { u32 verts_allocated = std::max(vertex_draw_count, max_index + 1); - m_attrib_ring_buffer.reserve_and_map(verts_allocated * max_vertex_attrib_size); + __glcheck m_attrib_ring_buffer.reserve_and_map(verts_allocated * max_vertex_attrib_size); for (int index = 0; index < rsx::limits::vertex_count; ++index) { @@ -365,7 +363,6 @@ u32 GLGSRender::set_vertex_buffer() } else if (register_vertex_info[index].size > 0) { - //Untested! auto &vertex_data = register_vertex_data[index]; auto &vertex_info = register_vertex_info[index]; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 189e64402d..067c96c08c 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -342,18 +342,30 @@ namespace rsx void thread::begin() { + draw_inline_vertex_array = false; + inline_vertex_array.clear(); first_count_commands.clear(); + draw_command = rsx::draw_command::none; draw_mode = to_primitive_type(method_registers[NV4097_SET_BEGIN_END]); } void thread::end() { + for (u8 index = 0; index < rsx::limits::vertex_count; ++index) + { + register_vertex_info[index].size = 0; + register_vertex_data[index].clear(); + } + transform_constants.clear(); if (capture_current_frame) { for (const auto &first_count : first_count_commands) + { vertex_draw_count += first_count.second; + } + capture_frame("Draw " + std::to_string(vertex_draw_count)); vertex_draw_count = 0; } @@ -755,8 +767,6 @@ namespace rsx result.state.output_attributes = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK]; result.state.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL]; result.state.divider_op = rsx::method_registers[NV4097_SET_FREQUENCY_DIVIDER_OPERATION]; - - result.state.is_array = 0; result.state.is_int = 0; for (u8 index = 0; index < rsx::limits::vertex_count; ++index) @@ -765,7 +775,6 @@ namespace rsx if (vertex_arrays_info[index].size > 0) { - result.state.is_array |= 1 << index; is_int = is_int_type(vertex_arrays_info[index].type); result.state.frequency[index] = vertex_arrays_info[index].frequency; } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 2ad12d998d..e25a8942f2 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -197,6 +197,7 @@ namespace rsx enum class draw_command { + none, array, inlined_array, indexed, diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index 96e8c224a0..a5d5f95259 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -90,7 +90,7 @@ namespace rsx //find begin of data size_t begin = id + index * element_size_in_words; - size_t position = 0;//entry.size(); + size_t position = entry.size(); entry.resize(position + element_size); memcpy(entry.data() + position, method_registers + begin, element_size); @@ -226,17 +226,47 @@ namespace rsx } }; - force_inline void set_begin_end(thread* rsx, u32 arg) + force_inline void set_begin_end(thread* rsxthr, u32 arg) { if (arg) { - rsx->draw_inline_vertex_array = false; - rsx->inline_vertex_array.clear(); - rsx->begin(); + rsxthr->begin(); return; } - rsx->end(); + u32 max_vertex_count = 0; + + for (u8 index = 0; index < rsx::limits::vertex_count; ++index) + { + auto &vertex_info = rsxthr->register_vertex_info[index]; + + if (vertex_info.size > 0) + { + auto &vertex_data = rsxthr->register_vertex_data[index]; + + u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size); + u32 element_count = vertex_data.size() / element_size; + + vertex_info.frequency = element_count; + rsx::method_registers[NV4097_SET_FREQUENCY_DIVIDER_OPERATION] |= 1 << index; + + if (rsxthr->draw_command == rsx::draw_command::none) + { + max_vertex_count = std::max(max_vertex_count, element_count); + } + } + } + + if (rsxthr->draw_command == rsx::draw_command::none && max_vertex_count) + { + rsxthr->draw_command = rsx::draw_command::array; + rsxthr->first_count_commands.push_back(std::make_pair(0, max_vertex_count)); + } + + if (!rsxthr->first_count_commands.empty()) + { + rsxthr->end(); + } } force_inline void get_report(thread* rsx, u32 arg) diff --git a/rsx_program_decompiler b/rsx_program_decompiler index 9f2d4c3c61..a9e8d5ac4b 160000 --- a/rsx_program_decompiler +++ b/rsx_program_decompiler @@ -1 +1 @@ -Subproject commit 9f2d4c3c61b38d24c166398bd4f9c6d2b2e6fcb9 +Subproject commit a9e8d5ac4b718e247759f97615dde8759b1f0419