From 2a882255002446dcec109ddc8075ac1be63939f5 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sat, 21 Nov 2015 21:41:41 -0600 Subject: [PATCH 1/9] TracePlayer - Expose internal playback pointers --- src/xenia/gpu/trace_player.cc | 7 +++++++ src/xenia/gpu/trace_player.h | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/xenia/gpu/trace_player.cc b/src/xenia/gpu/trace_player.cc index 40291453f..43299ef2e 100644 --- a/src/xenia/gpu/trace_player.cc +++ b/src/xenia/gpu/trace_player.cc @@ -92,11 +92,17 @@ void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data, auto command_processor = graphics_system_->command_processor(); command_processor->set_swap_mode(SwapMode::kIgnored); + player_start_ptr_ = trace_data; + player_target_ptr_ = trace_data + trace_size; + player_current_ptr_ = trace_data; + playing_trace_ = true; auto trace_ptr = trace_data; bool pending_break = false; const PacketStartCommand* pending_packet = nullptr; while (trace_ptr < trace_data + trace_size) { + player_current_ptr_ = trace_ptr; + auto type = static_cast(xe::load(trace_ptr)); switch (type) { case TraceCommandType::kPrimaryBufferStart: { @@ -184,6 +190,7 @@ void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data, } } + playing_trace_ = false; command_processor->set_swap_mode(SwapMode::kNormal); command_processor->IssueSwap(0, 1280, 720); } diff --git a/src/xenia/gpu/trace_player.h b/src/xenia/gpu/trace_player.h index 6e78ac3a6..d0ef59fb4 100644 --- a/src/xenia/gpu/trace_player.h +++ b/src/xenia/gpu/trace_player.h @@ -10,6 +10,7 @@ #ifndef XENIA_GPU_TRACE_PLAYER_H_ #define XENIA_GPU_TRACE_PLAYER_H_ +#include #include #include "xenia/gpu/trace_protocol.h" @@ -34,8 +35,14 @@ class TracePlayer : public TraceReader { GraphicsSystem* graphics_system() const { return graphics_system_; } int current_frame_index() const { return current_frame_index_; } int current_command_index() const { return current_command_index_; } + bool playing_trace() const { return playing_trace_; } const Frame* current_frame() const; + // Only valid if playing_trace is true. + const uint8_t* player_current_ptr() const { return player_current_ptr_; } + const uint8_t* player_start_ptr() const { return player_start_ptr_; } + const uint8_t* player_target_ptr() const { return player_target_ptr_; } + void SeekFrame(int target_frame); void SeekCommand(int target_command); @@ -49,6 +56,10 @@ class TracePlayer : public TraceReader { GraphicsSystem* graphics_system_; int current_frame_index_; int current_command_index_; + std::atomic playing_trace_ = false; + std::atomic player_current_ptr_ = 0; + std::atomic player_start_ptr_ = 0; + std::atomic player_target_ptr_ = 0; }; } // namespace gpu From 764044850939d3cd4af901701cab5f98f0f9de25 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sat, 21 Nov 2015 21:42:24 -0600 Subject: [PATCH 2/9] TracePlayer: Allow seeking forward more than one command --- src/xenia/gpu/trace_player.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/xenia/gpu/trace_player.cc b/src/xenia/gpu/trace_player.cc index 43299ef2e..33ac1919d 100644 --- a/src/xenia/gpu/trace_player.cc +++ b/src/xenia/gpu/trace_player.cc @@ -64,9 +64,9 @@ void TracePlayer::SeekCommand(int target_command) { auto frame = current_frame(); const auto& command = frame->commands[target_command]; assert_true(frame->start_ptr <= command.end_ptr); - if (target_command && previous_command_index == target_command - 1) { + if (previous_command_index != -1 && target_command > previous_command_index) { // Seek forward. - const auto& previous_command = frame->commands[target_command - 1]; + const auto& previous_command = frame->commands[previous_command_index]; PlayTrace(previous_command.end_ptr, command.end_ptr - previous_command.end_ptr, TracePlaybackMode::kBreakOnSwap); From 7a1d7bd652c1fc5d533a7e4cb532003fa141efe5 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sat, 21 Nov 2015 21:44:35 -0600 Subject: [PATCH 3/9] Display a progress bar while the command processor is playing a trace - Masks a race condition in the texture cache b/t the UI thread and the GL4 command processor --- src/xenia/gpu/trace_viewer.cc | 52 +++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/src/xenia/gpu/trace_viewer.cc b/src/xenia/gpu/trace_viewer.cc index 53c750428..ed50a3c97 100644 --- a/src/xenia/gpu/trace_viewer.cc +++ b/src/xenia/gpu/trace_viewer.cc @@ -820,6 +820,34 @@ static const char* kEndiannessNames[] = { "unspecified endianness", "8-in-16", "8-in-32", "16-in-32", }; +void ProgressBar(float frac, float width, float height = 0, + const ImVec4& color = ImVec4(0, 1, 0, 1), + const ImVec4& border_color = ImVec4(0, 1, 0, 1)) { + if (height == 0) { + height = ImGui::GetTextLineHeightWithSpacing(); + } + frac = xe::saturate(frac); + + const auto fontAtlas = ImGui::GetIO().Fonts; + + auto pos = ImGui::GetCursorScreenPos(); + auto col = ImGui::ColorConvertFloat4ToU32(color); + auto border_col = ImGui::ColorConvertFloat4ToU32(border_color); + + if (frac > 0) { + // Progress bar + ImGui::GetWindowDrawList()->AddRectFilled( + pos, ImVec2(pos.x + width * frac, pos.y + height), col); + } + if (border_color.w > 0.f) { + // Border + ImGui::GetWindowDrawList()->AddRect( + pos, ImVec2(pos.x + width, pos.y + height), border_col); + } + + ImGui::Dummy(ImVec2(width, height)); +} + void TraceViewer::DrawStateUI() { auto command_processor = graphics_system_->command_processor(); auto& regs = *graphics_system_->register_file(); @@ -893,8 +921,25 @@ void TraceViewer::DrawStateUI() { } } + if (player_->playing_trace()) { + ImGui::Text("Playing trace..."); + uint64_t start = uint64_t(player_->player_start_ptr()); + uint64_t end = uint64_t(player_->player_target_ptr()); + uint64_t cur = uint64_t(player_->player_current_ptr()); + + uint64_t rel_cur = cur - start; + uint64_t rel_end = end - start; + + float width = ImGui::GetWindowWidth() - 20.f; + + ProgressBar((float)rel_cur / (float)rel_end, width); + ImGui::End(); + return; + } + auto enable_mode = static_cast(regs[XE_GPU_REG_RB_MODECONTROL].u32 & 0x7); + const char* mode_name = "Unknown"; switch (enable_mode) { case ModeControl::kIgnore: @@ -915,9 +960,12 @@ void TraceViewer::DrawStateUI() { kPrimNames[int(draw_info.prim_type)], draw_info.index_count); break; } - case ModeControl::kCopy: - ImGui::Text("Copy Command %d", player_->current_command_index()); + case ModeControl::kCopy: { + uint32_t copy_dest_base = regs[XE_GPU_REG_RB_COPY_DEST_BASE].u32; + ImGui::Text("Copy Command %d (to %.8X)", player_->current_command_index(), + copy_dest_base); break; + } } ImGui::Columns(2); From 7c25795c05902d4ba3652bc1acf30bde3a90d4dc Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sat, 21 Nov 2015 21:45:11 -0600 Subject: [PATCH 4/9] Display texture guest address and swizzle information --- src/xenia/gpu/trace_viewer.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/xenia/gpu/trace_viewer.cc b/src/xenia/gpu/trace_viewer.cc index ed50a3c97..90ed3309f 100644 --- a/src/xenia/gpu/trace_viewer.cc +++ b/src/xenia/gpu/trace_viewer.cc @@ -583,6 +583,7 @@ void TraceViewer::DrawTextureInfo(const Shader::SamplerDesc& desc) { } ImGui::NextColumn(); ImGui::Text("Fetch Slot: %d", desc.fetch_slot); + ImGui::Text("Guest Address: %.8X", texture_info.guest_address); switch (texture_info.dimension) { case Dimension::k1D: ImGui::Text("1D: %dpx", texture_info.width + 1); @@ -599,6 +600,14 @@ void TraceViewer::DrawTextureInfo(const Shader::SamplerDesc& desc) { ImGui::Text("Cube: ?"); break; } + static const char* swizzle_map[] = {"Red", "Green", "Blue", "Alpha", "Zero", + "One", "UNK6", "UNK7"}; + ImGui::Text("Swizzle: %s %s %s %s", + swizzle_map[(texture_info.swizzle >> 0) & 0x7], + swizzle_map[(texture_info.swizzle >> 3) & 0x7], + swizzle_map[(texture_info.swizzle >> 6) & 0x7], + swizzle_map[(texture_info.swizzle >> 9) & 0x7]); + ImGui::Columns(1); } From e565bafdab0a579dbd17c0973f8e55e838f32aff Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sat, 21 Nov 2015 22:29:47 -0600 Subject: [PATCH 5/9] Prevent interaction with the command list UI while a trace is still playing --- src/xenia/gpu/trace_viewer.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/xenia/gpu/trace_viewer.cc b/src/xenia/gpu/trace_viewer.cc index 90ed3309f..b67d793ad 100644 --- a/src/xenia/gpu/trace_viewer.cc +++ b/src/xenia/gpu/trace_viewer.cc @@ -398,10 +398,18 @@ void TraceViewer::DrawCommandListUI() { if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Move to the last command"); } + if (player_->playing_trace()) { + // Don't allow the user to change the command index just yet... + // TODO: Find a way to disable the slider below. + target_command = player_->current_command_index(); + } + ImGui::PushItemWidth(float(column_width - 15)); ImGui::SliderInt("", &target_command, -1, command_count - 1); ImGui::PopItemWidth(); - if (target_command != player_->current_command_index()) { + + if (target_command != player_->current_command_index() && + !player_->playing_trace()) { did_seek = true; player_->SeekCommand(target_command); } From 1078d21bd239e4b4a0bf9d326cfed532147ac7e3 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sat, 21 Nov 2015 22:37:24 -0600 Subject: [PATCH 6/9] Stop resizing columns for the fetch constants --- src/xenia/gpu/trace_viewer.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/xenia/gpu/trace_viewer.cc b/src/xenia/gpu/trace_viewer.cc index b67d793ad..03710af28 100644 --- a/src/xenia/gpu/trace_viewer.cc +++ b/src/xenia/gpu/trace_viewer.cc @@ -1473,7 +1473,6 @@ void TraceViewer::DrawStateUI() { } if (ImGui::CollapsingHeader("Fetch Constants (raw)")) { ImGui::Columns(2); - ImGui::SetColumnOffset(1, 85.0f); for (int i = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0; i <= XE_GPU_REG_SHADER_CONSTANT_FETCH_31_5; ++i) { ImGui::Text("f%02d_%d", (i - XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0) / 6, From 646db5b8be18c05e24dc42593b9ad809159e78c7 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sun, 22 Nov 2015 09:54:25 -0600 Subject: [PATCH 7/9] Disable controller UI while playing a trace --- src/xenia/gpu/trace_viewer.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/xenia/gpu/trace_viewer.cc b/src/xenia/gpu/trace_viewer.cc index 03710af28..2314d9c70 100644 --- a/src/xenia/gpu/trace_viewer.cc +++ b/src/xenia/gpu/trace_viewer.cc @@ -192,9 +192,16 @@ void TraceViewer::DrawControllerUI() { if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Skip to last frame"); } + if (player_->playing_trace()) { + // Don't allow the user to change the frame index just yet... + // TODO: Find a way to disable the slider below. + target_frame = player_->current_frame_index(); + } + ImGui::SameLine(); ImGui::SliderInt("", &target_frame, 0, player_->frame_count() - 1); - if (target_frame != player_->current_frame_index()) { + if (target_frame != player_->current_frame_index() && + !player_->playing_trace()) { player_->SeekFrame(target_frame); } ImGui::End(); From a59e83e0d09d0e5fca73639a3139338c2677a958 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sun, 22 Nov 2015 10:15:50 -0600 Subject: [PATCH 8/9] Style --- src/xenia/gpu/trace_viewer.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/xenia/gpu/trace_viewer.cc b/src/xenia/gpu/trace_viewer.cc index 2314d9c70..f3af7a1ff 100644 --- a/src/xenia/gpu/trace_viewer.cc +++ b/src/xenia/gpu/trace_viewer.cc @@ -615,8 +615,8 @@ void TraceViewer::DrawTextureInfo(const Shader::SamplerDesc& desc) { ImGui::Text("Cube: ?"); break; } - static const char* swizzle_map[] = {"Red", "Green", "Blue", "Alpha", "Zero", - "One", "UNK6", "UNK7"}; + static const char* swizzle_map[] = {"Red", "Green", "Blue", "Alpha", + "Zero", "One", "UNK6", "UNK7"}; ImGui::Text("Swizzle: %s %s %s %s", swizzle_map[(texture_info.swizzle >> 0) & 0x7], swizzle_map[(texture_info.swizzle >> 3) & 0x7], From 414519fb6c6f8f34ac6385fda985ad8c4d2bdb75 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sun, 22 Nov 2015 11:36:31 -0600 Subject: [PATCH 9/9] Expose a playback percentage rather than pointers in TracePlayer --- src/xenia/gpu/trace_player.cc | 9 +++++---- src/xenia/gpu/trace_player.h | 11 ++++------- src/xenia/gpu/trace_viewer.cc | 9 +-------- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/xenia/gpu/trace_player.cc b/src/xenia/gpu/trace_player.cc index 33ac1919d..3e762f451 100644 --- a/src/xenia/gpu/trace_player.cc +++ b/src/xenia/gpu/trace_player.cc @@ -92,16 +92,17 @@ void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data, auto command_processor = graphics_system_->command_processor(); command_processor->set_swap_mode(SwapMode::kIgnored); - player_start_ptr_ = trace_data; - player_target_ptr_ = trace_data + trace_size; - player_current_ptr_ = trace_data; + playback_percent_ = 0; + auto trace_end = trace_data + trace_size; playing_trace_ = true; auto trace_ptr = trace_data; bool pending_break = false; const PacketStartCommand* pending_packet = nullptr; while (trace_ptr < trace_data + trace_size) { - player_current_ptr_ = trace_ptr; + playback_percent_ = uint32_t( + (float(trace_ptr - trace_data) / float(trace_end - trace_data)) * + 10000); auto type = static_cast(xe::load(trace_ptr)); switch (type) { diff --git a/src/xenia/gpu/trace_player.h b/src/xenia/gpu/trace_player.h index d0ef59fb4..70678ec1c 100644 --- a/src/xenia/gpu/trace_player.h +++ b/src/xenia/gpu/trace_player.h @@ -39,9 +39,8 @@ class TracePlayer : public TraceReader { const Frame* current_frame() const; // Only valid if playing_trace is true. - const uint8_t* player_current_ptr() const { return player_current_ptr_; } - const uint8_t* player_start_ptr() const { return player_start_ptr_; } - const uint8_t* player_target_ptr() const { return player_target_ptr_; } + // Scalar from 0-10000 + uint32_t playback_percent() const { return playback_percent_; } void SeekFrame(int target_frame); void SeekCommand(int target_command); @@ -56,10 +55,8 @@ class TracePlayer : public TraceReader { GraphicsSystem* graphics_system_; int current_frame_index_; int current_command_index_; - std::atomic playing_trace_ = false; - std::atomic player_current_ptr_ = 0; - std::atomic player_start_ptr_ = 0; - std::atomic player_target_ptr_ = 0; + bool playing_trace_ = false; + std::atomic playback_percent_ = 0; }; } // namespace gpu diff --git a/src/xenia/gpu/trace_viewer.cc b/src/xenia/gpu/trace_viewer.cc index f3af7a1ff..14513f989 100644 --- a/src/xenia/gpu/trace_viewer.cc +++ b/src/xenia/gpu/trace_viewer.cc @@ -947,16 +947,9 @@ void TraceViewer::DrawStateUI() { if (player_->playing_trace()) { ImGui::Text("Playing trace..."); - uint64_t start = uint64_t(player_->player_start_ptr()); - uint64_t end = uint64_t(player_->player_target_ptr()); - uint64_t cur = uint64_t(player_->player_current_ptr()); - - uint64_t rel_cur = cur - start; - uint64_t rel_end = end - start; - float width = ImGui::GetWindowWidth() - 20.f; - ProgressBar((float)rel_cur / (float)rel_end, width); + ProgressBar(float(player_->playback_percent()) / 10000.f, width); ImGui::End(); return; }