Merge pull request #469 from DrChat/trace_viewer_ui
Trace Viewer UI Improvements
This commit is contained in:
commit
42abdabf66
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,9 +977,12 @@ 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);
|
||||||
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue