rsx/common: Make RSXFragmentProgram key and not just pointer.

This commit is contained in:
Vincent Lejeune 2016-01-26 20:42:54 +01:00
parent 791070c158
commit 149fa9d750
8 changed files with 39 additions and 24 deletions

View file

@ -335,7 +335,7 @@ public:
u32 ctrl = (vmfprog.outputFromH0 ? 0 : 0x40) | (vmfprog.depthReplace ? 0xe : 0); u32 ctrl = (vmfprog.outputFromH0 ? 0 : 0x40) | (vmfprog.depthReplace ? 0xe : 0);
std::vector<texture_dimension> td; std::vector<texture_dimension> td;
RSXFragmentProgram prog; 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(); GLFragmentDecompilerThread(m_glsl_shader, param_array, prog, size).Task();
vm::close(); vm::close();
} }

View file

@ -113,7 +113,7 @@ std::string FragmentProgramDecompiler::AddConst()
return name; return name;
} }
auto data = vm::ps3::ptr<u32>::make(m_prog.addr + m_size + 4 * SIZE_32(u32)); auto data = (be_t<u32>*) ((char*)m_prog.addr + m_size + 4 * SIZE_32(u32));
m_offset = 2 * 4 * sizeof(u32); m_offset = 2 * 4 * sizeof(u32);
u32 x = GetData(data[0]); u32 x = GetData(data[0]);
@ -493,7 +493,7 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
std::string FragmentProgramDecompiler::Decompile() std::string FragmentProgramDecompiler::Decompile()
{ {
auto data = vm::ps3::ptr<u32>::make(m_prog.addr); auto data = (be_t<u32>*) m_prog.addr;
m_size = 0; m_size = 0;
m_location = 0; m_location = 0;
m_loop_count = 0; m_loop_count = 0;

View file

@ -26,7 +26,6 @@ class FragmentProgramDecompiler
std::string main; std::string main;
u32& m_size; u32& m_size;
const RSXFragmentProgram &m_prog;
u32 m_const_index; u32 m_const_index;
u32 m_offset; u32 m_offset;
u32 m_location; u32 m_location;
@ -75,6 +74,7 @@ class FragmentProgramDecompiler
*/ */
bool handle_tex_srb(u32 opcode); bool handle_tex_srb(u32 opcode);
protected: protected:
const RSXFragmentProgram &m_prog;
u32 m_ctrl; u32 m_ctrl;
/** returns the type name of float vectors. /** returns the type name of float vectors.
*/ */

View file

@ -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 // 64-bit Fowler/Noll/Vo FNV-1a hash code
size_t hash = 0xCBF29CE484222325ULL; size_t hash = 0xCBF29CE484222325ULL;
const qword *instbuffer = (const qword*)program; const qword *instbuffer = (const qword*)program.addr;
size_t instIndex = 0; size_t instIndex = 0;
while (true) while (true)
{ {
@ -101,10 +101,13 @@ size_t fragment_program_hash::operator()(const void *program) const
return 0; 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; if (binary1.texture_dimensions != binary2.texture_dimensions || binary1.unnormalized_coords != binary2.unnormalized_coords ||
const qword *instBuffer2 = (const qword*)binary2; 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; size_t instIndex = 0;
while (true) while (true)
{ {

View file

@ -43,12 +43,12 @@ namespace program_hash_util
struct fragment_program_hash struct fragment_program_hash
{ {
size_t operator()(const void *program) const; size_t operator()(const RSXFragmentProgram &program) const;
}; };
struct fragment_program_compare 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 fragment_program_type = typename backend_traits::fragment_program_type;
using binary_to_vertex_program = std::unordered_map<RSXVertexProgram, vertex_program_type, program_hash_util::vertex_program_hash, program_hash_util::vertex_program_compare> ; using binary_to_vertex_program = std::unordered_map<RSXVertexProgram, vertex_program_type, program_hash_util::vertex_program_hash, program_hash_util::vertex_program_compare> ;
using binary_to_fragment_program = std::unordered_map<void *, fragment_program_type, program_hash_util::fragment_program_hash, program_hash_util::fragment_program_compare>; using binary_to_fragment_program = std::unordered_map<RSXFragmentProgram, fragment_program_type, program_hash_util::fragment_program_hash, program_hash_util::fragment_program_compare>;
struct pipeline_key struct pipeline_key
@ -130,16 +130,18 @@ private:
/// bool here to inform that the program was preexisting. /// bool here to inform that the program was preexisting.
std::tuple<const fragment_program_type&, bool> search_fragment_program(const RSXFragmentProgram& rsx_fp) std::tuple<const fragment_program_type&, bool> 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()) if (I != m_fragment_shader_cache.end())
{ {
return std::forward_as_tuple(I->second, true); return std::forward_as_tuple(I->second, true);
} }
LOG_NOTICE(RSX, "FP not found in buffer!"); 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<void*> fragment_program_ucode_copy = malloc(fragment_program_size); gsl::not_null<void*> fragment_program_ucode_copy = malloc(fragment_program_size);
std::memcpy(fragment_program_ucode_copy, vm::base(rsx_fp.addr), fragment_program_size); std::memcpy(fragment_program_ucode_copy, rsx_fp.addr, fragment_program_size);
fragment_program_type &new_shader = m_fragment_shader_cache[fragment_program_ucode_copy]; 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++); backend_traits::recompile_fragment_program(rsx_fp, new_shader, m_next_id++);
return std::forward_as_tuple(new_shader, false); return std::forward_as_tuple(new_shader, false);
@ -147,7 +149,13 @@ private:
public: public:
program_state_cache() = default; 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 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 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()) if (I != m_fragment_shader_cache.end())
return I->second; return I->second;
throw new EXCEPTION("Trying to get unknow shader program"); 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 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()) if (I != m_fragment_shader_cache.end())
return I->second.FragmentConstantOffsetCache.size() * 4 * sizeof(float); return I->second.FragmentConstantOffsetCache.size() * 4 * sizeof(float);
LOG_ERROR(RSX, "Can't retrieve constant offset cache"); LOG_ERROR(RSX, "Can't retrieve constant offset cache");
@ -209,7 +217,7 @@ public:
void fill_fragment_constans_buffer(gsl::span<f32, gsl::dynamic_range> dst_buffer, const RSXFragmentProgram &fragment_program) const void fill_fragment_constans_buffer(gsl::span<f32, gsl::dynamic_range> 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()) if (I == m_fragment_shader_cache.end())
return; return;
__m128i mask = _mm_set_epi8(0xE, 0xF, 0xC, 0xD, __m128i mask = _mm_set_epi8(0xE, 0xF, 0xC, 0xD,
@ -222,7 +230,7 @@ public:
size_t offset = 0; size_t offset = 0;
for (size_t offset_in_fragment_program : I->second.FragmentConstantOffsetCache) 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 &vector = _mm_loadu_si128((__m128i*)data);
const __m128i &shuffled_vector = _mm_shuffle_epi8(vector, mask); const __m128i &shuffled_vector = _mm_shuffle_epi8(vector, mask);
_mm_stream_si128((__m128i*)dst_buffer.subspan(offset, 4).data(), shuffled_vector); _mm_stream_si128((__m128i*)dst_buffer.subspan(offset, 4).data(), shuffled_vector);

View file

@ -42,7 +42,7 @@ void D3D12GSRender::load_program()
u32 shader_program = rsx::method_registers[NV4097_SET_SHADER_PROGRAM]; u32 shader_program = rsx::method_registers[NV4097_SET_SHADER_PROGRAM];
m_fragment_program.offset = shader_program & ~0x3; 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]; m_fragment_program.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL];
std::array<texture_dimension, 16> texture_dimensions; std::array<texture_dimension, 16> texture_dimensions;

View file

@ -741,7 +741,7 @@ bool GLGSRender::load_program()
RSXFragmentProgram fragment_program; RSXFragmentProgram fragment_program;
u32 shader_program = rsx::method_registers[NV4097_SET_SHADER_PROGRAM]; u32 shader_program = rsx::method_registers[NV4097_SET_SHADER_PROGRAM];
fragment_program.offset = shader_program & ~0x3; 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]; fragment_program.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL];
std::array<texture_dimension, 16> texture_dimensions; std::array<texture_dimension, 16> texture_dimensions;

View file

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "GCM.h"
enum enum
{ {
@ -214,11 +215,14 @@ enum class texture_dimension : u8
struct RSXFragmentProgram struct RSXFragmentProgram
{ {
u32 size; u32 size;
u32 addr; void *addr;
u32 offset; u32 offset;
u32 ctrl; u32 ctrl;
u16 unnormalized_coords; u16 unnormalized_coords;
u32 texture_dimensions; 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 texture_dimension get_texture_dimension(u8 id) const
{ {