Refine GPU visibility uniforms and fix worker usage

This commit is contained in:
Elias Stepanik 2025-06-13 13:17:55 +02:00
parent 4589204097
commit 4717186086
5 changed files with 38 additions and 26 deletions

View File

@ -2,9 +2,9 @@
// Input arrays must match in length and are processed per invocation.
struct Params {
centre: vec3<i32>;
radius: i32;
centre_radius: vec4<i32>;
count: u32;
_pad: u32;
};
@group(0) @binding(0) var<storage, read> occupied: array<vec3<i32>>;
@ -19,10 +19,12 @@ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
if idx >= params.count { return; }
let key = occupied[idx];
if spawned[idx] != 0u { return; }
let dx = key.x - params.centre.x;
let dy = key.y - params.centre.y;
let dz = key.z - params.centre.z;
if dx*dx + dy*dy + dz*dz <= params.radius * params.radius {
let centre = params.centre_radius.xyz;
let radius = params.centre_radius.w;
let dx = key.x - centre.x;
let dy = key.y - centre.y;
let dz = key.z - centre.z;
if dx*dx + dy*dy + dz*dz <= radius * radius {
let i = atomicAdd(&out_count, 1u);
out_keys[i] = key;
}

View File

@ -12,7 +12,7 @@ impl Plugin for AppPlugin {
app.add_plugins(crate::plugins::input::input_plugin::InputPlugin);
app.add_plugins(WireframePlugin::default());
app.add_systems(Update, (debug_gizmos));
app.add_systems(Update, debug_gizmos);
app.register_type::<Option<Handle<Image>>>();
app.register_type::<AlphaMode>();
}

View File

@ -1,4 +1,3 @@
use bevy::color::palettes::css::{BLUE, GREEN, RED};
use bevy::prelude::*;
pub fn debug_gizmos(mut gizmos: Gizmos) {

View File

@ -4,7 +4,6 @@ use crate::plugins::environment::systems::voxels::meshing_gpu::{
GpuMeshingWorker, queue_gpu_meshing,
};
use bevy_app_compute::prelude::{AppComputePlugin, AppComputeWorkerPlugin};
use crate::plugins::environment::systems::voxels::queue_systems;
use crate::plugins::environment::systems::voxels::queue_systems::process_chunk_queue;
use crate::plugins::environment::systems::voxels::visibility_gpu::{
enqueue_visible_chunks_gpu, GpuVisibilityWorker,
@ -14,7 +13,7 @@ use crate::plugins::environment::systems::voxels::structure::{
ChunkBudget, ChunkCullingCfg, ChunkQueue, MeshBufferPool, PrevCameraChunk, SparseVoxelOctree,
SpawnedChunks,
};
use bevy::app::{App, Plugin, PreStartup, PreUpdate, Startup};
use bevy::app::{App, Plugin, Startup};
use bevy::prelude::*;
pub struct EnvironmentPlugin;

View File

@ -1,15 +1,15 @@
use bevy::prelude::*;
use bevy_app_compute::prelude::*;
use super::structure::{ChunkCullingCfg, ChunkQueue, PrevCameraChunk, SpawnedChunks, SparseVoxelOctree};
use super::structure::{ChunkCullingCfg, ChunkQueue, PrevCameraChunk, SpawnedChunks, SparseVoxelOctree, ChunkKey};
use crate::plugins::environment::systems::voxels::helper::world_to_chunk;
#[repr(C)]
#[derive(ShaderType, Copy, Clone, Default)]
#[derive(ShaderType, Copy, Clone, Default, bytemuck::Pod, bytemuck::Zeroable)]
pub struct Params {
pub centre: IVec3,
pub radius: i32,
pub centre_radius: [i32; 4],
pub count: u32,
pub _pad: u32,
}
#[derive(TypePath)]
@ -32,7 +32,7 @@ impl ComputeWorker for GpuVisibilityWorker {
.add_rw_storage::<[IVec3; 1]>("out_keys", &[IVec3::ZERO; 1])
.add_rw_storage::<u32>("out_count", &0u32)
.add_uniform("params", &Params::default())
.add_pass::<VisibilityShader>([1, 1, 1], &["occupied", "spawned", "out_keys", "out_count", "params"])
.add_pass::<VisibilityShader>([1024, 1, 1], &["occupied", "spawned", "out_keys", "out_count", "params"])
.one_shot()
.build()
}
@ -51,15 +51,19 @@ pub fn enqueue_visible_chunks_gpu(
let Ok(tree) = tree_q.get_single() else { return };
let Ok(cam_tf) = cam_q.get_single() else { return };
let cam_pos = cam_tf.translation();
let centre = world_to_chunk(tree, cam_pos);
if prev_cam.0 == Some(centre) { return; }
prev_cam.0 = Some(centre);
let centre_key = world_to_chunk(tree, cam_pos);
if prev_cam.0 == Some(centre_key) { return; }
prev_cam.0 = Some(centre_key);
if !worker.ready() { return; }
let occupied: Vec<IVec3> = tree.occupied_chunks.iter().copied().collect();
let mut spawned_flags = Vec::with_capacity(occupied.len());
for key in &occupied {
let occupied_keys: Vec<ChunkKey> = tree.occupied_chunks.iter().copied().collect();
let occupied: Vec<IVec3> = occupied_keys
.iter()
.map(|k| IVec3::new(k.0, k.1, k.2))
.collect();
let mut spawned_flags = Vec::with_capacity(occupied_keys.len());
for key in &occupied_keys {
spawned_flags.push(if spawned.0.contains_key(key) { 1u32 } else { 0u32 });
}
worker.write_slice("occupied", &occupied);
@ -67,11 +71,18 @@ pub fn enqueue_visible_chunks_gpu(
worker.write_slice("out_keys", &vec![IVec3::ZERO; occupied.len()]);
worker.write("out_count", &0u32);
let params = Params { centre, radius: cfg.view_distance_chunks, count: occupied.len() as u32 };
let params = Params {
centre_radius: [
centre_key.0,
centre_key.1,
centre_key.2,
cfg.view_distance_chunks,
],
count: occupied.len() as u32,
_pad: 0,
};
worker.write("params", &params);
let workgroups = ((occupied.len() as f32) / 64.0).ceil() as u32;
worker.pass(0).dispatch([workgroups, 1, 1]);
worker.execute();
let count: u32 = worker.read("out_count");
@ -79,7 +90,8 @@ pub fn enqueue_visible_chunks_gpu(
queue.keys.clear();
queue.set.clear();
for key in keys.into_iter().take(count as usize) {
queue.keys.push_back(key.into());
queue.set.insert(key.into());
let ck = ChunkKey(key.x, key.y, key.z);
queue.keys.push_back(ck);
queue.set.insert(ck);
}
}