diff --git a/rpcs3/Emu/RSX/Common/surface_store.h b/rpcs3/Emu/RSX/Common/surface_store.h index 1e4571ff50..42397e6037 100644 --- a/rpcs3/Emu/RSX/Common/surface_store.h +++ b/rpcs3/Emu/RSX/Common/surface_store.h @@ -94,7 +94,7 @@ namespace rsx using surface_type = typename Traits::surface_type; using command_list_type = typename Traits::command_list_type; using download_buffer_object = typename Traits::download_buffer_object; - using surface_subresource = typename surface_subresource_storage; + using surface_subresource = surface_subresource_storage; std::unordered_map m_render_targets_storage = {}; std::unordered_map m_depth_stencil_storage = {}; diff --git a/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp b/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp index 18d06e2614..8bf68aebd1 100644 --- a/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp +++ b/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp @@ -2,69 +2,104 @@ #include "GLCommonDecompiler.h" -std::string getFunctionImpl(FUNCTION f) +namespace gl { - switch (f) + std::string getFunctionImpl(FUNCTION f) { - default: - abort(); - case FUNCTION::FUNCTION_DP2: - return "vec4(dot($0.xy, $1.xy))"; - case FUNCTION::FUNCTION_DP2A: - return "vec4(dot($0.xy, $1.xy) + $2.x)"; - case FUNCTION::FUNCTION_DP3: - return "vec4(dot($0.xyz, $1.xyz))"; - case FUNCTION::FUNCTION_DP4: - return "vec4(dot($0, $1))"; - case FUNCTION::FUNCTION_DPH: - return "vec4(dot(vec4($0.xyz, 1.0), $1))"; - case FUNCTION::FUNCTION_SFL: - return "vec4(0., 0., 0., 0.)"; - case FUNCTION::FUNCTION_STR: - return "vec4(1., 1., 1., 1.)"; - case FUNCTION::FUNCTION_FRACT: - return "fract($0)"; - case FUNCTION::FUNCTION_REFL: - return "vec4($0 - 2.0 * (dot($0, $1)) * $1)"; - case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D: - return "texture($t, $0.x)"; - case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_PROJ: - return "textureProj($t, $0.x, $1.x)"; // Note: $1.x is bias - case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD: - return "textureLod($t, $0.x, $1.x)"; - case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_GRAD: - return "textureGrad($t, $0.x, $1.x, $2.x)"; - case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D: - return "texture($t, $0.xy * $t_coord_scale)"; - case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ: - return "textureProj($t, $0 , $1.x)"; // Note: $1.x is bias - case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD: - return "textureLod($t, $0.xy * $t_coord_scale, $1.x)"; - case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_GRAD: - return "textureGrad($t, $0.xy * $t_coord_scale , $1.xy, $2.xy)"; - case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE: - return "texture($t, $0.xyz)"; - case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_PROJ: - return "texture($t, ($0.xyz / $0.w))"; - case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_LOD: - return "textureLod($t, $0.xyz, $1.x)"; - case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_GRAD: - return "textureGrad($t, $0.xyz, $1.xyz, $2.xyz)"; - case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D: - return "texture($t, $0.xyz)"; - case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_PROJ: - return "textureProj($t, $0.xyzw, $1.x)"; // Note: $1.x is bias - case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_LOD: - return "textureLod($t, $0.xyz, $1.x)"; - case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_GRAD: - return "textureGrad($t, $0.xyz, $1.xyz, $2.xyz)"; - case FUNCTION::FUNCTION_DFDX: - return "dFdx($0)"; - case FUNCTION::FUNCTION_DFDY: - return "dFdy($0)"; - case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D: - return "textureLod($t, $0.xy, 0)"; - case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA: - return "texture2DReconstruct($t, $0.xy * $t_coord_scale)"; + switch (f) + { + default: + abort(); + case FUNCTION::FUNCTION_DP2: + return "vec4(dot($0.xy, $1.xy))"; + case FUNCTION::FUNCTION_DP2A: + return "vec4(dot($0.xy, $1.xy) + $2.x)"; + case FUNCTION::FUNCTION_DP3: + return "vec4(dot($0.xyz, $1.xyz))"; + case FUNCTION::FUNCTION_DP4: + return "vec4(dot($0, $1))"; + case FUNCTION::FUNCTION_DPH: + return "vec4(dot(vec4($0.xyz, 1.0), $1))"; + case FUNCTION::FUNCTION_SFL: + return "vec4(0., 0., 0., 0.)"; + case FUNCTION::FUNCTION_STR: + return "vec4(1., 1., 1., 1.)"; + case FUNCTION::FUNCTION_FRACT: + return "fract($0)"; + case FUNCTION::FUNCTION_REFL: + return "vec4($0 - 2.0 * (dot($0, $1)) * $1)"; + case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D: + return "texture($t, $0.x)"; + case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_PROJ: + return "textureProj($t, $0.x, $1.x)"; // Note: $1.x is bias + case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD: + return "textureLod($t, $0.x, $1.x)"; + case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_GRAD: + return "textureGrad($t, $0.x, $1.x, $2.x)"; + case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D: + return "texture($t, $0.xy * $t_coord_scale)"; + case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ: + return "textureProj($t, $0 , $1.x)"; // Note: $1.x is bias + case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD: + return "textureLod($t, $0.xy * $t_coord_scale, $1.x)"; + case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_GRAD: + return "textureGrad($t, $0.xy * $t_coord_scale , $1.xy, $2.xy)"; + case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE: + return "texture($t, $0.xyz)"; + case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_PROJ: + return "texture($t, ($0.xyz / $0.w))"; + case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_LOD: + return "textureLod($t, $0.xyz, $1.x)"; + case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_GRAD: + return "textureGrad($t, $0.xyz, $1.xyz, $2.xyz)"; + case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D: + return "texture($t, $0.xyz)"; + case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_PROJ: + return "textureProj($t, $0.xyzw, $1.x)"; // Note: $1.x is bias + case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_LOD: + return "textureLod($t, $0.xyz, $1.x)"; + case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_GRAD: + return "textureGrad($t, $0.xyz, $1.xyz, $2.xyz)"; + case FUNCTION::FUNCTION_DFDX: + return "dFdx($0)"; + case FUNCTION::FUNCTION_DFDY: + return "dFdy($0)"; + case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D: + return "textureLod($t, $0.xy, 0)"; + case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA: + return "texture2DReconstruct($t, $0.xy * $t_coord_scale)"; + } + } + + int get_varying_register_location(const std::string &var_name) + { + static const std::pair reg_table[] = + { + { "diff_color", 1 }, + { "spec_color", 2 }, + { "back_diff_color", 1 }, + { "back_spec_color", 2 }, + { "front_diff_color", 3 }, + { "front_spec_color", 4 }, + { "fog_c", 5 }, + { "tc0", 6 }, + { "tc1", 7 }, + { "tc2", 8 }, + { "tc3", 9 }, + { "tc4", 10 }, + { "tc5", 11 }, + { "tc6", 12 }, + { "tc7", 13 }, + { "tc8", 14 }, + { "tc9", 15 } + }; + + for (const auto& v: reg_table) + { + if (v.first == var_name) + return v.second; + } + + fmt::throw_exception("register named %s should not be declared!", var_name.c_str()); } } diff --git a/rpcs3/Emu/RSX/GL/GLCommonDecompiler.h b/rpcs3/Emu/RSX/GL/GLCommonDecompiler.h index 69e2495c55..e2328495f1 100644 --- a/rpcs3/Emu/RSX/GL/GLCommonDecompiler.h +++ b/rpcs3/Emu/RSX/GL/GLCommonDecompiler.h @@ -4,4 +4,8 @@ #include "../Common/GLSLCommon.h" #include -std::string getFunctionImpl(FUNCTION f); +namespace gl +{ + std::string getFunctionImpl(FUNCTION f); + int get_varying_register_location(const std::string &var_name); +} diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp index 6d154a8650..4097d7893d 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp @@ -7,6 +7,7 @@ #include "GLCommonDecompiler.h" #include "../GCM.h" + std::string GLFragmentDecompilerThread::getFloatTypeName(size_t elementCount) { return glsl::getFloatTypeNameImpl(elementCount); @@ -14,7 +15,7 @@ std::string GLFragmentDecompilerThread::getFloatTypeName(size_t elementCount) std::string GLFragmentDecompilerThread::getFunction(FUNCTION f) { - return getFunctionImpl(f); + return gl::getFunctionImpl(f); } std::string GLFragmentDecompilerThread::saturate(const std::string & code) @@ -35,6 +36,7 @@ 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); + std::vector inputs_to_declare; for (const ParamType& PT : m_parr.params[PF_PARAM_IN]) { @@ -57,7 +59,7 @@ void GLFragmentDecompilerThread::insertIntputs(std::stringstream & OS) if (var_name == "fogc") var_name = "fog_c"; - OS << "in " << PT.type << " " << var_name << ";\n"; + inputs_to_declare.push_back(var_name); } } @@ -65,14 +67,19 @@ void GLFragmentDecompilerThread::insertIntputs(std::stringstream & OS) { if (m_prog.front_color_diffuse_output && m_prog.back_color_diffuse_output) { - OS << "in vec4 front_diff_color;\n"; + inputs_to_declare.push_back("front_diff_color"); } if (m_prog.front_color_specular_output && m_prog.back_color_specular_output) { - OS << "in vec4 front_spec_color;\n"; + inputs_to_declare.push_back("front_spec_color"); } } + + for (auto &name: inputs_to_declare) + { + OS << "layout(location=" << gl::get_varying_register_location(name) << ") in vec4 " << name << ";\n"; + } } void GLFragmentDecompilerThread::insertOutputs(std::stringstream & OS) @@ -225,7 +232,6 @@ void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS) } } - OS << "//FP_HASH=" << fmt::format("%llX", program_hash_util::fragment_program_hash()(m_prog)) << "\n"; OS << "void fs_main(" << parameters << ")\n"; OS << "{\n"; diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index b1179717a2..95c70dd0ac 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -550,13 +550,7 @@ void GLGSRender::end() index_ptr += (index_size << type_scale); } - for (int i = 0; i < draw_count; ++i) - { - if (counts[i] > 0) - glDrawElements(draw_mode, counts[i], index_type, offsets[i]); - } - - //glMultiDrawElements(draw_mode, counts.data(), index_type, offsets.data(), (GLsizei)draw_count); + glMultiDrawElements(draw_mode, counts.data(), index_type, offsets.data(), (GLsizei)draw_count); } } else @@ -581,15 +575,7 @@ void GLGSRender::end() counts.push_back(range.second); } - ///* - // TEST FOR DRIVER BUGS - AMD: SHAME, SHAME, SHAME - for (int i = 0; i < draw_count; i++) - { - if (counts[i] > 0) - glDrawArrays(draw_mode, firsts[i], counts[i]); - }//*/ - - //glMultiDrawArrays(draw_mode, firsts.data(), counts.data(), (GLsizei)draw_count); + glMultiDrawArrays(draw_mode, firsts.data(), counts.data(), (GLsizei)draw_count); } } diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index 4425869ccf..ff6c69deda 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -21,7 +21,7 @@ std::string GLVertexDecompilerThread::getIntTypeName(size_t elementCount) std::string GLVertexDecompilerThread::getFunction(FUNCTION f) { - return getFunctionImpl(f); + return gl::getFunctionImpl(f); } std::string GLVertexDecompilerThread::compareFunction(COMPARE f, const std::string &Op0, const std::string &Op1) @@ -31,7 +31,8 @@ std::string GLVertexDecompilerThread::compareFunction(COMPARE f, const std::stri void GLVertexDecompilerThread::insertHeader(std::stringstream &OS) { - OS << "#version 430\n\n"; + OS << "#version 430\n"; + OS << "#extension GL_ARB_separate_program_objects: enable\n\n"; OS << "layout(std140, binding = 0) uniform VertexContextBuffer\n"; OS << "{\n"; OS << " mat4 scale_offset_mat;\n"; @@ -109,13 +110,12 @@ void GLVertexDecompilerThread::insertOutputs(std::stringstream & OS, const std:: bool front_back_diffuse = (insert_back_diffuse && insert_front_diffuse); bool front_back_specular = (insert_back_specular && insert_front_specular); + std::vector outputs_to_declare; + for (auto &i : reg_table) { - if (m_parr.HasParam(PF_PARAM_NONE, "vec4", i.src_reg) && i.need_declare) + if (i.need_declare) { - if (i.check_mask && (rsx_vertex_program.output_mask & i.check_mask_value) == 0) - continue; - if (i.name == "front_diff_color") insert_front_diffuse = false; @@ -130,24 +130,20 @@ void GLVertexDecompilerThread::insertOutputs(std::stringstream & OS, const std:: if (front_back_specular && name == "spec_color") name = "back_spec_color"; - OS << "out vec4 " << name << ";\n"; - } - else - { - //Mesa drivers are very strict on shader-stage matching - //Force some outputs to be declared even if unused - if (i.need_declare && (rsx_vertex_program.output_mask & i.check_mask_value) > 0) - { - OS << "out vec4 " << i.name << ";\n"; - } + outputs_to_declare.push_back(name); } } if (insert_back_diffuse && insert_front_diffuse) - OS << "out vec4 front_diff_color;\n"; + outputs_to_declare.push_back("front_diff_color"); if (insert_back_specular && insert_front_specular) - OS << "out vec4 front_spec_color;\n"; + outputs_to_declare.push_back("front_spec_color"); + + for (auto &name: outputs_to_declare) + { + OS << "layout(location=" << gl::get_varying_register_location(name) << ") out vec4 " << name << ";\n"; + } } void GLVertexDecompilerThread::insertMainStart(std::stringstream & OS)