From 149fa9d75063b50b45217a6fc44d0c7d3cef37f8 Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Tue, 26 Jan 2016 20:42:54 +0100 Subject: [PATCH] rsx/common: Make RSXFragmentProgram key and not just pointer. --- rpcs3/Emu/RSX/CgBinaryProgram.h | 2 +- .../RSX/Common/FragmentProgramDecompiler.cpp | 4 +-- .../RSX/Common/FragmentProgramDecompiler.h | 2 +- rpcs3/Emu/RSX/Common/ProgramStateCache.cpp | 13 +++++--- rpcs3/Emu/RSX/Common/ProgramStateCache.h | 32 ++++++++++++------- rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp | 2 +- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 2 +- rpcs3/Emu/RSX/RSXFragmentProgram.h | 6 +++- 8 files changed, 39 insertions(+), 24 deletions(-) diff --git a/rpcs3/Emu/RSX/CgBinaryProgram.h b/rpcs3/Emu/RSX/CgBinaryProgram.h index b907fc121a..31b9dfefbb 100644 --- a/rpcs3/Emu/RSX/CgBinaryProgram.h +++ b/rpcs3/Emu/RSX/CgBinaryProgram.h @@ -335,7 +335,7 @@ public: u32 ctrl = (vmfprog.outputFromH0 ? 0 : 0x40) | (vmfprog.depthReplace ? 0xe : 0); std::vector td; RSXFragmentProgram prog; - prog.size = 0, prog.addr = ptr + vmprog.ucode, prog.offset = 0, prog.ctrl = ctrl; + prog.size = 0, prog.addr = vm::base(ptr + vmprog.ucode), prog.offset = 0, prog.ctrl = ctrl; GLFragmentDecompilerThread(m_glsl_shader, param_array, prog, size).Task(); vm::close(); } diff --git a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp index 88435164e3..73dc096733 100644 --- a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp @@ -113,7 +113,7 @@ std::string FragmentProgramDecompiler::AddConst() return name; } - auto data = vm::ps3::ptr::make(m_prog.addr + m_size + 4 * SIZE_32(u32)); + auto data = (be_t*) ((char*)m_prog.addr + m_size + 4 * SIZE_32(u32)); m_offset = 2 * 4 * sizeof(u32); u32 x = GetData(data[0]); @@ -493,7 +493,7 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode) std::string FragmentProgramDecompiler::Decompile() { - auto data = vm::ps3::ptr::make(m_prog.addr); + auto data = (be_t*) m_prog.addr; m_size = 0; m_location = 0; m_loop_count = 0; diff --git a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h index 81279fde0e..92761b7769 100644 --- a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h +++ b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h @@ -26,7 +26,6 @@ class FragmentProgramDecompiler std::string main; u32& m_size; - const RSXFragmentProgram &m_prog; u32 m_const_index; u32 m_offset; u32 m_location; @@ -75,6 +74,7 @@ class FragmentProgramDecompiler */ bool handle_tex_srb(u32 opcode); protected: + const RSXFragmentProgram &m_prog; u32 m_ctrl; /** returns the type name of float vectors. */ diff --git a/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp index d98ef92d2b..02d510b361 100644 --- a/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp +++ b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp @@ -74,11 +74,11 @@ size_t fragment_program_utils::get_fragment_program_ucode_size(void *ptr) } } -size_t fragment_program_hash::operator()(const void *program) const +size_t fragment_program_hash::operator()(const RSXFragmentProgram& program) const { // 64-bit Fowler/Noll/Vo FNV-1a hash code size_t hash = 0xCBF29CE484222325ULL; - const qword *instbuffer = (const qword*)program; + const qword *instbuffer = (const qword*)program.addr; size_t instIndex = 0; while (true) { @@ -101,10 +101,13 @@ size_t fragment_program_hash::operator()(const void *program) const return 0; } -bool fragment_program_compare::operator()(const void *binary1, const void *binary2) const +bool fragment_program_compare::operator()(const RSXFragmentProgram& binary1, const RSXFragmentProgram& binary2) const { - const qword *instBuffer1 = (const qword*)binary1; - const qword *instBuffer2 = (const qword*)binary2; + if (binary1.texture_dimensions != binary2.texture_dimensions || binary1.unnormalized_coords != binary2.unnormalized_coords || + binary1.height != binary2.height || binary1.origin_mode != binary2.origin_mode || binary1.pixel_center_mode != binary2.pixel_center_mode) + return false; + const qword *instBuffer1 = (const qword*)binary1.addr; + const qword *instBuffer2 = (const qword*)binary2.addr; size_t instIndex = 0; while (true) { diff --git a/rpcs3/Emu/RSX/Common/ProgramStateCache.h b/rpcs3/Emu/RSX/Common/ProgramStateCache.h index c172e34bed..1f6e82050a 100644 --- a/rpcs3/Emu/RSX/Common/ProgramStateCache.h +++ b/rpcs3/Emu/RSX/Common/ProgramStateCache.h @@ -43,12 +43,12 @@ namespace program_hash_util struct fragment_program_hash { - size_t operator()(const void *program) const; + size_t operator()(const RSXFragmentProgram &program) const; }; struct fragment_program_compare { - bool operator()(const void *binary1, const void *binary2) const; + bool operator()(const RSXFragmentProgram &binary1, const RSXFragmentProgram &binary2) const; }; } @@ -76,7 +76,7 @@ class program_state_cache using fragment_program_type = typename backend_traits::fragment_program_type; using binary_to_vertex_program = std::unordered_map ; - using binary_to_fragment_program = std::unordered_map; + using binary_to_fragment_program = std::unordered_map; struct pipeline_key @@ -130,16 +130,18 @@ private: /// bool here to inform that the program was preexisting. std::tuple search_fragment_program(const RSXFragmentProgram& rsx_fp) { - const auto& I = m_fragment_shader_cache.find(vm::base(rsx_fp.addr)); + const auto& I = m_fragment_shader_cache.find(rsx_fp); if (I != m_fragment_shader_cache.end()) { return std::forward_as_tuple(I->second, true); } LOG_NOTICE(RSX, "FP not found in buffer!"); - size_t fragment_program_size = program_hash_util::fragment_program_utils::get_fragment_program_ucode_size(vm::base(rsx_fp.addr)); + size_t fragment_program_size = program_hash_util::fragment_program_utils::get_fragment_program_ucode_size(rsx_fp.addr); gsl::not_null fragment_program_ucode_copy = malloc(fragment_program_size); - std::memcpy(fragment_program_ucode_copy, vm::base(rsx_fp.addr), fragment_program_size); - fragment_program_type &new_shader = m_fragment_shader_cache[fragment_program_ucode_copy]; + std::memcpy(fragment_program_ucode_copy, rsx_fp.addr, fragment_program_size); + RSXFragmentProgram new_fp_key = rsx_fp; + new_fp_key.addr = fragment_program_ucode_copy; + fragment_program_type &new_shader = m_fragment_shader_cache[new_fp_key]; backend_traits::recompile_fragment_program(rsx_fp, new_shader, m_next_id++); return std::forward_as_tuple(new_shader, false); @@ -147,7 +149,13 @@ private: public: program_state_cache() = default; - ~program_state_cache() = default; + ~program_state_cache() + { + for (auto& pair : m_fragment_shader_cache) + { + free(pair.first.addr); + } + }; const vertex_program_type& get_transform_program(const RSXVertexProgram& rsx_vp) const { @@ -159,7 +167,7 @@ public: const fragment_program_type& get_shader_program(const RSXFragmentProgram& rsx_fp) const { - auto I = m_fragment_shader_cache.find(vm::base(rsx_fp.addr)); + auto I = m_fragment_shader_cache.find(rsx_fp); if (I != m_fragment_shader_cache.end()) return I->second; throw new EXCEPTION("Trying to get unknow shader program"); @@ -200,7 +208,7 @@ public: size_t get_fragment_constants_buffer_size(const RSXFragmentProgram &fragmentShader) const { - const auto I = m_fragment_shader_cache.find(vm::base(fragmentShader.addr)); + const auto I = m_fragment_shader_cache.find(fragmentShader); if (I != m_fragment_shader_cache.end()) return I->second.FragmentConstantOffsetCache.size() * 4 * sizeof(float); LOG_ERROR(RSX, "Can't retrieve constant offset cache"); @@ -209,7 +217,7 @@ public: void fill_fragment_constans_buffer(gsl::span dst_buffer, const RSXFragmentProgram &fragment_program) const { - const auto I = m_fragment_shader_cache.find(vm::base(fragment_program.addr)); + const auto I = m_fragment_shader_cache.find(fragment_program); if (I == m_fragment_shader_cache.end()) return; __m128i mask = _mm_set_epi8(0xE, 0xF, 0xC, 0xD, @@ -222,7 +230,7 @@ public: size_t offset = 0; for (size_t offset_in_fragment_program : I->second.FragmentConstantOffsetCache) { - void *data = vm::base(fragment_program.addr + (u32)offset_in_fragment_program); + void *data = (char*)fragment_program.addr + (u32)offset_in_fragment_program; const __m128i &vector = _mm_loadu_si128((__m128i*)data); const __m128i &shuffled_vector = _mm_shuffle_epi8(vector, mask); _mm_stream_si128((__m128i*)dst_buffer.subspan(offset, 4).data(), shuffled_vector); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp index 27d6c716ee..6c9243ac43 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp @@ -42,7 +42,7 @@ void D3D12GSRender::load_program() u32 shader_program = rsx::method_registers[NV4097_SET_SHADER_PROGRAM]; m_fragment_program.offset = shader_program & ~0x3; - m_fragment_program.addr = rsx::get_address(m_fragment_program.offset, (shader_program & 0x3) - 1); + m_fragment_program.addr = vm::base(rsx::get_address(m_fragment_program.offset, (shader_program & 0x3) - 1)); m_fragment_program.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL]; std::array texture_dimensions; diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 6dddb5e455..8c87976a94 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -741,7 +741,7 @@ bool GLGSRender::load_program() RSXFragmentProgram fragment_program; u32 shader_program = rsx::method_registers[NV4097_SET_SHADER_PROGRAM]; fragment_program.offset = shader_program & ~0x3; - fragment_program.addr = rsx::get_address(fragment_program.offset, (shader_program & 0x3) - 1); + fragment_program.addr = vm::base(rsx::get_address(fragment_program.offset, (shader_program & 0x3) - 1)); fragment_program.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL]; std::array texture_dimensions; diff --git a/rpcs3/Emu/RSX/RSXFragmentProgram.h b/rpcs3/Emu/RSX/RSXFragmentProgram.h index a07064c192..643aa90068 100644 --- a/rpcs3/Emu/RSX/RSXFragmentProgram.h +++ b/rpcs3/Emu/RSX/RSXFragmentProgram.h @@ -1,4 +1,5 @@ #pragma once +#include "GCM.h" enum { @@ -214,11 +215,14 @@ enum class texture_dimension : u8 struct RSXFragmentProgram { u32 size; - u32 addr; + void *addr; u32 offset; u32 ctrl; u16 unnormalized_coords; u32 texture_dimensions; + rsx::window_origin origin_mode; + rsx::window_pixel_center pixel_center_mode; + u16 height; texture_dimension get_texture_dimension(u8 id) const {