Complete two-pass GPU occlusion, diagnostics, and LOD integration

This commit is contained in:
Emil
2026-09-23 22:47:15 +03:00
parent 94f7593e55
commit ae537c0a4b
8 changed files with 593 additions and 118 deletions
+33 -1
View File
@@ -4,12 +4,13 @@
#include <faset/render/renderer.hpp>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
using namespace faset::render;
namespace {
void require(bool condition, const char* message) {
void require(bool condition, const std::string& message) {
if (!condition)
throw std::runtime_error(message);
}
@@ -21,6 +22,7 @@ RendererConfig config(VisibilityMode mode) {
result.headless = true;
result.validation = true;
result.visibility_mode = mode;
result.visibility_diagnostics = true;
return result;
}
@@ -68,6 +70,10 @@ int main() {
gpu.stats().gpu_frustum_rejected == 1,
"GPU frustum/indirect counts are wrong");
require(gpu.stats().validation_errors == 0, "Vulkan validation rejected GPU path");
if (gpu.stats().gpu_ms > 0)
require(gpu.stats().gpu_main_cull_ms > 0 &&
gpu.stats().gpu_main_raster_ms > 0,
"GPU visibility pass timings are missing");
require(different_pixels(direct.pixels(), gpu.pixels(), 5) < 160,
"GPU and direct opaque images differ");
@@ -76,6 +82,32 @@ int main() {
require(gpu.stats().gpu_visible_instances == 0 && gpu.stats().gpu_bins == 0,
"Empty frame must reset indirect counts");
require(gpu.stats().validation_errors == 0, "Empty GPU frame failed validation");
gpu.set_visibility_diagnostics(false);
gpu.render(scene());
require(!gpu.stats().visibility_counters_valid &&
gpu.stats().gpu_visibility_active,
"Normal GPU rendering must not read diagnostic visibility counters");
gpu.set_visibility_diagnostics(true);
gpu.render(scene());
require(gpu.stats().visibility_counters_valid &&
gpu.stats().gpu_visible_instances == 1,
"Visibility counters can be enabled for diagnostics");
Renderer occlusion(config(VisibilityMode::GpuOcclusion));
occlusion.render(scene());
auto hzb = occlusion.hzb_debug_image(0);
if (occlusion.stats().gpu_ms > 0)
require(occlusion.stats().gpu_hzb_ms > 0 &&
occlusion.stats().gpu_post_cull_ms > 0 &&
occlusion.stats().gpu_post_raster_ms > 0,
"HZB/post pass timings are missing");
require(hzb && hzb->width == 512 && hzb->height == 256 &&
hzb->rgba.size() == std::size_t(hzb->width) * hzb->height * 4,
"Current HZB debug image has wrong dimensions");
require(std::any_of(hzb->rgba.begin(), hzb->rgba.end(),
[](std::uint8_t value) { return value < 250; }),
"Current HZB debug image contains no scene depth (min=" +
std::to_string(*std::min_element(hzb->rgba.begin(), hzb->rgba.end())) +
")");
std::cout << "GPU frustum, fixed indirect and direct-image comparison passed\n";
return 0;
} catch (const std::exception& error) {