Skip to content

Commit

Permalink
Merge pull request RPCS3#1448 from vlj/rsx
Browse files Browse the repository at this point in the history
rsx: Add vertex input and output in RSXVertexProgram.
  • Loading branch information
vlj committed Jan 23, 2016
2 parents 52110e0 + 4ce4cf5 commit 9875bf9
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 44 deletions.
20 changes: 12 additions & 8 deletions rpcs3/Emu/RSX/Common/ProgramStateCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@

using namespace program_hash_util;

size_t vertex_program_hash::operator()(const std::vector<u32> &program) const
size_t vertex_program_hash::operator()(const RSXVertexProgram &program) const
{
// 64-bit Fowler/Noll/Vo FNV-1a hash code
size_t hash = 0xCBF29CE484222325ULL;
const qword *instbuffer = (const qword*)program.data();
const qword *instbuffer = (const qword*)program.data.data();
size_t instIndex = 0;
bool end = false;
for (unsigned i = 0; i < program.size() / 4; i++)
for (unsigned i = 0; i < program.data.size() / 4; i++)
{
const qword inst = instbuffer[instIndex];
hash ^= inst.dword[0];
Expand All @@ -22,13 +22,17 @@ size_t vertex_program_hash::operator()(const std::vector<u32> &program) const
return hash;
}

bool vertex_program_compare::operator()(const std::vector<u32> &binary1, const std::vector<u32> &binary2) const
bool vertex_program_compare::operator()(const RSXVertexProgram &binary1, const RSXVertexProgram &binary2) const
{
if (binary1.size() != binary2.size()) return false;
const qword *instBuffer1 = (const qword*)binary1.data();
const qword *instBuffer2 = (const qword*)binary2.data();
if (binary1.output_mask != binary2.output_mask)
return false;
if (binary1.rsx_vertex_inputs != binary2.rsx_vertex_inputs)
return false;
if (binary1.data.size() != binary2.data.size()) return false;
const qword *instBuffer1 = (const qword*)binary1.data.data();
const qword *instBuffer2 = (const qword*)binary2.data.data();
size_t instIndex = 0;
for (unsigned i = 0; i < binary1.size() / 4; i++)
for (unsigned i = 0; i < binary1.data.size() / 4; i++)
{
const qword& inst1 = instBuffer1[instIndex];
const qword& inst2 = instBuffer2[instIndex];
Expand Down
12 changes: 6 additions & 6 deletions rpcs3/Emu/RSX/Common/ProgramStateCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ namespace program_hash_util

struct vertex_program_hash
{
size_t operator()(const std::vector<u32> &program) const;
size_t operator()(const RSXVertexProgram &program) const;
};

struct vertex_program_compare
{
bool operator()(const std::vector<u32> &binary1, const std::vector<u32> &binary2) const;
bool operator()(const RSXVertexProgram &binary1, const RSXVertexProgram &binary2) const;
};

struct fragment_program_utils
Expand Down Expand Up @@ -75,7 +75,7 @@ class program_state_cache
using vertex_program_type = typename backend_traits::vertex_program_type;
using fragment_program_type = typename backend_traits::fragment_program_type;

using binary_to_vertex_program = std::unordered_map<std::vector<u32>, 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>;


Expand Down Expand Up @@ -115,13 +115,13 @@ class program_state_cache
/// bool here to inform that the program was preexisting.
std::tuple<const vertex_program_type&, bool> search_vertex_program(const RSXVertexProgram& rsx_vp)
{
const auto& I = m_vertex_shader_cache.find(rsx_vp.data);
const auto& I = m_vertex_shader_cache.find(rsx_vp);
if (I != m_vertex_shader_cache.end())
{
return std::forward_as_tuple(I->second, true);
}
LOG_NOTICE(RSX, "VP not found in buffer!");
vertex_program_type& new_shader = m_vertex_shader_cache[rsx_vp.data];
vertex_program_type& new_shader = m_vertex_shader_cache[rsx_vp];
backend_traits::recompile_vertex_program(rsx_vp, new_shader, m_next_id++);

return std::forward_as_tuple(new_shader, false);
Expand Down Expand Up @@ -151,7 +151,7 @@ class program_state_cache

const vertex_program_type& get_transform_program(const RSXVertexProgram& rsx_vp) const
{
auto I = m_vertex_shader_cache.find(rsx_vp.data);
auto I = m_vertex_shader_cache.find(rsx_vp);
if (I != m_vertex_shader_cache.end())
return I->second;
throw new EXCEPTION("Trying to get unknow transform program");
Expand Down
15 changes: 1 addition & 14 deletions rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,7 @@ void Shader::Compile(const std::string &code, SHADER_TYPE st)

void D3D12GSRender::load_program()
{
u32 transform_program_start = rsx::method_registers[NV4097_SET_TRANSFORM_PROGRAM_START];
m_vertex_program.data.reserve((512 - transform_program_start) * 4);

for (int i = transform_program_start; i < 512; ++i)
{
m_vertex_program.data.resize((i - transform_program_start) * 4 + 4);
memcpy(m_vertex_program.data.data() + (i - transform_program_start) * 4, transform_program + i * 4, 4 * sizeof(u32));

D3 d3;
d3.HEX = transform_program[i * 4 + 3];

if (d3.end)
break;
}
m_vertex_program = get_current_vertex_program();

u32 shader_program = rsx::method_registers[NV4097_SET_SHADER_PROGRAM];
m_fragment_program.offset = shader_program & ~0x3;
Expand Down
17 changes: 1 addition & 16 deletions rpcs3/Emu/RSX/GL/GLGSRender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,22 +738,7 @@ bool GLGSRender::do_method(u32 cmd, u32 arg)
bool GLGSRender::load_program()
{
#if 1
RSXVertexProgram vertex_program;
u32 transform_program_start = rsx::method_registers[NV4097_SET_TRANSFORM_PROGRAM_START];
vertex_program.data.reserve((512 - transform_program_start) * 4);

for (int i = transform_program_start; i < 512; ++i)
{
vertex_program.data.resize((i - transform_program_start) * 4 + 4);
memcpy(vertex_program.data.data() + (i - transform_program_start) * 4, transform_program + i * 4, 4 * sizeof(u32));

D3 d3;
d3.HEX = transform_program[i * 4 + 3];

if (d3.end)
break;
}

RSXVertexProgram vertex_program = get_current_vertex_program();
RSXFragmentProgram fragment_program;
u32 shader_program = rsx::method_registers[NV4097_SET_SHADER_PROGRAM];
fragment_program.offset = shader_program & ~0x3;
Expand Down
56 changes: 56 additions & 0 deletions rpcs3/Emu/RSX/RSXThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,62 @@ namespace rsx
return rsx::get_address(offset_zeta, m_context_dma_z);
}

RSXVertexProgram thread::get_current_vertex_program() const
{
RSXVertexProgram result = {};
u32 transform_program_start = rsx::method_registers[NV4097_SET_TRANSFORM_PROGRAM_START];
result.data.reserve((512 - transform_program_start) * 4);

for (int i = transform_program_start; i < 512; ++i)
{
result.data.resize((i - transform_program_start) * 4 + 4);
memcpy(result.data.data() + (i - transform_program_start) * 4, transform_program + i * 4, 4 * sizeof(u32));

D3 d3;
d3.HEX = transform_program[i * 4 + 3];

if (d3.end)
break;
}
result.output_mask = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK];

u32 input_mask = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_INPUT_MASK];
u32 modulo_mask = rsx::method_registers[NV4097_SET_FREQUENCY_DIVIDER_OPERATION];
result.rsx_vertex_inputs.clear();
for (u8 index = 0; index < rsx::limits::vertex_count; ++index)
{
bool enabled = !!(input_mask & (1 << index));
if (!enabled)
continue;

if (vertex_arrays_info[index].size > 0)
{
result.rsx_vertex_inputs.push_back(
{
index,
vertex_arrays_info[index].size,
vertex_arrays_info[index].frequency,
!!((modulo_mask >> index) & 0x1),
true
}
);
}
else if (register_vertex_info[index].size > 0)
{
result.rsx_vertex_inputs.push_back(
{
index,
register_vertex_info[index].size,
register_vertex_info[index].frequency,
!!((modulo_mask >> index) & 0x1),
false
}
);
}
}
return result;
}

void thread::reset()
{
//setup method registers
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/RSX/RSXThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ namespace rsx
protected:
std::array<u32, 4> get_color_surface_addresses() const;
u32 get_zeta_surface_address() const;
RSXVertexProgram get_current_vertex_program() const;

public:
u32 draw_array_count;
Expand Down
16 changes: 16 additions & 0 deletions rpcs3/Emu/RSX/RSXVertexProgram.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,23 @@ static const std::string rsx_vp_vec_op_names[] =
"SEQ", "SFL", "SGT", "SLE", "SNE", "STR", "SSG", "NULL", "NULL", "TXL"
};

struct rsx_vertex_input
{
u8 location; // between 0 and 15
u8 size; // between 1 and 4
u16 frequency;
bool is_modulo; // either modulo frequency or divide frequency
bool is_array; // false if "reg value"

bool operator==(const rsx_vertex_input other) const
{
return location == other.location && size == other.size && frequency == other.frequency && is_modulo == other.is_modulo && is_array == other.is_array;
}
};

struct RSXVertexProgram
{
std::vector<u32> data;
std::vector<rsx_vertex_input> rsx_vertex_inputs;
u32 output_mask;
};

0 comments on commit 9875bf9

Please sign in to comment.