Merge pull request #469 from DrChat/trace_viewer_ui

Trace Viewer UI Improvements
This commit is contained in:
Ben Vanik 2015-11-22 09:59:10 -08:00
commit 42abdabf66
3 changed files with 87 additions and 7 deletions

View File

@ -64,9 +64,9 @@ void TracePlayer::SeekCommand(int target_command) {
auto frame = current_frame(); auto frame = current_frame();
const auto& command = frame->commands[target_command]; const auto& command = frame->commands[target_command];
assert_true(frame->start_ptr <= command.end_ptr); 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. // 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, PlayTrace(previous_command.end_ptr,
command.end_ptr - previous_command.end_ptr, command.end_ptr - previous_command.end_ptr,
TracePlaybackMode::kBreakOnSwap); TracePlaybackMode::kBreakOnSwap);
@ -92,11 +92,18 @@ void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data,
auto command_processor = graphics_system_->command_processor(); auto command_processor = graphics_system_->command_processor();
command_processor->set_swap_mode(SwapMode::kIgnored); command_processor->set_swap_mode(SwapMode::kIgnored);
playback_percent_ = 0;
auto trace_end = trace_data + trace_size;
playing_trace_ = true;
auto trace_ptr = trace_data; auto trace_ptr = trace_data;
bool pending_break = false; bool pending_break = false;
const PacketStartCommand* pending_packet = nullptr; const PacketStartCommand* pending_packet = nullptr;
while (trace_ptr < trace_data + trace_size) { while (trace_ptr < trace_data + trace_size) {
playback_percent_ = uint32_t(
(float(trace_ptr - trace_data) / float(trace_end - trace_data)) *
10000);
auto type = static_cast<TraceCommandType>(xe::load<uint32_t>(trace_ptr)); auto type = static_cast<TraceCommandType>(xe::load<uint32_t>(trace_ptr));
switch (type) { switch (type) {
case TraceCommandType::kPrimaryBufferStart: { case TraceCommandType::kPrimaryBufferStart: {
@ -184,6 +191,7 @@ void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data,
} }
} }
playing_trace_ = false;
command_processor->set_swap_mode(SwapMode::kNormal); command_processor->set_swap_mode(SwapMode::kNormal);
command_processor->IssueSwap(0, 1280, 720); command_processor->IssueSwap(0, 1280, 720);
} }

View File

@ -10,6 +10,7 @@
#ifndef XENIA_GPU_TRACE_PLAYER_H_ #ifndef XENIA_GPU_TRACE_PLAYER_H_
#define XENIA_GPU_TRACE_PLAYER_H_ #define XENIA_GPU_TRACE_PLAYER_H_
#include <atomic>
#include <string> #include <string>
#include "xenia/gpu/trace_protocol.h" #include "xenia/gpu/trace_protocol.h"
@ -34,8 +35,13 @@ class TracePlayer : public TraceReader {
GraphicsSystem* graphics_system() const { return graphics_system_; } GraphicsSystem* graphics_system() const { return graphics_system_; }
int current_frame_index() const { return current_frame_index_; } int current_frame_index() const { return current_frame_index_; }
int current_command_index() const { return current_command_index_; } int current_command_index() const { return current_command_index_; }
bool playing_trace() const { return playing_trace_; }
const Frame* current_frame() const; const Frame* current_frame() const;
// Only valid if playing_trace is true.
// Scalar from 0-10000
uint32_t playback_percent() const { return playback_percent_; }
void SeekFrame(int target_frame); void SeekFrame(int target_frame);
void SeekCommand(int target_command); void SeekCommand(int target_command);
@ -49,6 +55,8 @@ class TracePlayer : public TraceReader {
GraphicsSystem* graphics_system_; GraphicsSystem* graphics_system_;
int current_frame_index_; int current_frame_index_;
int current_command_index_; int current_command_index_;
bool playing_trace_ = false;
std::atomic<uint32_t> playback_percent_ = 0;
}; };
} // namespace gpu } // namespace gpu

View File

@ -192,9 +192,16 @@ void TraceViewer::DrawControllerUI() {
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Skip to last frame"); 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::SameLine();
ImGui::SliderInt("", &target_frame, 0, player_->frame_count() - 1); 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); player_->SeekFrame(target_frame);
} }
ImGui::End(); ImGui::End();
@ -398,10 +405,18 @@ void TraceViewer::DrawCommandListUI() {
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Move to the last command"); 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::PushItemWidth(float(column_width - 15));
ImGui::SliderInt("", &target_command, -1, command_count - 1); ImGui::SliderInt("", &target_command, -1, command_count - 1);
ImGui::PopItemWidth(); ImGui::PopItemWidth();
if (target_command != player_->current_command_index()) {
if (target_command != player_->current_command_index() &&
!player_->playing_trace()) {
did_seek = true; did_seek = true;
player_->SeekCommand(target_command); player_->SeekCommand(target_command);
} }
@ -583,6 +598,7 @@ void TraceViewer::DrawTextureInfo(const Shader::SamplerDesc& desc) {
} }
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::Text("Fetch Slot: %d", desc.fetch_slot); ImGui::Text("Fetch Slot: %d", desc.fetch_slot);
ImGui::Text("Guest Address: %.8X", texture_info.guest_address);
switch (texture_info.dimension) { switch (texture_info.dimension) {
case Dimension::k1D: case Dimension::k1D:
ImGui::Text("1D: %dpx", texture_info.width + 1); ImGui::Text("1D: %dpx", texture_info.width + 1);
@ -599,6 +615,14 @@ void TraceViewer::DrawTextureInfo(const Shader::SamplerDesc& desc) {
ImGui::Text("Cube: ?"); ImGui::Text("Cube: ?");
break; 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); ImGui::Columns(1);
} }
@ -820,6 +844,34 @@ static const char* kEndiannessNames[] = {
"unspecified endianness", "8-in-16", "8-in-32", "16-in-32", "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() { void TraceViewer::DrawStateUI() {
auto command_processor = graphics_system_->command_processor(); auto command_processor = graphics_system_->command_processor();
auto& regs = *graphics_system_->register_file(); auto& regs = *graphics_system_->register_file();
@ -893,8 +945,18 @@ void TraceViewer::DrawStateUI() {
} }
} }
if (player_->playing_trace()) {
ImGui::Text("Playing trace...");
float width = ImGui::GetWindowWidth() - 20.f;
ProgressBar(float(player_->playback_percent()) / 10000.f, width);
ImGui::End();
return;
}
auto enable_mode = auto enable_mode =
static_cast<ModeControl>(regs[XE_GPU_REG_RB_MODECONTROL].u32 & 0x7); static_cast<ModeControl>(regs[XE_GPU_REG_RB_MODECONTROL].u32 & 0x7);
const char* mode_name = "Unknown"; const char* mode_name = "Unknown";
switch (enable_mode) { switch (enable_mode) {
case ModeControl::kIgnore: case ModeControl::kIgnore:
@ -915,10 +977,13 @@ void TraceViewer::DrawStateUI() {
kPrimNames[int(draw_info.prim_type)], draw_info.index_count); kPrimNames[int(draw_info.prim_type)], draw_info.index_count);
break; break;
} }
case ModeControl::kCopy: case ModeControl::kCopy: {
ImGui::Text("Copy Command %d", player_->current_command_index()); 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; break;
} }
}
ImGui::Columns(2); ImGui::Columns(2);
ImGui::BulletText("Viewport State:"); ImGui::BulletText("Viewport State:");
@ -1408,7 +1473,6 @@ void TraceViewer::DrawStateUI() {
} }
if (ImGui::CollapsingHeader("Fetch Constants (raw)")) { if (ImGui::CollapsingHeader("Fetch Constants (raw)")) {
ImGui::Columns(2); ImGui::Columns(2);
ImGui::SetColumnOffset(1, 85.0f);
for (int i = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0; for (int i = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0;
i <= XE_GPU_REG_SHADER_CONSTANT_FETCH_31_5; ++i) { 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, ImGui::Text("f%02d_%d", (i - XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0) / 6,