[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:
Triang3l
2022-01-29 13:22:03 +03:00
parent 372bdd3ec9
commit fe3f0f26e4
428 changed files with 75942 additions and 18360 deletions

View File

@@ -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();