mirror of
https://github.com/xenia-project/xenia.git
synced 2024-11-27 13:30:44 +00:00
[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
This commit is contained in:
parent
28670d8ec2
commit
e37e3ef382
@ -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(
|
||||
|
@ -916,9 +916,7 @@ bool CommandProcessor::ExecutePacketType3_XE_SWAP(RingBuffer* reader,
|
||||
uint32_t frontbuffer_height = reader->ReadAndSwap<uint32_t>();
|
||||
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;
|
||||
|
@ -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<bool> worker_running_;
|
||||
kernel::object_ref<kernel::XHostThread> worker_thread_;
|
||||
|
||||
bool ignore_swap_ = false;
|
||||
|
||||
std::queue<std::function<void()>> pending_fns_;
|
||||
|
||||
// MicroEngine binary from PM4_ME_INIT
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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<TracePlayer>(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<xe::ui::ImGuiDrawer>(window_.get(), kZOrderImGui);
|
||||
imgui_drawer_->SetPresenterAndImmediateDrawer(presenter_.get(),
|
||||
imgui_drawer_->SetPresenterAndImmediateDrawer(presenter,
|
||||
immediate_drawer_.get());
|
||||
trace_viewer_dialog_ = std::unique_ptr<TraceViewerDialog>(
|
||||
new TraceViewerDialog(imgui_drawer_.get(), *this));
|
||||
window_->SetPresenter(presenter_.get());
|
||||
window_->SetPresenter(presenter);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -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<TracePlayer> player_;
|
||||
|
||||
std::unique_ptr<xe::ui::Presenter> presenter_;
|
||||
std::unique_ptr<xe::ui::ImmediateDrawer> immediate_drawer_;
|
||||
std::unique_ptr<xe::ui::ImGuiDrawer> imgui_drawer_;
|
||||
std::unique_ptr<TraceViewerDialog> trace_viewer_dialog_;
|
||||
|
@ -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<VkCommandBuffer> 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_) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user