Terrain !
This commit is contained in:
+1
-1
@@ -18,7 +18,7 @@ pub struct Camera
|
||||
fov: f32,
|
||||
pub aspect: f32,
|
||||
|
||||
speed: f32,
|
||||
pub speed: f32,
|
||||
pub pressed_keyset: HashSet<KeyCode>,
|
||||
}
|
||||
|
||||
|
||||
+197
-62
@@ -4,6 +4,7 @@ use core::sync;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::hash::Hash;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
@@ -13,6 +14,8 @@ use bytemuck::Pod;
|
||||
use bytemuck::Zeroable;
|
||||
use crevice::std140::AsStd140;
|
||||
use crevice::std430::AsStd430;
|
||||
use egui::Color32;
|
||||
use egui::Label;
|
||||
use egui::emath::fast_midpoint;
|
||||
use egui::mutex::Mutex;
|
||||
use egui_plot::BarChart;
|
||||
@@ -21,6 +24,9 @@ use glam::Vec3;
|
||||
use glam::Vec4;
|
||||
use itertools::Itertools;
|
||||
use rand::random;
|
||||
use rayon::iter::IndexedParallelIterator;
|
||||
use rayon::iter::IntoParallelRefIterator;
|
||||
use rayon::iter::ParallelIterator;
|
||||
use wgpu::BindGroup;
|
||||
use wgpu::BindGroupEntry;
|
||||
use wgpu::BindGroupLayoutDescriptor;
|
||||
@@ -54,6 +60,7 @@ use wgpu::util::DownloadBuffer;
|
||||
use wgpu::util::StagingBelt;
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::event::DeviceEvent;
|
||||
use winit::event::MouseScrollDelta;
|
||||
use winit::event::WindowEvent;
|
||||
use winit::event_loop;
|
||||
use winit::event_loop::ActiveEventLoop;
|
||||
@@ -66,9 +73,14 @@ use winit::window::WindowId;
|
||||
|
||||
use crate::camera::Camera;
|
||||
use crate::egui_renderer::EguiRenderer;
|
||||
use crate::producers::BallGenerator;
|
||||
use crate::producers::ChunkedProducer;
|
||||
use crate::producers::Producer;
|
||||
use crate::producers::SineGenerator;
|
||||
use crate::producers::TerrainGenerator;
|
||||
use crate::voxel::cache::CacheNodeRequest;
|
||||
use crate::voxel::cache::CacheResponse;
|
||||
use crate::voxel::cache::ColorBytes;
|
||||
use crate::voxel::cache::DestinationElement;
|
||||
use crate::voxel::cache::LocationPoolElement;
|
||||
use crate::voxel::cache::RequestBuffer;
|
||||
@@ -103,6 +115,10 @@ struct State
|
||||
|
||||
pipeline: RenderPipeline,
|
||||
voxel_cache: Arc<Mutex<VoxelCache<4>>>,
|
||||
terrain_generator: Arc<TerrainGenerator<4>>,
|
||||
chunk_pos_map: Arc<HashMap<u32, (usize, usize, usize)>>,
|
||||
instance_buffer: Buffer,
|
||||
instance_count: usize,
|
||||
usage_vec: Arc<Mutex<Vec<usize>>>,
|
||||
insertion_debounce: bool,
|
||||
|
||||
@@ -123,6 +139,16 @@ struct Immediates
|
||||
frame_timestamp: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
|
||||
#[repr(C)]
|
||||
struct InstanceAttribute
|
||||
{
|
||||
x: f32,
|
||||
y: f32,
|
||||
z: f32,
|
||||
id: u32,
|
||||
}
|
||||
|
||||
impl State
|
||||
{
|
||||
async fn new(display: OwnedDisplayHandle, window: Arc<Window>) -> State
|
||||
@@ -141,7 +167,7 @@ impl State
|
||||
.unwrap();
|
||||
let (device, queue) = adapter
|
||||
.request_device(&wgpu::DeviceDescriptor {
|
||||
required_features: Features::IMMEDIATES,
|
||||
required_features: Features::IMMEDIATES | Features::SHADER_EARLY_DEPTH_TEST,
|
||||
required_limits: wgpu::Limits {
|
||||
max_immediate_size: 112,
|
||||
max_storage_buffers_per_shader_stage: 16,
|
||||
@@ -160,9 +186,34 @@ impl State
|
||||
|
||||
let egui_renderer = EguiRenderer::new(&device, surface_format, &window);
|
||||
|
||||
let mut voxel_cache = VoxelCache::<4>::new(16000, device.clone(), queue.clone());
|
||||
let id = voxel_cache.structure_table.allocate_structure(true);
|
||||
println!("id: {id}");
|
||||
let mut voxel_cache = VoxelCache::<4>::new(100_000, device.clone(), queue.clone());
|
||||
|
||||
let terrain_generator = TerrainGenerator::<4>::new(5, "vxls_height.tif", 0.2, "img.jpg");
|
||||
|
||||
let mut chunk_pos_map = HashMap::new();
|
||||
let chunk_instances = (0..terrain_generator.chunk_width)
|
||||
.cartesian_product(0..terrain_generator.chunk_height)
|
||||
.cartesian_product(0..terrain_generator.chunk_alt)
|
||||
.map(|((x, z), y)| {
|
||||
let chunk_id = voxel_cache.structure_table.allocate_structure(true);
|
||||
//dbg!(chunk_id);
|
||||
|
||||
chunk_pos_map.insert(chunk_id, (x, y, z));
|
||||
InstanceAttribute {
|
||||
x: x as f32,
|
||||
y: y as f32,
|
||||
z: z as f32,
|
||||
id: chunk_id,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let instance_count = chunk_instances.len();
|
||||
|
||||
let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Instance buffer"),
|
||||
contents: bytemuck::cast_slice(chunk_instances.as_slice()),
|
||||
usage: BufferUsages::COPY_DST | BufferUsages::VERTEX,
|
||||
});
|
||||
|
||||
let shader_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||
label: Some("Main shader module"),
|
||||
@@ -187,13 +238,28 @@ impl State
|
||||
module: &shader_module,
|
||||
entry_point: Some("chunk"),
|
||||
compilation_options: Default::default(),
|
||||
buffers: &[],
|
||||
buffers: &[Some(wgpu::VertexBufferLayout {
|
||||
array_stride: (size_of::<f32>() * 3 + size_of::<u32>()) as u64,
|
||||
step_mode: wgpu::VertexStepMode::Instance,
|
||||
attributes: &[
|
||||
wgpu::VertexAttribute {
|
||||
format: wgpu::VertexFormat::Float32x3,
|
||||
offset: 0,
|
||||
shader_location: 0,
|
||||
},
|
||||
wgpu::VertexAttribute {
|
||||
format: wgpu::VertexFormat::Uint32,
|
||||
offset: (size_of::<f32>() * 3) as u64,
|
||||
shader_location: 1,
|
||||
},
|
||||
],
|
||||
})],
|
||||
},
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
strip_index_format: None,
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: None,
|
||||
cull_mode: Some(wgpu::Face::Front),
|
||||
unclipped_depth: false,
|
||||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
conservative: false,
|
||||
@@ -201,7 +267,7 @@ impl State
|
||||
depth_stencil: Some(wgpu::DepthStencilState {
|
||||
format: wgpu::TextureFormat::Depth24PlusStencil8,
|
||||
depth_write_enabled: Some(true),
|
||||
depth_compare: Some(wgpu::CompareFunction::LessEqual),
|
||||
depth_compare: Some(wgpu::CompareFunction::Less),
|
||||
stencil: wgpu::StencilState::default(),
|
||||
bias: wgpu::DepthBiasState::default(),
|
||||
}),
|
||||
@@ -235,6 +301,10 @@ impl State
|
||||
voxel_cache: Arc::new(Mutex::new(voxel_cache)),
|
||||
insertion_debounce: false,
|
||||
camera: Default::default(),
|
||||
instance_buffer,
|
||||
instance_count,
|
||||
terrain_generator: Arc::new(terrain_generator),
|
||||
chunk_pos_map: chunk_pos_map.into(),
|
||||
};
|
||||
|
||||
// Configure surface for the first time
|
||||
@@ -323,9 +393,7 @@ impl State
|
||||
fn render(&mut self)
|
||||
{
|
||||
self.camera.update();
|
||||
|
||||
// Write random shit in request buffer
|
||||
let mut belt = StagingBelt::new(self.device.clone(), size_of::<u32>() as u64);
|
||||
self.voxel_cache.lock().next_frame();
|
||||
|
||||
// Create texture view.
|
||||
// NOTE: We must handle Timeout because the surface may be unavailable
|
||||
@@ -395,6 +463,7 @@ impl State
|
||||
});
|
||||
|
||||
renderpass.set_pipeline(&self.pipeline);
|
||||
renderpass.set_vertex_buffer(0, self.instance_buffer.slice(..));
|
||||
renderpass.set_bind_group(0, Some(&self.voxel_cache.lock().bind_group()), &[]);
|
||||
let imm = [Immediates {
|
||||
view_proj: self.camera.view_proj(),
|
||||
@@ -402,7 +471,7 @@ impl State
|
||||
frame_timestamp: self.voxel_cache.lock().current_timestamp(),
|
||||
}];
|
||||
renderpass.set_immediates(0, unsafe { as_raw_bytes(&imm) });
|
||||
renderpass.draw(0..36, 0..1);
|
||||
renderpass.draw(0..36, 0..(self.instance_count as u32));
|
||||
|
||||
// End the renderpass.
|
||||
drop(renderpass);
|
||||
@@ -410,14 +479,20 @@ impl State
|
||||
|
||||
let requests = self.device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("dummy_dumb_dinky_aaaahhh_buffer"),
|
||||
size: 16 * 256,
|
||||
size: 16 * 1024,
|
||||
usage: BufferUsages::STORAGE | BufferUsages::COPY_SRC,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
|
||||
self.voxel_cache
|
||||
.lock()
|
||||
.cache_post_render(&mut encoder, requests.clone());
|
||||
if !self
|
||||
.camera
|
||||
.pressed_keyset
|
||||
.contains(&winit::keyboard::KeyCode::KeyF)
|
||||
{
|
||||
self.voxel_cache
|
||||
.lock()
|
||||
.cache_post_render(&mut encoder, requests.clone());
|
||||
}
|
||||
|
||||
// If you wanted to call any drawing commands, they would go here.
|
||||
{
|
||||
@@ -425,6 +500,17 @@ impl State
|
||||
egui::Window::new("Window ! ").resizable(true).show(
|
||||
self.egui_renderer.context(),
|
||||
|ui| {
|
||||
if self
|
||||
.camera
|
||||
.pressed_keyset
|
||||
.contains(&winit::keyboard::KeyCode::KeyF)
|
||||
{
|
||||
ui.label(
|
||||
egui::RichText::new("Cache paused")
|
||||
.color(Color32::RED)
|
||||
.size(28.),
|
||||
);
|
||||
}
|
||||
egui_plot::Plot::new("Plot").show(ui, |plot_ui| {
|
||||
plot_ui.bar_chart(BarChart::new(
|
||||
"histo",
|
||||
@@ -488,17 +574,24 @@ impl State
|
||||
self.insertion_debounce = false;
|
||||
}
|
||||
|
||||
if (self
|
||||
// if (self
|
||||
// .camera
|
||||
// .pressed_keyset
|
||||
// .contains(&winit::keyboard::KeyCode::KeyF))
|
||||
// && !self.insertion_debounce
|
||||
// {
|
||||
if !self
|
||||
.camera
|
||||
.pressed_keyset
|
||||
.contains(&winit::keyboard::KeyCode::KeyF))
|
||||
&& !self.insertion_debounce
|
||||
.contains(&winit::keyboard::KeyCode::KeyF)
|
||||
{
|
||||
self.insertion_debounce = true;
|
||||
let request_count = self.voxel_cache.lock().total_request_count();
|
||||
let cloned_cache = self.voxel_cache.clone();
|
||||
let cloned_device = self.device.clone();
|
||||
let cloned_queue = self.queue.clone();
|
||||
let cloned_generator = self.terrain_generator.clone();
|
||||
let cloned_map = self.chunk_pos_map.clone();
|
||||
let (tx, rx) = sync_channel(1);
|
||||
DownloadBuffer::read_buffer(
|
||||
&self.device.clone(),
|
||||
@@ -513,58 +606,88 @@ impl State
|
||||
let cache_node_requests: Vec<CacheNodeRequest> =
|
||||
bytemuck::pod_collect_to_vec(&buffer.unwrap());
|
||||
|
||||
let mut sine_gen = SineGenerator::<4>::new(4);
|
||||
let generator = cloned_generator;
|
||||
let gen_test = SineGenerator::<4>::new(5);
|
||||
|
||||
let mut structure_nodes = vec![];
|
||||
let mut color_nodes = vec![];
|
||||
let mut color_nodes: Vec<[ColorBytes; 64]> = vec![];
|
||||
let mut location_nodes = vec![];
|
||||
let mut destinations = vec![];
|
||||
for request in cache_node_requests.iter().take(request_count as usize)
|
||||
{
|
||||
let location;
|
||||
let node;
|
||||
if request.child_index == u32::MAX
|
||||
{
|
||||
// Produce root node
|
||||
node = sine_gen.produce_node(0, 0, 0, 0);
|
||||
location = LocationPoolElement {
|
||||
structure_id: 0,
|
||||
structure_locator: NTreeNodeLocator::<4>::root().as_usize() as u32,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
// Figure out depth of request
|
||||
let locator = NTreeNodeLocator::<4>::from_usize(
|
||||
request.structure_locator as usize,
|
||||
);
|
||||
let depth = locator.depth();
|
||||
//let (x, y, z) = locator.node_location();
|
||||
|
||||
let child_x = request.child_index / (4 * 4);
|
||||
let child_y = (request.child_index % (4 * 4)) / 4;
|
||||
let child_z = request.child_index % 4;
|
||||
cache_node_requests
|
||||
.par_iter()
|
||||
.take(request_count as usize)
|
||||
.map(|request| {
|
||||
// Unpack structure id
|
||||
let (chunk_x, chunk_y, chunk_z) =
|
||||
*cloned_map.get(&request.structure_id).unwrap();
|
||||
|
||||
let child_locator =
|
||||
locator.child(child_x as usize, child_y as usize, child_z as usize);
|
||||
let location;
|
||||
let node;
|
||||
if request.child_index == u32::MAX
|
||||
{
|
||||
// Produce root node
|
||||
node =
|
||||
generator.produce_node(0, 0, 0, 0, (chunk_x, chunk_y, chunk_z));
|
||||
location = LocationPoolElement {
|
||||
structure_id: request.structure_id,
|
||||
structure_locator: NTreeNodeLocator::<4>::root().as_usize()
|
||||
as u32,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
// Figure out depth of request
|
||||
let locator = NTreeNodeLocator::<4>::from_usize(
|
||||
request.structure_locator as usize,
|
||||
);
|
||||
let depth = locator.depth();
|
||||
//let (x, y, z) = locator.node_location();
|
||||
|
||||
let (nx, ny, nz) = child_locator.node_location();
|
||||
let child_z = request.child_index / (4 * 4);
|
||||
let child_y = (request.child_index % (4 * 4)) / 4;
|
||||
let child_x = request.child_index % 4;
|
||||
|
||||
node = sine_gen.produce_node(depth + 1, nx, ny, nz);
|
||||
let child_locator = locator.child(
|
||||
child_x as usize,
|
||||
child_y as usize,
|
||||
child_z as usize,
|
||||
);
|
||||
|
||||
location = LocationPoolElement {
|
||||
structure_id: 0,
|
||||
structure_locator: child_locator.as_usize() as u32,
|
||||
};
|
||||
}
|
||||
let (nx, ny, nz) = child_locator.node_location();
|
||||
|
||||
structure_nodes.push(node.structure);
|
||||
color_nodes.push(node.colors);
|
||||
location_nodes.push(location);
|
||||
destinations.push(DestinationElement {
|
||||
node: request.node_index,
|
||||
child: request.child_index,
|
||||
node = generator.produce_node(
|
||||
depth + 1,
|
||||
nx,
|
||||
ny,
|
||||
nz,
|
||||
(chunk_x, chunk_y, chunk_z),
|
||||
);
|
||||
|
||||
location = LocationPoolElement {
|
||||
structure_id: request.structure_id,
|
||||
structure_locator: child_locator.as_usize() as u32,
|
||||
};
|
||||
}
|
||||
|
||||
(
|
||||
node.structure,
|
||||
node.colors,
|
||||
location,
|
||||
DestinationElement {
|
||||
node: request.node_index,
|
||||
child: request.child_index,
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
.for_each(|data| {
|
||||
structure_nodes.push(data.0);
|
||||
color_nodes.push(std::array::from_fn(|i| data.1[i].into()));
|
||||
location_nodes.push(data.2);
|
||||
destinations.push(data.3);
|
||||
});
|
||||
}
|
||||
|
||||
if structure_nodes.len() != 0
|
||||
{
|
||||
@@ -607,7 +730,7 @@ impl State
|
||||
}
|
||||
},
|
||||
);
|
||||
println!("Total request count: {}", request_count);
|
||||
//println!("Total request count: {}", request_count);
|
||||
loop
|
||||
{
|
||||
if rx.try_recv().is_ok()
|
||||
@@ -617,10 +740,17 @@ impl State
|
||||
let _ = self.device.poll(wgpu::wgt::PollType::Poll);
|
||||
}
|
||||
|
||||
self.voxel_cache.lock().next_frame();
|
||||
drop(rx);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mouse_wheel(&mut self, delta: MouseScrollDelta)
|
||||
{
|
||||
if let MouseScrollDelta::LineDelta(_, y) = delta
|
||||
{
|
||||
self.camera.speed += y * (self.camera.speed * 0.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -679,6 +809,11 @@ impl ApplicationHandler for App
|
||||
// here as this event is always followed up by redraw request.
|
||||
state.resize(size);
|
||||
}
|
||||
WindowEvent::MouseWheel { delta, .. } =>
|
||||
{
|
||||
state.mouse_wheel(delta);
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
+377
-16
@@ -1,3 +1,6 @@
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
|
||||
use glam::Vec3;
|
||||
use itertools::Itertools;
|
||||
|
||||
@@ -5,7 +8,7 @@ use crate::voxel::gpu::ExplicitNTreeNode;
|
||||
use crate::voxel::gpu::StructurePointer;
|
||||
use crate::voxel::sparse::Color;
|
||||
|
||||
pub struct SineGenerator<const N: usize>
|
||||
pub struct BallGenerator<const N: usize>
|
||||
{
|
||||
chunk_power: usize,
|
||||
}
|
||||
@@ -15,22 +18,28 @@ pub fn map(x: f32, x_min: f32, x_max: f32, y_min: f32, y_max: f32) -> f32
|
||||
((x - x_min) / (x_max - x_min)) * (y_max - y_min) + y_min
|
||||
}
|
||||
|
||||
impl<const N: usize> SineGenerator<N>
|
||||
pub trait Producer<const N: usize>
|
||||
where
|
||||
[(); N * N * N]:,
|
||||
{
|
||||
fn produce_node(&self, depth: usize, nx: usize, ny: usize, nz: usize) -> ExplicitNTreeNode<N>;
|
||||
}
|
||||
|
||||
impl<const N: usize> BallGenerator<N>
|
||||
where
|
||||
[(); N * N * N]:,
|
||||
{
|
||||
pub fn new(chunk_power: usize) -> Self
|
||||
{
|
||||
SineGenerator { chunk_power }
|
||||
BallGenerator { chunk_power }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn produce_node(
|
||||
&self,
|
||||
depth: usize,
|
||||
nx: usize,
|
||||
ny: usize,
|
||||
nz: usize,
|
||||
) -> ExplicitNTreeNode<N>
|
||||
impl<const N: usize> Producer<N> for BallGenerator<N>
|
||||
where
|
||||
[(); N * N * N]:,
|
||||
{
|
||||
fn produce_node(&self, depth: usize, nx: usize, ny: usize, nz: usize) -> ExplicitNTreeNode<N>
|
||||
{
|
||||
let node_size = N.pow((self.chunk_power - depth) as u32);
|
||||
let child_size = node_size / N;
|
||||
@@ -49,23 +58,38 @@ where
|
||||
let gvy = gny + cy * child_size + (child_size / 2);
|
||||
let gvz = gnz + cz * child_size + (child_size / 2);
|
||||
|
||||
let dist = Vec3::new(gvx as f32 - 128., gvy as f32 - 128., gvz as f32 - 128.).length();
|
||||
let dist = Vec3::new(
|
||||
gvx as f32 - (global_size / 2) as f32,
|
||||
gvy as f32 - (global_size / 2) as f32,
|
||||
gvz as f32 - (global_size / 2) as f32,
|
||||
)
|
||||
.length();
|
||||
let child_diagonal_length = (child_size as f32 / 2.) * f32::sqrt(3.);
|
||||
|
||||
let alpha;
|
||||
if (dist - 128.).abs() <= child_diagonal_length
|
||||
if (dist - (global_size as f32 / 2.)).abs() <= child_diagonal_length
|
||||
{
|
||||
children.push(StructurePointer::new(depth <= 3, false, 0));
|
||||
//children.push(StructurePointer::new(depth <= 3, false, 0));
|
||||
children.push(StructurePointer(
|
||||
if depth < (self.chunk_power - 1)
|
||||
{
|
||||
0xFFFFFFFF
|
||||
}
|
||||
else
|
||||
{
|
||||
0
|
||||
},
|
||||
));
|
||||
alpha = if dist > 128. { 0. } else { 1. };
|
||||
}
|
||||
else if dist > 128.
|
||||
else if dist > (global_size as f32 / 2.)
|
||||
{
|
||||
children.push(StructurePointer::new(false, false, 0));
|
||||
children.push(StructurePointer(0));
|
||||
alpha = 0.;
|
||||
}
|
||||
else
|
||||
{
|
||||
children.push(StructurePointer::new(false, false, 0));
|
||||
children.push(StructurePointer(0));
|
||||
alpha = 1.;
|
||||
}
|
||||
|
||||
@@ -86,3 +110,340 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SineGenerator<const N: usize>
|
||||
{
|
||||
chunk_power: usize,
|
||||
}
|
||||
|
||||
impl<const N: usize> SineGenerator<N>
|
||||
where
|
||||
[(); N * N * N]:,
|
||||
{
|
||||
pub fn new(chunk_power: usize) -> Self
|
||||
{
|
||||
Self { chunk_power }
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Producer<N> for SineGenerator<N>
|
||||
where
|
||||
[(); N * N * N]:,
|
||||
{
|
||||
fn produce_node(&self, depth: usize, nx: usize, ny: usize, nz: usize) -> ExplicitNTreeNode<N>
|
||||
{
|
||||
let node_size = N.pow((self.chunk_power - depth) as u32);
|
||||
let child_size = node_size / N;
|
||||
let global_size = N.pow(self.chunk_power as u32);
|
||||
|
||||
let mut children = vec![];
|
||||
let mut children_color = vec![];
|
||||
|
||||
let gnx = nx * node_size;
|
||||
let gny = ny * node_size;
|
||||
let gnz = nz * node_size;
|
||||
// Iterate on children of this node
|
||||
for ((cx, cy), cz) in (0..N).cartesian_product(0..N).cartesian_product(0..N)
|
||||
{
|
||||
let total_sub_voxels = child_size * child_size * child_size;
|
||||
let mut filled_sub_voxels = 0;
|
||||
|
||||
let gcx = gnx + cx * child_size;
|
||||
let gcy = gny + cy * child_size;
|
||||
let gcz = gnz + cz * child_size;
|
||||
|
||||
// prepare 2d values
|
||||
|
||||
// Iterate on children
|
||||
for (x, z) in (0..child_size).cartesian_product(0..child_size)
|
||||
{
|
||||
let gvx = gcx + x;
|
||||
let gvz = gcz + z;
|
||||
//let gvy = gcy;
|
||||
let sx = map(gvx as f32, 0., global_size as f32, -8., 8.).abs();
|
||||
let sz = map(gvz as f32, 0., global_size as f32, -8., 8.).abs();
|
||||
let sample = (fastapprox::fast::cos(sx) + fastapprox::fast::cos(sz)) * 0.5;
|
||||
let sample_height = map(sample, -1., 1., 0., 500.);
|
||||
|
||||
let prop = map(
|
||||
sample_height,
|
||||
gcy as f32,
|
||||
(gcy + child_size) as f32,
|
||||
0.,
|
||||
child_size as f32,
|
||||
)
|
||||
.clamp(0., child_size as f32)
|
||||
.floor() as usize;
|
||||
filled_sub_voxels += prop;
|
||||
}
|
||||
|
||||
let alpha;
|
||||
if filled_sub_voxels == 0
|
||||
{
|
||||
children.push(StructurePointer(0));
|
||||
alpha = 0.;
|
||||
}
|
||||
else if filled_sub_voxels >= total_sub_voxels
|
||||
{
|
||||
children.push(StructurePointer(0));
|
||||
alpha = 1.;
|
||||
}
|
||||
else
|
||||
{
|
||||
children.push(StructurePointer(
|
||||
if depth < (self.chunk_power - 1)
|
||||
{
|
||||
0xFFFFFFFF
|
||||
}
|
||||
else
|
||||
{
|
||||
0
|
||||
},
|
||||
));
|
||||
//children.push(StructurePointer(0));
|
||||
alpha = if filled_sub_voxels > total_sub_voxels / 2
|
||||
{
|
||||
1.
|
||||
}
|
||||
else
|
||||
{
|
||||
0.
|
||||
};
|
||||
}
|
||||
|
||||
children_color.push(Color(
|
||||
(gcx + child_size / 2) as f32 / global_size as f32,
|
||||
(gcy + child_size / 2) as f32 / global_size as f32,
|
||||
(gcz + child_size / 2) as f32 / global_size as f32,
|
||||
alpha,
|
||||
));
|
||||
}
|
||||
|
||||
ExplicitNTreeNode {
|
||||
structure: std::array::from_fn(|i| children[i]),
|
||||
colors: std::array::from_fn(|i| children_color[i]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TerrainGenerator<const N: usize>
|
||||
where
|
||||
[(); N * N * N]:,
|
||||
{
|
||||
chunk_power: usize,
|
||||
heightmap_width: usize,
|
||||
heightmap_height: usize,
|
||||
terrain_width: usize,
|
||||
terrain_height: usize,
|
||||
heightmap_min: f32,
|
||||
heightmap_max: f32,
|
||||
heightmap: Vec<f32>,
|
||||
colormap: Vec<u8>,
|
||||
|
||||
pub chunk_width: usize,
|
||||
pub chunk_height: usize,
|
||||
pub chunk_alt: usize,
|
||||
}
|
||||
|
||||
impl<const N: usize> TerrainGenerator<N>
|
||||
where
|
||||
[(); N * N * N]:,
|
||||
{
|
||||
pub fn new<P: AsRef<Path>>(
|
||||
chunk_power: usize,
|
||||
height_path: P,
|
||||
height_factor: f32,
|
||||
color_path: P,
|
||||
) -> Self
|
||||
{
|
||||
let mut tiff_dec = tiff::decoder::Decoder::new(File::open(height_path).unwrap()).unwrap();
|
||||
let (heightmap_width, heightmap_height) = tiff_dec.dimensions().unwrap();
|
||||
let (heightmap_width, heightmap_height) =
|
||||
(heightmap_width as usize, heightmap_height as usize);
|
||||
|
||||
let heightmap = match tiff_dec.read_image().unwrap()
|
||||
{
|
||||
tiff::decoder::DecodingResult::F32(vec) => vec,
|
||||
_ => panic!("Unsupported format"),
|
||||
};
|
||||
|
||||
let mut color = image::ImageReader::open(color_path).unwrap();
|
||||
color.no_limits();
|
||||
|
||||
let color = color.decode().unwrap();
|
||||
let colormap = color.as_rgb8().unwrap().to_vec();
|
||||
|
||||
let terrain_width = color.width() as usize;
|
||||
let terrain_height = color.height() as usize;
|
||||
|
||||
let heightmap_min = heightmap.iter().copied().reduce(f32::min).unwrap();
|
||||
let heightmap_max = heightmap.iter().copied().reduce(f32::max).unwrap();
|
||||
|
||||
// Decide size in chunks
|
||||
let height_amplitude = heightmap_max - heightmap_min;
|
||||
let chunk_size = N.pow(chunk_power as u32);
|
||||
let chunk_width = terrain_width.div_ceil(chunk_size);
|
||||
let chunk_height = terrain_height.div_ceil(chunk_size);
|
||||
let chunk_alt = ((height_amplitude / height_factor) as usize).div_ceil(chunk_size);
|
||||
|
||||
Self {
|
||||
chunk_power,
|
||||
heightmap_width,
|
||||
heightmap_height,
|
||||
heightmap_min,
|
||||
heightmap_max,
|
||||
terrain_width,
|
||||
terrain_height,
|
||||
heightmap,
|
||||
colormap,
|
||||
|
||||
chunk_width,
|
||||
chunk_height,
|
||||
chunk_alt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> ChunkedProducer<N> for TerrainGenerator<N>
|
||||
where
|
||||
[(); N * N * N]:,
|
||||
{
|
||||
fn produce_node(
|
||||
&self,
|
||||
depth: usize,
|
||||
nx: usize,
|
||||
ny: usize,
|
||||
nz: usize,
|
||||
chunk_pos: (usize, usize, usize),
|
||||
) -> ExplicitNTreeNode<N>
|
||||
{
|
||||
let node_size = N.pow((self.chunk_power - depth) as u32);
|
||||
let child_size = node_size / N;
|
||||
let global_size = N.pow(self.chunk_power as u32);
|
||||
|
||||
let mut children = vec![StructurePointer(0); N * N * N];
|
||||
let mut children_color = vec![Color(0., 0., 0., 0.); N * N * N];
|
||||
|
||||
let gnx = chunk_pos.0 * global_size + nx * node_size;
|
||||
let gny = chunk_pos.1 * global_size + ny * node_size;
|
||||
let gnz = chunk_pos.2 * global_size + nz * node_size;
|
||||
// Iterate on children of this node
|
||||
for (cx, cz) in (0..N).cartesian_product(0..N)
|
||||
{
|
||||
let gcx = gnx + cx * child_size;
|
||||
let gcz = gnz + cz * child_size;
|
||||
|
||||
// prepare 2d values
|
||||
|
||||
// Iterate on children
|
||||
let mut sample_max = self.heightmap_min;
|
||||
let mut sample_min = self.heightmap_max;
|
||||
let mut color_avg = Color(0., 0., 0., 0.);
|
||||
let mut count = 0;
|
||||
for (x, z) in (0..child_size).cartesian_product(0..child_size)
|
||||
{
|
||||
let gvx = gcx + x;
|
||||
let gvz = gcz + z;
|
||||
if gvx < self.terrain_width && gvz < self.terrain_height
|
||||
{
|
||||
// Height sample
|
||||
let height_x = (gvx * self.heightmap_width) / self.terrain_width;
|
||||
let height_z = (gvz * self.heightmap_height) / self.terrain_height;
|
||||
|
||||
let sample = self.heightmap[height_x + height_z * self.heightmap_width];
|
||||
sample_max = sample_max.max(sample);
|
||||
sample_min = sample_min.min(sample);
|
||||
|
||||
let sample_color_r = self.colormap[(gvx + gvz * self.terrain_width) * 3];
|
||||
let sample_color_g = self.colormap[(gvx + gvz * self.terrain_width) * 3 + 1];
|
||||
let sample_color_b = self.colormap[(gvx + gvz * self.terrain_width) * 3 + 2];
|
||||
|
||||
color_avg.0 += map(sample_color_r as f32, 0., 256., 0., 1.);
|
||||
color_avg.1 += map(sample_color_g as f32, 0., 256., 0., 1.);
|
||||
color_avg.2 += map(sample_color_b as f32, 0., 256., 0., 1.);
|
||||
count += 1;
|
||||
}
|
||||
//let gvy = gcy;
|
||||
}
|
||||
|
||||
color_avg.0 /= count as f32;
|
||||
color_avg.1 /= count as f32;
|
||||
color_avg.2 /= count as f32;
|
||||
|
||||
let sample_min = map(
|
||||
sample_min,
|
||||
self.heightmap_min,
|
||||
self.heightmap_max,
|
||||
0.,
|
||||
(self.chunk_alt * global_size) as f32,
|
||||
) as usize;
|
||||
let sample_max = map(
|
||||
sample_max,
|
||||
self.heightmap_min,
|
||||
self.heightmap_max,
|
||||
0.,
|
||||
(self.chunk_alt * global_size) as f32,
|
||||
) as usize;
|
||||
|
||||
for cy in 0..N
|
||||
{
|
||||
let gcy = gny + cy * child_size;
|
||||
let index = cz * N * N + cy * N + cx;
|
||||
let alpha;
|
||||
if gcy > sample_max
|
||||
{
|
||||
children[index] = StructurePointer(0);
|
||||
alpha = 0.;
|
||||
}
|
||||
else if gcy + child_size < sample_min
|
||||
{
|
||||
children[index] = StructurePointer(0);
|
||||
alpha = 1.;
|
||||
}
|
||||
else
|
||||
{
|
||||
children[index] = StructurePointer(
|
||||
if depth < (self.chunk_power - 1)
|
||||
{
|
||||
0xFFFFFFFF
|
||||
}
|
||||
else
|
||||
{
|
||||
0
|
||||
},
|
||||
);
|
||||
//children.push(StructurePointer(0));
|
||||
alpha = if (sample_max + sample_min / 2) > gcy + (child_size / 2)
|
||||
{
|
||||
1.
|
||||
}
|
||||
else
|
||||
{
|
||||
0.
|
||||
};
|
||||
}
|
||||
|
||||
children_color[index] = Color(color_avg.0, color_avg.1, color_avg.2, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
ExplicitNTreeNode {
|
||||
structure: std::array::from_fn(|i| children[i]),
|
||||
colors: std::array::from_fn(|i| children_color[i]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ChunkedProducer<const N: usize>
|
||||
where
|
||||
[(); N * N * N]:,
|
||||
{
|
||||
fn produce_node(
|
||||
&self,
|
||||
depth: usize,
|
||||
nx: usize,
|
||||
ny: usize,
|
||||
nz: usize,
|
||||
chunk_pos: (usize, usize, usize),
|
||||
) -> ExplicitNTreeNode<N>;
|
||||
}
|
||||
|
||||
+67
-33
@@ -209,32 +209,39 @@ where
|
||||
|
||||
|
||||
@compute
|
||||
@workgroup_size(16)
|
||||
@workgroup_size(64)
|
||||
fn main(
|
||||
@builtin(global_invocation_id) global_invocation_id: vec3<u32>
|
||||
)
|
||||
{{
|
||||
let request_count_round_up =
|
||||
((request_count / {children_count}) + select(u32(0), u32(1), request_count % {children_count} != 0)) * {children_count};
|
||||
|
||||
let index = global_invocation_id.x;
|
||||
let total = arrayLength(&sort_indirection);
|
||||
|
||||
/*
|
||||
let request_count_round_up =
|
||||
((request_count / {children_count}) + select(u32(0), u32(1), request_count % {children_count} != 0)) * {children_count};
|
||||
if(index * 2 >= request_count_round_up)
|
||||
{{ return; }}
|
||||
*/
|
||||
|
||||
let sub_phase = (both_phase >> 16) & 0xFFFF;
|
||||
let phase = both_phase & 0xFFFF;
|
||||
let phase_total_width = u32(1 << (phase + 1));
|
||||
|
||||
request_count = 0;
|
||||
|
||||
|
||||
// Check if phase is last
|
||||
let phase_total_width = u32(1 << (phase + 1));
|
||||
/*
|
||||
let phase_count = u32(ceil(log2(f32(request_count))));
|
||||
if(phase > phase_count)
|
||||
{{
|
||||
//return;
|
||||
return;
|
||||
}}
|
||||
*/
|
||||
|
||||
/*
|
||||
if(phase == 0)
|
||||
{{
|
||||
let a = index * 2;
|
||||
@@ -242,6 +249,7 @@ where
|
||||
sort_indirection[a].child = a % {children_count};
|
||||
sort_indirection[b].child = b % {children_count};
|
||||
}}
|
||||
*/
|
||||
|
||||
var swap_indices = vec2<u32>(0, 0);
|
||||
|
||||
@@ -255,7 +263,9 @@ where
|
||||
}}
|
||||
|
||||
// Do swap
|
||||
if(swap_indices.y >= request_count_round_up)
|
||||
|
||||
//if(swap_indices.y >= request_count_round_up)
|
||||
if(swap_indices.y >= total)
|
||||
{{
|
||||
// Suppose that swap_indices.y is -inf, dont swap
|
||||
return;
|
||||
@@ -306,7 +316,7 @@ where
|
||||
@group(0) @binding(2) var<storage, read_write> request_counts: u32;
|
||||
|
||||
@compute
|
||||
@workgroup_size(16)
|
||||
@workgroup_size(64)
|
||||
fn main(
|
||||
@builtin(global_invocation_id) global_invocation_id: vec3<u32>
|
||||
)
|
||||
@@ -398,7 +408,7 @@ where
|
||||
@group(0) @binding(2) var<storage, read_write> request_counts: atomic<u32>;
|
||||
|
||||
@compute
|
||||
@workgroup_size(16)
|
||||
@workgroup_size(64)
|
||||
fn main(
|
||||
@builtin(global_invocation_id) global_invocation_id: vec3<u32>
|
||||
)
|
||||
@@ -455,7 +465,7 @@ where
|
||||
@group(0) @binding(2) var<storage, read_write> request_count: atomic<u32>;
|
||||
|
||||
@compute
|
||||
@workgroup_size(16)
|
||||
@workgroup_size(64)
|
||||
fn main(
|
||||
@builtin(global_invocation_id) global_invocation_id: vec3<u32>
|
||||
)
|
||||
@@ -469,6 +479,10 @@ where
|
||||
{{
|
||||
for(var i = 0; i < {children_count}; i += 1)
|
||||
{{
|
||||
if(request_buffer[index].children[i] != 0)
|
||||
{{
|
||||
atomicAdd(&request_count, 1);
|
||||
}}
|
||||
request_buffer[index].children[i] = 0;
|
||||
}}
|
||||
}}
|
||||
@@ -522,7 +536,7 @@ where
|
||||
compute_pass.set_pipeline(&self.reset_pipeline);
|
||||
|
||||
let shader_invocations = self.cache_size; // one invocation per element
|
||||
let workgroup_invocations = shader_invocations.div_ceil(16);
|
||||
let workgroup_invocations = shader_invocations.div_ceil(64);
|
||||
compute_pass.dispatch_workgroups(workgroup_invocations as u32, 1, 1);
|
||||
}
|
||||
|
||||
@@ -535,8 +549,9 @@ where
|
||||
|
||||
compute_pass.set_bind_group(0, Some(&self.bindgroup), &[]);
|
||||
let request_element_count = self.cache_size; // Each child slot is sorted
|
||||
let workgroups_invocations = request_element_count.div_ceil(16);
|
||||
let workgroups_invocations = request_element_count.div_ceil(64);
|
||||
|
||||
/*
|
||||
// = Perform list compaction
|
||||
|
||||
// == Running sum
|
||||
@@ -562,21 +577,22 @@ where
|
||||
// == Stream compaction
|
||||
compute_pass.set_pipeline(&self.compaction_pipeline);
|
||||
compute_pass.dispatch_workgroups(workgroups_invocations as u32, 1, 1);
|
||||
*/
|
||||
|
||||
// == Bitonic sort
|
||||
compute_pass.set_pipeline(&self.sort_pipeline);
|
||||
let sort_element_count = request_element_count * N * N * N;
|
||||
let sort_element_count = self.cache_size * N * N * N;
|
||||
let phases_upper_bound = sort_element_count.next_power_of_two().ilog2();
|
||||
|
||||
// Phase 0 dispatch all
|
||||
for i in 0..phases_upper_bound
|
||||
for i in 0..=phases_upper_bound
|
||||
{
|
||||
for j in 0..=i
|
||||
{
|
||||
compute_pass.set_immediates(0, bytemuck::bytes_of(
|
||||
&(i | (j << 16))
|
||||
));
|
||||
compute_pass.dispatch_workgroups(sort_element_count.div_ceil(2).div_ceil(16) as u32, 1, 1);
|
||||
compute_pass.dispatch_workgroups(sort_element_count.div_ceil(2).div_ceil(64) as u32, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -714,7 +730,7 @@ impl UsageBuffer
|
||||
|
||||
|
||||
@compute
|
||||
@workgroup_size(16)
|
||||
@workgroup_size(64)
|
||||
fn main(
|
||||
@builtin(global_invocation_id) global_invocation_id: vec3<u32>
|
||||
)
|
||||
@@ -810,9 +826,9 @@ impl UsageBuffer
|
||||
let shader_invocations = self.cache_size.div_ceil(2); // bitonic sorting :
|
||||
// half as many shaders
|
||||
// per element
|
||||
let workgroup_invocations = shader_invocations.div_ceil(16);
|
||||
let workgroup_invocations = shader_invocations.div_ceil(64);
|
||||
|
||||
for i in 0..sort_steps
|
||||
for i in 0..=sort_steps
|
||||
{
|
||||
for j in 0..=i
|
||||
{
|
||||
@@ -842,8 +858,8 @@ impl StructureTable
|
||||
let pointer_table = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("structure_table_pointer_table"),
|
||||
size: size_of::<u32>() as u64,
|
||||
usage: BufferUsages::STORAGE | BufferUsages::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
usage: BufferUsages::STORAGE | BufferUsages::COPY_DST | BufferUsages::COPY_SRC,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
|
||||
StructureTable {
|
||||
@@ -867,7 +883,7 @@ impl StructureTable
|
||||
let pointer_table = self.device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("structure_table_pointer_table"),
|
||||
size: size_of::<u32>() as u64 * self.allocation_table.len() as u64,
|
||||
usage: BufferUsages::STORAGE,
|
||||
usage: BufferUsages::STORAGE | BufferUsages::COPY_SRC | BufferUsages::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
|
||||
@@ -986,11 +1002,25 @@ pub struct DestinationElement
|
||||
pub child: u32,
|
||||
}
|
||||
|
||||
pub struct ColorBytes(pub u8, pub u8, pub u8, pub u8);
|
||||
|
||||
impl From<Color> for ColorBytes
|
||||
{
|
||||
fn from(value: Color) -> Self {
|
||||
Self(
|
||||
(value.0 * 255.) as u8,
|
||||
(value.1 * 255.) as u8,
|
||||
(value.2 * 255.) as u8,
|
||||
(value.3 * 255.) as u8,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ColorPoolElement<const N: usize>
|
||||
where
|
||||
[(); N * N * N]:,
|
||||
{
|
||||
colors: [Color; N * N * N],
|
||||
colors: [ColorBytes; N * N * N],
|
||||
}
|
||||
|
||||
pub struct LocationPoolElement
|
||||
@@ -1343,7 +1373,7 @@ where
|
||||
|
||||
struct ColorPoolElement
|
||||
{{
|
||||
colors: array<vec4<f32>, {children_count}>
|
||||
colors: array<u32, {children_count}>
|
||||
}}
|
||||
|
||||
struct LocationPoolElement
|
||||
@@ -1427,7 +1457,7 @@ where
|
||||
@group(2) @binding(0) var<storage, read_write> requests: array<CacheNodeRequest>;
|
||||
|
||||
@compute
|
||||
@workgroup_size(16)
|
||||
@workgroup_size(64)
|
||||
fn main(
|
||||
@builtin(global_invocation_id) global_invocation_id: vec3<u32>
|
||||
)
|
||||
@@ -1435,7 +1465,7 @@ where
|
||||
// One shader invocation per invocation on both structure table domain
|
||||
// and cache domain
|
||||
var index = global_invocation_id.x;
|
||||
let max_requests_count = arrayLength(&requests);
|
||||
let max_requests_count = min(arrayLength(&requests), arrayLength(&lru_list));
|
||||
total_request_count = min(max_requests_count, pools_request_count + structure_table_request_count);
|
||||
if(index >= total_request_count)
|
||||
{{
|
||||
@@ -1586,7 +1616,7 @@ where
|
||||
@group(2) @binding(3) var<storage, read> destinations: array<DestinationElement>;
|
||||
|
||||
@compute
|
||||
@workgroup_size(16)
|
||||
@workgroup_size(64)
|
||||
fn main(
|
||||
@builtin(global_invocation_id) global_invocation_id: vec3<u32>
|
||||
)
|
||||
@@ -1594,7 +1624,8 @@ where
|
||||
// Copy with indirection
|
||||
let index = global_invocation_id.x;
|
||||
let total = arrayLength(&structure_nodes);
|
||||
if(index >= total)
|
||||
let total_cache = arrayLength(&lru_list);
|
||||
if(index >= total || index >= total_cache)
|
||||
{{
|
||||
return;
|
||||
}}
|
||||
@@ -1604,7 +1635,10 @@ where
|
||||
{{
|
||||
// Phase 1
|
||||
// Copy into cache page
|
||||
structure_pool[overwritten_element] = structure_nodes[index];
|
||||
for(var i = 0; i < {children_count}; i++)
|
||||
{{
|
||||
structure_pool[overwritten_element].pointers[i] = select(u32(0), u32(1)<<31, structure_nodes[index].pointers[i] != 0);
|
||||
}}
|
||||
color_pool[overwritten_element] = color_nodes[index];
|
||||
location_pool[overwritten_element] = locations[index];
|
||||
|
||||
@@ -1620,7 +1654,7 @@ where
|
||||
if(destinations[index].child == 0xFFFFFFFF)
|
||||
{{
|
||||
structure_table_pointers[destinations[index].node] = new_pointer;
|
||||
}}else
|
||||
}}else if usage_buffer[destinations[index].node] != parameters.frame_timestamp + 1
|
||||
{{
|
||||
structure_pool[destinations[index].node].pointers[destinations[index].child] = new_pointer;
|
||||
}}
|
||||
@@ -1662,7 +1696,7 @@ where
|
||||
var<immediate> frame_timestamp: u32;
|
||||
|
||||
@compute
|
||||
@workgroup_size(16)
|
||||
@workgroup_size(64)
|
||||
fn main(
|
||||
@builtin(global_invocation_id) global_invocation_id: vec3<u32>
|
||||
)
|
||||
@@ -1863,7 +1897,7 @@ where
|
||||
|
||||
// Compute necessary shader invocations
|
||||
let shader_invocation_count = request_target.size() / size_of::<CacheNodeRequest>() as u64;
|
||||
let workgroup_invocation_count = shader_invocation_count.div_ceil(16);
|
||||
let workgroup_invocation_count = shader_invocation_count.div_ceil(64);
|
||||
write_requests_pass.dispatch_workgroups(workgroup_invocation_count as u32, 1, 1);
|
||||
}
|
||||
|
||||
@@ -1930,7 +1964,7 @@ where
|
||||
// Compute dispatch amounts
|
||||
let shader_invocation_count =
|
||||
insertion.structure_nodes.size() as usize / size_of::<StructurePoolElement<N>>();
|
||||
let workgroup_invocations = shader_invocation_count.div_ceil(16);
|
||||
let workgroup_invocations = shader_invocation_count.div_ceil(64);
|
||||
|
||||
cache_insertion_pass.dispatch_workgroups(workgroup_invocations as u32, 1, 1);
|
||||
}
|
||||
@@ -1944,7 +1978,7 @@ where
|
||||
|
||||
// Compute dispatch amounts
|
||||
let shader_invocation_count = self.size + self.structure_table.allocation_table.len();
|
||||
let workgroup_invocations = shader_invocation_count.div_ceil(16);
|
||||
let workgroup_invocations = shader_invocation_count.div_ceil(64);
|
||||
|
||||
cache_insertion_pass.dispatch_workgroups(workgroup_invocations as u32, 1, 1);
|
||||
}
|
||||
@@ -1964,7 +1998,7 @@ where
|
||||
// Compute dispatch amounts
|
||||
let shader_invocation_count =
|
||||
insertion.structure_nodes.size() as usize / size_of::<StructurePoolElement<N>>();
|
||||
let workgroup_invocations = shader_invocation_count.div_ceil(16);
|
||||
let workgroup_invocations = shader_invocation_count.div_ceil(64);
|
||||
|
||||
cache_insertion_pass.dispatch_workgroups(workgroup_invocations as u32, 1, 1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user