Report effective visibility and stable GPU instance identity
Native and manual checks / native (ubuntu-24.04) (push) Failing after 36s
Native and manual checks / manual (push) Successful in 28s
Windows editor and software Vulkan / windows-graphics (push) Canceled after 0s
Native and manual checks / native (windows-2025) (push) Canceled after 0s

This commit is contained in:
Emil
2026-09-24 00:28:12 +03:00
parent 433bce08c0
commit 22012c1a80
12 changed files with 157 additions and 18 deletions
+3
View File
@@ -150,6 +150,9 @@ struct FrameStats {
std::uint32_t texture_count{};
std::uint32_t vertices{}, draw_calls{}, culled_meshes{}, validation_errors{};
bool gpu_visibility_active{}, hzb_valid{};
// Requested and actual paths for the last frame; actual may be less capable.
VisibilityMode requested_visibility_mode{VisibilityMode::Direct};
VisibilityMode effective_visibility_mode{VisibilityMode::Direct};
bool visibility_counters_valid{};
std::uint32_t gpu_bins{}, gpu_visible_instances{}, gpu_frustum_rejected{};
std::uint32_t gpu_occlusion_deferred{}, gpu_post_visible{};
+16
View File
@@ -1,5 +1,6 @@
#pragma once
#include <faset/render/renderer.hpp>
#include <array>
#include <cstddef>
#include <cstdint>
#include <span>
@@ -22,6 +23,12 @@ Bounds local_bounds(const Mesh& mesh);
Bounds transformed_bounds(const Bounds& local, const Mat4& model);
Bounds transformed_bounds(const Mesh& mesh, const Mat4& model);
// Resolve a requested mode against the current device and target capabilities.
// Missing HZB retains GPU frustum culling, but callers must report that fallback.
VisibilityMode select_effective_visibility_mode(VisibilityMode requested,
bool gpu_available,
bool hzb_available) noexcept;
struct InstanceUpdate {
std::uint32_t slot{};
std::uint64_t generation{};
@@ -30,6 +37,15 @@ struct InstanceUpdate {
bool previous_valid{};
};
// GPU instance metadata: history valid, stable slot, then generation low/high.
// A zero generation identifies an anonymous, untracked draw.
constexpr std::array<std::uint32_t, 4>
gpu_instance_metadata(const InstanceUpdate& update, bool history_compatible) noexcept {
return {update.previous_valid && history_compatible ? 1U : 0U, update.slot,
static_cast<std::uint32_t>(update.generation),
static_cast<std::uint32_t>(update.generation >> 32)};
}
// One update per logical instance per rendered frame. finish_frame() promotes the
// current state to *rendered* history and retires keys absent from that frame.
// Reordering the input never renumbers live instances. Mesh changes retain the