mirror of
https://github.com/sal063/AC6_recomp
synced 2026-08-14 12:34:45 -04:00
chore: resolve merge conflicts, clean up workspace, update README
- Resolve merge conflicts in CMakeLists.txt, .gitignore, and all src/ files, keeping the HEAD (native renderer) versions throughout - Remove stale SDK alternate-tree ref (rexglue-sdk~6e0ca2f) from index - Drop scratch files: 'New Text Document.txt', *.bak - Rewrite README with full setup instructions, prereqs table, build preset table, run command, project layout overview, and Linux section
This commit is contained in:
+1
-3003
File diff suppressed because it is too large
Load Diff
+1
-180
@@ -1,180 +1 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <rex/cvar.h>
|
||||
#include <rex/runtime.h>
|
||||
|
||||
#include "ac6_native_renderer/types.h"
|
||||
#include "d3d_state.h"
|
||||
|
||||
REXCVAR_DECLARE(bool, ac6_allow_gpu_trace_stream);
|
||||
REXCVAR_DECLARE(bool, ac6_native_present_enabled);
|
||||
REXCVAR_DECLARE(bool, ac6_native_present_force_pm4_fallback);
|
||||
REXCVAR_DECLARE(bool, ac6_native_present_enable_postfx);
|
||||
REXCVAR_DECLARE(bool, ac6_native_present_enable_ui_compose);
|
||||
REXCVAR_DECLARE(bool, ac6_native_present_allow_unstable);
|
||||
|
||||
namespace ac6::graphics {
|
||||
|
||||
enum class SwapRoutingMode : uint32_t {
|
||||
kCompatPm4 = 0,
|
||||
kNativeAuthoritative = 1,
|
||||
kEmergencyHold = 2,
|
||||
};
|
||||
|
||||
enum class SwapIngressPath : uint32_t {
|
||||
kUnknown = 0,
|
||||
kKernelDirectSwap = 1,
|
||||
kPm4XeSwap = 2,
|
||||
};
|
||||
|
||||
enum class SwapExecutionPath : uint32_t {
|
||||
kUnknown = 0,
|
||||
kDirectPresentSwap = 1,
|
||||
kNativeRasterReplay = 2,
|
||||
kNativeMinimalUav = 3,
|
||||
kPm4Fallback = 4,
|
||||
kEmergencyHoldNoPresent = 5,
|
||||
};
|
||||
|
||||
enum class CadencePolicy : uint32_t {
|
||||
kTimerVblank = 0,
|
||||
kPresentCompletion = 1,
|
||||
kHybridDebug = 2,
|
||||
};
|
||||
|
||||
struct SelectedPassPreviewSummary {
|
||||
bool valid{false};
|
||||
uint32_t draw_count{0};
|
||||
uint32_t clear_count{0};
|
||||
uint32_t resolve_count{0};
|
||||
uint32_t sampled_clear_color_count{0};
|
||||
uint32_t sampled_clear_rect_count{0};
|
||||
uint32_t first_clear_color{0};
|
||||
uint32_t last_clear_color{0};
|
||||
bool using_clear_fill{false};
|
||||
bool using_raster_replay{false};
|
||||
bool using_scene_stage_intermediate{false};
|
||||
};
|
||||
|
||||
struct NativeReplayPlanSummary {
|
||||
bool valid{false};
|
||||
uint64_t frame_index{0};
|
||||
uint32_t pass_count{0};
|
||||
uint32_t swap_size_match_pass_count{0};
|
||||
uint32_t draw_event_count{0};
|
||||
uint32_t clear_event_count{0};
|
||||
uint32_t resolve_event_count{0};
|
||||
uint32_t largest_pass_draw_count{0};
|
||||
uint32_t first_pass_draw_count{0};
|
||||
uint32_t last_pass_draw_count{0};
|
||||
uint32_t selected_pass_index{0};
|
||||
uint32_t selected_pass_score{0};
|
||||
uint32_t selected_pass_start_sequence{0};
|
||||
uint32_t selected_pass_end_sequence{0};
|
||||
uint32_t selected_pass_draw_count{0};
|
||||
uint32_t selected_pass_clear_count{0};
|
||||
uint32_t selected_pass_resolve_count{0};
|
||||
uint32_t selected_pass_streak{0};
|
||||
bool selected_pass_is_last{false};
|
||||
bool selected_pass_has_resolve{false};
|
||||
bool selected_pass_is_stable{false};
|
||||
uint32_t present_candidate_rt0{0};
|
||||
uint32_t present_candidate_depth_stencil{0};
|
||||
uint32_t present_candidate_viewport_x{0};
|
||||
uint32_t present_candidate_viewport_y{0};
|
||||
uint32_t present_candidate_viewport_width{0};
|
||||
uint32_t present_candidate_viewport_height{0};
|
||||
bool present_candidate_matches_swap_size{false};
|
||||
};
|
||||
|
||||
struct NativeGraphicsStatusSnapshot {
|
||||
uint64_t decision_frame_index{0};
|
||||
bool bootstrap_enabled{false};
|
||||
bool parallel_renderer_enabled{false};
|
||||
bool parallel_renderer_initialized{false};
|
||||
bool backend_active{false};
|
||||
bool placeholder_present_enabled{false};
|
||||
bool native_present_enabled{false};
|
||||
bool native_present_authoritative{false};
|
||||
bool provider_ready{false};
|
||||
bool presenter_ready{false};
|
||||
bool placeholder_resources_initialized{false};
|
||||
bool last_swap_intercepted{false};
|
||||
bool last_swap_fell_back{false};
|
||||
bool effects_capture_available{false};
|
||||
bool effects_pass_classification_valid{false};
|
||||
bool parity_confidence_good{false};
|
||||
uint64_t total_swap_count{0};
|
||||
uint64_t intercepted_swap_count{0};
|
||||
uint64_t fallback_swap_count{0};
|
||||
uint32_t last_frontbuffer_virtual_address{0};
|
||||
uint32_t last_frontbuffer_physical_address{0};
|
||||
uint32_t last_frontbuffer_width{0};
|
||||
uint32_t last_frontbuffer_height{0};
|
||||
uint32_t last_texture_format{0};
|
||||
uint32_t last_color_space{0};
|
||||
uint32_t last_present_mode{0};
|
||||
uint32_t last_fallback_reason{0};
|
||||
uint32_t configured_output_scale_percent{100};
|
||||
uint32_t effective_output_width{0};
|
||||
uint32_t effective_output_height{0};
|
||||
uint32_t post_process_pass_count{0};
|
||||
uint32_t ui_pass_count{0};
|
||||
uint32_t scene_pass_count{0};
|
||||
uint32_t missing_effects_counter{0};
|
||||
uint32_t pixelation_counter{0};
|
||||
uint32_t parity_confidence_score{0};
|
||||
uint64_t parallel_renderer_frame_count{0};
|
||||
uint64_t parallel_renderer_built_pass_count{0};
|
||||
uint64_t parallel_renderer_transient_allocation_count{0};
|
||||
uint32_t parallel_renderer_frame_slot{0};
|
||||
uint32_t parallel_renderer_max_frames_in_flight{0};
|
||||
uint32_t parallel_renderer_scene_pass_count{0};
|
||||
uint32_t parallel_renderer_post_process_pass_count{0};
|
||||
uint32_t parallel_renderer_ui_pass_count{0};
|
||||
uint32_t parallel_renderer_selected_pass_index{0};
|
||||
uint32_t parallel_renderer_total_draw_count{0};
|
||||
uint32_t parallel_renderer_total_clear_count{0};
|
||||
uint32_t parallel_renderer_total_resolve_count{0};
|
||||
bool parallel_renderer_capture_valid{false};
|
||||
bool parallel_frame_plan_valid{false};
|
||||
bool parallel_frame_plan_has_scene_stage{false};
|
||||
bool parallel_frame_plan_has_post_process_stage{false};
|
||||
bool parallel_frame_plan_has_ui_stage{false};
|
||||
bool parallel_frame_plan_present_from_selected_pass{false};
|
||||
uint32_t parallel_frame_plan_scene_pass_index{0};
|
||||
uint32_t parallel_frame_plan_post_process_pass_index{0};
|
||||
uint32_t parallel_frame_plan_ui_pass_index{0};
|
||||
uint32_t parallel_frame_plan_present_pass_index{0};
|
||||
uint32_t parallel_frame_plan_scene_stage_score{0};
|
||||
uint32_t parallel_frame_plan_post_process_stage_score{0};
|
||||
uint32_t parallel_frame_plan_ui_stage_score{0};
|
||||
uint32_t parallel_frame_plan_present_stage_score{0};
|
||||
uint32_t parallel_frame_plan_scene_stage_draw_count{0};
|
||||
uint32_t parallel_frame_plan_post_process_stage_draw_count{0};
|
||||
uint32_t parallel_frame_plan_ui_stage_draw_count{0};
|
||||
uint32_t parallel_frame_plan_scene_stage_texture_peak{0};
|
||||
uint32_t parallel_frame_plan_post_process_stage_texture_peak{0};
|
||||
uint32_t parallel_frame_plan_ui_stage_texture_peak{0};
|
||||
uint32_t parallel_frame_plan_scene_stage_stream_peak{0};
|
||||
uint32_t parallel_frame_plan_post_process_stage_stream_peak{0};
|
||||
uint32_t parallel_frame_plan_ui_stage_stream_peak{0};
|
||||
uint32_t parallel_frame_plan_output_width{0};
|
||||
uint32_t parallel_frame_plan_output_height{0};
|
||||
SwapRoutingMode routing_mode{SwapRoutingMode::kCompatPm4};
|
||||
SwapIngressPath ingress_path{SwapIngressPath::kUnknown};
|
||||
SwapExecutionPath execution_path{SwapExecutionPath::kUnknown};
|
||||
CadencePolicy cadence_policy{CadencePolicy::kTimerVblank};
|
||||
renderer::BackendType parallel_renderer_backend{renderer::BackendType::kUnknown};
|
||||
renderer::FeatureLevel parallel_renderer_feature_level{renderer::FeatureLevel::kBootstrap};
|
||||
d3d::FrameCaptureSummary capture_summary{};
|
||||
NativeReplayPlanSummary replay_plan{};
|
||||
SelectedPassPreviewSummary selected_pass_preview{};
|
||||
};
|
||||
|
||||
void ConfigureGraphicsBackend(rex::RuntimeConfig& config);
|
||||
NativeGraphicsStatusSnapshot GetNativeGraphicsStatus();
|
||||
|
||||
} // namespace ac6::graphics
|
||||
|
||||
|
||||
@@ -1,378 +1 @@
|
||||
#include "ac6_native_graphics_overlay.h"
|
||||
|
||||
#include <rex/graphics/flags.h>
|
||||
#include <rex/ui/keybinds.h>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include "ac6_native_graphics.h"
|
||||
#include "d3d_hooks.h"
|
||||
#include "render_hooks.h"
|
||||
|
||||
namespace ac6::graphics {
|
||||
namespace {
|
||||
|
||||
const char* DescribeNativeMode(const NativeGraphicsStatusSnapshot& status) {
|
||||
if (!status.bootstrap_enabled) {
|
||||
return "Disabled";
|
||||
}
|
||||
if (!status.backend_active) {
|
||||
return "Configured, backend inactive";
|
||||
}
|
||||
if (status.routing_mode == SwapRoutingMode::kEmergencyHold) {
|
||||
return "Emergency hold";
|
||||
}
|
||||
if (status.native_present_authoritative) {
|
||||
return "Native present authoritative";
|
||||
}
|
||||
if (status.native_present_enabled) {
|
||||
return "Native present gated (fallback active)";
|
||||
}
|
||||
if (status.placeholder_present_enabled) {
|
||||
return "Diagnostic takeover";
|
||||
}
|
||||
return "Observe only";
|
||||
}
|
||||
|
||||
const char* DescribeRoutingMode(SwapRoutingMode mode) {
|
||||
switch (mode) {
|
||||
case SwapRoutingMode::kNativeAuthoritative:
|
||||
return "native";
|
||||
case SwapRoutingMode::kEmergencyHold:
|
||||
return "emergency";
|
||||
case SwapRoutingMode::kCompatPm4:
|
||||
default:
|
||||
return "compat";
|
||||
}
|
||||
}
|
||||
|
||||
const char* DescribeExecutionPath(SwapExecutionPath path) {
|
||||
switch (path) {
|
||||
case SwapExecutionPath::kDirectPresentSwap:
|
||||
return "direct-present-swap";
|
||||
case SwapExecutionPath::kNativeRasterReplay:
|
||||
return "native-raster-replay";
|
||||
case SwapExecutionPath::kNativeMinimalUav:
|
||||
return "native-minimal-uav";
|
||||
case SwapExecutionPath::kPm4Fallback:
|
||||
return "pm4-fallback";
|
||||
case SwapExecutionPath::kEmergencyHoldNoPresent:
|
||||
return "emergency-hold";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const char* DescribeCadencePolicy(CadencePolicy policy) {
|
||||
switch (policy) {
|
||||
case CadencePolicy::kPresentCompletion:
|
||||
return "present";
|
||||
case CadencePolicy::kHybridDebug:
|
||||
return "hybrid";
|
||||
case CadencePolicy::kTimerVblank:
|
||||
default:
|
||||
return "timer";
|
||||
}
|
||||
}
|
||||
|
||||
const char* DescribeParallelRendererBackend(ac6::renderer::BackendType backend) {
|
||||
switch (backend) {
|
||||
case ac6::renderer::BackendType::kD3D12:
|
||||
return "d3d12";
|
||||
case ac6::renderer::BackendType::kVulkan:
|
||||
return "vulkan";
|
||||
case ac6::renderer::BackendType::kMetal:
|
||||
return "metal";
|
||||
case ac6::renderer::BackendType::kUnknown:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const char* DescribeParallelRendererFeatureLevel(ac6::renderer::FeatureLevel level) {
|
||||
switch (level) {
|
||||
case ac6::renderer::FeatureLevel::kSceneSubmission:
|
||||
return "scene_submission";
|
||||
case ac6::renderer::FeatureLevel::kParityValidation:
|
||||
return "parity_validation";
|
||||
case ac6::renderer::FeatureLevel::kShipping:
|
||||
return "shipping";
|
||||
case ac6::renderer::FeatureLevel::kBootstrap:
|
||||
default:
|
||||
return "bootstrap";
|
||||
}
|
||||
}
|
||||
|
||||
const char* DescribeFallbackReason(uint32_t reason) {
|
||||
switch (reason) {
|
||||
case 1:
|
||||
return "native present disabled";
|
||||
case 2:
|
||||
return "forced PM4 fallback";
|
||||
case 3:
|
||||
return "native resources unavailable";
|
||||
case 4:
|
||||
return "native composer failed";
|
||||
case 5:
|
||||
return "low parity confidence";
|
||||
default:
|
||||
return "none";
|
||||
}
|
||||
}
|
||||
|
||||
const char* DescribeLastSwapOutcome(const NativeGraphicsStatusSnapshot& status) {
|
||||
if (!status.total_swap_count) {
|
||||
return "No direct swaps yet";
|
||||
}
|
||||
if (status.last_swap_intercepted) {
|
||||
return "Presented through native diagnostic path";
|
||||
}
|
||||
if (status.last_swap_fell_back) {
|
||||
return "Handled by legacy PM4 presentation";
|
||||
}
|
||||
return "Observed";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NativeGraphicsStatusDialog::NativeGraphicsStatusDialog(rex::ui::ImGuiDrawer* imgui_drawer)
|
||||
: ImGuiDialog(imgui_drawer) {
|
||||
rex::ui::RegisterBind("bind_ac6_native_graphics_overlay", "F4",
|
||||
"Toggle AC6 native graphics status overlay",
|
||||
[this] { ToggleVisible(); });
|
||||
}
|
||||
|
||||
NativeGraphicsStatusDialog::~NativeGraphicsStatusDialog() {
|
||||
rex::ui::UnregisterBind("bind_ac6_native_graphics_overlay");
|
||||
}
|
||||
|
||||
void NativeGraphicsStatusDialog::OnDraw(ImGuiIO& io) {
|
||||
if (!visible_) {
|
||||
return;
|
||||
}
|
||||
|
||||
NativeGraphicsStatusSnapshot native_status = GetNativeGraphicsStatus();
|
||||
ac6::FrameStats frame_stats = ac6::GetFrameStats();
|
||||
ac6::d3d::DrawStatsSnapshot draw_stats = ac6::d3d::GetDrawStats();
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(10, 84), ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowSize(ImVec2(430, 486), ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowBgAlpha(0.72f);
|
||||
if (!ImGui::Begin("AC6 Native Graphics##status", &visible_, ImGuiWindowFlags_NoCollapse)) {
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::Text("Mode: %s", DescribeNativeMode(native_status));
|
||||
ImGui::Text("Backend: %s | Provider: %s | Presenter: %s",
|
||||
native_status.backend_active ? "active" : "inactive",
|
||||
native_status.provider_ready ? "ready" : "missing",
|
||||
native_status.presenter_ready ? "ready" : "missing");
|
||||
ImGui::Text("Parallel renderer: %s | backend=%s | level=%s",
|
||||
native_status.parallel_renderer_initialized ? "initialized" : "inactive",
|
||||
DescribeParallelRendererBackend(native_status.parallel_renderer_backend),
|
||||
DescribeParallelRendererFeatureLevel(
|
||||
native_status.parallel_renderer_feature_level));
|
||||
ImGui::Text("Parallel renderer frames: %llu | passes=%llu | slot=%u/%u",
|
||||
static_cast<unsigned long long>(native_status.parallel_renderer_frame_count),
|
||||
static_cast<unsigned long long>(native_status.parallel_renderer_built_pass_count),
|
||||
native_status.parallel_renderer_frame_slot,
|
||||
native_status.parallel_renderer_max_frames_in_flight);
|
||||
ImGui::Text("Parallel capture: %s | selected pass=%u",
|
||||
native_status.parallel_renderer_capture_valid ? "observed frame" : "bootstrap only",
|
||||
native_status.parallel_renderer_selected_pass_index);
|
||||
ImGui::Text("Parallel pass classes: scene=%u postfx=%u ui=%u",
|
||||
native_status.parallel_renderer_scene_pass_count,
|
||||
native_status.parallel_renderer_post_process_pass_count,
|
||||
native_status.parallel_renderer_ui_pass_count);
|
||||
ImGui::Text("Parallel workload: draws=%u clears=%u resolves=%u",
|
||||
native_status.parallel_renderer_total_draw_count,
|
||||
native_status.parallel_renderer_total_clear_count,
|
||||
native_status.parallel_renderer_total_resolve_count);
|
||||
ImGui::Text("Parallel frame plan: %s | output=%ux%u | selected-present=%s",
|
||||
native_status.parallel_frame_plan_valid ? "valid" : "not ready",
|
||||
native_status.parallel_frame_plan_output_width,
|
||||
native_status.parallel_frame_plan_output_height,
|
||||
native_status.parallel_frame_plan_present_from_selected_pass ? "yes" : "no");
|
||||
ImGui::Text("Planned stages: scene=%s postfx=%s ui=%s present=%u",
|
||||
native_status.parallel_frame_plan_has_scene_stage ? "yes" : "no",
|
||||
native_status.parallel_frame_plan_has_post_process_stage ? "yes" : "no",
|
||||
native_status.parallel_frame_plan_has_ui_stage ? "yes" : "no",
|
||||
native_status.parallel_frame_plan_present_pass_index);
|
||||
ImGui::Text("Planned pass indices: scene=%u postfx=%u ui=%u",
|
||||
native_status.parallel_frame_plan_scene_pass_index,
|
||||
native_status.parallel_frame_plan_post_process_pass_index,
|
||||
native_status.parallel_frame_plan_ui_pass_index);
|
||||
ImGui::Text("Planned stage scores: scene=%u postfx=%u ui=%u present=%u",
|
||||
native_status.parallel_frame_plan_scene_stage_score,
|
||||
native_status.parallel_frame_plan_post_process_stage_score,
|
||||
native_status.parallel_frame_plan_ui_stage_score,
|
||||
native_status.parallel_frame_plan_present_stage_score);
|
||||
ImGui::Text("Stage draw counts: scene=%u postfx=%u ui=%u",
|
||||
native_status.parallel_frame_plan_scene_stage_draw_count,
|
||||
native_status.parallel_frame_plan_post_process_stage_draw_count,
|
||||
native_status.parallel_frame_plan_ui_stage_draw_count);
|
||||
ImGui::Text("Stage state peaks: tex %u/%u/%u | streams %u/%u/%u",
|
||||
native_status.parallel_frame_plan_scene_stage_texture_peak,
|
||||
native_status.parallel_frame_plan_post_process_stage_texture_peak,
|
||||
native_status.parallel_frame_plan_ui_stage_texture_peak,
|
||||
native_status.parallel_frame_plan_scene_stage_stream_peak,
|
||||
native_status.parallel_frame_plan_post_process_stage_stream_peak,
|
||||
native_status.parallel_frame_plan_ui_stage_stream_peak);
|
||||
ImGui::Text("Native present: %s | authoritative=%s | PM4 force fallback=%s",
|
||||
native_status.native_present_enabled ? "enabled" : "disabled",
|
||||
native_status.native_present_authoritative ? "yes" : "no",
|
||||
REXCVAR_GET(ac6_native_present_force_pm4_fallback) ? "yes" : "no");
|
||||
ImGui::Text("Routing: %s | Exec: %s | Cadence: %s",
|
||||
DescribeRoutingMode(native_status.routing_mode),
|
||||
DescribeExecutionPath(native_status.execution_path),
|
||||
DescribeCadencePolicy(native_status.cadence_policy));
|
||||
ImGui::Text("Runtime controls: postfx=%s ui_compose=%s allow_unstable=%s",
|
||||
REXCVAR_GET(ac6_native_present_enable_postfx) ? "on" : "off",
|
||||
REXCVAR_GET(ac6_native_present_enable_ui_compose) ? "on" : "off",
|
||||
REXCVAR_GET(ac6_native_present_allow_unstable) ? "on" : "off");
|
||||
ImGui::Text("Placeholder resources: %s",
|
||||
native_status.placeholder_resources_initialized ? "initialized" : "inactive");
|
||||
ImGui::Text("GPU trace stream: %s | allow=%s", REXCVAR_GET(trace_gpu_stream) ? "on" : "off",
|
||||
REXCVAR_GET(ac6_allow_gpu_trace_stream) ? "true" : "false");
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Direct swaps: %llu total | %llu native | %llu legacy",
|
||||
static_cast<unsigned long long>(native_status.total_swap_count),
|
||||
static_cast<unsigned long long>(native_status.intercepted_swap_count),
|
||||
static_cast<unsigned long long>(native_status.fallback_swap_count));
|
||||
ImGui::Text("Last outcome: %s", DescribeLastSwapOutcome(native_status));
|
||||
ImGui::Text("Fallback reason: %s", DescribeFallbackReason(native_status.last_fallback_reason));
|
||||
ImGui::Text("Output scale: %u%% -> %ux%u", native_status.configured_output_scale_percent,
|
||||
native_status.effective_output_width, native_status.effective_output_height);
|
||||
ImGui::Text("Last frontbuffer: %ux%u fmt %08X cs %u", native_status.last_frontbuffer_width,
|
||||
native_status.last_frontbuffer_height, native_status.last_texture_format,
|
||||
native_status.last_color_space);
|
||||
ImGui::Text("Last FB VA/PA: %08X / %08X", native_status.last_frontbuffer_virtual_address,
|
||||
native_status.last_frontbuffer_physical_address);
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Capture: %s frame=%llu draws=%u clears=%u resolves=%u",
|
||||
native_status.capture_summary.capture_enabled ? "enabled" : "disabled",
|
||||
static_cast<unsigned long long>(native_status.capture_summary.frame_index),
|
||||
native_status.capture_summary.draw_count, native_status.capture_summary.clear_count,
|
||||
native_status.capture_summary.resolve_count);
|
||||
if (native_status.capture_summary.record_signature_valid) {
|
||||
ImGui::Text("Record signature: %016llX",
|
||||
static_cast<unsigned long long>(native_status.capture_summary.record_signature));
|
||||
ImGui::Text("Recorded draw mix: indexed=%u shared=%u primitive=%u",
|
||||
native_status.capture_summary.indexed_draw_count,
|
||||
native_status.capture_summary.indexed_shared_draw_count,
|
||||
native_status.capture_summary.primitive_draw_count);
|
||||
ImGui::Text("Recorded RT0s: unique=%u switches=%u",
|
||||
native_status.capture_summary.unique_rt0_count,
|
||||
native_status.capture_summary.rt0_switch_count);
|
||||
ImGui::Text("Recorded RT0 first/last: %08X / %08X",
|
||||
native_status.capture_summary.first_draw_render_target_0,
|
||||
native_status.capture_summary.last_draw_render_target_0);
|
||||
} else {
|
||||
ImGui::TextUnformatted("Record signature: unavailable (enable ac6_render_capture)");
|
||||
}
|
||||
ImGui::Text("Frame-end RT0/DS: %08X / %08X",
|
||||
native_status.capture_summary.frame_end_render_target_0,
|
||||
native_status.capture_summary.frame_end_depth_stencil);
|
||||
ImGui::Text("Frame-end viewport: %ux%u | RTs=%u tex=%u fetch=%u",
|
||||
native_status.capture_summary.frame_end_viewport_width,
|
||||
native_status.capture_summary.frame_end_viewport_height,
|
||||
native_status.capture_summary.frame_end_render_target_count,
|
||||
native_status.capture_summary.frame_end_texture_count,
|
||||
native_status.capture_summary.frame_end_texture_fetch_count);
|
||||
ImGui::Text("Frame-end streams=%u samplers=%u | last draw prim=%u count=%u flags=%u",
|
||||
native_status.capture_summary.frame_end_stream_count,
|
||||
native_status.capture_summary.frame_end_sampler_count,
|
||||
native_status.capture_summary.last_draw_primitive_type,
|
||||
native_status.capture_summary.last_draw_count,
|
||||
native_status.capture_summary.last_draw_flags);
|
||||
|
||||
ImGui::Separator();
|
||||
if (native_status.replay_plan.valid) {
|
||||
ImGui::Text("Replay plan: frame=%llu passes=%u draws=%u clears=%u resolves=%u",
|
||||
static_cast<unsigned long long>(native_status.replay_plan.frame_index),
|
||||
native_status.replay_plan.pass_count,
|
||||
native_status.replay_plan.draw_event_count,
|
||||
native_status.replay_plan.clear_event_count,
|
||||
native_status.replay_plan.resolve_event_count);
|
||||
ImGui::Text("Swap-size matching passes: %u | selected=%u score=%u",
|
||||
native_status.replay_plan.swap_size_match_pass_count,
|
||||
native_status.replay_plan.selected_pass_index,
|
||||
native_status.replay_plan.selected_pass_score);
|
||||
ImGui::Text("Pass draw counts: first=%u last=%u largest=%u",
|
||||
native_status.replay_plan.first_pass_draw_count,
|
||||
native_status.replay_plan.last_pass_draw_count,
|
||||
native_status.replay_plan.largest_pass_draw_count);
|
||||
ImGui::Text("Selected pass seq: %u..%u | draws=%u clears=%u resolves=%u",
|
||||
native_status.replay_plan.selected_pass_start_sequence,
|
||||
native_status.replay_plan.selected_pass_end_sequence,
|
||||
native_status.replay_plan.selected_pass_draw_count,
|
||||
native_status.replay_plan.selected_pass_clear_count,
|
||||
native_status.replay_plan.selected_pass_resolve_count);
|
||||
ImGui::Text("Selected pass flags: last=%s resolve=%s stable=%s streak=%u",
|
||||
native_status.replay_plan.selected_pass_is_last ? "yes" : "no",
|
||||
native_status.replay_plan.selected_pass_has_resolve ? "yes" : "no",
|
||||
native_status.replay_plan.selected_pass_is_stable ? "yes" : "no",
|
||||
native_status.replay_plan.selected_pass_streak);
|
||||
ImGui::Text("Present candidate RT0/DS: %08X / %08X",
|
||||
native_status.replay_plan.present_candidate_rt0,
|
||||
native_status.replay_plan.present_candidate_depth_stencil);
|
||||
ImGui::Text("Present candidate viewport: %u,%u %ux%u | swap match=%s",
|
||||
native_status.replay_plan.present_candidate_viewport_x,
|
||||
native_status.replay_plan.present_candidate_viewport_y,
|
||||
native_status.replay_plan.present_candidate_viewport_width,
|
||||
native_status.replay_plan.present_candidate_viewport_height,
|
||||
native_status.replay_plan.present_candidate_matches_swap_size ? "yes" : "no");
|
||||
if (native_status.selected_pass_preview.valid) {
|
||||
ImGui::Text("Selected-pass preview: source=%s sampled clears=%u captured rects=%u",
|
||||
native_status.selected_pass_preview.using_clear_fill
|
||||
? "captured clear colors"
|
||||
: "fallback candidate tint",
|
||||
native_status.selected_pass_preview.sampled_clear_color_count,
|
||||
native_status.selected_pass_preview.sampled_clear_rect_count);
|
||||
ImGui::Text("Preview events: draws=%u clears=%u resolves=%u",
|
||||
native_status.selected_pass_preview.draw_count,
|
||||
native_status.selected_pass_preview.clear_count,
|
||||
native_status.selected_pass_preview.resolve_count);
|
||||
ImGui::Text("Preview renderer: %s",
|
||||
native_status.selected_pass_preview.using_raster_replay
|
||||
? "offscreen raster replay"
|
||||
: "legacy diagnostic fill");
|
||||
if (native_status.selected_pass_preview.clear_count) {
|
||||
ImGui::Text("Preview clear colors: first=%08X last=%08X",
|
||||
native_status.selected_pass_preview.first_clear_color,
|
||||
native_status.selected_pass_preview.last_clear_color);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ImGui::TextUnformatted("Replay plan: unavailable (no captured frame events yet)");
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Parity confidence: %u (%s)", native_status.parity_confidence_score,
|
||||
native_status.parity_confidence_good ? "good" : "low");
|
||||
ImGui::Text("Effects classification: %s | capture=%s",
|
||||
native_status.effects_pass_classification_valid ? "valid" : "pending",
|
||||
native_status.effects_capture_available ? "available" : "none");
|
||||
ImGui::Text("Pass classes: scene=%u postfx=%u ui=%u", native_status.scene_pass_count,
|
||||
native_status.post_process_pass_count, native_status.ui_pass_count);
|
||||
ImGui::Text("Visual issue counters: missing_fx=%u pixelation=%u",
|
||||
native_status.missing_effects_counter, native_status.pixelation_counter);
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Guest frame: %.1f FPS (%.2f ms) frame=%llu", frame_stats.fps,
|
||||
frame_stats.frame_time_ms, static_cast<unsigned long long>(frame_stats.frame_count));
|
||||
ImGui::Text("D3D stats: draws=%u clears=%u resolves=%u", draw_stats.draw_calls,
|
||||
draw_stats.clear_calls, draw_stats.resolve_calls);
|
||||
ImGui::Text("Indexed=%u shared=%u primitive=%u", draw_stats.draw_calls_indexed,
|
||||
draw_stats.draw_calls_indexed_shared, draw_stats.draw_calls_primitive);
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::TextUnformatted("F4 toggles this panel. F3 toggles the base debug overlay.");
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
} // namespace ac6::graphics
|
||||
|
||||
|
||||
+1
-88
@@ -1,88 +1 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <rex/cvar.h>
|
||||
#include <rex/graphics/flags.h>
|
||||
#include <rex/logging.h>
|
||||
#include <rex/rex_app.h>
|
||||
#include <rex/ui/overlay/debug_overlay.h>
|
||||
#include <rex/version.h>
|
||||
|
||||
#include "ac6_native_graphics.h"
|
||||
#include "ac6_native_graphics_overlay.h"
|
||||
#include "render_hooks.h"
|
||||
|
||||
REXCVAR_DECLARE(bool, vfetch_index_rounding_bias);
|
||||
REXCVAR_DECLARE(bool, guest_vblank_sync_to_refresh);
|
||||
|
||||
class Ac6recompApp : public rex::ReXApp {
|
||||
public:
|
||||
using rex::ReXApp::ReXApp;
|
||||
|
||||
static std::unique_ptr<rex::ui::WindowedApp> Create(
|
||||
rex::ui::WindowedAppContext& ctx) {
|
||||
return std::unique_ptr<Ac6recompApp>(new Ac6recompApp(ctx, "ac6recomp",
|
||||
PPCImageConfig));
|
||||
}
|
||||
|
||||
protected:
|
||||
void OnPreSetup(rex::RuntimeConfig& config) override {
|
||||
REXCVAR_SET(vfetch_index_rounding_bias, true);
|
||||
if (REXCVAR_GET(trace_gpu_stream) && !REXCVAR_GET(ac6_allow_gpu_trace_stream)) {
|
||||
gpu_trace_stream_blocked_ = true;
|
||||
REXLOG_WARN(
|
||||
"AC6 safety guard disabled trace_gpu_stream to avoid unstable GPU "
|
||||
"trace compression during native graphics experiments. Set "
|
||||
"ac6_allow_gpu_trace_stream=true to re-enable it explicitly.");
|
||||
REXCVAR_SET(trace_gpu_stream, false);
|
||||
}
|
||||
ac6::graphics::ConfigureGraphicsBackend(config);
|
||||
// Keep timing/sync policy deterministic across launches.
|
||||
// If unlock is disabled, force sync back on so stale config/runtime state
|
||||
// cannot leave AC6 running uncapped.
|
||||
if (REXCVAR_GET(ac6_unlock_fps)) {
|
||||
REXCVAR_SET(vsync, false);
|
||||
REXCVAR_SET(guest_vblank_sync_to_refresh, false);
|
||||
} else {
|
||||
REXCVAR_SET(vsync, true);
|
||||
REXCVAR_SET(guest_vblank_sync_to_refresh, true);
|
||||
}
|
||||
}
|
||||
|
||||
void OnCreateDialogs(rex::ui::ImGuiDrawer* drawer) override {
|
||||
debug_overlay()->SetStatsProvider([] {
|
||||
auto gs = ac6::GetFrameStats();
|
||||
return rex::ui::FrameStats{gs.frame_time_ms, gs.fps, gs.frame_count};
|
||||
});
|
||||
|
||||
native_graphics_status_dialog_ =
|
||||
std::make_unique<ac6::graphics::NativeGraphicsStatusDialog>(drawer);
|
||||
|
||||
if (window()) {
|
||||
std::string title = std::string(GetName()) + " " + REXGLUE_BUILD_TITLE;
|
||||
auto native_status = ac6::graphics::GetNativeGraphicsStatus();
|
||||
if (native_status.bootstrap_enabled) {
|
||||
if (native_status.routing_mode == ac6::graphics::SwapRoutingMode::kEmergencyHold) {
|
||||
title += " | native emergency";
|
||||
} else if (native_status.native_present_authoritative) {
|
||||
title += " | native swap present";
|
||||
} else if (native_status.native_present_enabled) {
|
||||
title += " | native swap gated";
|
||||
} else if (native_status.placeholder_present_enabled) {
|
||||
title += " | native swap diagnostic";
|
||||
} else {
|
||||
title += " | native swap observe";
|
||||
}
|
||||
}
|
||||
if (gpu_trace_stream_blocked_) {
|
||||
title += " | trace stream blocked";
|
||||
}
|
||||
window()->SetTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool gpu_trace_stream_blocked_ = false;
|
||||
std::unique_ptr<ac6::graphics::NativeGraphicsStatusDialog> native_graphics_status_dialog_;
|
||||
};
|
||||
|
||||
|
||||
+1
-29
@@ -1,29 +1 @@
|
||||
/**
|
||||
* @file d3d_hooks.h
|
||||
* @brief Public interface for the D3D state shadowing layer.
|
||||
*
|
||||
* Provides per-frame draw statistics, a frame capture snapshot for renderer
|
||||
* analysis, and a read-only view of the current D3D device shadow state.
|
||||
* Call OnFrameBoundary() once per frame (typically from the present/swap hook)
|
||||
* to snapshot stats and reset counters.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <rex/cvar.h>
|
||||
|
||||
#include "d3d_state.h"
|
||||
|
||||
namespace ac6::d3d {
|
||||
|
||||
void OnFrameBoundary();
|
||||
|
||||
DrawStatsSnapshot GetDrawStats();
|
||||
|
||||
FrameCaptureSnapshot GetFrameCapture();
|
||||
FrameCaptureSummary GetFrameCaptureSummary();
|
||||
|
||||
ShadowState GetShadowState();
|
||||
|
||||
} // namespace ac6::d3d
|
||||
|
||||
REXCVAR_DECLARE(bool, ac6_render_capture);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user