From 7884356e90ebd443b1f527516ec7d2bef5ad5be3 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 26 Sep 2016 15:21:17 +0300 Subject: [PATCH] gl/vk: Bug fixes and improvements (#2155) * gl: Fix broken buffer reserve computation * gl: Texture format fixes * gl: Two sided lighting * gl: Always update glsl output registers * gl: Simplify vertex input declaration * vk: Always write output registers * vk/gl: swizzle component read on depth textures * gl/vk: Use proper MVP matrix gl: fix broken mvp when window_origin=top * vk/gl: Move fragment operations block into the proxy function --- rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp | 170 +++++++++++++++++++++---- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 24 +--- rpcs3/Emu/RSX/GL/GLRenderTargets.h | 1 + rpcs3/Emu/RSX/GL/GLTexture.cpp | 45 +++---- rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp | 1 - rpcs3/Emu/RSX/GL/GLVertexProgram.cpp | 126 +++++++++++++++++- rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp | 91 ++++++++++--- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 17 +-- rpcs3/Emu/RSX/VK/VKRenderTargets.h | 1 + rpcs3/Emu/RSX/VK/VKTextureCache.h | 2 +- rpcs3/Emu/RSX/VK/VKVertexProgram.cpp | 54 +++++++- 11 files changed, 421 insertions(+), 111 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp index 99495b125397..d0abd4f9d55c 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "GLFragmentProgram.h" @@ -42,15 +43,43 @@ void GLFragmentDecompilerThread::insertHeader(std::stringstream & OS) void GLFragmentDecompilerThread::insertIntputs(std::stringstream & OS) { + bool two_sided_enabled = m_prog.front_back_color_enabled && (m_prog.back_color_diffuse_output || m_prog.back_color_specular_output); + for (const ParamType& PT : m_parr.params[PF_PARAM_IN]) { for (const ParamItem& PI : PT.items) { - //Rename fogc to fog_c to differentiate the input register from the variable - if (PI.name == "fogc") - OS << "in vec4 fog_c;" << std::endl; - - OS << "in " << PT.type << " " << PI.name << ";" << std::endl; + //ssa is defined in the program body and is not a varying type + if (PI.name == "ssa") continue; + + std::string var_name = PI.name; + + if (two_sided_enabled) + { + if (m_prog.back_color_diffuse_output && var_name == "diff_color") + var_name = "back_diff_color"; + + if (m_prog.back_color_specular_output && var_name == "spec_color") + var_name = "back_spec_color"; + } + + if (var_name == "fogc") + var_name = "fog_c"; + + OS << "in " << PT.type << " " << var_name << ";" << std::endl; + } + } + + if (two_sided_enabled) + { + if (m_prog.front_color_diffuse_output && m_prog.back_color_diffuse_output) + { + OS << "in vec4 front_diff_color;" << std::endl; + } + + if (m_prog.front_color_specular_output && m_prog.back_color_specular_output) + { + OS << "in vec4 front_spec_color;" << std::endl; } } } @@ -184,16 +213,38 @@ void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS) { insert_glsl_legacy_function(OS); - OS << "void main ()" << std::endl; + const std::set output_values = + { + "r0", "r1", "r2", "r3", "r4", + "h0", "h2", "h4", "h6", "h8" + }; + + std::string parameters = ""; + for (auto ®_name : output_values) + { + if (m_parr.HasParam(PF_PARAM_NONE, "vec4", reg_name)) + { + if (parameters.length()) + parameters += ", "; + + parameters += "inout vec4 " + reg_name; + } + } + + OS << "void fs_main(" << parameters << ")" << std::endl; OS << "{" << std::endl; for (const ParamType& PT : m_parr.params[PF_PARAM_NONE]) { for (const ParamItem& PI : PT.items) { + if (output_values.find(PI.name) != output_values.end()) + continue; + OS << " " << PT.type << " " << PI.name; if (!PI.value.empty()) OS << " = " << PI.value; + OS << ";" << std::endl; } } @@ -214,11 +265,49 @@ void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS) } } - // search if there is fogc in inputs + bool two_sided_enabled = m_prog.front_back_color_enabled && (m_prog.back_color_diffuse_output || m_prog.back_color_specular_output); + for (const ParamType& PT : m_parr.params[PF_PARAM_IN]) { for (const ParamItem& PI : PT.items) { + if (two_sided_enabled) + { + if (PI.name == "spec_color") + { + if (m_prog.back_color_specular_output) + { + if (m_prog.back_color_specular_output && m_prog.front_color_specular_output) + { + OS << " vec4 spec_color = gl_FrontFacing ? front_spec_color : back_spec_color;\n"; + } + else + { + OS << " vec4 spec_color = back_spec_color;\n"; + } + } + + continue; + } + + else if (PI.name == "diff_color") + { + if (m_prog.back_color_diffuse_output) + { + if (m_prog.back_color_diffuse_output && m_prog.front_color_diffuse_output) + { + OS << " vec4 diff_color = gl_FrontFacing ? front_diff_color : back_diff_color;\n"; + } + else + { + OS << " vec4 diff_color = back_diff_color;\n"; + } + } + + continue; + } + } + if (PI.name == "fogc") { insert_fog_declaration(OS, m_prog.fog_equation); @@ -238,25 +327,21 @@ void GLFragmentDecompilerThread::insertMainEnd(std::stringstream & OS) { "ocol3", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r4" : "h8" }, }; - std::string first_output_name; - for (int i = 0; i < sizeof(table) / sizeof(*table); ++i) + const std::set output_values = { - if (m_parr.HasParam(PF_PARAM_NONE, "vec4", table[i].second)) - { - OS << " " << table[i].first << " = " << table[i].second << ";" << std::endl; - if (first_output_name.empty()) first_output_name = table[i].first; - } - } + "r0", "r1", "r2", "r3", "r4", + "h0", "h2", "h4", "h6", "h8" + }; - if (m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) + std::string first_output_name = ""; + std::string color_output_block = ""; + + for (int i = 0; i < sizeof(table) / sizeof(*table); ++i) { + if (m_parr.HasParam(PF_PARAM_NONE, "vec4", table[i].second)) { - /** Note: Naruto Shippuden : Ultimate Ninja Storm 2 sets CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS in a shader - * but it writes depth in r1.z and not h2.z. - * Maybe there's a different flag for depth ? - */ - //OS << ((m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) ? "\tgl_FragDepth = r1.z;\n" : "\tgl_FragDepth = h0.z;\n") << std::endl; - OS << " gl_FragDepth = r1.z;\n"; + color_output_block += " " + table[i].first + " = " + table[i].second + ";\n"; + if (first_output_name.empty()) first_output_name = table[i].second; } } @@ -294,6 +379,41 @@ void GLFragmentDecompilerThread::insertMainEnd(std::stringstream & OS) OS << make_comparison_test(m_prog.alpha_func, "alpha_test != 0 && ", first_output_name + ".a", "alpha_ref"); } + OS << "}" << std::endl << std::endl; + + OS << "void main()" << std::endl; + OS << "{" << std::endl; + + std::string parameters = ""; + for (auto ®_name : output_values) + { + if (m_parr.HasParam(PF_PARAM_NONE, "vec4", reg_name)) + { + if (parameters.length()) + parameters += ", "; + + parameters += reg_name; + OS << " vec4 " << reg_name << " = vec4(0.);" << std::endl; + } + } + + OS << std::endl << " fs_main(" + parameters + ");" << std::endl << std::endl; + + //Append the color output assignments + OS << color_output_block; + + if (m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) + { + { + /** Note: Naruto Shippuden : Ultimate Ninja Storm 2 sets CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS in a shader + * but it writes depth in r1.z and not h2.z. + * Maybe there's a different flag for depth ? + */ + //OS << ((m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) ? "\tgl_FragDepth = r1.z;\n" : "\tgl_FragDepth = h0.z;\n") << std::endl; + OS << " gl_FragDepth = r1.z;\n"; + } + } + OS << "}" << std::endl; } @@ -320,8 +440,12 @@ void GLFragmentProgram::Decompile(const RSXFragmentProgram& prog) { for (const ParamItem& PI : PT.items) { - if (PT.type == "sampler2D") + if (PT.type == "sampler1D" || + PT.type == "sampler2D" || + PT.type == "sampler3D" || + PT.type == "samplerCube") continue; + size_t offset = atoi(PI.name.c_str() + 2); FragmentConstantOffsetCache.push_back(offset); } diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 711ac24b16da..1ae79b5d415d 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -477,31 +477,17 @@ void GLGSRender::end() void GLGSRender::set_viewport() { - u16 viewport_x = rsx::method_registers.viewport_origin_x(); - u16 viewport_y = rsx::method_registers.viewport_origin_y(); - u16 viewport_w = rsx::method_registers.viewport_width(); - u16 viewport_h = rsx::method_registers.viewport_height(); + //NOTE: scale offset matrix already contains the viewport transformation + glViewport(0, 0, rsx::method_registers.surface_clip_width(), rsx::method_registers.surface_clip_height()); u16 scissor_x = rsx::method_registers.scissor_origin_x(); u16 scissor_w = rsx::method_registers.scissor_width(); u16 scissor_y = rsx::method_registers.scissor_origin_y(); u16 scissor_h = rsx::method_registers.scissor_height(); - rsx::window_origin shader_window_origin = rsx::method_registers.shader_window_origin(); - - if (shader_window_origin == rsx::window_origin::bottom) - { - __glcheck glViewport(viewport_x, viewport_y, viewport_w, viewport_h); - __glcheck glScissor(scissor_x, scissor_y, scissor_w, scissor_h); - } - else - { - u16 shader_window_height = rsx::method_registers.shader_window_height(); - - __glcheck glViewport(viewport_x, shader_window_height - viewport_y - viewport_h + 1, viewport_w, viewport_h); - __glcheck glScissor(scissor_x, shader_window_height - scissor_y - scissor_h + 1, scissor_w, scissor_h); - } - + //NOTE: window origin does not affect scissor region (probably only affects viewport matrix; already applied) + //See LIMBO [NPUB-30373] which uses shader window origin = top + __glcheck glScissor(scissor_x, scissor_y, scissor_w, scissor_h); glEnable(GL_SCISSOR_TEST); } diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.h b/rpcs3/Emu/RSX/GL/GLRenderTargets.h index f81556d8c29d..6a59086b3f5c 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.h +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.h @@ -122,6 +122,7 @@ struct gl_render_target_traits .type(format.type) .format(format.format) .internal_format(format.internal_format) + .swizzle(gl::texture::channel::r, gl::texture::channel::r, gl::texture::channel::r, gl::texture::channel::r) .wrap(gl::texture::wrap::clamp_to_border, gl::texture::wrap::clamp_to_border, gl::texture::wrap::clamp_to_border) .apply(); diff --git a/rpcs3/Emu/RSX/GL/GLTexture.cpp b/rpcs3/Emu/RSX/GL/GLTexture.cpp index 81c71f996b7e..0c32e45d58ac 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.cpp +++ b/rpcs3/Emu/RSX/GL/GLTexture.cpp @@ -128,6 +128,7 @@ namespace case CELL_GCM_TEXTURE_R5G5B5A1: case CELL_GCM_TEXTURE_R6G5B5: case CELL_GCM_TEXTURE_R5G6B5: + //case CELL_GCM_TEXTURE_A4R4G4B4: case CELL_GCM_TEXTURE_A8R8G8B8: // TODO case CELL_GCM_TEXTURE_DEPTH24_D8: case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: @@ -140,24 +141,20 @@ namespace case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: return { GL_ALPHA, GL_RED, GL_GREEN, GL_BLUE }; - case CELL_GCM_TEXTURE_B8: - return { GL_RED, GL_RED, GL_RED, GL_RED }; + case CELL_GCM_TEXTURE_A4R4G4B4: + return{ GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA }; - case CELL_GCM_TEXTURE_A4R4G4B4: - return { GL_BLUE, GL_ALPHA, GL_RED, GL_GREEN }; + case CELL_GCM_TEXTURE_B8: + case CELL_GCM_TEXTURE_X16: + case CELL_GCM_TEXTURE_X32_FLOAT: + return { GL_RED, GL_RED, GL_RED, GL_RED }; case CELL_GCM_TEXTURE_G8B8: return { GL_GREEN, GL_RED, GL_GREEN, GL_RED}; - case CELL_GCM_TEXTURE_X16: - return { GL_RED, GL_RED, GL_RED, GL_RED }; - case CELL_GCM_TEXTURE_Y16_X16: return { GL_RED, GL_GREEN, GL_RED, GL_GREEN}; - case CELL_GCM_TEXTURE_X32_FLOAT: - return { GL_RED, GL_RED, GL_RED, GL_RED }; - case CELL_GCM_TEXTURE_Y16_X16_FLOAT: return { GL_GREEN, GL_RED, GL_GREEN, GL_RED }; @@ -492,25 +489,15 @@ namespace rsx glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, tex.get_exact_mipmap_count() - 1); - if (format != CELL_GCM_TEXTURE_B8 && format != CELL_GCM_TEXTURE_X16 && format != CELL_GCM_TEXTURE_X32_FLOAT) - { - u8 remap_a = tex.remap() & 0x3; - u8 remap_r = (tex.remap() >> 2) & 0x3; - u8 remap_g = (tex.remap() >> 4) & 0x3; - u8 remap_b = (tex.remap() >> 6) & 0x3; - - __glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, glRemap[remap_a]); - __glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, glRemap[remap_r]); - __glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, glRemap[remap_g]); - __glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, glRemap[remap_b]); - } - else - { - __glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, glRemap[0]); - __glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, glRemap[1]); - __glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, glRemap[2]); - __glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, glRemap[3]); - } + u8 remap_a = tex.remap() & 0x3; + u8 remap_r = (tex.remap() >> 2) & 0x3; + u8 remap_g = (tex.remap() >> 4) & 0x3; + u8 remap_b = (tex.remap() >> 6) & 0x3; + + __glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, glRemap[remap_a]); + __glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, glRemap[remap_r]); + __glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, glRemap[remap_g]); + __glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, glRemap[remap_b]); __glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_S, gl_wrap(tex.wrap_s())); __glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_T, gl_wrap(tex.wrap_t())); diff --git a/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp b/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp index 2585e3b83743..77ab582a79a6 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexBuffers.cpp @@ -351,7 +351,6 @@ namespace const rsx::draw_indexed_array_command& command) { u32 min_index = 0, max_index = 0; - u32 max_vertex_attrib_size = 0; rsx::index_array_type type = rsx::method_registers.index_type(); u32 type_size = ::narrow(get_index_type_size(type)); diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index 03777afe5696..33bc48948a4a 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -198,13 +198,42 @@ static const reg_info reg_table[] = void GLVertexDecompilerThread::insertOutputs(std::stringstream & OS, const std::vector & outputs) { - for (const auto &i : reg_table) + bool insert_front_diffuse = (rsx_vertex_program.output_mask & 1); + bool insert_back_diffuse = (rsx_vertex_program.output_mask & 4); + + bool insert_front_specular = (rsx_vertex_program.output_mask & 2); + bool insert_back_specular = (rsx_vertex_program.output_mask & 8); + + bool front_back_diffuse = (insert_back_diffuse && insert_front_diffuse); + bool front_back_specular = (insert_back_specular && insert_front_specular); + + for (auto &i : reg_table) { if (m_parr.HasParam(PF_PARAM_NONE, "vec4", i.src_reg) && i.need_declare) { - OS << "out vec4 " << i.name << ";" << std::endl; + if (i.name == "front_diff_color") + insert_front_diffuse = false; + + if (i.name == "front_spec_color") + insert_front_specular = false; + + std::string name = i.name; + + if (front_back_diffuse && name == "diff_color") + name = "back_diff_color"; + + if (front_back_specular && name == "spec_color") + name = "back_spec_color"; + + OS << "out vec4 " << name << ";" << std::endl; } } + + if (insert_back_diffuse && insert_front_diffuse) + OS << "out vec4 front_diff_color;" << std::endl; + + if (insert_back_specular && insert_front_specular) + OS << "out vec4 front_spec_color;" << std::endl; } void add_input(std::stringstream & OS, const ParamItem &PI, const std::vector &inputs) @@ -247,17 +276,34 @@ void GLVertexDecompilerThread::insertMainStart(std::stringstream & OS) { insert_glsl_legacy_function(OS); - OS << "void main()" << std::endl; + std::string parameters = ""; + for (int i = 0; i < 16; ++i) + { + std::string reg_name = "dst_reg" + std::to_string(i); + if (m_parr.HasParam(PF_PARAM_NONE, "vec4", reg_name)) + { + if (parameters.length()) + parameters += ", "; + + parameters += "inout vec4 " + reg_name; + } + } + + OS << "void vs_main(" << parameters << ")" << std::endl; OS << "{" << std::endl; - // Declare inside main function - for (const ParamType& PT : m_parr.params[PF_PARAM_NONE]) + //Declare temporary registers, ignoring those mapped to outputs + for (const ParamType PT : m_parr.params[PF_PARAM_NONE]) { for (const ParamItem &PI : PT.items) { + if (PI.name.substr(0, 7) == "dst_reg") + continue; + OS << " " << PT.type << " " << PI.name; if (!PI.value.empty()) OS << " = " << PI.value; + OS << ";" << std::endl; } } @@ -282,10 +328,68 @@ void GLVertexDecompilerThread::insertMainStart(std::stringstream & OS) void GLVertexDecompilerThread::insertMainEnd(std::stringstream & OS) { - for (const auto &i : reg_table) + OS << "}" << std::endl << std::endl; + + OS << "void main ()" << std::endl; + OS << "{" << std::endl; + + std::string parameters = ""; + + if (ParamType *vec4Types = m_parr.SearchParam(PF_PARAM_NONE, "vec4")) + { + for (int i = 0; i < 16; ++i) + { + std::string reg_name = "dst_reg" + std::to_string(i); + for (auto &PI : vec4Types->items) + { + if (reg_name == PI.name) + { + if (parameters.length()) + parameters += ", "; + + parameters += reg_name; + OS << " vec4 " << reg_name; + + if (!PI.value.empty()) + OS << "= " << PI.value; + + OS << ";" << std::endl; + } + } + } + } + + OS << std::endl << " vs_main(" << parameters << ");" << std::endl << std::endl; + + bool insert_front_diffuse = (rsx_vertex_program.output_mask & 1); + bool insert_front_specular = (rsx_vertex_program.output_mask & 2); + + bool insert_back_diffuse = (rsx_vertex_program.output_mask & 4); + bool insert_back_specular = (rsx_vertex_program.output_mask & 8); + + bool front_back_diffuse = (insert_back_diffuse && insert_front_diffuse); + bool front_back_specular = (insert_back_specular && insert_front_specular); + + for (auto &i : reg_table) { if (m_parr.HasParam(PF_PARAM_NONE, "vec4", i.src_reg)) - OS << " " << i.name << " = " << i.src_reg << i.src_reg_mask << ";" << std::endl; + { + if (i.name == "front_diff_color") + insert_front_diffuse = false; + + if (i.name == "front_spec_color") + insert_front_specular = false; + + std::string name = i.name; + + if (front_back_diffuse && name == "diff_color") + name = "back_diff_color"; + + if (front_back_specular && name == "spec_color") + name = "back_spec_color"; + + OS << " " << name << " = " << i.src_reg << i.src_reg_mask << ";" << std::endl; + } } for (const auto& uc : get_user_clip_planes(rsx_vertex_program)) @@ -293,6 +397,14 @@ void GLVertexDecompilerThread::insertMainEnd(std::stringstream & OS) OS << uc.second; } + if (insert_back_diffuse && insert_front_diffuse) + if (m_parr.HasParam(PF_PARAM_NONE, "vec4", "dst_reg1")) + OS << " front_diff_color = dst_reg1;\n"; + + if (insert_back_specular && insert_front_specular) + if (m_parr.HasParam(PF_PARAM_NONE, "vec4", "dst_reg2")) + OS << " front_spec_color = dst_reg2;\n"; + OS << " gl_Position = gl_Position * scaleOffsetMat;" << std::endl; OS << "}" << std::endl; } diff --git a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp index 6bef08028279..a8cf14a99f8c 100644 --- a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp @@ -231,16 +231,38 @@ void VKFragmentDecompilerThread::insertMainStart(std::stringstream & OS) { vk::insert_glsl_legacy_function(OS); - OS << "void main ()" << std::endl; + const std::set output_values = + { + "r0", "r1", "r2", "r3", "r4", + "h0", "h2", "h4", "h6", "h8" + }; + + std::string parameters = ""; + for (auto ®_name : output_values) + { + if (m_parr.HasParam(PF_PARAM_NONE, "vec4", reg_name)) + { + if (parameters.length()) + parameters += ", "; + + parameters += "inout vec4 " + reg_name; + } + } + + OS << "void fs_main(" << parameters << ")" << std::endl; OS << "{" << std::endl; for (const ParamType& PT : m_parr.params[PF_PARAM_NONE]) { for (const ParamItem& PI : PT.items) { + if (output_values.find(PI.name) != output_values.end()) + continue; + OS << " " << PT.type << " " << PI.name; if (!PI.value.empty()) OS << " = " << PI.value; + OS << ";" << std::endl; } } @@ -312,25 +334,21 @@ void VKFragmentDecompilerThread::insertMainEnd(std::stringstream & OS) { "ocol3", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r4" : "h8" }, }; - std::string first_output_name; - for (int i = 0; i < sizeof(table) / sizeof(*table); ++i) + const std::set output_values = { - if (m_parr.HasParam(PF_PARAM_NONE, "vec4", table[i].second)) - { - OS << " " << table[i].first << " = " << table[i].second << ";" << std::endl; - if (first_output_name.empty()) first_output_name = table[i].first; - } - } + "r0", "r1", "r2", "r3", "r4", + "h0", "h2", "h4", "h6", "h8" + }; - if (m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) + std::string first_output_name = ""; + std::string color_output_block = ""; + + for (int i = 0; i < sizeof(table) / sizeof(*table); ++i) { + if (m_parr.HasParam(PF_PARAM_NONE, "vec4", table[i].second)) { - /** Note: Naruto Shippuden : Ultimate Ninja Storm 2 sets CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS in a shader - * but it writes depth in r1.z and not h2.z. - * Maybe there's a different flag for depth ? - */ - //OS << ((m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) ? "\tgl_FragDepth = r1.z;\n" : "\tgl_FragDepth = h0.z;\n") << std::endl; - OS << " gl_FragDepth = r1.z;\n"; + color_output_block += " " + table[i].first + " = " + table[i].second + ";\n"; + if (first_output_name.empty()) first_output_name = table[i].second; } } @@ -368,6 +386,41 @@ void VKFragmentDecompilerThread::insertMainEnd(std::stringstream & OS) OS << make_comparison_test(m_prog.alpha_func, "bool(alpha_test) && ", first_output_name + ".a", "alpha_ref"); } + OS << "}" << std::endl << std::endl; + + OS << "void main()" << std::endl; + OS << "{" << std::endl; + + std::string parameters = ""; + for (auto ®_name : output_values) + { + if (m_parr.HasParam(PF_PARAM_NONE, "vec4", reg_name)) + { + if (parameters.length()) + parameters += ", "; + + parameters += reg_name; + OS << " vec4 " << reg_name << " = vec4(0.);" << std::endl; + } + } + + OS << std::endl << " fs_main(" + parameters + ");" << std::endl << std::endl; + + //Append the color output assignments + OS << color_output_block; + + if (m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) + { + { + /** Note: Naruto Shippuden : Ultimate Ninja Storm 2 sets CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS in a shader + * but it writes depth in r1.z and not h2.z. + * Maybe there's a different flag for depth ? + */ + //OS << ((m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) ? "\tgl_FragDepth = r1.z;\n" : "\tgl_FragDepth = h0.z;\n") << std::endl; + OS << " gl_FragDepth = r1.z;\n"; + } + } + OS << "}" << std::endl; } @@ -396,8 +449,12 @@ void VKFragmentProgram::Decompile(const RSXFragmentProgram& prog) { for (const ParamItem& PI : PT.items) { - if (PT.type == "sampler2D") + if (PT.type == "sampler1D" || + PT.type == "sampler2D" || + PT.type == "sampler3D" || + PT.type == "samplerCube") continue; + size_t offset = atoi(PI.name.c_str() + 2); FragmentConstantOffsetCache.push_back(offset); } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index bc3c851cd9b3..9dc47a0d7dbf 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -792,24 +792,17 @@ void VKGSRender::end() void VKGSRender::set_viewport() { - u16 viewport_x = rsx::method_registers.viewport_origin_x(); - u16 viewport_y = rsx::method_registers.viewport_origin_y(); - u16 viewport_w = rsx::method_registers.viewport_width(); - u16 viewport_h = rsx::method_registers.viewport_height(); - u16 scissor_x = rsx::method_registers.scissor_origin_x(); u16 scissor_w = rsx::method_registers.scissor_width(); u16 scissor_y = rsx::method_registers.scissor_origin_y(); u16 scissor_h = rsx::method_registers.scissor_height(); - // u32 shader_window = rsx::method_registers[NV4097_SET_SHADER_WINDOW]; - // rsx::window_origin shader_window_origin = rsx::to_window_origin((shader_window >> 12) & 0xf); - + //NOTE: The scale_offset matrix already has viewport matrix factored in VkViewport viewport = {}; - viewport.x = viewport_x; - viewport.y = viewport_y; - viewport.width = viewport_w; - viewport.height = viewport_h; + viewport.x = 0; + viewport.y = 0; + viewport.width = rsx::method_registers.surface_clip_width(); + viewport.height = rsx::method_registers.surface_clip_height(); viewport.minDepth = 0.f; viewport.maxDepth = 1.f; diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index f6791b898abf..de6b5c38e29a 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -67,6 +67,7 @@ namespace rsx VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT|VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0)); + ds->native_layout = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R }; change_image_layout(*cmd, ds->value, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, range); //Clear new surface.. diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 740c8ab66cce..39bb3b09aa29 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -191,7 +191,7 @@ namespace vk if (rtt_texture = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr)) { m_temporary_image_view.push_back(std::make_unique(*vk::get_current_renderer(), rtt_texture->value, VK_IMAGE_VIEW_TYPE_2D, rtt_texture->info.format, - vk::default_component_map(), + rtt_texture->native_layout, vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_DEPTH_BIT))); return m_temporary_image_view.back().get(); } diff --git a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp index f4ffe5b39955..457a118c9728 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp @@ -253,17 +253,34 @@ void VKVertexDecompilerThread::insertMainStart(std::stringstream & OS) { vk::insert_glsl_legacy_function(OS); - OS << "void main()" << std::endl; + std::string parameters = ""; + for (int i = 0; i < 16; ++i) + { + std::string reg_name = "dst_reg" + std::to_string(i); + if (m_parr.HasParam(PF_PARAM_NONE, "vec4", reg_name)) + { + if (parameters.length()) + parameters += ", "; + + parameters += "inout vec4 " + reg_name; + } + } + + OS << "void vs_main(" << parameters << ")" << std::endl; OS << "{" << std::endl; - // Declare inside main function + //Declare temporary registers, ignoring those mapped to outputs for (const ParamType PT : m_parr.params[PF_PARAM_NONE]) { for (const ParamItem &PI : PT.items) { + if (PI.name.substr(0, 7) == "dst_reg") + continue; + OS << " " << PT.type << " " << PI.name; if (!PI.value.empty()) OS << " = " << PI.value; + OS << ";" << std::endl; } } @@ -277,6 +294,39 @@ void VKVertexDecompilerThread::insertMainStart(std::stringstream & OS) void VKVertexDecompilerThread::insertMainEnd(std::stringstream & OS) { + OS << "}" << std::endl << std::endl; + + OS << "void main ()" << std::endl; + OS << "{" << std::endl; + + std::string parameters = ""; + + if (ParamType *vec4Types = m_parr.SearchParam(PF_PARAM_NONE, "vec4")) + { + for (int i = 0; i < 16; ++i) + { + std::string reg_name = "dst_reg" + std::to_string(i); + for (auto &PI : vec4Types->items) + { + if (reg_name == PI.name) + { + if (parameters.length()) + parameters += ", "; + + parameters += reg_name; + OS << " vec4 " << reg_name; + + if (!PI.value.empty()) + OS << "= " << PI.value; + + OS << ";" << std::endl; + } + } + } + } + + OS << std::endl << " vs_main(" << parameters << ");" << std::endl << std::endl; + bool insert_front_diffuse = (rsx_vertex_program.output_mask & 1); bool insert_front_specular = (rsx_vertex_program.output_mask & 2);