[UI] Image post-processing and full presentation/window rework
[GPU] Add FXAA post-processing [UI] Add FidelityFX FSR and CAS post-processing [UI] Add blue noise dithering from 10bpc to 8bpc [GPU] Apply the DC PWL gamma ramp closer to the spec, supporting fully white color [UI] Allow the GPU CP thread to present on the host directly, bypassing the UI thread OS paint event [UI] Allow variable refresh rate (or tearing) [UI] Present the newest frame (restart) on DXGI [UI] Replace GraphicsContext with a far more advanced Presenter with more coherent surface connection and UI overlay state management [UI] Connect presentation to windows via the Surface class, not native window handles [Vulkan] Switch to simpler Vulkan setup with no instance/device separation due to interdependencies and to pass fewer objects around [Vulkan] Lower the minimum required Vulkan version to 1.0 [UI/GPU] Various cleanup, mainly ComPtr usage [UI] Support per-monitor DPI awareness v2 on Windows [UI] DPI-scale Dear ImGui [UI] Replace the remaining non-detachable window delegates with unified window event and input listeners [UI] Allow listeners to safely destroy or close the window, and to register/unregister listeners without use-after-free and the ABA problem [UI] Explicit Z ordering of input listeners and UI overlays, top-down for input, bottom-up for drawing [UI] Add explicit window lifecycle phases [UI] Replace Window virtual functions with explicit desired state, its application, actual state, its feedback [UI] GTK: Apply the initial size to the drawing area [UI] Limit internal UI frame rate to that of the monitor [UI] Hide the cursor using a timer instead of polling due to no repeated UI thread paints with GPU CP thread presentation, and only within the window
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2022 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
@@ -30,6 +30,9 @@
|
||||
#include "xenia/memory.h"
|
||||
#include "xenia/ui/file_picker.h"
|
||||
#include "xenia/ui/imgui_drawer.h"
|
||||
#include "xenia/ui/immediate_drawer.h"
|
||||
#include "xenia/ui/presenter.h"
|
||||
#include "xenia/ui/ui_event.h"
|
||||
#include "xenia/ui/virtual_key.h"
|
||||
#include "xenia/ui/window.h"
|
||||
#include "xenia/ui/windowed_app_context.h"
|
||||
@@ -51,7 +54,8 @@ static const ImVec4 kColorIgnored =
|
||||
|
||||
TraceViewer::TraceViewer(xe::ui::WindowedAppContext& app_context,
|
||||
const std::string_view name)
|
||||
: xe::ui::WindowedApp(app_context, name, "some.trace") {
|
||||
: xe::ui::WindowedApp(app_context, name, "some.trace"),
|
||||
window_listener_(*this) {
|
||||
AddPositionalOption("target_trace_file");
|
||||
}
|
||||
|
||||
@@ -102,22 +106,27 @@ bool TraceViewer::OnInitialize() {
|
||||
}
|
||||
|
||||
bool TraceViewer::Setup() {
|
||||
enum : size_t {
|
||||
kZOrderImGui,
|
||||
kZOrderTraceViewerInput,
|
||||
};
|
||||
|
||||
// Main display window.
|
||||
assert_true(app_context().IsInUIThread());
|
||||
window_ = xe::ui::Window::Create(app_context(), "xenia-gpu-trace-viewer");
|
||||
if (!window_->Initialize()) {
|
||||
XELOGE("Failed to initialize main window");
|
||||
window_ = xe::ui::Window::Create(app_context(), "xenia-gpu-trace-viewer",
|
||||
1920, 1200);
|
||||
window_->AddListener(&window_listener_);
|
||||
window_->AddInputListener(&window_listener_, kZOrderTraceViewerInput);
|
||||
if (!window_->Open()) {
|
||||
XELOGE("Failed to open the main window");
|
||||
return false;
|
||||
}
|
||||
window_->on_closed.AddListener(
|
||||
[this](xe::ui::UIEvent* e) { app_context().QuitFromUIThread(); });
|
||||
window_->Resize(1920, 1200);
|
||||
|
||||
// Create the emulator but don't initialize so we can setup the window.
|
||||
emulator_ = std::make_unique<Emulator>("", "", "", "");
|
||||
X_STATUS result = emulator_->Setup(
|
||||
window_.get(), nullptr, [this]() { return CreateGraphicsSystem(); },
|
||||
nullptr);
|
||||
window_.get(), nullptr, nullptr,
|
||||
[this]() { return CreateGraphicsSystem(); }, nullptr);
|
||||
if (XFAILED(result)) {
|
||||
XELOGE("Failed to setup emulator: {:08X}", result);
|
||||
return false;
|
||||
@@ -125,31 +134,55 @@ bool TraceViewer::Setup() {
|
||||
memory_ = emulator_->memory();
|
||||
graphics_system_ = emulator_->graphics_system();
|
||||
|
||||
window_->set_imgui_input_enabled(true);
|
||||
|
||||
window_->on_key_char.AddListener([&](xe::ui::KeyEvent* e) {
|
||||
if (e->virtual_key() == xe::ui::VirtualKey::kF5) {
|
||||
graphics_system_->ClearCaches();
|
||||
e->set_handled(true);
|
||||
}
|
||||
});
|
||||
|
||||
player_ = std::make_unique<TracePlayer>(graphics_system_);
|
||||
player_->SetPresentLastCopy(true);
|
||||
|
||||
window_->on_painting.AddListener([this](xe::ui::UIEvent* e) {
|
||||
DrawUI();
|
||||
|
||||
// Continuous paint.
|
||||
window_->Invalidate();
|
||||
});
|
||||
window_->Invalidate();
|
||||
// Setup drawing to the window.
|
||||
xe::ui::GraphicsProvider& graphics_provider = *graphics_system_->provider();
|
||||
presenter_ = graphics_provider.CreatePresenter();
|
||||
if (!presenter_) {
|
||||
XELOGE("Failed to initialize the presenter");
|
||||
return false;
|
||||
}
|
||||
immediate_drawer_ = graphics_provider.CreateImmediateDrawer();
|
||||
if (!immediate_drawer_) {
|
||||
XELOGE("Failed to initialize the immediate drawer");
|
||||
return false;
|
||||
}
|
||||
immediate_drawer_->SetPresenter(presenter_.get());
|
||||
imgui_drawer_ =
|
||||
std::make_unique<xe::ui::ImGuiDrawer>(window_.get(), kZOrderImGui);
|
||||
imgui_drawer_->SetPresenterAndImmediateDrawer(presenter_.get(),
|
||||
immediate_drawer_.get());
|
||||
trace_viewer_dialog_ = std::unique_ptr<TraceViewerDialog>(
|
||||
new TraceViewerDialog(imgui_drawer_.get(), *this));
|
||||
window_->SetPresenter(presenter_.get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TraceViewer::TraceViewerWindowListener::OnClosing(xe::ui::UIEvent& e) {
|
||||
trace_viewer_.app_context().QuitFromUIThread();
|
||||
}
|
||||
|
||||
void TraceViewer::TraceViewerWindowListener::OnKeyDown(xe::ui::KeyEvent& e) {
|
||||
switch (e.virtual_key()) {
|
||||
case xe::ui::VirtualKey::kF5:
|
||||
trace_viewer_.graphics_system_->ClearCaches();
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
e.set_handled(true);
|
||||
}
|
||||
|
||||
void TraceViewer::TraceViewerDialog::OnDraw(ImGuiIO& io) {
|
||||
trace_viewer_.DrawUI();
|
||||
}
|
||||
|
||||
bool TraceViewer::Load(const std::filesystem::path& trace_file_path) {
|
||||
auto file_name = trace_file_path.filename();
|
||||
window_->set_title("Xenia GPU Trace Viewer: " + xe::path_to_utf8(file_name));
|
||||
window_->SetTitle("Xenia GPU Trace Viewer: " + xe::path_to_utf8(file_name));
|
||||
|
||||
if (!player_->Open(trace_file_path)) {
|
||||
XELOGE("Could not load trace file");
|
||||
@@ -233,8 +266,9 @@ void TraceViewer::DrawControllerUI() {
|
||||
|
||||
void TraceViewer::DrawPacketDisassemblerUI() {
|
||||
ImGui::SetNextWindowCollapsed(true, ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowPos(ImVec2(float(window_->width()) - 500 - 5, 5),
|
||||
ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowPos(
|
||||
ImVec2(float(window_->GetActualLogicalWidth()) - 500 - 5, 5),
|
||||
ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowSize(ImVec2(500, 300));
|
||||
if (!ImGui::Begin("Packet Disassembler", nullptr)) {
|
||||
ImGui::End();
|
||||
@@ -1052,8 +1086,9 @@ void TraceViewer::DrawStateUI() {
|
||||
auto command_processor = graphics_system_->command_processor();
|
||||
auto& regs = *graphics_system_->register_file();
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(float(window_->width()) - 500 - 5, 30),
|
||||
ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowPos(
|
||||
ImVec2(float(window_->GetActualLogicalWidth()) - 500 - 5, 30),
|
||||
ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowSize(ImVec2(500, 680));
|
||||
if (!ImGui::Begin("State", nullptr)) {
|
||||
ImGui::End();
|
||||
|
||||
Reference in New Issue
Block a user