Hacktastic GPU trace viewer; textures, shaders, state, etc.
This commit is contained in:
parent
4a211a4195
commit
41174b0e64
|
@ -79,19 +79,54 @@ void Control::OnGotFocus(UIEvent& e) { on_got_focus(e); }
|
||||||
|
|
||||||
void Control::OnLostFocus(UIEvent& e) { on_lost_focus(e); }
|
void Control::OnLostFocus(UIEvent& e) { on_lost_focus(e); }
|
||||||
|
|
||||||
void Control::OnKeyDown(KeyEvent& e) { on_key_down(e); }
|
void Control::OnKeyDown(KeyEvent& e) {
|
||||||
|
on_key_down(e);
|
||||||
|
if (parent_ && !e.is_handled()) {
|
||||||
|
parent_->OnKeyDown(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Control::OnKeyUp(KeyEvent& e) { on_key_up(e); }
|
void Control::OnKeyUp(KeyEvent& e) {
|
||||||
|
on_key_up(e);
|
||||||
|
if (parent_ && !e.is_handled()) {
|
||||||
|
parent_->OnKeyUp(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Control::OnKeyChar(KeyEvent& e) { on_key_char(e); }
|
void Control::OnKeyChar(KeyEvent& e) {
|
||||||
|
on_key_char(e);
|
||||||
|
if (parent_ && !e.is_handled()) {
|
||||||
|
parent_->OnKeyChar(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Control::OnMouseDown(MouseEvent& e) { on_mouse_down(e); }
|
void Control::OnMouseDown(MouseEvent& e) {
|
||||||
|
on_mouse_down(e);
|
||||||
|
if (parent_ && !e.is_handled()) {
|
||||||
|
parent_->OnMouseDown(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Control::OnMouseMove(MouseEvent& e) { on_mouse_move(e); }
|
void Control::OnMouseMove(MouseEvent& e) {
|
||||||
|
on_mouse_move(e);
|
||||||
|
if (parent_ && !e.is_handled()) {
|
||||||
|
parent_->OnMouseMove(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Control::OnMouseUp(MouseEvent& e) { on_mouse_up(e); }
|
void Control::OnMouseUp(MouseEvent& e) {
|
||||||
|
on_mouse_up(e);
|
||||||
|
if (parent_ && !e.is_handled()) {
|
||||||
|
parent_->OnMouseUp(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Control::OnMouseWheel(MouseEvent& e) { on_mouse_wheel(e); }
|
void Control::OnMouseWheel(MouseEvent& e) {
|
||||||
|
on_mouse_wheel(e);
|
||||||
|
if (parent_ && !e.is_handled()) {
|
||||||
|
parent_->OnMouseWheel(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
} // namespace poly
|
} // namespace poly
|
||||||
|
|
|
@ -54,6 +54,7 @@ CommandProcessor::CommandProcessor(GL4GraphicsSystem* graphics_system)
|
||||||
graphics_system_(graphics_system),
|
graphics_system_(graphics_system),
|
||||||
register_file_(graphics_system_->register_file()),
|
register_file_(graphics_system_->register_file()),
|
||||||
trace_writer_(graphics_system->memory()->membase()),
|
trace_writer_(graphics_system->memory()->membase()),
|
||||||
|
trace_state_(TraceState::kDisabled),
|
||||||
worker_running_(true),
|
worker_running_(true),
|
||||||
swap_mode_(SwapMode::kNormal),
|
swap_mode_(SwapMode::kNormal),
|
||||||
time_base_(0),
|
time_base_(0),
|
||||||
|
@ -118,12 +119,40 @@ void CommandProcessor::Shutdown() {
|
||||||
context_.reset();
|
context_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandProcessor::RequestFrameTrace(const std::wstring& root_path) {
|
||||||
|
if (trace_state_ == TraceState::kStreaming) {
|
||||||
|
XELOGE("Streaming trace; cannot also trace frame.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (trace_state_ == TraceState::kSingleFrame) {
|
||||||
|
XELOGE("Frame trace already pending; ignoring.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
trace_state_ = TraceState::kSingleFrame;
|
||||||
|
trace_frame_path_ = root_path;
|
||||||
|
}
|
||||||
|
|
||||||
void CommandProcessor::BeginTracing(const std::wstring& root_path) {
|
void CommandProcessor::BeginTracing(const std::wstring& root_path) {
|
||||||
std::wstring path = poly::join_paths(root_path, L"gpu_trace");
|
if (trace_state_ == TraceState::kStreaming) {
|
||||||
|
XELOGE("Streaming already active; ignoring request.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (trace_state_ == TraceState::kSingleFrame) {
|
||||||
|
XELOGE("Frame trace pending; ignoring streaming request.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::wstring path = poly::join_paths(root_path, L"stream");
|
||||||
|
trace_state_ = TraceState::kStreaming;
|
||||||
trace_writer_.Open(path);
|
trace_writer_.Open(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandProcessor::EndTracing() { trace_writer_.Close(); }
|
void CommandProcessor::EndTracing() {
|
||||||
|
if (!trace_writer_.is_open()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assert_true(trace_state_ == TraceState::kStreaming);
|
||||||
|
trace_writer_.Close();
|
||||||
|
}
|
||||||
|
|
||||||
void CommandProcessor::CallInThread(std::function<void()> fn) {
|
void CommandProcessor::CallInThread(std::function<void()> fn) {
|
||||||
if (pending_fns_.empty() &&
|
if (pending_fns_.empty() &&
|
||||||
|
@ -862,8 +891,20 @@ bool CommandProcessor::ExecutePacketType3_XE_SWAP(RingbufferReader* reader,
|
||||||
IssueSwap();
|
IssueSwap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (trace_writer_.is_open()) {
|
||||||
trace_writer_.WriteEvent(EventType::kSwap);
|
trace_writer_.WriteEvent(EventType::kSwap);
|
||||||
trace_writer_.Flush();
|
trace_writer_.Flush();
|
||||||
|
if (trace_state_ == TraceState::kSingleFrame) {
|
||||||
|
trace_state_ = TraceState::kDisabled;
|
||||||
|
trace_writer_.Close();
|
||||||
|
}
|
||||||
|
} else if (trace_state_ == TraceState::kSingleFrame) {
|
||||||
|
// New trace request - we only start tracing at the beginning of a frame.
|
||||||
|
auto frame_number = L"frame_" + std::to_wstring(counter_);
|
||||||
|
auto path = trace_frame_path_ + frame_number;
|
||||||
|
trace_writer_.Open(path);
|
||||||
|
}
|
||||||
|
++counter_;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1098,7 +1139,6 @@ bool CommandProcessor::ExecutePacketType3_EVENT_WRITE_EXT(
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandProcessor::ExecutePacketType3_DRAW_INDX(RingbufferReader* reader,
|
bool CommandProcessor::ExecutePacketType3_DRAW_INDX(RingbufferReader* reader,
|
||||||
|
|
||||||
uint32_t packet,
|
uint32_t packet,
|
||||||
uint32_t count) {
|
uint32_t count) {
|
||||||
// initiate fetch of index buffer and draw
|
// initiate fetch of index buffer and draw
|
||||||
|
@ -1107,7 +1147,6 @@ bool CommandProcessor::ExecutePacketType3_DRAW_INDX(RingbufferReader* reader,
|
||||||
uint32_t dword1 = reader->Read();
|
uint32_t dword1 = reader->Read();
|
||||||
uint32_t index_count = dword1 >> 16;
|
uint32_t index_count = dword1 >> 16;
|
||||||
auto prim_type = static_cast<PrimitiveType>(dword1 & 0x3F);
|
auto prim_type = static_cast<PrimitiveType>(dword1 & 0x3F);
|
||||||
|
|
||||||
uint32_t src_sel = (dword1 >> 6) & 0x3;
|
uint32_t src_sel = (dword1 >> 6) & 0x3;
|
||||||
if (src_sel == 0x0) {
|
if (src_sel == 0x0) {
|
||||||
// Indexed draw.
|
// Indexed draw.
|
||||||
|
@ -1655,12 +1694,12 @@ CommandProcessor::UpdateStatus CommandProcessor::UpdateViewportState() {
|
||||||
// http://fossies.org/dox/MesaLib-10.3.5/fd2__gmem_8c_source.html
|
// http://fossies.org/dox/MesaLib-10.3.5/fd2__gmem_8c_source.html
|
||||||
// http://www.x.org/docs/AMD/old/evergreen_3D_registers_v2.pdf
|
// http://www.x.org/docs/AMD/old/evergreen_3D_registers_v2.pdf
|
||||||
|
|
||||||
uint32_t mode_control = regs[XE_GPU_REG_PA_SU_SC_MODE_CNTL].u32;
|
uint32_t pa_su_sc_mode_cntl = regs[XE_GPU_REG_PA_SU_SC_MODE_CNTL].u32;
|
||||||
|
|
||||||
// Window parameters.
|
// Window parameters.
|
||||||
// See r200UpdateWindow:
|
// See r200UpdateWindow:
|
||||||
// https://github.com/freedreno/mesa/blob/master/src/mesa/drivers/dri/r200/r200_state.c
|
// https://github.com/freedreno/mesa/blob/master/src/mesa/drivers/dri/r200/r200_state.c
|
||||||
if ((mode_control >> 17) & 1) {
|
if ((pa_su_sc_mode_cntl >> 17) & 1) {
|
||||||
uint32_t window_offset = regs[XE_GPU_REG_PA_SC_WINDOW_OFFSET].u32;
|
uint32_t window_offset = regs[XE_GPU_REG_PA_SC_WINDOW_OFFSET].u32;
|
||||||
draw_batcher_.set_window_offset(window_offset & 0x7FFF,
|
draw_batcher_.set_window_offset(window_offset & 0x7FFF,
|
||||||
(window_offset >> 16) & 0x7FFF);
|
(window_offset >> 16) & 0x7FFF);
|
||||||
|
|
|
@ -68,6 +68,7 @@ class CommandProcessor {
|
||||||
void set_swap_mode(SwapMode swap_mode) { swap_mode_ = swap_mode; }
|
void set_swap_mode(SwapMode swap_mode) { swap_mode_ = swap_mode; }
|
||||||
void IssueSwap();
|
void IssueSwap();
|
||||||
|
|
||||||
|
void RequestFrameTrace(const std::wstring& root_path);
|
||||||
void BeginTracing(const std::wstring& root_path);
|
void BeginTracing(const std::wstring& root_path);
|
||||||
void EndTracing();
|
void EndTracing();
|
||||||
|
|
||||||
|
@ -78,6 +79,11 @@ class CommandProcessor {
|
||||||
|
|
||||||
void ExecutePacket(uint32_t ptr, uint32_t count);
|
void ExecutePacket(uint32_t ptr, uint32_t count);
|
||||||
|
|
||||||
|
// HACK: for debugging; would be good to have this in a base type.
|
||||||
|
TextureCache* texture_cache() { return &texture_cache_; }
|
||||||
|
GL4Shader* active_vertex_shader() const { return active_vertex_shader_; }
|
||||||
|
GL4Shader* active_pixel_shader() const { return active_pixel_shader_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class RingbufferReader;
|
class RingbufferReader;
|
||||||
|
|
||||||
|
@ -208,6 +214,13 @@ class CommandProcessor {
|
||||||
RegisterFile* register_file_;
|
RegisterFile* register_file_;
|
||||||
|
|
||||||
TraceWriter trace_writer_;
|
TraceWriter trace_writer_;
|
||||||
|
enum class TraceState {
|
||||||
|
kDisabled,
|
||||||
|
kStreaming,
|
||||||
|
kSingleFrame,
|
||||||
|
};
|
||||||
|
TraceState trace_state_;
|
||||||
|
std::wstring trace_frame_path_;
|
||||||
|
|
||||||
std::thread worker_thread_;
|
std::thread worker_thread_;
|
||||||
std::atomic<bool> worker_running_;
|
std::atomic<bool> worker_running_;
|
||||||
|
|
|
@ -72,10 +72,6 @@ X_STATUS GL4GraphicsSystem::Setup(cpu::Processor* processor,
|
||||||
command_processor_->set_swap_handler(
|
command_processor_->set_swap_handler(
|
||||||
[this](const SwapParameters& swap_params) { SwapHandler(swap_params); });
|
[this](const SwapParameters& swap_params) { SwapHandler(swap_params); });
|
||||||
|
|
||||||
if (!FLAGS_trace_gpu.empty()) {
|
|
||||||
command_processor_->BeginTracing(poly::to_wstring(FLAGS_trace_gpu));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let the processor know we want register access callbacks.
|
// Let the processor know we want register access callbacks.
|
||||||
memory_->AddMappedRange(
|
memory_->AddMappedRange(
|
||||||
0x7FC80000, 0xFFFF0000, 0x0000FFFF, this,
|
0x7FC80000, 0xFFFF0000, 0x0000FFFF, this,
|
||||||
|
@ -93,11 +89,15 @@ X_STATUS GL4GraphicsSystem::Setup(cpu::Processor* processor,
|
||||||
(WAITORTIMERCALLBACK)VsyncCallbackThunk, this, 16,
|
(WAITORTIMERCALLBACK)VsyncCallbackThunk, this, 16,
|
||||||
timer_period, WT_EXECUTEINPERSISTENTTHREAD);
|
timer_period, WT_EXECUTEINPERSISTENTTHREAD);
|
||||||
|
|
||||||
|
if (FLAGS_trace_gpu_stream) {
|
||||||
|
BeginTracing();
|
||||||
|
}
|
||||||
|
|
||||||
return X_STATUS_SUCCESS;
|
return X_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GL4GraphicsSystem::Shutdown() {
|
void GL4GraphicsSystem::Shutdown() {
|
||||||
command_processor_->EndTracing();
|
EndTracing();
|
||||||
|
|
||||||
DeleteTimerQueueTimer(timer_queue_, vsync_timer_, nullptr);
|
DeleteTimerQueueTimer(timer_queue_, vsync_timer_, nullptr);
|
||||||
DeleteTimerQueue(timer_queue_);
|
DeleteTimerQueue(timer_queue_);
|
||||||
|
@ -126,6 +126,17 @@ void GL4GraphicsSystem::RequestSwap() {
|
||||||
command_processor_->CallInThread([&]() { command_processor_->IssueSwap(); });
|
command_processor_->CallInThread([&]() { command_processor_->IssueSwap(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GL4GraphicsSystem::RequestFrameTrace() {
|
||||||
|
command_processor_->RequestFrameTrace(
|
||||||
|
poly::to_wstring(FLAGS_trace_gpu_prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL4GraphicsSystem::BeginTracing() {
|
||||||
|
command_processor_->BeginTracing(poly::to_wstring(FLAGS_trace_gpu_prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL4GraphicsSystem::EndTracing() { command_processor_->EndTracing(); }
|
||||||
|
|
||||||
void GL4GraphicsSystem::PlayTrace(const uint8_t* trace_data, size_t trace_size,
|
void GL4GraphicsSystem::PlayTrace(const uint8_t* trace_data, size_t trace_size,
|
||||||
TracePlaybackMode playback_mode) {
|
TracePlaybackMode playback_mode) {
|
||||||
command_processor_->CallInThread(
|
command_processor_->CallInThread(
|
||||||
|
|
|
@ -32,12 +32,18 @@ class GL4GraphicsSystem : public GraphicsSystem {
|
||||||
void Shutdown() override;
|
void Shutdown() override;
|
||||||
|
|
||||||
RegisterFile* register_file() { return ®ister_file_; }
|
RegisterFile* register_file() { return ®ister_file_; }
|
||||||
|
CommandProcessor* command_processor() const {
|
||||||
|
return command_processor_.get();
|
||||||
|
}
|
||||||
|
|
||||||
void InitializeRingBuffer(uint32_t ptr, uint32_t page_count) override;
|
void InitializeRingBuffer(uint32_t ptr, uint32_t page_count) override;
|
||||||
void EnableReadPointerWriteBack(uint32_t ptr, uint32_t block_size) override;
|
void EnableReadPointerWriteBack(uint32_t ptr, uint32_t block_size) override;
|
||||||
|
|
||||||
void RequestSwap() override;
|
void RequestSwap() override;
|
||||||
|
|
||||||
|
void RequestFrameTrace() override;
|
||||||
|
void BeginTracing() override;
|
||||||
|
void EndTracing() override;
|
||||||
void PlayTrace(const uint8_t* trace_data, size_t trace_size,
|
void PlayTrace(const uint8_t* trace_data, size_t trace_size,
|
||||||
TracePlaybackMode playback_mode) override;
|
TracePlaybackMode playback_mode) override;
|
||||||
|
|
||||||
|
|
|
@ -170,11 +170,11 @@ GL4ProfilerDisplay::GL4ProfilerDisplay(WGLControl* control)
|
||||||
// Watch for toggle/mode keys and such.
|
// Watch for toggle/mode keys and such.
|
||||||
control->on_key_down.AddListener([](poly::ui::KeyEvent& e) {
|
control->on_key_down.AddListener([](poly::ui::KeyEvent& e) {
|
||||||
Profiler::OnKeyDown(e.key_code());
|
Profiler::OnKeyDown(e.key_code());
|
||||||
e.set_handled(true);
|
//e.set_handled(true);
|
||||||
});
|
});
|
||||||
control->on_key_up.AddListener([](poly::ui::KeyEvent& e) {
|
control->on_key_up.AddListener([](poly::ui::KeyEvent& e) {
|
||||||
Profiler::OnKeyUp(e.key_code());
|
Profiler::OnKeyUp(e.key_code());
|
||||||
e.set_handled(true);
|
//e.set_handled(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -352,8 +352,6 @@ bool GL4Shader::CompileProgram(std::string source) {
|
||||||
glGetProgramBinary(program_, binary_length, &binary_length, &binary_format,
|
glGetProgramBinary(program_, binary_length, &binary_length, &binary_format,
|
||||||
translated_binary_.data());
|
translated_binary_.data());
|
||||||
|
|
||||||
// Append to shader dump.
|
|
||||||
if (FLAGS_dump_shaders.size()) {
|
|
||||||
// If we are on nvidia, we can find the disassembly string.
|
// If we are on nvidia, we can find the disassembly string.
|
||||||
// I haven't been able to figure out from the format how to do this
|
// I haven't been able to figure out from the format how to do this
|
||||||
// without a search like this.
|
// without a search like this.
|
||||||
|
@ -374,7 +372,10 @@ bool GL4Shader::CompileProgram(std::string source) {
|
||||||
search_offset = p - search_start;
|
search_offset = p - search_start;
|
||||||
++search_offset;
|
++search_offset;
|
||||||
}
|
}
|
||||||
|
host_disassembly_ = std::string(disasm_start);
|
||||||
|
|
||||||
|
// Append to shader dump.
|
||||||
|
if (FLAGS_dump_shaders.size()) {
|
||||||
if (disasm_start) {
|
if (disasm_start) {
|
||||||
FILE* f = fopen(file_name, "a");
|
FILE* f = fopen(file_name, "a");
|
||||||
fprintf(f, "\n\n/*\n");
|
fprintf(f, "\n\n/*\n");
|
||||||
|
|
|
@ -108,6 +108,7 @@ TextureCache::TextureEntryView* TextureCache::Demand(
|
||||||
}
|
}
|
||||||
|
|
||||||
auto view = std::make_unique<TextureEntryView>();
|
auto view = std::make_unique<TextureEntryView>();
|
||||||
|
view->texture = texture_entry;
|
||||||
view->sampler = sampler_entry;
|
view->sampler = sampler_entry;
|
||||||
view->sampler_hash = sampler_hash;
|
view->sampler_hash = sampler_hash;
|
||||||
view->texture_sampler_handle = 0;
|
view->texture_sampler_handle = 0;
|
||||||
|
|
|
@ -26,11 +26,13 @@ namespace gl4 {
|
||||||
|
|
||||||
class TextureCache {
|
class TextureCache {
|
||||||
public:
|
public:
|
||||||
|
struct TextureEntry;
|
||||||
struct SamplerEntry {
|
struct SamplerEntry {
|
||||||
SamplerInfo sampler_info;
|
SamplerInfo sampler_info;
|
||||||
GLuint handle;
|
GLuint handle;
|
||||||
};
|
};
|
||||||
struct TextureEntryView {
|
struct TextureEntryView {
|
||||||
|
TextureEntry* texture;
|
||||||
SamplerEntry* sampler;
|
SamplerEntry* sampler;
|
||||||
uint64_t sampler_hash;
|
uint64_t sampler_hash;
|
||||||
GLuint64 texture_sampler_handle;
|
GLuint64 texture_sampler_handle;
|
||||||
|
|
|
@ -14,7 +14,8 @@
|
||||||
|
|
||||||
DECLARE_string(gpu);
|
DECLARE_string(gpu);
|
||||||
|
|
||||||
DECLARE_string(trace_gpu);
|
DECLARE_string(trace_gpu_prefix);
|
||||||
|
DECLARE_bool(trace_gpu_stream);
|
||||||
|
|
||||||
DECLARE_string(dump_shaders);
|
DECLARE_string(dump_shaders);
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,9 @@
|
||||||
|
|
||||||
DEFINE_string(gpu, "any", "Graphics system. Use: [any, gl4]");
|
DEFINE_string(gpu, "any", "Graphics system. Use: [any, gl4]");
|
||||||
|
|
||||||
DEFINE_string(trace_gpu, "", "Trace GPU data to the given root path.");
|
DEFINE_string(trace_gpu_prefix, "scratch/gpu/gpu_trace_",
|
||||||
|
"Prefix path for GPU trace files.");
|
||||||
|
DEFINE_bool(trace_gpu_stream, false, "Trace all GPU packets.");
|
||||||
|
|
||||||
DEFINE_string(dump_shaders, "",
|
DEFINE_string(dump_shaders, "",
|
||||||
"Path to write GPU shaders to as they are compiled.");
|
"Path to write GPU shaders to as they are compiled.");
|
||||||
|
|
|
@ -43,6 +43,9 @@ class GraphicsSystem {
|
||||||
|
|
||||||
void DispatchInterruptCallback(uint32_t source, uint32_t cpu);
|
void DispatchInterruptCallback(uint32_t source, uint32_t cpu);
|
||||||
|
|
||||||
|
virtual void RequestFrameTrace() {}
|
||||||
|
virtual void BeginTracing() {}
|
||||||
|
virtual void EndTracing() {}
|
||||||
enum class TracePlaybackMode {
|
enum class TracePlaybackMode {
|
||||||
kUntilEnd,
|
kUntilEnd,
|
||||||
kBreakOnSwap,
|
kBreakOnSwap,
|
||||||
|
|
|
@ -9,21 +9,28 @@
|
||||||
|
|
||||||
#include "xenia/gpu/register_file.h"
|
#include "xenia/gpu/register_file.h"
|
||||||
|
|
||||||
|
#include "poly/math.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
|
||||||
RegisterFile::RegisterFile() { memset(values, 0, sizeof(values)); }
|
RegisterFile::RegisterFile() { memset(values, 0, sizeof(values)); }
|
||||||
|
|
||||||
const char* RegisterFile::GetRegisterName(uint32_t index) {
|
const RegisterInfo* RegisterFile::GetRegisterInfo(uint32_t index) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
#define XE_GPU_REGISTER(index, type, name) \
|
#define XE_GPU_REGISTER(index, type, name) \
|
||||||
case index: \
|
case index: { \
|
||||||
return #name;
|
static const RegisterInfo reg_info = { \
|
||||||
|
RegisterInfo::Type::type, #name, \
|
||||||
|
}; \
|
||||||
|
return ®_info; \
|
||||||
|
\
|
||||||
|
}
|
||||||
#include "xenia/gpu/register_table.inc"
|
#include "xenia/gpu/register_table.inc"
|
||||||
#undef XE_GPU_REGISTER
|
#undef XE_GPU_REGISTER
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace gpu
|
} // namespace gpu
|
||||||
|
|
|
@ -21,11 +21,20 @@ enum Register {
|
||||||
#undef XE_GPU_REGISTER
|
#undef XE_GPU_REGISTER
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RegisterInfo {
|
||||||
|
enum class Type {
|
||||||
|
kDword,
|
||||||
|
kFloat,
|
||||||
|
};
|
||||||
|
Type type;
|
||||||
|
const char* name;
|
||||||
|
};
|
||||||
|
|
||||||
class RegisterFile {
|
class RegisterFile {
|
||||||
public:
|
public:
|
||||||
RegisterFile();
|
RegisterFile();
|
||||||
|
|
||||||
const char* GetRegisterName(uint32_t index);
|
static const RegisterInfo* GetRegisterInfo(uint32_t index);
|
||||||
|
|
||||||
static const size_t kRegisterCount = 0x5003;
|
static const size_t kRegisterCount = 0x5003;
|
||||||
union RegisterValue {
|
union RegisterValue {
|
||||||
|
@ -34,6 +43,7 @@ class RegisterFile {
|
||||||
};
|
};
|
||||||
RegisterValue values[kRegisterCount];
|
RegisterValue values[kRegisterCount];
|
||||||
|
|
||||||
|
RegisterValue& operator[](int reg) { return values[reg]; }
|
||||||
RegisterValue& operator[](Register reg) { return values[reg]; }
|
RegisterValue& operator[](Register reg) { return values[reg]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -31,6 +31,7 @@ class Shader {
|
||||||
return translated_disassembly_;
|
return translated_disassembly_;
|
||||||
}
|
}
|
||||||
const std::vector<uint8_t> translated_binary() { return translated_binary_; }
|
const std::vector<uint8_t> translated_binary() { return translated_binary_; }
|
||||||
|
const std::string& host_disassembly() const { return host_disassembly_; }
|
||||||
|
|
||||||
const uint32_t* data() const { return data_.data(); }
|
const uint32_t* data() const { return data_.data(); }
|
||||||
|
|
||||||
|
@ -98,6 +99,7 @@ class Shader {
|
||||||
std::string ucode_disassembly_;
|
std::string ucode_disassembly_;
|
||||||
std::string translated_disassembly_;
|
std::string translated_disassembly_;
|
||||||
std::vector<uint8_t> translated_binary_;
|
std::vector<uint8_t> translated_binary_;
|
||||||
|
std::string host_disassembly_;
|
||||||
std::string error_log_;
|
std::string error_log_;
|
||||||
|
|
||||||
AllocCounts alloc_counts_;
|
AllocCounts alloc_counts_;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -85,6 +85,8 @@ class TraceWriter {
|
||||||
TraceWriter(uint8_t* membase) : membase_(membase), file_(nullptr) {}
|
TraceWriter(uint8_t* membase) : membase_(membase), file_(nullptr) {}
|
||||||
~TraceWriter() = default;
|
~TraceWriter() = default;
|
||||||
|
|
||||||
|
bool is_open() const { return file_ != nullptr; }
|
||||||
|
|
||||||
bool Open(const std::wstring& path) {
|
bool Open(const std::wstring& path) {
|
||||||
Close();
|
Close();
|
||||||
file_ = _wfopen(path.c_str(), L"wb");
|
file_ = _wfopen(path.c_str(), L"wb");
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "poly/logging.h"
|
#include "poly/logging.h"
|
||||||
#include "poly/threading.h"
|
#include "poly/threading.h"
|
||||||
|
#include "xenia/gpu/graphics_system.h"
|
||||||
#include "xenia/emulator.h"
|
#include "xenia/emulator.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
@ -44,6 +45,13 @@ bool MainWindow::Initialize() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Resize(1280, 720);
|
Resize(1280, 720);
|
||||||
|
on_key_down.AddListener([this](poly::ui::KeyEvent& e) {
|
||||||
|
if (e.key_code() == 115) {
|
||||||
|
emulator()->graphics_system()->RequestFrameTrace();
|
||||||
|
e.set_handled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue