From fa55a8072cd1c2d88892156ddb4c4bbb3fe017f1 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 9 Jul 2018 21:31:31 +0300 Subject: [PATCH] rsx: Improve vertex textures support - Adds proper support for vertex textures, including dimensions other than 2D textures - Minor analyser fixup, removes spurious 'analyser failed' errors - Minor optimizations for program state tracking --- rpcs3/Emu/RSX/Common/GLSLCommon.h | 5 ++ rpcs3/Emu/RSX/Common/ProgramStateCache.cpp | 18 +++++- rpcs3/Emu/RSX/Common/ProgramStateCache.h | 1 + .../RSX/Common/VertexProgramDecompiler.cpp | 39 +++++++++++- rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.cpp | 2 +- rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp | 3 +- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 26 ++++++-- rpcs3/Emu/RSX/GL/GLGSRender.h | 3 +- rpcs3/Emu/RSX/GL/GLProgramBuffer.h | 4 +- rpcs3/Emu/RSX/GL/GLTexture.cpp | 18 +++++- rpcs3/Emu/RSX/GL/GLTexture.h | 3 +- rpcs3/Emu/RSX/GL/GLVertexProgram.cpp | 11 ---- rpcs3/Emu/RSX/RSXTexture.cpp | 61 +++---------------- rpcs3/Emu/RSX/RSXTexture.h | 15 +---- rpcs3/Emu/RSX/RSXThread.cpp | 27 ++++++-- rpcs3/Emu/RSX/RSXThread.h | 8 +-- rpcs3/Emu/RSX/RSXVertexProgram.h | 8 +++ rpcs3/Emu/RSX/VK/VKGSRender.cpp | 4 +- rpcs3/Emu/RSX/rsx_cache.h | 4 ++ rpcs3/Emu/RSX/rsx_methods.cpp | 11 +++- 20 files changed, 166 insertions(+), 105 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/GLSLCommon.h b/rpcs3/Emu/RSX/Common/GLSLCommon.h index 3f526e42e6..3683d1c25e 100644 --- a/rpcs3/Emu/RSX/Common/GLSLCommon.h +++ b/rpcs3/Emu/RSX/Common/GLSLCommon.h @@ -604,8 +604,13 @@ namespace glsl return "dFdx($0)"; case FUNCTION::FUNCTION_DFDY: return "dFdy($0)"; + case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH1D: + return "textureLod($t, $0.x, 0)"; case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D: return "textureLod($t, $0.xy, 0)"; + case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH3D: + case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCHCUBE: + return "textureLod($t, $0.xyz, 0)"; case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA: return "TEX2D_DEPTH_RGBA8($_i, $t, $0.xy)"; } diff --git a/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp index 0fee68931a..61221b2ad8 100644 --- a/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp +++ b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp @@ -31,7 +31,7 @@ size_t vertex_program_utils::get_vertex_program_ucode_hash(const RSXVertexProgra vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vertex_program(const u32* data, u32 entry, RSXVertexProgram& dst_prog) { - vertex_program_utils::vertex_program_metadata result; + vertex_program_utils::vertex_program_metadata result{}; u32 last_instruction_address = 0; u32 first_instruction_address = entry; @@ -79,6 +79,17 @@ vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vert instruction_range.first = std::min(current_instrution, instruction_range.first); instruction_range.second = std::max(current_instrution, instruction_range.second); + // Basic vec op analysis, must be done before flow analysis + switch (d1.vec_opcode) + { + case RSX_VEC_OPCODE_TXL: + { + d2.HEX = instruction->word[2]; + result.referenced_textures_mask |= (1 << d2.tex_num); + break; + } + } + bool static_jump = false; bool function_call = true; @@ -223,7 +234,7 @@ vertex_program_utils::vertex_program_metadata vertex_program_utils::analyse_vert // Verification for (const u32 target : dst_prog.jump_table) { - if (!result.instruction_mask[target]) + if (!dst_prog.instruction_mask[target]) { LOG_ERROR(RSX, "vp_analyser: Failed, branch target 0x%x was not resolved", target); } @@ -237,6 +248,7 @@ size_t vertex_program_storage_hash::operator()(const RSXVertexProgram &program) { size_t hash = vertex_program_utils::get_vertex_program_ucode_hash(program); hash ^= program.output_mask; + hash ^= program.texture_dimensions; return hash; } @@ -244,6 +256,8 @@ bool vertex_program_compare::operator()(const RSXVertexProgram &binary1, const R { if (binary1.output_mask != binary2.output_mask) return false; + if (binary1.texture_dimensions != binary2.texture_dimensions) + return false; if (binary1.data.size() != binary2.data.size()) return false; if (binary1.jump_table != binary2.jump_table) diff --git a/rpcs3/Emu/RSX/Common/ProgramStateCache.h b/rpcs3/Emu/RSX/Common/ProgramStateCache.h index f971a38e38..210ae351e7 100644 --- a/rpcs3/Emu/RSX/Common/ProgramStateCache.h +++ b/rpcs3/Emu/RSX/Common/ProgramStateCache.h @@ -31,6 +31,7 @@ namespace program_hash_util { std::bitset<512> instruction_mask; u32 ucode_length; + u32 referenced_textures_mask; }; static size_t get_vertex_program_ucode_hash(const RSXVertexProgram &program); diff --git a/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp b/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp index bb28dc1b23..5f533ee740 100644 --- a/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Common/VertexProgramDecompiler.cpp @@ -176,7 +176,24 @@ void VertexProgramDecompiler::SetDST(bool is_sca, std::string value) std::string VertexProgramDecompiler::GetTex() { - return m_parr.AddParam(PF_PARAM_UNIFORM, "sampler2D", std::string("vtex") + std::to_string(d2.tex_num)); + std::string sampler; + switch (m_prog.get_texture_dimension(d2.tex_num)) + { + case rsx::texture_dimension_extended::texture_dimension_1d: + sampler = "sampler1D"; + break; + case rsx::texture_dimension_extended::texture_dimension_2d: + sampler = "sampler2D"; + break; + case rsx::texture_dimension_extended::texture_dimension_3d: + sampler = "sampler3D"; + break; + case rsx::texture_dimension_extended::texture_dimension_cubemap: + sampler = "samplerCube"; + break; + } + + return m_parr.AddParam(PF_PARAM_UNIFORM, sampler, std::string("vtex") + std::to_string(d2.tex_num)); } std::string VertexProgramDecompiler::Format(const std::string& code) @@ -612,8 +629,26 @@ std::string VertexProgramDecompiler::Decompile() case RSX_VEC_OPCODE_SNE: SetDSTVec(getFloatTypeName(4) + "(" + compareFunction(COMPARE::FUNCTION_SNE, "$0", "$1") + ")"); break; case RSX_VEC_OPCODE_STR: SetDSTVec(getFunction(FUNCTION::FUNCTION_STR)); break; case RSX_VEC_OPCODE_SSG: SetDSTVec("sign($0)"); break; - case RSX_VEC_OPCODE_TXL: SetDSTVec(getFunction(FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D)); break; + case RSX_VEC_OPCODE_TXL: + { + switch (m_prog.get_texture_dimension(d2.tex_num)) + { + case rsx::texture_dimension_extended::texture_dimension_1d: + SetDSTVec(getFunction(FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH1D)); + break; + case rsx::texture_dimension_extended::texture_dimension_2d: + SetDSTVec(getFunction(FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D)); + break; + case rsx::texture_dimension_extended::texture_dimension_3d: + SetDSTVec(getFunction(FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH3D)); + break; + case rsx::texture_dimension_extended::texture_dimension_cubemap: + SetDSTVec(getFunction(FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCHCUBE)); + break; + } + break; + } default: AddCode(fmt::format("//Unknown vp opcode 0x%x", u32{ d1.vec_opcode })); LOG_ERROR(RSX, "Unknown vp opcode 0x%x", u32{ d1.vec_opcode }); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.cpp b/rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.cpp index 7e8e71ce65..e186661166 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.cpp @@ -25,7 +25,7 @@ std::string getFunctionImp(FUNCTION f) switch (f) { default: - abort(); + fmt::throw_exception("Unsupported program function %d", (u32)f); case FUNCTION::FUNCTION_DP2: return "dot($0.xy, $1.xy).xxxx"; case FUNCTION::FUNCTION_DP2A: diff --git a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp index 4494a97dd0..93c61500b3 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp @@ -6,6 +6,7 @@ #include "D3D12Formats.h" #include "../rsx_methods.h" #include "../rsx_utils.h" +#include "../Common/TextureUtils.h" #define TO_STRING(x) #x @@ -53,7 +54,7 @@ void D3D12GSRender::load_program() return std::make_tuple(true, native_pitch); }; - get_current_vertex_program(false); + get_current_vertex_program({}, true); get_current_fragment_program_legacy(rtt_lookup_func); if (!current_fragment_program.valid) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 1dc4ab7a74..970bb63c32 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -24,7 +24,7 @@ namespace GLGSRender::GLGSRender() : GSRender() { - m_shaders_cache.reset(new gl::shader_cache(m_prog_buffer, "opengl", "v1.5")); + m_shaders_cache.reset(new gl::shader_cache(m_prog_buffer, "opengl", "v1.6")); if (g_cfg.video.disable_vertex_cache) m_vertex_cache.reset(new gl::null_vertex_cache()); @@ -330,7 +330,7 @@ void GLGSRender::end() *sampler_state = m_gl_texture_cache.upload_texture(unused, rsx::method_registers.fragment_textures[i], m_rtts); if (m_textures_dirty[i]) - m_gl_sampler_states[i].apply(rsx::method_registers.fragment_textures[i], fs_sampler_state[i].get()); + m_fs_sampler_states[i].apply(rsx::method_registers.fragment_textures[i], fs_sampler_state[i].get()); } else { @@ -354,6 +354,9 @@ void GLGSRender::end() if (rsx::method_registers.vertex_textures[i].enabled()) { *sampler_state = m_gl_texture_cache.upload_texture(unused, rsx::method_registers.vertex_textures[i], m_rtts); + + if (m_vertex_textures_dirty[i]) + m_vs_sampler_states[i].apply(rsx::method_registers.vertex_textures[i], vs_sampler_state[i].get()); } else *sampler_state = {}; @@ -783,8 +786,14 @@ void GLGSRender::on_init_thread() for (int i = 0; i < rsx::limits::fragment_textures_count; ++i) { - m_gl_sampler_states[i].create(); - m_gl_sampler_states[i].bind(i); + m_fs_sampler_states[i].create(); + m_fs_sampler_states[i].bind(i); + } + + for (int i = 0; i < rsx::limits::vertex_textures_count; ++i) + { + m_vs_sampler_states[i].create(); + m_vs_sampler_states[i].bind(rsx::limits::fragment_textures_count + i); } //Occlusion query @@ -917,7 +926,12 @@ void GLGSRender::on_exit() m_gl_persistent_stream_buffer.reset(); m_gl_volatile_stream_buffer.reset(); - for (auto &sampler : m_gl_sampler_states) + for (auto &sampler : m_fs_sampler_states) + { + sampler.remove(); + } + + for (auto &sampler : m_vs_sampler_states) { sampler.remove(); } @@ -1101,7 +1115,7 @@ void GLGSRender::load_program(const gl::vertex_upload_info& upload_info) get_current_fragment_program(fs_sampler_state); verify(HERE), current_fragment_program.valid; - get_current_vertex_program(); + get_current_vertex_program(vs_sampler_state); current_vertex_program.skip_vertex_input_check = true; //not needed for us since decoding is done server side current_fragment_program.unnormalized_coords = 0; //unused diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index b7ed3d235c..491bd27946 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -279,7 +279,8 @@ private: GLFragmentProgram m_fragment_prog; GLVertexProgram m_vertex_prog; - gl::sampler_state m_gl_sampler_states[rsx::limits::fragment_textures_count]; + gl::sampler_state m_fs_sampler_states[rsx::limits::fragment_textures_count]; + gl::sampler_state m_vs_sampler_states[rsx::limits::vertex_textures_count]; gl::glsl::program *m_program; diff --git a/rpcs3/Emu/RSX/GL/GLProgramBuffer.h b/rpcs3/Emu/RSX/GL/GLProgramBuffer.h index 7230ce0960..c30ac209e8 100644 --- a/rpcs3/Emu/RSX/GL/GLProgramBuffer.h +++ b/rpcs3/Emu/RSX/GL/GLProgramBuffer.h @@ -48,14 +48,14 @@ struct GLTraits for (int i = 0; i < rsx::limits::fragment_textures_count; ++i) { int location; - if (result.uniforms.has_location("tex" + std::to_string(i), &location)) + if (result.uniforms.has_location(rsx::constants::fragment_texture_names[i], &location)) result.uniforms[location] = i; } for (int i = 0; i < rsx::limits::vertex_textures_count; ++i) { int location; - if (result.uniforms.has_location("vtex" + std::to_string(i), &location)) + if (result.uniforms.has_location(rsx::constants::vertex_texture_names[i], &location)) result.uniforms[location] = (i + rsx::limits::fragment_textures_count); } diff --git a/rpcs3/Emu/RSX/GL/GLTexture.cpp b/rpcs3/Emu/RSX/GL/GLTexture.cpp index 0db427b00c..d3446636fc 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.cpp +++ b/rpcs3/Emu/RSX/GL/GLTexture.cpp @@ -204,7 +204,7 @@ namespace gl } //Apply sampler state settings - void sampler_state::apply(rsx::fragment_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image) + void sampler_state::apply(const rsx::fragment_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image) { const color4f border_color = rsx::decode_border_color(tex.border_color()); @@ -274,6 +274,22 @@ namespace gl glSamplerParameteri(samplerHandle, GL_TEXTURE_COMPARE_MODE, GL_NONE); } + void sampler_state::apply(const rsx::vertex_texture& tex, const rsx::sampled_image_descriptor_base* /*sampled_image*/) + { + const color4f border_color = rsx::decode_border_color(tex.border_color()); + glSamplerParameterfv(samplerHandle, GL_TEXTURE_BORDER_COLOR, border_color.rgba); + + glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_S, wrap_mode(tex.wrap_s())); + glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_T, wrap_mode(tex.wrap_t())); + glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_R, wrap_mode(tex.wrap_r())); + glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glSamplerParameteri(samplerHandle, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glSamplerParameterf(samplerHandle, GL_TEXTURE_LOD_BIAS, tex.bias()); + glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_LOD, (tex.min_lod() >> 8)); + glSamplerParameteri(samplerHandle, GL_TEXTURE_MAX_LOD, (tex.max_lod() >> 8)); + glSamplerParameteri(samplerHandle, GL_TEXTURE_COMPARE_MODE, GL_NONE); + } + bool is_compressed_format(u32 texture_format) { switch (texture_format) diff --git a/rpcs3/Emu/RSX/GL/GLTexture.h b/rpcs3/Emu/RSX/GL/GLTexture.h index 066da41ce6..cbdb656b90 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.h +++ b/rpcs3/Emu/RSX/GL/GLTexture.h @@ -57,6 +57,7 @@ namespace gl glBindSampler(index, samplerHandle); } - void apply(rsx::fragment_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image); + void apply(const rsx::fragment_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image); + void apply(const rsx::vertex_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image); }; } diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index 7801e2dd15..27730d3695 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -191,17 +191,6 @@ void GLVertexDecompilerThread::insertMainStart(std::stringstream & OS) OS << " vec4 " << PI.name << "= read_location(" << std::to_string(PI.location) << ");\n"; } } - - for (const ParamType &PT : m_parr.params[PF_PARAM_UNIFORM]) - { - if (PT.type == "sampler2D") - { - for (const ParamItem &PI : PT.items) - { - OS << " vec2 " << PI.name << "_coord_scale = vec2(1.);\n"; - } - } - } } void GLVertexDecompilerThread::insertMainEnd(std::stringstream & OS) diff --git a/rpcs3/Emu/RSX/RSXTexture.cpp b/rpcs3/Emu/RSX/RSXTexture.cpp index 522837227b..3673083ad9 100644 --- a/rpcs3/Emu/RSX/RSXTexture.cpp +++ b/rpcs3/Emu/RSX/RSXTexture.cpp @@ -396,11 +396,6 @@ namespace rsx return (max_mipmap_count > 0) ? max_mipmap_count : 1; } - u8 vertex_texture::unsigned_remap() const - { - return ((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 12) & 0xf); - } - std::pair, std::array> vertex_texture::decoded_remap() const { return @@ -416,26 +411,6 @@ namespace rsx return 0xAAE4; } - u8 vertex_texture::zfunc() const - { - return ((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 28) & 0xf); - } - - u8 vertex_texture::gamma() const - { - return ((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 20) & 0xf); - } - - u8 vertex_texture::aniso_bias() const - { - return ((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 4) & 0xf); - } - - u8 vertex_texture::signed_remap() const - { - return ((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 24) & 0xf); - } - bool vertex_texture::enabled() const { return location() <= 1 && ((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 31) & 0x1); @@ -451,16 +426,6 @@ namespace rsx return ((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 7) & 0xfff); } - rsx::texture_max_anisotropy vertex_texture::max_aniso() const - { - return rsx::to_texture_max_anisotropy((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 4) & 0x7); - } - - bool vertex_texture::alpha_kill_enabled() const - { - return ((registers[NV4097_SET_VERTEX_TEXTURE_CONTROL0 + (m_index * 8)] >> 2) & 0x1); - } - u16 vertex_texture::bias() const { return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)]) & 0x1fff); @@ -468,37 +433,27 @@ namespace rsx rsx::texture_minify_filter vertex_texture::min_filter() const { - return rsx::to_texture_minify_filter((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 16) & 0x7); + return rsx::texture_minify_filter::nearest; } rsx::texture_magnify_filter vertex_texture::mag_filter() const { - return rsx::to_texture_magnify_filter((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 24) & 0x7); + return rsx::texture_magnify_filter::nearest; } - u8 vertex_texture::convolution_filter() const + rsx::texture_wrap_mode vertex_texture::wrap_s() const { - return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 13) & 0xf); + return rsx::to_texture_wrap_mode((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)]) & 0xf); } - bool vertex_texture::a_signed() const + rsx::texture_wrap_mode vertex_texture::wrap_t() const { - return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 28) & 0x1); + return rsx::to_texture_wrap_mode((registers[NV4097_SET_VERTEX_TEXTURE_ADDRESS + (m_index * 8)] >> 8) & 0xf); } - bool vertex_texture::r_signed() const + rsx::texture_wrap_mode vertex_texture::wrap_r() const { - return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 29) & 0x1); - } - - bool vertex_texture::g_signed() const - { - return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 30) & 0x1); - } - - bool vertex_texture::b_signed() const - { - return ((registers[NV4097_SET_VERTEX_TEXTURE_FILTER + (m_index * 8)] >> 31) & 0x1); + return rsx::texture_wrap_mode::wrap; } u16 vertex_texture::width() const diff --git a/rpcs3/Emu/RSX/RSXTexture.h b/rpcs3/Emu/RSX/RSXTexture.h index 0d132b8926..19d05b1bca 100644 --- a/rpcs3/Emu/RSX/RSXTexture.h +++ b/rpcs3/Emu/RSX/RSXTexture.h @@ -123,11 +123,9 @@ namespace rsx u16 mipmap() const; // Address - u8 unsigned_remap() const; - u8 zfunc() const; - u8 gamma() const; - u8 aniso_bias() const; - u8 signed_remap() const; + rsx::texture_wrap_mode wrap_s() const; + rsx::texture_wrap_mode wrap_t() const; + rsx::texture_wrap_mode wrap_r() const; std::pair, std::array> decoded_remap() const; u32 remap() const; @@ -136,18 +134,11 @@ namespace rsx bool enabled() const; u16 min_lod() const; u16 max_lod() const; - rsx::texture_max_anisotropy max_aniso() const; - bool alpha_kill_enabled() const; // Filter u16 bias() const; rsx::texture_minify_filter min_filter() const; rsx::texture_magnify_filter mag_filter() const; - u8 convolution_filter() const; - bool a_signed() const; - bool r_signed() const; - bool g_signed() const; - bool b_signed() const; // Image Rect u16 width() const; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 1c08e1d6f0..32d6bff805 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -829,15 +829,15 @@ namespace rsx } default: { - //TODO: Reorder draw commands between synchronization events to maximize batched sizes + // TODO: Reorder draw commands between synchronization events to maximize batched sizes static const std::pair skippable_ranges[] = { - //Texture configuration + // Texture configuration { NV4097_SET_TEXTURE_OFFSET, 8 * 16 }, { NV4097_SET_TEXTURE_CONTROL2, 16 }, { NV4097_SET_TEXTURE_CONTROL3, 16 }, { NV4097_SET_VERTEX_TEXTURE_OFFSET, 8 * 4 }, - //Surface configuration + // Surface configuration { NV4097_SET_SURFACE_CLIP_HORIZONTAL, 1 }, { NV4097_SET_SURFACE_CLIP_VERTICAL, 1 }, { NV4097_SET_SURFACE_COLOR_AOFFSET, 1 }, @@ -855,7 +855,11 @@ namespace rsx { NV4097_SET_SURFACE_PITCH_B, 1 }, { NV4097_SET_SURFACE_PITCH_C, 1 }, { NV4097_SET_SURFACE_PITCH_D, 1 }, - { NV4097_SET_SURFACE_PITCH_Z, 1 } + { NV4097_SET_SURFACE_PITCH_Z, 1 }, + // Program configuration + { NV4097_SET_TRANSFORM_PROGRAM_START, 1 }, + { NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK, 1 }, + { NV4097_SET_TRANSFORM_PROGRAM, 512 } }; if (has_deferred_call) @@ -1393,7 +1397,7 @@ namespace rsx return rsx::get_address(offset_zeta, m_context_dma_z); } - void thread::get_current_vertex_program(bool skip_vertex_inputs) + void thread::get_current_vertex_program(const std::array, rsx::limits::vertex_textures_count>& sampler_descriptors, bool skip_textures, bool skip_vertex_inputs) { if (!(m_graphics_state & rsx::pipeline_state::vertex_program_dirty)) return; @@ -1406,6 +1410,7 @@ namespace rsx current_vertex_program.rsx_vertex_inputs.resize(0); current_vertex_program.data.reserve(512 * 4); current_vertex_program.jump_table.clear(); + current_vertex_program.texture_dimensions = 0; current_vp_metadata = program_hash_util::vertex_program_utils::analyse_vertex_program ( @@ -1414,6 +1419,18 @@ namespace rsx current_vertex_program // [out] Program object ); + if (!skip_textures && current_vp_metadata.referenced_textures_mask != 0) + { + for (u32 i = 0; i < rsx::limits::vertex_textures_count; ++i) + { + const auto &tex = rsx::method_registers.vertex_textures[i]; + if (tex.enabled() && (current_vp_metadata.referenced_textures_mask & (1 << i))) + { + current_vertex_program.texture_dimensions |= ((u32)sampler_descriptors[i]->image_type << (i << 1)); + } + } + } + if (!skip_vertex_inputs) { const u32 input_mask = rsx::method_registers.vertex_attrib_input_mask(); diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 26a4efc2ab..4fd1d44c7e 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -362,6 +362,9 @@ namespace rsx u32 m_graphics_state = 0; u64 ROP_sync_timestamp = 0; + program_hash_util::fragment_program_utils::fragment_program_metadata current_fp_metadata = {}; + program_hash_util::vertex_program_utils::vertex_program_metadata current_vp_metadata = {}; + protected: std::array get_color_surface_addresses() const; u32 get_zeta_surface_address() const; @@ -374,10 +377,7 @@ namespace rsx RSXVertexProgram current_vertex_program = {}; RSXFragmentProgram current_fragment_program = {}; - program_hash_util::fragment_program_utils::fragment_program_metadata current_fp_metadata = {}; - program_hash_util::vertex_program_utils::vertex_program_metadata current_vp_metadata = {}; - - void get_current_vertex_program(bool skip_vertex_inputs = true); + void get_current_vertex_program(const std::array, rsx::limits::vertex_textures_count>& sampler_descriptors, bool skip_textures = false, bool skip_vertex_inputs = true); /** * Gets current fragment program and associated fragment state diff --git a/rpcs3/Emu/RSX/RSXVertexProgram.h b/rpcs3/Emu/RSX/RSXVertexProgram.h index 04d33ee3b3..b22e4bdd3f 100644 --- a/rpcs3/Emu/RSX/RSXVertexProgram.h +++ b/rpcs3/Emu/RSX/RSXVertexProgram.h @@ -1,5 +1,7 @@ #pragma once +#include "RSXTexture.h" + #include #include @@ -231,10 +233,16 @@ struct RSXVertexProgram std::vector data; std::vector rsx_vertex_inputs; u32 output_mask; + u32 texture_dimensions; bool skip_vertex_input_check; u32 base_address; u32 entry; std::bitset<512> instruction_mask; std::set jump_table; + + rsx::texture_dimension_extended get_texture_dimension(u8 id) const + { + return (rsx::texture_dimension_extended)((texture_dimensions >> (id * 2)) & 0x3); + } }; \ No newline at end of file diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 1091af88fe..bcd8a883f5 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -626,7 +626,7 @@ VKGSRender::VKGSRender() : GSRender() else m_vertex_cache.reset(new vk::weak_vertex_cache()); - m_shaders_cache.reset(new vk::shader_cache(*m_prog_buffer.get(), "vulkan", "v1.5")); + m_shaders_cache.reset(new vk::shader_cache(*m_prog_buffer.get(), "vulkan", "v1.6")); open_command_buffer(); @@ -2200,7 +2200,7 @@ void VKGSRender::load_program(const vk::vertex_upload_info& vertex_info) get_current_fragment_program(fs_sampler_state); verify(HERE), current_fragment_program.valid; - get_current_vertex_program(); + get_current_vertex_program(vs_sampler_state); } auto &vertex_program = current_vertex_program; diff --git a/rpcs3/Emu/RSX/rsx_cache.h b/rpcs3/Emu/RSX/rsx_cache.h index 64ab2adc9b..91e425cb4e 100644 --- a/rpcs3/Emu/RSX/rsx_cache.h +++ b/rpcs3/Emu/RSX/rsx_cache.h @@ -378,6 +378,7 @@ namespace rsx u64 pipeline_storage_hash; u32 vp_ctrl; + u32 vp_texture_dimensions; u64 vp_instruction_mask[8]; u32 vp_base_address; @@ -698,6 +699,7 @@ namespace rsx u64 state_hash = 0; state_hash ^= rpcs3::hash_base(data.vp_ctrl); state_hash ^= rpcs3::hash_base(data.fp_ctrl); + state_hash ^= rpcs3::hash_base(data.vp_texture_dimensions); state_hash ^= rpcs3::hash_base(data.fp_texture_dimensions); state_hash ^= rpcs3::hash_base(data.fp_unnormalized_coords); state_hash ^= rpcs3::hash_base(data.fp_height); @@ -750,6 +752,7 @@ namespace rsx pipeline_storage_type pipeline = data.pipeline_properties; vp.output_mask = data.vp_ctrl; + vp.texture_dimensions = data.vp_texture_dimensions; vp.base_address = data.vp_base_address; vp.entry = data.vp_entry; @@ -796,6 +799,7 @@ namespace rsx data_block.pipeline_storage_hash = m_storage.get_hash(pipeline); data_block.vp_ctrl = vp.output_mask; + data_block.vp_texture_dimensions = vp.texture_dimensions; data_block.vp_base_address = vp.base_address; data_block.vp_entry = vp.entry; diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index fed6265522..0bc25f8824 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -563,7 +563,11 @@ namespace rsx static void impl(thread* rsx, u32 _reg, u32 arg) { rsx->m_textures_dirty[index] = true; - rsx->m_graphics_state |= rsx::pipeline_state::fragment_program_dirty; + + if (rsx->current_fp_metadata.referenced_textures_mask & (1 << index)) + { + rsx->m_graphics_state |= rsx::pipeline_state::fragment_program_dirty; + } } }; @@ -573,6 +577,11 @@ namespace rsx static void impl(thread* rsx, u32 _reg, u32 arg) { rsx->m_vertex_textures_dirty[index] = true; + + if (rsx->current_vp_metadata.referenced_textures_mask & (1 << index)) + { + rsx->m_graphics_state |= rsx::pipeline_state::vertex_program_dirty; + } } }; }