Starting to properly attribute virtual vs. physical memory accesses.
This commit is contained in:
@@ -51,10 +51,9 @@ CommandProcessor::CachedPipeline::~CachedPipeline() {
|
||||
|
||||
CommandProcessor::CommandProcessor(GL4GraphicsSystem* graphics_system)
|
||||
: memory_(graphics_system->memory()),
|
||||
membase_(graphics_system->memory()->membase()),
|
||||
graphics_system_(graphics_system),
|
||||
register_file_(graphics_system_->register_file()),
|
||||
trace_writer_(graphics_system->memory()->membase()),
|
||||
trace_writer_(graphics_system->memory()->physical_membase()),
|
||||
trace_state_(TraceState::kDisabled),
|
||||
worker_running_(true),
|
||||
swap_mode_(SwapMode::kNormal),
|
||||
@@ -212,8 +211,8 @@ void CommandProcessor::WorkerMain() {
|
||||
// TODO(benvanik): use reader->Read_update_freq_ and only issue after moving
|
||||
// that many indices.
|
||||
if (read_ptr_writeback_ptr_) {
|
||||
poly::store_and_swap<uint32_t>(membase_ + read_ptr_writeback_ptr_,
|
||||
read_ptr_index_);
|
||||
poly::store_and_swap<uint32_t>(
|
||||
memory_->TranslatePhysical(read_ptr_writeback_ptr_), read_ptr_index_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -488,7 +487,7 @@ void CommandProcessor::WriteRegister(uint32_t index, uint32_t value) {
|
||||
// Enabled - write to address.
|
||||
uint32_t scratch_addr = regs->values[XE_GPU_REG_SCRATCH_ADDR].u32;
|
||||
uint32_t mem_addr = scratch_addr + (scratch_reg * 4);
|
||||
poly::store_and_swap<uint32_t>(membase_ + xenos::GpuToCpu(mem_addr),
|
||||
poly::store_and_swap<uint32_t>(memory_->TranslatePhysical(mem_addr),
|
||||
value);
|
||||
}
|
||||
}
|
||||
@@ -651,8 +650,8 @@ void CommandProcessor::ExecutePrimaryBuffer(uint32_t start_index,
|
||||
|
||||
// Execute commands!
|
||||
uint32_t ptr_mask = (primary_buffer_size_ / sizeof(uint32_t)) - 1;
|
||||
RingbufferReader reader(membase_, primary_buffer_ptr_, ptr_mask, start_ptr,
|
||||
end_ptr);
|
||||
RingbufferReader reader(memory_->physical_membase(), primary_buffer_ptr_,
|
||||
ptr_mask, start_ptr, end_ptr);
|
||||
while (reader.can_read()) {
|
||||
ExecutePacket(&reader);
|
||||
}
|
||||
@@ -670,8 +669,8 @@ void CommandProcessor::ExecuteIndirectBuffer(uint32_t ptr, uint32_t length) {
|
||||
|
||||
// Execute commands!
|
||||
uint32_t ptr_mask = 0;
|
||||
RingbufferReader reader(membase_, primary_buffer_ptr_, ptr_mask, ptr,
|
||||
ptr + length * sizeof(uint32_t));
|
||||
RingbufferReader reader(memory_->physical_membase(), primary_buffer_ptr_,
|
||||
ptr_mask, ptr, ptr + length * sizeof(uint32_t));
|
||||
while (reader.can_read()) {
|
||||
ExecutePacket(&reader);
|
||||
}
|
||||
@@ -681,8 +680,8 @@ void CommandProcessor::ExecuteIndirectBuffer(uint32_t ptr, uint32_t length) {
|
||||
|
||||
void CommandProcessor::ExecutePacket(uint32_t ptr, uint32_t count) {
|
||||
uint32_t ptr_mask = 0;
|
||||
RingbufferReader reader(membase_, primary_buffer_ptr_, ptr_mask, ptr,
|
||||
ptr + count * sizeof(uint32_t));
|
||||
RingbufferReader reader(memory_->physical_membase(), primary_buffer_ptr_,
|
||||
ptr_mask, ptr, ptr + count * sizeof(uint32_t));
|
||||
while (reader.can_read()) {
|
||||
ExecutePacket(&reader);
|
||||
}
|
||||
@@ -992,7 +991,7 @@ bool CommandProcessor::ExecutePacketType3_WAIT_REG_MEM(RingbufferReader* reader,
|
||||
// Memory.
|
||||
auto endianness = static_cast<Endian>(poll_reg_addr & 0x3);
|
||||
poll_reg_addr &= ~0x3;
|
||||
value = poly::load<uint32_t>(membase_ + GpuToCpu(poll_reg_addr));
|
||||
value = poly::load<uint32_t>(memory_->TranslatePhysical(poll_reg_addr));
|
||||
value = GpuSwap(value, endianness);
|
||||
trace_writer_.WriteMemoryRead(poll_reg_addr, 4);
|
||||
} else {
|
||||
@@ -1095,7 +1094,7 @@ bool CommandProcessor::ExecutePacketType3_COND_WRITE(RingbufferReader* reader,
|
||||
auto endianness = static_cast<Endian>(poll_reg_addr & 0x3);
|
||||
poll_reg_addr &= ~0x3;
|
||||
trace_writer_.WriteMemoryRead(poll_reg_addr, 4);
|
||||
value = poly::load<uint32_t>(membase_ + GpuToCpu(poll_reg_addr));
|
||||
value = poly::load<uint32_t>(memory_->TranslatePhysical(poll_reg_addr));
|
||||
value = GpuSwap(value, endianness);
|
||||
} else {
|
||||
// Register.
|
||||
@@ -1136,7 +1135,7 @@ bool CommandProcessor::ExecutePacketType3_COND_WRITE(RingbufferReader* reader,
|
||||
auto endianness = static_cast<Endian>(write_reg_addr & 0x3);
|
||||
write_reg_addr &= ~0x3;
|
||||
write_data = GpuSwap(write_data, endianness);
|
||||
poly::store(membase_ + GpuToCpu(write_reg_addr), write_data);
|
||||
poly::store(memory_->TranslatePhysical(write_reg_addr), write_data);
|
||||
trace_writer_.WriteMemoryWrite(write_reg_addr, 4);
|
||||
} else {
|
||||
// Register.
|
||||
@@ -1182,7 +1181,7 @@ bool CommandProcessor::ExecutePacketType3_EVENT_WRITE_SHD(
|
||||
auto endianness = static_cast<Endian>(address & 0x3);
|
||||
address &= ~0x3;
|
||||
data_value = GpuSwap(data_value, endianness);
|
||||
poly::store(membase_ + GpuToCpu(address), data_value);
|
||||
poly::store(memory_->TranslatePhysical(address), data_value);
|
||||
trace_writer_.WriteMemoryWrite(address, 4);
|
||||
return true;
|
||||
}
|
||||
@@ -1207,7 +1206,7 @@ bool CommandProcessor::ExecutePacketType3_EVENT_WRITE_EXT(
|
||||
};
|
||||
assert_true(endianness == xenos::Endian::k8in16);
|
||||
poly::copy_and_swap_16_aligned(
|
||||
reinterpret_cast<uint16_t*>(membase_ + GpuToCpu(address)), extents,
|
||||
reinterpret_cast<uint16_t*>(memory_->TranslatePhysical(address)), extents,
|
||||
poly::countof(extents));
|
||||
trace_writer_.WriteMemoryWrite(address, sizeof(extents));
|
||||
return true;
|
||||
@@ -1367,8 +1366,8 @@ bool CommandProcessor::ExecutePacketType3_LOAD_ALU_CONSTANT(
|
||||
}
|
||||
trace_writer_.WriteMemoryRead(address, size_dwords * 4);
|
||||
for (uint32_t n = 0; n < size_dwords; n++, index++) {
|
||||
uint32_t data =
|
||||
poly::load_and_swap<uint32_t>(membase_ + GpuToCpu(address + n * 4));
|
||||
uint32_t data = poly::load_and_swap<uint32_t>(
|
||||
memory_->TranslatePhysical(address + n * 4));
|
||||
WriteRegister(index, data);
|
||||
}
|
||||
return true;
|
||||
@@ -1397,8 +1396,7 @@ bool CommandProcessor::ExecutePacketType3_IM_LOAD(RingbufferReader* reader,
|
||||
uint32_t size_dwords = start_size & 0xFFFF; // dwords
|
||||
assert_true(start == 0);
|
||||
trace_writer_.WriteMemoryRead(addr, size_dwords * 4);
|
||||
LoadShader(shader_type,
|
||||
reinterpret_cast<uint32_t*>(membase_ + GpuToCpu(addr)),
|
||||
LoadShader(shader_type, addr, memory_->TranslatePhysical<uint32_t*>(addr),
|
||||
size_dwords);
|
||||
return true;
|
||||
}
|
||||
@@ -1414,8 +1412,8 @@ bool CommandProcessor::ExecutePacketType3_IM_LOAD_IMMEDIATE(
|
||||
uint32_t size_dwords = start_size & 0xFFFF; // dwords
|
||||
assert_true(start == 0);
|
||||
reader->CheckRead(size_dwords);
|
||||
LoadShader(shader_type, reinterpret_cast<uint32_t*>(membase_ + reader->ptr()),
|
||||
size_dwords);
|
||||
LoadShader(shader_type, reader->ptr(),
|
||||
memory_->TranslatePhysical<uint32_t*>(reader->ptr()), size_dwords);
|
||||
reader->Advance(size_dwords);
|
||||
return true;
|
||||
}
|
||||
@@ -1429,11 +1427,12 @@ bool CommandProcessor::ExecutePacketType3_INVALIDATE_STATE(
|
||||
}
|
||||
|
||||
bool CommandProcessor::LoadShader(ShaderType shader_type,
|
||||
const uint32_t* address,
|
||||
uint32_t guest_address,
|
||||
const uint32_t* host_address,
|
||||
uint32_t dword_count) {
|
||||
// Hash the input memory and lookup the shader.
|
||||
GL4Shader* shader_ptr = nullptr;
|
||||
uint64_t hash = XXH64(address, dword_count * sizeof(uint32_t), 0);
|
||||
uint64_t hash = XXH64(host_address, dword_count * sizeof(uint32_t), 0);
|
||||
auto it = shader_cache_.find(hash);
|
||||
if (it != shader_cache_.end()) {
|
||||
// Found in the cache.
|
||||
@@ -1442,17 +1441,16 @@ bool CommandProcessor::LoadShader(ShaderType shader_type,
|
||||
} else {
|
||||
// Not found in cache.
|
||||
// No translation is performed here, as it depends on program_cntl.
|
||||
auto shader =
|
||||
std::make_unique<GL4Shader>(shader_type, hash, address, dword_count);
|
||||
auto shader = std::make_unique<GL4Shader>(shader_type, hash, host_address,
|
||||
dword_count);
|
||||
shader_ptr = shader.get();
|
||||
shader_cache_.insert({hash, shader_ptr});
|
||||
all_shaders_.emplace_back(std::move(shader));
|
||||
|
||||
XELOGGPU("Set %s shader at %0.8X (%db):\n%s",
|
||||
shader_type == ShaderType::kVertex ? "vertex" : "pixel",
|
||||
uint32_t(reinterpret_cast<uintptr_t>(address) -
|
||||
reinterpret_cast<uintptr_t>(membase_)),
|
||||
dword_count * 4, shader_ptr->ucode_disassembly().c_str());
|
||||
guest_address, dword_count * 4,
|
||||
shader_ptr->ucode_disassembly().c_str());
|
||||
}
|
||||
switch (shader_type) {
|
||||
case ShaderType::kVertex:
|
||||
@@ -2299,11 +2297,11 @@ CommandProcessor::UpdateStatus CommandProcessor::PopulateIndexBuffer() {
|
||||
&allocation)) {
|
||||
if (info.format == IndexFormat::kInt32) {
|
||||
auto dest = reinterpret_cast<uint32_t*>(allocation.host_ptr);
|
||||
auto src = reinterpret_cast<const uint32_t*>(membase_ + info.guest_base);
|
||||
auto src = memory_->TranslatePhysical<const uint32_t*>(info.guest_base);
|
||||
poly::copy_and_swap_32_aligned(dest, src, info.count);
|
||||
} else {
|
||||
auto dest = reinterpret_cast<uint16_t*>(allocation.host_ptr);
|
||||
auto src = reinterpret_cast<const uint16_t*>(membase_ + info.guest_base);
|
||||
auto src = memory_->TranslatePhysical<const uint16_t*>(info.guest_base);
|
||||
poly::copy_and_swap_16_aligned(dest, src, info.count);
|
||||
}
|
||||
draw_batcher_.set_index_buffer(allocation);
|
||||
@@ -2357,7 +2355,7 @@ CommandProcessor::UpdateStatus CommandProcessor::PopulateVertexBuffers() {
|
||||
// it (and if it matches just discard and reuse).
|
||||
poly::copy_and_swap_32_aligned(
|
||||
reinterpret_cast<uint32_t*>(allocation.host_ptr),
|
||||
reinterpret_cast<const uint32_t*>(membase_ + (fetch->address << 2)),
|
||||
memory_->TranslatePhysical<const uint32_t*>(fetch->address << 2),
|
||||
valid_range / 4);
|
||||
|
||||
if (!has_bindless_vbos_) {
|
||||
@@ -2697,7 +2695,7 @@ bool CommandProcessor::IssueCopy() {
|
||||
assert_true(fetch->type == 3);
|
||||
assert_true(fetch->endian == 2);
|
||||
assert_true(fetch->size == 6);
|
||||
const uint8_t* vertex_addr = membase_ + (fetch->address << 2);
|
||||
const uint8_t* vertex_addr = memory_->TranslatePhysical(fetch->address << 2);
|
||||
trace_writer_.WriteMemoryRead(fetch->address << 2, fetch->size * 4);
|
||||
int32_t dest_min_x = int32_t((std::min(
|
||||
std::min(
|
||||
@@ -2734,7 +2732,7 @@ bool CommandProcessor::IssueCopy() {
|
||||
// Destination pointer in guest memory.
|
||||
// We have GL throw bytes directly into it.
|
||||
// TODO(benvanik): copy to staging texture then PBO back?
|
||||
void* ptr = membase_ + GpuToCpu(copy_dest_base);
|
||||
void* ptr = memory_->TranslatePhysical(copy_dest_base);
|
||||
|
||||
// Make active so glReadPixels reads from us.
|
||||
switch (copy_command) {
|
||||
|
||||
@@ -193,8 +193,8 @@ class CommandProcessor {
|
||||
bool ExecutePacketType3_INVALIDATE_STATE(RingbufferReader* reader,
|
||||
uint32_t packet, uint32_t count);
|
||||
|
||||
bool LoadShader(ShaderType shader_type, const uint32_t* address,
|
||||
uint32_t dword_count);
|
||||
bool LoadShader(ShaderType shader_type, uint32_t guest_address,
|
||||
const uint32_t* host_address, uint32_t dword_count);
|
||||
|
||||
bool IssueDraw();
|
||||
UpdateStatus UpdateShaders(PrimitiveType prim_type);
|
||||
@@ -214,7 +214,6 @@ class CommandProcessor {
|
||||
GLuint depth_target);
|
||||
|
||||
Memory* memory_;
|
||||
uint8_t* membase_;
|
||||
GL4GraphicsSystem* graphics_system_;
|
||||
RegisterFile* register_file_;
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ void GL4GraphicsSystem::PlayTrace(const uint8_t* trace_data, size_t trace_size,
|
||||
case TraceCommandType::kPacketStart: {
|
||||
auto cmd = reinterpret_cast<const PacketStartCommand*>(trace_ptr);
|
||||
trace_ptr += sizeof(*cmd);
|
||||
std::memcpy(memory()->Translate(cmd->base_ptr), trace_ptr,
|
||||
std::memcpy(memory()->TranslatePhysical(cmd->base_ptr), trace_ptr,
|
||||
cmd->count * 4);
|
||||
trace_ptr += cmd->count * 4;
|
||||
pending_packet = cmd;
|
||||
@@ -203,7 +203,7 @@ void GL4GraphicsSystem::PlayTrace(const uint8_t* trace_data, size_t trace_size,
|
||||
case TraceCommandType::kMemoryRead: {
|
||||
auto cmd = reinterpret_cast<const MemoryReadCommand*>(trace_ptr);
|
||||
trace_ptr += sizeof(*cmd);
|
||||
std::memcpy(memory()->Translate(cmd->base_ptr), trace_ptr,
|
||||
std::memcpy(memory()->TranslatePhysical(cmd->base_ptr), trace_ptr,
|
||||
cmd->length);
|
||||
trace_ptr += cmd->length;
|
||||
break;
|
||||
|
||||
@@ -676,7 +676,8 @@ void TextureSwap(Endian endianness, void* dest, const void* src,
|
||||
|
||||
bool TextureCache::UploadTexture2D(GLuint texture,
|
||||
const TextureInfo& texture_info) {
|
||||
const auto host_address = memory_->Translate(texture_info.guest_address);
|
||||
const auto host_address =
|
||||
memory_->TranslatePhysical(texture_info.guest_address);
|
||||
|
||||
const auto& config =
|
||||
texture_configs[uint32_t(texture_info.format_info->format)];
|
||||
@@ -778,7 +779,8 @@ bool TextureCache::UploadTexture2D(GLuint texture,
|
||||
|
||||
bool TextureCache::UploadTextureCube(GLuint texture,
|
||||
const TextureInfo& texture_info) {
|
||||
const auto host_address = memory_->Translate(texture_info.guest_address);
|
||||
const auto host_address =
|
||||
memory_->TranslatePhysical(texture_info.guest_address);
|
||||
|
||||
const auto& config =
|
||||
texture_configs[uint32_t(texture_info.format_info->format)];
|
||||
|
||||
@@ -832,7 +832,7 @@ class TracePlayer : public TraceReader {
|
||||
};
|
||||
|
||||
void DrawControllerUI(xe::ui::MainWindow* window, TracePlayer& player,
|
||||
uint8_t* membase) {
|
||||
Memory* memory) {
|
||||
ImGui::SetNextWindowPos(ImVec2(5, 5), ImGuiSetCondition_FirstUseEver);
|
||||
if (!ImGui::Begin("Controller", nullptr, ImVec2(340, 60))) {
|
||||
ImGui::End();
|
||||
@@ -871,7 +871,7 @@ void DrawControllerUI(xe::ui::MainWindow* window, TracePlayer& player,
|
||||
}
|
||||
|
||||
void DrawCommandListUI(xe::ui::MainWindow* window, TracePlayer& player,
|
||||
uint8_t* membase) {
|
||||
Memory* memory) {
|
||||
ImGui::SetNextWindowPos(ImVec2(5, 70), ImGuiSetCondition_FirstUseEver);
|
||||
if (!ImGui::Begin("Command List", nullptr, ImVec2(200, 640))) {
|
||||
ImGui::End();
|
||||
@@ -1013,7 +1013,7 @@ ShaderDisplayType DrawShaderTypeUI() {
|
||||
}
|
||||
|
||||
void DrawShaderUI(xe::ui::MainWindow* window, TracePlayer& player,
|
||||
uint8_t* membase, gl4::GL4Shader* shader,
|
||||
Memory* memory, gl4::GL4Shader* shader,
|
||||
ShaderDisplayType display_type) {
|
||||
// Must be prepared for advanced display modes.
|
||||
if (display_type != ShaderDisplayType::kUcode) {
|
||||
@@ -1166,10 +1166,10 @@ void DrawTextureInfo(TracePlayer& player, const Shader::SamplerDesc& desc) {
|
||||
ImGui::Columns(1);
|
||||
}
|
||||
|
||||
void DrawVertexFetcher(const uint8_t* membase, gl4::GL4Shader* shader,
|
||||
void DrawVertexFetcher(const Memory* memory, gl4::GL4Shader* shader,
|
||||
const Shader::BufferDesc& desc,
|
||||
const xe_gpu_vertex_fetch_t* fetch) {
|
||||
const uint8_t* addr = membase + (fetch->address << 2);
|
||||
const uint8_t* addr = memory->TranslatePhysical(fetch->address << 2);
|
||||
uint32_t vertex_count = (fetch->size * 4) / desc.stride_words;
|
||||
int column_count = 0;
|
||||
for (uint32_t el_index = 0; el_index < desc.element_count; ++el_index) {
|
||||
@@ -1379,7 +1379,7 @@ static const char* kEndiannessNames[] = {
|
||||
};
|
||||
|
||||
void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player,
|
||||
uint8_t* membase) {
|
||||
Memory* memory) {
|
||||
auto gs = static_cast<gl4::GL4GraphicsSystem*>(player.graphics_system());
|
||||
auto cp = gs->command_processor();
|
||||
auto& regs = *gs->register_file();
|
||||
@@ -1809,7 +1809,7 @@ void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player,
|
||||
ImGui::BeginChild("#vertex_shader_text", ImVec2(0, 400));
|
||||
auto shader = cp->active_vertex_shader();
|
||||
if (shader) {
|
||||
DrawShaderUI(window, player, membase, shader, shader_display_type);
|
||||
DrawShaderUI(window, player, memory, shader, shader_display_type);
|
||||
} else {
|
||||
ImGui::TextColored(kColorError, "ERROR: no vertex shader set");
|
||||
}
|
||||
@@ -1820,7 +1820,7 @@ void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player,
|
||||
ImGui::BeginChild("#pixel_shader_text", ImVec2(0, 400));
|
||||
auto shader = cp->active_pixel_shader();
|
||||
if (shader) {
|
||||
DrawShaderUI(window, player, membase, shader, shader_display_type);
|
||||
DrawShaderUI(window, player, memory, shader, shader_display_type);
|
||||
} else {
|
||||
ImGui::TextColored(kColorError, "ERROR: no pixel shader set");
|
||||
}
|
||||
@@ -1864,10 +1864,10 @@ void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player,
|
||||
ImGui::NextColumn();
|
||||
ImGui::Separator();
|
||||
}
|
||||
size_t element_size =
|
||||
uint32_t element_size =
|
||||
draw_info.index_format == IndexFormat::kInt32 ? 4 : 2;
|
||||
const uint8_t* data_ptr =
|
||||
membase + draw_info.index_buffer_ptr + (display_start * element_size);
|
||||
const uint8_t* data_ptr = memory->TranslatePhysical(
|
||||
draw_info.index_buffer_ptr + (display_start * element_size));
|
||||
for (int i = display_start; i < display_end;
|
||||
++i, data_ptr += element_size) {
|
||||
if (i < 10) {
|
||||
@@ -1927,7 +1927,7 @@ void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player,
|
||||
fetch->size * 4,
|
||||
kEndiannessNames[int(fetch->endian)])) {
|
||||
ImGui::BeginChild("#vertices", ImVec2(0, 300));
|
||||
DrawVertexFetcher(membase, shader, desc, fetch);
|
||||
DrawVertexFetcher(memory, shader, desc, fetch);
|
||||
ImGui::EndChild();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
@@ -2019,7 +2019,7 @@ void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player,
|
||||
}
|
||||
|
||||
void DrawPacketDisassemblerUI(xe::ui::MainWindow* window, TracePlayer& player,
|
||||
uint8_t* membase) {
|
||||
Memory* memory) {
|
||||
ImGui::SetNextWindowCollapsed(true, ImGuiSetCondition_FirstUseEver);
|
||||
ImGui::SetNextWindowPos(ImVec2(float(window->width()) - 500 - 5, 5),
|
||||
ImGuiSetCondition_FirstUseEver);
|
||||
@@ -2160,13 +2160,13 @@ void DrawPacketDisassemblerUI(xe::ui::MainWindow* window, TracePlayer& player,
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void DrawUI(xe::ui::MainWindow* window, TracePlayer& player, uint8_t* membase) {
|
||||
void DrawUI(xe::ui::MainWindow* window, TracePlayer& player, Memory* memory) {
|
||||
ImGui::ShowTestWindow();
|
||||
|
||||
DrawControllerUI(window, player, membase);
|
||||
DrawCommandListUI(window, player, membase);
|
||||
DrawStateUI(window, player, membase);
|
||||
DrawPacketDisassemblerUI(window, player, membase);
|
||||
DrawControllerUI(window, player, memory);
|
||||
DrawCommandListUI(window, player, memory);
|
||||
DrawStateUI(window, player, memory);
|
||||
DrawPacketDisassemblerUI(window, player, memory);
|
||||
}
|
||||
|
||||
void ImImpl_Setup();
|
||||
@@ -2276,7 +2276,7 @@ int trace_viewer_main(std::vector<std::wstring>& args) {
|
||||
|
||||
ImGui::NewFrame();
|
||||
|
||||
DrawUI(window, player, emulator->memory()->membase());
|
||||
DrawUI(window, player, emulator->memory());
|
||||
|
||||
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
|
||||
ImGui::Render();
|
||||
|
||||
Reference in New Issue
Block a user