[App] Refactor title bar display and add cpu backend

This commit is contained in:
Herman S.
2026-04-27 00:57:10 +09:00
parent d7421f8b0a
commit d8a0f832a8
15 changed files with 119 additions and 88 deletions
+36 -6
View File
@@ -104,6 +104,8 @@
#endif
#endif
#include "xenia/apu/audio_system.h"
#include "xenia/cpu/backend/backend.h"
#include "xenia/cpu/processor.h"
#include "xenia/emulator.h"
#include "xenia/gpu/command_processor.h"
@@ -1960,16 +1962,44 @@ void EmulatorWindow::UpdateTitle() {
}
}
// Graphics system name, if available
std::string graphics_name;
std::string graphics_suffix;
auto graphics_system = emulator()->graphics_system();
if (graphics_system) {
auto graphics_name = graphics_system->name();
if (!graphics_name.empty()) {
sb.Append(" <");
sb.Append(graphics_name);
sb.Append(">");
graphics_name = graphics_system->name();
auto command_processor = graphics_system->command_processor();
if (command_processor) {
graphics_suffix = command_processor->GetTitleStateSuffix();
}
}
std::string audio_name;
auto audio_system = emulator()->audio_system();
if (audio_system) {
audio_name = audio_system->name();
}
std::string cpu_name;
auto processor = emulator()->processor();
if (processor && processor->backend()) {
cpu_name = processor->backend()->name();
}
if (!graphics_name.empty() || !cpu_name.empty()) {
sb.Append(" <");
if (!graphics_name.empty()) {
sb.Append(graphics_name);
sb.Append(graphics_suffix);
if (!audio_name.empty()) {
sb.Append(" - ");
sb.Append(audio_name);
}
}
if (!cpu_name.empty()) {
if (!graphics_name.empty()) {
sb.Append(" - ");
}
sb.Append(cpu_name);
}
sb.Append(">");
}
if (Clock::guest_time_scalar() != 1.0) {
sb.AppendFormat(" (@{:.2f}x)", Clock::guest_time_scalar());
+2
View File
@@ -101,6 +101,8 @@ class A64Backend : public Backend {
A64CodeCache* code_cache() const { return code_cache_.get(); }
uintptr_t emitter_data() const { return emitter_data_; }
std::string name() const override { return "a64"; }
HostToGuestThunk host_to_guest_thunk() const { return host_to_guest_thunk_; }
GuestToHostThunk guest_to_host_thunk() const { return guest_to_host_thunk_; }
ResolveFunctionThunk resolve_function_thunk() const {
+3
View File
@@ -11,6 +11,7 @@
#define XENIA_CPU_BACKEND_BACKEND_H_
#include <memory>
#include <string>
#include "xenia/cpu/backend/machine_info.h"
#include "xenia/cpu/thread_debug_info.h"
@@ -50,6 +51,8 @@ class Backend {
const MachineInfo* machine_info() const { return &machine_info_; }
CodeCache* code_cache() const { return code_cache_; }
virtual std::string name() const { return "unknown"; }
virtual bool Initialize(Processor* processor);
virtual void* AllocThreadData();
+2
View File
@@ -18,6 +18,8 @@ namespace backend {
class NullBackend : public Backend {
public:
std::string name() const override { return "null"; }
void CommitExecutableRange(uint32_t guest_low, uint32_t guest_high) override;
std::unique_ptr<Assembler> CreateAssembler() override;
+2
View File
@@ -128,6 +128,8 @@ class X64Backend : public Backend {
X64CodeCache* code_cache() const { return code_cache_.get(); }
uintptr_t emitter_data() const { return emitter_data_; }
std::string name() const override { return "x64"; }
// Call a generated function, saving all stack parameters.
HostToGuestThunk host_to_guest_thunk() const { return host_to_guest_thunk_; }
// Function that guest code can call to transition into host code.
+2
View File
@@ -144,6 +144,8 @@ class CommandProcessor {
virtual bool Initialize();
virtual void Shutdown();
virtual std::string GetTitleStateSuffix() const { return {}; }
void CallInThread(std::function<void()> fn);
virtual void ClearCaches();
+28 -34
View File
@@ -12,14 +12,12 @@
#include <cstdarg>
#include <cstring>
#include "xenia/apu/audio_system.h"
#include "xenia/base/assert.h"
#include "xenia/base/byte_order.h"
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h"
#include "xenia/base/math.h"
#include "xenia/base/profiling.h"
#include "xenia/emulator.h"
#include "xenia/gpu/d3d12/d3d12_graphics_system.h"
#include "xenia/gpu/d3d12/d3d12_shader.h"
#include "xenia/gpu/d3d12/d3d12_zpd_query_pool.h"
@@ -798,40 +796,36 @@ void D3D12CommandProcessor::SetPrimitiveTopology(
}
}
std::string D3D12CommandProcessor::GetWindowTitleText() const {
std::ostringstream title;
title << "Direct3D 12";
if (render_target_cache_) {
// Rasterizer-ordered views are a feature very rarely used as of 2020 and
// that faces adoption complications (outside of Direct3D - on Vulkan - at
// least), but crucial to Xenia - raise awareness of its usage.
// https://github.com/KhronosGroup/Vulkan-Ecosystem/issues/27#issuecomment-455712319
// "In Xenia's title bar "D3D12 ROV" can be seen, which was a surprise, as I
// wasn't aware that Xenia D3D12 backend was using Raster Order Views
// feature" - oscarbg in that issue.
switch (render_target_cache_->GetPath()) {
case RenderTargetCache::Path::kHostRenderTargets:
title << " - RTV/DSV";
break;
case RenderTargetCache::Path::kPixelShaderInterlock:
title << " - ROV";
break;
default:
break;
}
uint32_t draw_resolution_scale_x =
texture_cache_ ? texture_cache_->draw_resolution_scale_x() : 1;
uint32_t draw_resolution_scale_y =
texture_cache_ ? texture_cache_->draw_resolution_scale_y() : 1;
if (draw_resolution_scale_x > 1 || draw_resolution_scale_y > 1) {
title << ' ' << draw_resolution_scale_x << 'x' << draw_resolution_scale_y;
}
std::string D3D12CommandProcessor::GetTitleStateSuffix() const {
if (!render_target_cache_) {
return {};
}
auto* audio_system = kernel_state_->emulator()->audio_system();
if (audio_system) {
title << " - " << audio_system->name();
std::ostringstream suffix;
// Rasterizer-ordered views are a feature very rarely used as of 2020 and
// that faces adoption complications (outside of Direct3D - on Vulkan - at
// least), but crucial to Xenia - raise awareness of its usage.
// https://github.com/KhronosGroup/Vulkan-Ecosystem/issues/27#issuecomment-455712319
// "In Xenia's title bar "D3D12 ROV" can be seen, which was a surprise, as I
// wasn't aware that Xenia D3D12 backend was using Raster Order Views
// feature" - oscarbg in that issue.
switch (render_target_cache_->GetPath()) {
case RenderTargetCache::Path::kHostRenderTargets:
suffix << " - RTV/DSV";
break;
case RenderTargetCache::Path::kPixelShaderInterlock:
suffix << " - ROV";
break;
default:
break;
}
return title.str();
uint32_t draw_resolution_scale_x =
texture_cache_ ? texture_cache_->draw_resolution_scale_x() : 1;
uint32_t draw_resolution_scale_y =
texture_cache_ ? texture_cache_->draw_resolution_scale_y() : 1;
if (draw_resolution_scale_x > 1 || draw_resolution_scale_y > 1) {
suffix << ' ' << draw_resolution_scale_x << 'x' << draw_resolution_scale_y;
}
return suffix.str();
}
bool D3D12CommandProcessor::SetupContext() {
@@ -229,8 +229,7 @@ class D3D12CommandProcessor final : public CommandProcessor {
void SetStencilReference(uint32_t stencil_ref);
void SetPrimitiveTopology(D3D12_PRIMITIVE_TOPOLOGY primitive_topology);
// Returns the text to display in the GPU backend name in the window title.
std::string GetWindowTitleText() const;
std::string GetTitleStateSuffix() const override;
protected:
bool SetupContext() override;
+1 -8
View File
@@ -28,14 +28,7 @@ bool D3D12GraphicsSystem::IsAvailable() {
return xe::ui::d3d12::D3D12Provider::IsD3D12APIAvailable();
}
std::string D3D12GraphicsSystem::name() const {
auto d3d12_command_processor =
static_cast<D3D12CommandProcessor*>(command_processor());
if (d3d12_command_processor != nullptr) {
return d3d12_command_processor->GetWindowTitleText();
}
return "Direct3D 12";
}
std::string D3D12GraphicsSystem::name() const { return "D3D12"; }
X_STATUS D3D12GraphicsSystem::Setup(cpu::Processor* processor,
kernel::KernelState* kernel_state,
@@ -471,6 +471,22 @@ MetalCommandProcessor::MetalCommandProcessor(
MetalGraphicsSystem* graphics_system, kernel::KernelState* kernel_state)
: CommandProcessor(graphics_system, kernel_state) {}
std::string MetalCommandProcessor::GetTitleStateSuffix() const {
if (!render_target_cache_) {
return {};
}
std::ostringstream suffix;
suffix << " - SPIRV-Cross";
uint32_t draw_resolution_scale_x =
texture_cache_ ? texture_cache_->draw_resolution_scale_x() : 1;
uint32_t draw_resolution_scale_y =
texture_cache_ ? texture_cache_->draw_resolution_scale_y() : 1;
if (draw_resolution_scale_x > 1 || draw_resolution_scale_y > 1) {
suffix << ' ' << draw_resolution_scale_x << 'x' << draw_resolution_scale_y;
}
return suffix.str();
}
MetalCommandProcessor::~MetalCommandProcessor() {
// End any active render encoder before releasing
// Note: Only call endEncoding if the encoder is still active
@@ -67,6 +67,8 @@ class MetalCommandProcessor : public CommandProcessor {
void InvalidateGpuMemory() override;
void ClearReadbackBuffers() override;
std::string GetTitleStateSuffix() const override;
// Track memory regions written by IssueCopy (resolve) so trace playback
// can skip overwriting them with stale data from the trace file.
void MarkResolvedMemory(uint32_t base_ptr, uint32_t length);
+1 -1
View File
@@ -26,7 +26,7 @@ bool MetalGraphicsSystem::IsAvailable() {
return xe::ui::metal::MetalProvider::IsMetalAPIAvailable();
}
std::string MetalGraphicsSystem::name() const { return "MetalGraphicsSystem"; }
std::string MetalGraphicsSystem::name() const { return "Metal"; }
X_STATUS MetalGraphicsSystem::Setup(cpu::Processor* processor,
kernel::KernelState* kernel_state,
@@ -13,13 +13,11 @@
#include <cstdint>
#include <cstring>
#include "xenia/apu/audio_system.h"
#include "xenia/base/assert.h"
#include "xenia/base/byte_order.h"
#include "xenia/base/logging.h"
#include "xenia/base/math.h"
#include "xenia/base/profiling.h"
#include "xenia/emulator.h"
#include "xenia/gpu/draw_util.h"
#include "xenia/gpu/gpu_flags.h"
#include "xenia/gpu/packet_disassembler.h"
@@ -190,33 +188,29 @@ void VulkanCommandProcessor::ReturnFromWait() {
CommandProcessor::ReturnFromWait();
}
std::string VulkanCommandProcessor::GetWindowTitleText() const {
std::ostringstream title;
title << "Vulkan";
if (render_target_cache_) {
switch (render_target_cache_->GetPath()) {
case RenderTargetCache::Path::kHostRenderTargets:
title << " - FBO";
break;
case RenderTargetCache::Path::kPixelShaderInterlock:
title << " - FSI";
break;
default:
break;
}
uint32_t draw_resolution_scale_x =
texture_cache_ ? texture_cache_->draw_resolution_scale_x() : 1;
uint32_t draw_resolution_scale_y =
texture_cache_ ? texture_cache_->draw_resolution_scale_y() : 1;
if (draw_resolution_scale_x > 1 || draw_resolution_scale_y > 1) {
title << ' ' << draw_resolution_scale_x << 'x' << draw_resolution_scale_y;
}
std::string VulkanCommandProcessor::GetTitleStateSuffix() const {
if (!render_target_cache_) {
return {};
}
auto* audio_system = kernel_state_->emulator()->audio_system();
if (audio_system) {
title << " - " << audio_system->name();
std::ostringstream suffix;
switch (render_target_cache_->GetPath()) {
case RenderTargetCache::Path::kHostRenderTargets:
suffix << " - FBO";
break;
case RenderTargetCache::Path::kPixelShaderInterlock:
suffix << " - FSI";
break;
default:
break;
}
return title.str();
uint32_t draw_resolution_scale_x =
texture_cache_ ? texture_cache_->draw_resolution_scale_x() : 1;
uint32_t draw_resolution_scale_y =
texture_cache_ ? texture_cache_->draw_resolution_scale_y() : 1;
if (draw_resolution_scale_x > 1 || draw_resolution_scale_y > 1) {
suffix << ' ' << draw_resolution_scale_x << 'x' << draw_resolution_scale_y;
}
return suffix.str();
}
bool VulkanCommandProcessor::SetupContext() {
@@ -271,8 +271,7 @@ class VulkanCommandProcessor final : public CommandProcessor {
void SetViewport(const VkViewport& viewport);
void SetScissor(const VkRect2D& scissor);
// Returns the text to display in the GPU backend name in the window title.
std::string GetWindowTitleText() const;
std::string GetTitleStateSuffix() const override;
// Debug marker methods - public so subsystems can annotate their operations.
void PushDebugMarker(const char* format, ...);
@@ -21,14 +21,7 @@ VulkanGraphicsSystem::VulkanGraphicsSystem() {}
VulkanGraphicsSystem::~VulkanGraphicsSystem() {}
std::string VulkanGraphicsSystem::name() const {
auto vulkan_command_processor =
static_cast<VulkanCommandProcessor*>(command_processor());
if (vulkan_command_processor != nullptr) {
return vulkan_command_processor->GetWindowTitleText();
}
return "Vulkan";
}
std::string VulkanGraphicsSystem::name() const { return "Vulkan"; }
X_STATUS VulkanGraphicsSystem::Setup(cpu::Processor* processor,
kernel::KernelState* kernel_state,