Merge pull request #28 from eliasstepanik/codex/fix-syntax-error-in-greedy_meshing.wgsl

Fix WGSL greedy meshing loop parsing
This commit is contained in:
Elias Stepanik 2025-06-15 01:19:27 +02:00 committed by GitHub
commit 2bdffe4083
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 29 additions and 14 deletions

View File

@ -21,7 +21,7 @@ struct Vertex {
@group(0) @binding(1) var<uniform> params: Params; @group(0) @binding(1) var<uniform> params: Params;
@group(0) @binding(2) var<storage, read_write> vertices: array<Vertex>; @group(0) @binding(2) var<storage, read_write> vertices: array<Vertex>;
@group(0) @binding(3) var<storage, read_write> indices: array<u32>; @group(0) @binding(3) var<storage, read_write> indices: array<u32>;
@group(0) @binding(4) var<storage, read_write> counts: atomic<u32>; @group(0) @binding(4) var<storage, read_write> counts: array<atomic<u32>, 2>;
const N: u32 = 16u; const N: u32 = 16u;
@ -86,16 +86,21 @@ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
} }
var height: u32 = 1u; var height: u32 = 1u;
outer: loop { loop {
if v0 + height >= N { if v0 + height >= N {
break; break;
} }
var can_expand: bool = true;
for (var du: u32 = 0u; du < width; du = du + 1u) { for (var du: u32 = 0u; du < width; du = du + 1u) {
let idx = (u0 + du) * N + v0 + height; let idx = (u0 + du) * N + v0 + height;
if !mask[idx] || visited[idx] { if !mask[idx] || visited[idx] {
break outer; can_expand = false;
break;
} }
} }
if !can_expand {
break;
}
height = height + 1u; height = height + 1u;
} }
@ -108,11 +113,11 @@ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
// Compute base world-space position. // Compute base world-space position.
var base = params.origin; var base = params.origin;
if axis == 0u { if axis == 0u {
base = base + vec3<f32>(f32(slice) + (dir > 0 ? 1.0 : 0.0), f32(u0), f32(v0)) * params.step; base = base + vec3<f32>(f32(slice) + select(0.0, 1.0, dir > 0), f32(u0), f32(v0)) * params.step;
} else if axis == 1u { } else if axis == 1u {
base = base + vec3<f32>(f32(v0), f32(slice) + (dir > 0 ? 1.0 : 0.0), f32(u0)) * params.step; base = base + vec3<f32>(f32(v0), f32(slice) + select(0.0, 1.0, dir > 0), f32(u0)) * params.step;
} else { } else {
base = base + vec3<f32>(f32(u0), f32(v0), f32(slice) + (dir > 0 ? 1.0 : 0.0)) * params.step; base = base + vec3<f32>(f32(u0), f32(v0), f32(slice) + select(0.0, 1.0, dir > 0)) * params.step;
} }
let size = vec2<f32>(f32(width) * params.step, f32(height) * params.step); let size = vec2<f32>(f32(width) * params.step, f32(height) * params.step);
@ -141,10 +146,10 @@ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
let p3 = base + v_unit * size.y; let p3 = base + v_unit * size.y;
let vi = atomicAdd(&counts[0], 4u); let vi = atomicAdd(&counts[0], 4u);
vertices[vi] = Vertex(pos: p0, normal: normal, uv: vec2<f32>(0.0, 1.0)); vertices[vi] = Vertex(p0, normal, vec2<f32>(0.0, 1.0));
vertices[vi + 1u] = Vertex(pos: p1, normal: normal, uv: vec2<f32>(1.0, 1.0)); vertices[vi + 1u] = Vertex(p1, normal, vec2<f32>(1.0, 1.0));
vertices[vi + 2u] = Vertex(pos: p2, normal: normal, uv: vec2<f32>(1.0, 0.0)); vertices[vi + 2u] = Vertex(p2, normal, vec2<f32>(1.0, 0.0));
vertices[vi + 3u] = Vertex(pos: p3, normal: normal, uv: vec2<f32>(0.0, 0.0)); vertices[vi + 3u] = Vertex(p3, normal, vec2<f32>(0.0, 0.0));
let ii = atomicAdd(&counts[1], 6u); let ii = atomicAdd(&counts[1], 6u);
if dir > 0 { if dir > 0 {

View File

@ -1,7 +1,7 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy_app_compute::prelude::*; use bevy_app_compute::prelude::*;
use super::structure::{MeshBufferPool, SparseVoxelOctree}; use super::structure::{CHUNK_SIZE, MeshBufferPool, SparseVoxelOctree};
#[repr(C)] #[repr(C)]
#[derive(ShaderType, Copy, Clone, Default)] #[derive(ShaderType, Copy, Clone, Default)]
@ -22,6 +22,11 @@ pub struct VertexGpu {
pub uv: Vec2, pub uv: Vec2,
} }
const MAX_VOXELS: usize = (CHUNK_SIZE as usize) * (CHUNK_SIZE as usize) * (CHUNK_SIZE as usize);
const MAX_QUADS: usize = MAX_VOXELS * 6;
const MAX_VERTICES: usize = MAX_QUADS * 4;
const MAX_INDICES: usize = MAX_QUADS * 6;
#[derive(TypePath)] #[derive(TypePath)]
struct GreedyMeshingShader; struct GreedyMeshingShader;
@ -37,11 +42,16 @@ pub struct GpuMeshingWorker;
impl ComputeWorker for GpuMeshingWorker { impl ComputeWorker for GpuMeshingWorker {
fn build(world: &mut World) -> AppComputeWorker<Self> { fn build(world: &mut World) -> AppComputeWorker<Self> {
// Allocate large temporary arrays on the heap to avoid stack overflows
let voxels = Box::new([0u32; MAX_VOXELS]);
let vertices = Box::new([VertexGpu::default(); MAX_VERTICES]);
let indices = Box::new([0u32; MAX_INDICES]);
AppComputeWorkerBuilder::new(world) AppComputeWorkerBuilder::new(world)
.add_storage("voxels", &[0u32; 1]) .add_storage("voxels", voxels.as_ref())
.add_uniform("params", &Params::default()) .add_uniform("params", &Params::default())
.add_storage("vertices", &[VertexGpu::default(); 1]) .add_storage("vertices", vertices.as_ref())
.add_storage("indices", &[0u32; 1]) .add_storage("indices", indices.as_ref())
.add_storage("counts", &[0u32; 2]) .add_storage("counts", &[0u32; 2])
.add_pass::<GreedyMeshingShader>( .add_pass::<GreedyMeshingShader>(
[1, 1, 1], [1, 1, 1],