From 97581d8635cd70a7fae3ca2a4593df00e07abfde Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sat, 9 Jul 2016 17:21:06 +0300 Subject: [PATCH 1/3] gl: Fix primitive type checks --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 2 +- rpcs3/Emu/RSX/GL/gl_helpers.cpp | 22 ++++++++++++++- rpcs3/Emu/RSX/GL/gl_helpers.h | 1 + rpcs3/Emu/RSX/GL/vertex_buffer.cpp | 45 +++++++++++++++++++++++------- 4 files changed, 58 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 92c21af251..4d3024cdeb 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -497,7 +497,7 @@ void GLGSRender::end() throw std::logic_error("bad index array type"); } } - else if (!is_primitive_native(draw_mode)) + else if (!gl::is_primitive_native(draw_mode)) { __glcheck glDrawElements(gl::draw_mode(draw_mode), vertex_draw_count, GL_UNSIGNED_SHORT, (GLvoid *)(std::ptrdiff_t)offset_in_index_buffer); } diff --git a/rpcs3/Emu/RSX/GL/gl_helpers.cpp b/rpcs3/Emu/RSX/GL/gl_helpers.cpp index 926ae5a0ae..a359b59b49 100644 --- a/rpcs3/Emu/RSX/GL/gl_helpers.cpp +++ b/rpcs3/Emu/RSX/GL/gl_helpers.cpp @@ -518,4 +518,24 @@ namespace gl { settings_.apply(*this); } -} \ No newline at end of file + + bool is_primitive_native(rsx::primitive_type in) + { + switch (in) + { + case rsx::primitive_type::points: + case rsx::primitive_type::lines: + case rsx::primitive_type::line_loop: + case rsx::primitive_type::line_strip: + case rsx::primitive_type::triangles: + case rsx::primitive_type::triangle_strip: + case rsx::primitive_type::triangle_fan: + return true; + case rsx::primitive_type::quads: + case rsx::primitive_type::quad_strip: + case rsx::primitive_type::polygon: + return false; + } + throw EXCEPTION("unknown primitive type"); + } +} diff --git a/rpcs3/Emu/RSX/GL/gl_helpers.h b/rpcs3/Emu/RSX/GL/gl_helpers.h index 5faca02438..71f8f7cf55 100644 --- a/rpcs3/Emu/RSX/GL/gl_helpers.h +++ b/rpcs3/Emu/RSX/GL/gl_helpers.h @@ -1509,6 +1509,7 @@ namespace gl }; GLenum draw_mode(rsx::primitive_type in); + bool is_primitive_native(rsx::primitive_type in); enum class indices_type { diff --git a/rpcs3/Emu/RSX/GL/vertex_buffer.cpp b/rpcs3/Emu/RSX/GL/vertex_buffer.cpp index 5da0c2d4e9..4d2d967443 100644 --- a/rpcs3/Emu/RSX/GL/vertex_buffer.cpp +++ b/rpcs3/Emu/RSX/GL/vertex_buffer.cpp @@ -131,7 +131,7 @@ namespace std::tuple get_index_array_for_emulated_non_indexed_draw(const std::vector> &first_count_commands, rsx::primitive_type primitive_mode, gl::ring_buffer &dst) { u32 vertex_draw_count = 0; - assert(!is_primitive_native(primitive_mode)); + assert(!gl::is_primitive_native(primitive_mode)); for (const auto &pair : first_count_commands) { @@ -153,6 +153,32 @@ namespace dst.unmap(); return std::make_tuple(vertex_draw_count, mapping.second); } + + std::tuple upload_index_buffer(void *ptr, rsx::index_array_type type, rsx::primitive_type draw_mode, const std::vector> first_count_commands, u32 initial_vertex_count) + { + u32 min_index, max_index, vertex_draw_count = initial_vertex_count; + + if (gl::is_primitive_native(draw_mode)) + { + if (type == rsx::index_array_type::u16) + std::tie(min_index, max_index) = write_index_array_data_to_buffer_untouched(gsl::span{(u16*)ptr, vertex_draw_count}, first_count_commands); + else + std::tie(min_index, max_index) = write_index_array_data_to_buffer_untouched(gsl::span{(u32*)ptr, vertex_draw_count}, first_count_commands); + + } + else + { + vertex_draw_count = (u32)get_index_count(draw_mode, gsl::narrow(vertex_draw_count)); + + u32 type_size = gsl::narrow(get_index_type_size(type)); + u32 block_sz = vertex_draw_count * type_size; + + gsl::span dst{ reinterpret_cast(ptr), gsl::narrow(block_sz) }; + std::tie(min_index, max_index) = write_index_array_data_to_buffer(dst, type, draw_mode, first_count_commands); + } + + return std::make_tuple(min_index, max_index, vertex_draw_count); + } } u32 GLGSRender::set_vertex_buffer() @@ -186,21 +212,18 @@ u32 GLGSRender::set_vertex_buffer() { rsx::index_array_type type = rsx::method_registers.index_type(); u32 type_size = gsl::narrow(get_index_type_size(type)); + for (const auto& first_count : first_count_commands) { vertex_draw_count += first_count.second; } - // Index count - vertex_draw_count = (u32)get_index_count(draw_mode, gsl::narrow(vertex_draw_count)); - u32 block_sz = vertex_draw_count * type_size; - - auto mapping = m_index_ring_buffer.alloc_and_map(block_sz); + u32 max_size = get_index_count(draw_mode, vertex_draw_count) * type_size; + auto mapping = m_index_ring_buffer.alloc_and_map(max_size); void *ptr = mapping.first; offset_in_index_buffer = mapping.second; - gsl::span dst{ reinterpret_cast(ptr), gsl::narrow(block_sz) }; - std::tie(min_index, max_index) = write_index_array_data_to_buffer(dst, type, draw_mode, first_count_commands); + std::tie(min_index, max_index, vertex_draw_count) = upload_index_buffer(ptr, type, draw_mode, first_count_commands, vertex_draw_count); m_index_ring_buffer.unmap(); } @@ -272,7 +295,8 @@ u32 GLGSRender::set_vertex_buffer() //Link texture to uniform m_program->uniforms.texture(location, index + texture_index_offset, texture); - if (!is_primitive_native(draw_mode)) + + if (!gl::is_primitive_native(draw_mode)) { std::tie(vertex_draw_count, offset_in_index_buffer) = get_index_array_for_emulated_non_indexed_draw({ { 0, vertex_draw_count } }, draw_mode, m_index_ring_buffer); } @@ -343,6 +367,7 @@ u32 GLGSRender::set_vertex_buffer() offset += first_count.second * element_size; } } + if (draw_command == rsx::draw_command::indexed) { data_size = (max_index + 1) * element_size; @@ -400,7 +425,7 @@ u32 GLGSRender::set_vertex_buffer() } } - if (draw_command == rsx::draw_command::array && !is_primitive_native(draw_mode)) + if (draw_command == rsx::draw_command::array && !gl::is_primitive_native(draw_mode)) { std::tie(vertex_draw_count, offset_in_index_buffer) = get_index_array_for_emulated_non_indexed_draw(first_count_commands, draw_mode, m_index_ring_buffer); } From ea6f3ff5ede6274af492cab6fe5e40a70c561b91 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 12 Jul 2016 23:10:26 +0300 Subject: [PATCH 2/3] gl: Properly determine front face winding --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 4d3024cdeb..9a1a4795b8 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -23,17 +23,6 @@ namespace } throw EXCEPTION("Unknown depth format"); } - - u32 get_front_face_ccw(u32 ffv) - { - switch (ffv) - { - default: // Disgaea 3 pass some garbage value at startup, this is needed to survive. - case CELL_GCM_CW: return GL_CW; - case CELL_GCM_CCW: return GL_CCW; - } - throw EXCEPTION("Unknown front face value: 0x%X", ffv); - } } GLGSRender::GLGSRender() : GSRender(frame_type::OpenGL) @@ -170,10 +159,14 @@ namespace GLenum front_face(rsx::front_face op) { + GLenum mask = 0; + if (rsx::to_window_origin((rsx::method_registers[NV4097_SET_SHADER_WINDOW] >> 12) & 0xf) == rsx::window_origin::bottom) + mask = 1; + switch (op) { - case rsx::front_face::cw: return GL_CW; - case rsx::front_face::ccw: return GL_CCW; + case rsx::front_face::cw: return GL_CW ^ mask; + case rsx::front_face::ccw: return GL_CCW ^ mask; } throw; } From 6401eefb26526ad0a04405cea2cd2c6e966a8719 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Wed, 13 Jul 2016 00:28:40 +0300 Subject: [PATCH 3/3] gl: reset texture scaling factor during bind reset vertex textures as well --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 9a1a4795b8..4649ae7749 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -425,6 +425,11 @@ void GLGSRender::end() glProgramUniform4f(m_program->id(), location, 1.f / width, 1.f / height, 1.f / depth, 1.0f); } + else + { + //This shader may have been re-used with a different texture config. Have to reset this + glProgramUniform4f(m_program->id(), location, 1.f, 1.f, 1.f, 1.f); + } } } } @@ -458,6 +463,11 @@ void GLGSRender::end() glProgramUniform4f(m_program->id(), location, 1.f / width, 1.f / height, 1.f / depth, 1.0f); } + else + { + //This shader may have been re-used with a different texture config. Have to reset this + glProgramUniform4f(m_program->id(), location, 1.f, 1.f, 1.f, 1.f); + } } } }