mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-05 14:31:24 +12:00
rsx/common: Make RSXFragmentProgram key and not just pointer.
This commit is contained in:
parent
791070c158
commit
149fa9d750
8 changed files with 39 additions and 24 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue