Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rsx: initial capture/replay functionality #4510

Merged
merged 4 commits into from May 13, 2018
Merged

rsx: initial capture/replay functionality #4510

merged 4 commits into from May 13, 2018

Conversation

jarveson
Copy link
Contributor

@jarveson jarveson commented May 3, 2018

This is an initial version of a 'renderdoc' type capturing/replay system. The base idea, similar to renderdoc, is that the emulator can now 'capture' all rsx data used during a frame, and can then 'replay' it later. The general idea would be this could be used to ease testing for regressions, and ease of development of fixes, as some graphics issues could instead now be captured and fixed from replay rather than needing the full title/app. This also has the added benefit of still being able to 'renderdoc' a replay.

Implementation notes:

  • Theres only additional if check to rsx::thread::end(), should be no speed hit when not capturing
  • The 'Boot Replay' function mimics actual game/elf syscall and rsx usage, this means there is no if (replay){} type checks anywhere in emucore/rsx, which should serve to give us the same code paths and most accurate replay
  • I added xxhash submodule for calculating faster, and sparser hashes

Usage notes:

  • Although you can capture with any backend, capturing is only supported with strict rendering mode (and probably always will be), attempting to capture in non strict will just error
  • Replaying, on the other hand, supports any of the options/backends
  • Shader cache is unused when replaying, that could be changed, but for now its the way it is
  • There isn't any 'progress' once clicked, the emulator should eventually post a success message with the capture file / location. (Longer than a few minutes and the capture probably froze)
  • Also, the emulator 'pauses' after the capture, mostly so you can see what frame should have been captured
  • Also, I didnt test this on linux, but hopefully it works

Notes/PSA:

  • This does seem to capture and replay chunks of games fairly well as it stands, although there are titles that still do not work fully with this.
  • Not every capture can be 'fixed', depending on how much processing it does on the ppu/spu

@Kravickas
Copy link
Contributor

Kravickas commented May 3, 2018

Is that log spam needed while in replay?
obrazek

Otherwise it captured well in a sec., replay worked too, too late to toy with different settings for replay.

@jarveson
Copy link
Contributor Author

jarveson commented May 3, 2018

Whoops, good catch, i added a 'cached state' during replay now, which will lower/remove most of the log spam

(u64)dbstate.buffers[i].width << 32 | dbstate.buffers[i].height, (u64)dbstate.buffers[i].pitch << 32 | dbstate.buffers[i].offset, 0);
}
cs.display_buffer_hash = replay_cmd.display_buffer_state;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

newline


const auto& ti = t.pack();
sys_rsx_context_attribute(context_id, 0x300, i, (u64)ti.tile << 32 | ti.limit, (u64)ti.pitch << 32 | ti.format, 0);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

newline

default:
return 0xFFFFFFFFu;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

newline

}
else
frame_capture.memory_data_map.insert(std::make_pair(data_hash, std::move(data)));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vbcrlf


int clip_w = rsx::method_registers.surface_clip_width();
/*int clip_w = rsx::method_registers.surface_clip_width();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove this if you wish, its based on some old reasoning on what can invalidate a draw command and is technically incorrect/incomplete anyway.


const auto& zci = zc.pack();
sys_rsx_context_attribute(context_id, 0x301, i, (u64)zci.region << 32 | zci.size, (u64)zci.start << 32 | zci.offset, (u64)zci.status0 << 32 | zci.status1);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might as well toss one in here if spacing the other blocks

Copy link
Contributor

@kd-11 kd-11 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love the minimal disruption to rsx core. Maybe this should be moved to RSX/Util or RSX/Capture? RSX/ is cluttered with things unrelated to core and imo they do not belong there (I will be moving some stuff like overlays from RSX core folders)

@jarveson
Copy link
Contributor Author

Sure, added 'RSX/Capture', threw rsx_trace.h in there as well for now, also broke out the capture methods to rsx_capture.h/cpp, also lots of fixes for yakuza capture/replay

Copy link
Contributor

@Megamouse Megamouse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

madness

case CELL_GCM_CONTEXT_DMA_MEMORY_HOST_BUFFER:
case CELL_GCM_LOCATION_MAIN:
{
if (u32 result = RSXIOMem.RealAddr(offset)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{

}
case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN:
{
if (u32 result = RSXIOMem.RealAddr(0x0e000000 + offset)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{

void insert_mem_block_in_map(std::unordered_set<u64>& mem_changes, frame_capture_data::memory_block&& block, frame_capture_data::memory_block_data&& data)
{
u64 data_hash = 0;
if (data.data.size() > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{

block.data_state = data_hash;

auto it = frame_capture.memory_data_map.find(data_hash);
if (it != frame_capture.memory_data_map.end()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{


// capture fragment shader mem
const u32 shader_program = method_registers.shader_program_address();
if (shader_program != 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{

tstate.size = tile.size;
}

for (u32 i = 0; i < limits::zculls_count; ++i) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{

{
const auto target = rsx::method_registers.surface_color_target();

u32 offset_color[] = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{

rsx::method_registers.surface_d_dma(),
};

auto check_add = [&replay_command](u32 offset, u32 dma) -> void {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{

insert_mem_block_in_map(replay_command.memory_state, std::move(block), std::move(block_data));
};

for (const auto& index : utility::get_rtt_indexes(target)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{

rsx::method_registers.surface_d_offset(),
};

u32 context_dma_color[] = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{

@kd-11 kd-11 merged commit 75b4093 into RPCS3:master May 13, 2018
@jarveson jarveson deleted the rsx_capture_replay branch June 2, 2018 09:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants