From e37e3ef3821ab3a1458f9dec27aaa6ac6b6eeecf Mon Sep 17 00:00:00 2001 From: Triang3l Date: Fri, 1 Jul 2022 19:50:19 +0300 Subject: [PATCH] [GPU] Display swap output in the trace viewer Resolve output is unreliable because resolving may be done to a subregion of a texture and even to 3D textures, and to any color format --- src/xenia/app/emulator_window.cc | 1 + src/xenia/gpu/command_processor.cc | 4 +--- src/xenia/gpu/command_processor.h | 3 --- src/xenia/gpu/d3d12/d3d12_command_processor.cc | 4 ---- src/xenia/gpu/trace_player.cc | 17 ++--------------- src/xenia/gpu/trace_player.h | 9 +-------- src/xenia/gpu/trace_viewer.cc | 15 +++++++-------- src/xenia/gpu/trace_viewer.h | 2 -- .../gpu/vulkan/vulkan_command_processor.cc | 8 -------- src/xenia/gpu/vulkan/vulkan_command_processor.h | 3 --- src/xenia/ui/presenter.cc | 6 ++++-- src/xenia/ui/presenter.h | 11 +++++++++-- 12 files changed, 25 insertions(+), 58 deletions(-) diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc index 7e6d9e6b7..cab817a10 100644 --- a/src/xenia/app/emulator_window.cc +++ b/src/xenia/app/emulator_window.cc @@ -683,6 +683,7 @@ EmulatorWindow::GetGuestOutputPaintEffectForCvarValue( ui::Presenter::GuestOutputPaintConfig EmulatorWindow::GetGuestOutputPaintConfigForCvars() { ui::Presenter::GuestOutputPaintConfig paint_config; + paint_config.SetAllowOverscanCutoff(true); paint_config.SetEffect(GetGuestOutputPaintEffectForCvarValue( cvars::postprocess_scaling_and_sharpening)); paint_config.SetCasAdditionalSharpness( diff --git a/src/xenia/gpu/command_processor.cc b/src/xenia/gpu/command_processor.cc index bb452c13d..8e9bc6067 100644 --- a/src/xenia/gpu/command_processor.cc +++ b/src/xenia/gpu/command_processor.cc @@ -916,9 +916,7 @@ bool CommandProcessor::ExecutePacketType3_XE_SWAP(RingBuffer* reader, uint32_t frontbuffer_height = reader->ReadAndSwap(); reader->AdvanceRead((count - 4) * sizeof(uint32_t)); - if (!ignore_swap_) { - IssueSwap(frontbuffer_ptr, frontbuffer_width, frontbuffer_height); - } + IssueSwap(frontbuffer_ptr, frontbuffer_width, frontbuffer_height); ++counter_; return true; diff --git a/src/xenia/gpu/command_processor.h b/src/xenia/gpu/command_processor.h index 367ed9ee2..ffc8eeffa 100644 --- a/src/xenia/gpu/command_processor.h +++ b/src/xenia/gpu/command_processor.h @@ -90,7 +90,6 @@ class CommandProcessor { virtual void ClearCaches(); - void SetIgnoreSwap(bool ignore_swap) { ignore_swap_ = ignore_swap; } // "Desired" is for the external thread managing the post-processing effect. SwapPostEffect GetDesiredSwapPostEffect() const { return swap_post_effect_desired_; @@ -265,8 +264,6 @@ class CommandProcessor { std::atomic worker_running_; kernel::object_ref worker_thread_; - bool ignore_swap_ = false; - std::queue> pending_fns_; // MicroEngine binary from PM4_ME_INIT diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index 79c0be085..955c2667b 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -1718,10 +1718,6 @@ void D3D12CommandProcessor::OnGammaRampPWLValueWritten() { void D3D12CommandProcessor::IssueSwap(uint32_t frontbuffer_ptr, uint32_t frontbuffer_width, uint32_t frontbuffer_height) { - // FIXME(Triang3l): frontbuffer_ptr is currently unreliable, in the trace - // player it's set to 0, but it's not needed anyway since the fetch constant - // contains the address. - SCOPE_profile_cpu_f("gpu"); ui::Presenter* presenter = graphics_system_->presenter(); diff --git a/src/xenia/gpu/trace_player.cc b/src/xenia/gpu/trace_player.cc index b1aa8f615..c127d4c56 100644 --- a/src/xenia/gpu/trace_player.cc +++ b/src/xenia/gpu/trace_player.cc @@ -89,19 +89,15 @@ void TracePlayer::PlayTrace(const uint8_t* trace_data, size_t trace_size, TracePlaybackMode playback_mode, bool clear_caches) { playing_trace_ = true; - // Pass a copy of present_last_copy_ to the thread so it's not accessible by - // multiple threads at once. - bool present_last_copy = present_last_copy_; graphics_system_->command_processor()->CallInThread([=]() { - PlayTraceOnThread(trace_data, trace_size, playback_mode, clear_caches, - present_last_copy); + PlayTraceOnThread(trace_data, trace_size, playback_mode, clear_caches); }); } void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data, size_t trace_size, TracePlaybackMode playback_mode, - bool clear_caches, bool present_last_copy) { + bool clear_caches) { auto memory = graphics_system_->memory(); auto command_processor = graphics_system_->command_processor(); @@ -109,10 +105,6 @@ void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data, command_processor->ClearCaches(); } - if (present_last_copy) { - command_processor->SetIgnoreSwap(true); - } - playback_percent_ = 0; auto trace_end = trace_data + trace_size; @@ -252,11 +244,6 @@ void TracePlayer::PlayTraceOnThread(const uint8_t* trace_data, playing_trace_ = false; - if (present_last_copy) { - command_processor->SetIgnoreSwap(false); - command_processor->IssueSwap(0, 1280, 720); - } - playback_event_->Set(); } diff --git a/src/xenia/gpu/trace_player.h b/src/xenia/gpu/trace_player.h index 4bb5fdd2c..9117e88a4 100644 --- a/src/xenia/gpu/trace_player.h +++ b/src/xenia/gpu/trace_player.h @@ -32,9 +32,6 @@ class TracePlayer : public TraceReader { TracePlayer(GraphicsSystem* graphics_system); GraphicsSystem* graphics_system() const { return graphics_system_; } - void SetPresentLastCopy(bool present_last_copy) { - present_last_copy_ = present_last_copy; - } int current_frame_index() const { return current_frame_index_; } int current_command_index() const { return current_command_index_; } bool is_playing_trace() const { return playing_trace_; } @@ -53,13 +50,9 @@ class TracePlayer : public TraceReader { void PlayTrace(const uint8_t* trace_data, size_t trace_size, TracePlaybackMode playback_mode, bool clear_caches); void PlayTraceOnThread(const uint8_t* trace_data, size_t trace_size, - TracePlaybackMode playback_mode, bool clear_caches, - bool present_last_copy); + TracePlaybackMode playback_mode, bool clear_caches); GraphicsSystem* graphics_system_; - // Whether to present the results of the latest resolve instead of displaying - // the front buffer from the trace. - bool present_last_copy_ = false; int current_frame_index_; int current_command_index_; bool playing_trace_ = false; diff --git a/src/xenia/gpu/trace_viewer.cc b/src/xenia/gpu/trace_viewer.cc index a4733ecbf..70f68c184 100644 --- a/src/xenia/gpu/trace_viewer.cc +++ b/src/xenia/gpu/trace_viewer.cc @@ -114,7 +114,7 @@ bool TraceViewer::Setup() { // Main display window. assert_true(app_context().IsInUIThread()); window_ = xe::ui::Window::Create(app_context(), "xenia-gpu-trace-viewer", - 1920, 1200); + 1920, 1080); window_->AddListener(&window_listener_); window_->AddInputListener(&window_listener_, kZOrderTraceViewerInput); if (!window_->Open()) { @@ -135,28 +135,27 @@ bool TraceViewer::Setup() { graphics_system_ = emulator_->graphics_system(); player_ = std::make_unique(graphics_system_); - player_->SetPresentLastCopy(true); // Setup drawing to the window. - xe::ui::GraphicsProvider& graphics_provider = *graphics_system_->provider(); - presenter_ = graphics_provider.CreatePresenter(); - if (!presenter_) { + ui::Presenter* presenter = graphics_system_->presenter(); + if (!presenter) { XELOGE("Failed to initialize the presenter"); return false; } + xe::ui::GraphicsProvider& graphics_provider = *graphics_system_->provider(); immediate_drawer_ = graphics_provider.CreateImmediateDrawer(); if (!immediate_drawer_) { XELOGE("Failed to initialize the immediate drawer"); return false; } - immediate_drawer_->SetPresenter(presenter_.get()); + immediate_drawer_->SetPresenter(presenter); imgui_drawer_ = std::make_unique(window_.get(), kZOrderImGui); - imgui_drawer_->SetPresenterAndImmediateDrawer(presenter_.get(), + imgui_drawer_->SetPresenterAndImmediateDrawer(presenter, immediate_drawer_.get()); trace_viewer_dialog_ = std::unique_ptr( new TraceViewerDialog(imgui_drawer_.get(), *this)); - window_->SetPresenter(presenter_.get()); + window_->SetPresenter(presenter); return true; } diff --git a/src/xenia/gpu/trace_viewer.h b/src/xenia/gpu/trace_viewer.h index ecca12792..8ef0e9b86 100644 --- a/src/xenia/gpu/trace_viewer.h +++ b/src/xenia/gpu/trace_viewer.h @@ -21,7 +21,6 @@ #include "xenia/ui/imgui_dialog.h" #include "xenia/ui/imgui_drawer.h" #include "xenia/ui/immediate_drawer.h" -#include "xenia/ui/presenter.h" #include "xenia/ui/window.h" #include "xenia/ui/window_listener.h" #include "xenia/ui/windowed_app.h" @@ -129,7 +128,6 @@ class TraceViewer : public xe::ui::WindowedApp { GraphicsSystem* graphics_system_ = nullptr; std::unique_ptr player_; - std::unique_ptr presenter_; std::unique_ptr immediate_drawer_; std::unique_ptr imgui_drawer_; std::unique_ptr trace_viewer_dialog_; diff --git a/src/xenia/gpu/vulkan/vulkan_command_processor.cc b/src/xenia/gpu/vulkan/vulkan_command_processor.cc index 43a7a2ab7..2dcf09f0e 100644 --- a/src/xenia/gpu/vulkan/vulkan_command_processor.cc +++ b/src/xenia/gpu/vulkan/vulkan_command_processor.cc @@ -269,11 +269,6 @@ void VulkanCommandProcessor::IssueSwap(uint32_t frontbuffer_ptr, return; } - if (!frontbuffer_ptr) { - // Trace viewer does this. - frontbuffer_ptr = last_copy_base_; - } - std::vector submit_buffers; if (frame_open_) { // TODO(DrChat): If the setup buffer is empty, don't bother queueing it up. @@ -1108,9 +1103,6 @@ bool VulkanCommandProcessor::IssueCopy() { texture->in_flight_fence = current_batch_fence_; - // For debugging purposes only (trace viewer) - last_copy_base_ = texture->texture_info.memory.base_address; - if (!frame_open_) { BeginFrame(); } else if (current_render_state_) { diff --git a/src/xenia/gpu/vulkan/vulkan_command_processor.h b/src/xenia/gpu/vulkan/vulkan_command_processor.h index 4359a3c90..062ef0f61 100644 --- a/src/xenia/gpu/vulkan/vulkan_command_processor.h +++ b/src/xenia/gpu/vulkan/vulkan_command_processor.h @@ -106,9 +106,6 @@ class VulkanCommandProcessor : public CommandProcessor { uint32_t coher_base_vc_ = 0; uint32_t coher_size_vc_ = 0; - // Last copy base address, for debugging only. - uint32_t last_copy_base_ = 0; - bool capturing_ = false; bool trace_requested_ = false; bool cache_clear_requested_ = false; diff --git a/src/xenia/ui/presenter.cc b/src/xenia/ui/presenter.cc index 766a632cf..ab28ca4b4 100644 --- a/src/xenia/ui/presenter.cc +++ b/src/xenia/ui/presenter.cc @@ -714,7 +714,8 @@ Presenter::GuestOutputPaintFlow Presenter::GetGuestOutputPaintFlow( // ratio while stretching throughout the entire surface's width, then limit // the Y cropping via letterboxing or stretching along X. uint32_t present_safe_area; - if (cvars::present_safe_area_y > 0 && cvars::present_safe_area_y < 100) { + if (config.GetAllowOverscanCutoff() && cvars::present_safe_area_y > 0 && + cvars::present_safe_area_y < 100) { present_safe_area = uint32_t(cvars::present_safe_area_y); } else { present_safe_area = 100; @@ -756,7 +757,8 @@ Presenter::GuestOutputPaintFlow Presenter::GetGuestOutputPaintFlow( // aspect ratio while stretching throughout the entire surface's height, // then limit the X cropping via letterboxing or stretching along Y. uint32_t present_safe_area; - if (cvars::present_safe_area_x > 0 && cvars::present_safe_area_x < 100) { + if (config.GetAllowOverscanCutoff() && cvars::present_safe_area_x > 0 && + cvars::present_safe_area_x < 100) { present_safe_area = uint32_t(cvars::present_safe_area_x); } else { present_safe_area = 100; diff --git a/src/xenia/ui/presenter.h b/src/xenia/ui/presenter.h index bb2fc7740..9862546ab 100644 --- a/src/xenia/ui/presenter.h +++ b/src/xenia/ui/presenter.h @@ -228,6 +228,11 @@ class Presenter { // In the sharpness setters, min / max with a constant as the first argument // also drops NaNs. + bool GetAllowOverscanCutoff() const { return allow_overscan_cutoff_; } + void SetAllowOverscanCutoff(bool new_allow_overscan_cutoff) { + allow_overscan_cutoff_ = new_allow_overscan_cutoff; + } + Effect GetEffect() const { return effect_; } void SetEffect(Effect new_effect) { effect_ = new_effect; } @@ -265,8 +270,10 @@ class Presenter { void SetDither(bool new_dither) { dither_ = new_dither; } private: - // Tools, rather than the emulator itself, must use kBilinear as the image - // must be as close to the original front buffer as possible. + // Tools, rather than the emulator itself, must not allow overscan cutoff + // and must use the kBilinear effect as the image must be as close to the + // original front buffer as possible. + bool allow_overscan_cutoff_ = false; Effect effect_ = Effect::kBilinear; float cas_additional_sharpness_ = kCasAdditionalSharpnessDefault; uint32_t fsr_max_upsampling_passes_ = kFsrMaxUpscalingPassesMax;