Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Delay Slot #594

Merged
merged 1 commit into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 0 additions & 17 deletions rend3-routine/shaders/src/depth.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -47,26 +47,9 @@ struct VertexOutput {

@vertex
fn vs_main(@builtin(instance_index) instance_index: u32, @builtin(vertex_index) vertex_index: u32) -> VertexOutput {
// If the vertex index is our sentinel invalid value, return a degenerate triangle.
//
// This is used by the culling shader to discard triangles when the ordering of the
// triangles are important, and atomics can't be used.
if vertex_index == INVALID_VERTEX {
var vs_out: VertexOutput;
vs_out.position = vec4<f32>(0.0);
return vs_out;
}
let indices = Indices(instance_index, vertex_index);

let data = object_buffer[indices.object];
// If the object is disabled, return a degenerate triangle.
//
// This happens when the object is deleted, and we're rendering last-frame's objects.
if data.enabled == 0u {
var vs_out: VertexOutput;
vs_out.position = vec4<f32>(0.0);
return vs_out;
}

let vs_in = get_vertices(indices);

Expand Down
17 changes: 0 additions & 17 deletions rend3-routine/shaders/src/opaque.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -87,26 +87,9 @@ struct VertexOutput {

@vertex
fn vs_main(@builtin(instance_index) instance_index: u32, @builtin(vertex_index) vertex_index: u32) -> VertexOutput {
// If the vertex index is our sentinel invalid value, return a degenerate triangle.
//
// This is used by the culling shader to discard triangles when the ordering of the
// triangles are important, and atomics can't be used.
if vertex_index == INVALID_VERTEX {
var vs_out: VertexOutput;
vs_out.position = vec4<f32>(0.0);
return vs_out;
}
let indices = Indices(instance_index, vertex_index);

let data = object_buffer[indices.object];
// If the object is disabled, return a degenerate triangle.
//
// This happens when the object is deleted, and we're rendering last-frame's objects.
if data.enabled == 0u {
var vs_out: VertexOutput;
vs_out.position = vec4<f32>(0.0);
return vs_out;
}

let vs_in = get_vertices(indices);

Expand Down
2 changes: 0 additions & 2 deletions rend3-routine/shaders/src/structures_object.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,4 @@ struct Object {
index_count: u32,
material_index: u32,
vertex_attribute_start_offsets: array<u32, {{vertex_array_counts}}>,
// 1 if enabled, 0 if disabled
enabled: u32,
}
2 changes: 0 additions & 2 deletions rend3/shaders/vertex_attributes.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ struct Indices {
vertex: u32,
}

const INVALID_VERTEX: u32 = 0x00FFFFFFu;

alias TriangleVertices = array<vec3f, 3>;
alias TriangleIndices = array<u32, 3>;
struct Triangle {
Expand Down
35 changes: 3 additions & 32 deletions rend3/src/managers/handle_alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,15 @@ where
{
max_allocated: AtomicUsize,
freelist: Mutex<Vec<usize>>,
/// We want the render routines to be able to rely on deleted handles being valid for at
/// least one frame.
///
/// To facilitate this, we first put the handle in the delay list, then at the top of
/// every frame, we move the handles from the delay list to the freelist.
///
/// We do not need to do this for everything though, only for Object handles, as these
/// are the root handle which the renderer accesses everything.
delay_list: Option<Mutex<Vec<usize>>>,
_phantom: PhantomData<T>,
}

impl<T> HandleAllocator<T>
where
RawResourceHandle<T>: DeletableRawResourceHandle,
{
pub fn new(delay_handle_reclaimation: bool) -> Self {
Self {
max_allocated: AtomicUsize::new(0),
freelist: Mutex::new(Vec::new()),
delay_list: delay_handle_reclaimation.then(|| Mutex::new(Vec::new())),
_phantom: PhantomData,
}
pub fn new() -> Self {
Self { max_allocated: AtomicUsize::new(0), freelist: Mutex::new(Vec::new()), _phantom: PhantomData }
}

pub fn allocate(&self, renderer: &Arc<Renderer>) -> ResourceHandle<T> {
Expand All @@ -57,21 +43,6 @@ where

pub fn deallocate(&self, handle: RawResourceHandle<T>) {
let idx = handle.idx;
if let Some(ref delay_list) = self.delay_list {
delay_list.lock().push(idx);
} else {
self.freelist.lock().push(idx);
}
}

pub fn reclaim_delayed_handles(&self) -> Vec<RawResourceHandle<T>> {
if let Some(ref delay_list) = self.delay_list {
let mut locked_delay_list = delay_list.lock();

self.freelist.lock().extend_from_slice(&locked_delay_list);
locked_delay_list.drain(..).map(|idx| RawResourceHandle::new(idx)).collect()
} else {
Vec::new()
}
self.freelist.lock().push(idx);
}
}
43 changes: 10 additions & 33 deletions rend3/src/managers/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ pub struct ShaderObject<M: Material> {
pub material_index: u32,
pub vertex_attribute_start_offsets:
<M::SupportedAttributeArrayType as MaterialArray<&'static VertexAttributeId>>::U32Array,
// 1 if enabled, 0 if disabled
pub enabled: u32,
}

impl<M: Material> Default for ShaderObject<M> {
Expand All @@ -44,7 +42,6 @@ impl<M: Material> Default for ShaderObject<M> {
index_count: Default::default(),
material_index: Default::default(),
vertex_attribute_start_offsets: Zeroable::zeroed(),
enabled: Default::default(),
}
}
}
Expand Down Expand Up @@ -91,7 +88,7 @@ struct ObjectArchetype {
set_object_transform: fn(&mut WasmVecAny, &mut FreelistDerivedBuffer, usize, Mat4),
duplicate_object: fn(&WasmVecAny, usize, ObjectChange) -> Object,
remove: fn(&mut ObjectArchetype, usize),
evaluate: fn(&mut ObjectArchetype, &Device, &mut CommandEncoder, &ScatterCopy, &[RawObjectHandle]),
evaluate: fn(&mut ObjectArchetype, &Device, &mut CommandEncoder, &ScatterCopy),
}

/// Manages objects. That's it. ¯\\\_(ツ)\_/¯
Expand Down Expand Up @@ -163,15 +160,9 @@ impl ObjectManager {
(archetype.remove)(archetype, handle.idx);
}

pub fn evaluate(
&mut self,
device: &Device,
encoder: &mut CommandEncoder,
scatter: &ScatterCopy,
deferred_removals: &[RawObjectHandle],
) {
pub fn evaluate(&mut self, device: &Device, encoder: &mut CommandEncoder, scatter: &ScatterCopy) {
for archetype in self.archetype.values_mut() {
(archetype.evaluate)(archetype, device, encoder, scatter, deferred_removals);
(archetype.evaluate)(archetype, device, encoder, scatter);
}
}

Expand Down Expand Up @@ -279,7 +270,6 @@ pub(super) fn object_add_callback<M: Material>(_material: &M, args: ObjectAddCal
first_index: (index_range.start / 4) as u32,
index_count: ((index_range.end - index_range.start) / 4) as u32,
vertex_attribute_start_offsets,
enabled: true as u32,
},
material_handle: args.object.material,
mesh_kind: args.object.mesh_kind,
Expand Down Expand Up @@ -330,35 +320,22 @@ fn duplicate_object<M: Material>(data: &WasmVecAny, idx: usize, change: ObjectCh
fn remove<M: Material>(archetype: &mut ObjectArchetype, idx: usize) {
let data_vec = archetype.data_vec.downcast_slice_mut::<Option<InternalObject<M>>>().unwrap();

// We don't actually remove the object at this point,
// we just mark it as disabled. Next frame, this handle
// will be provided in `deferred_removals` in `evaluate`
// so we can actually delete it.
//
// We defer objects one frame so that temporal culling
// has valid data.
archetype.buffer.use_index(idx);
data_vec[idx].as_mut().unwrap().inner.enabled = false as u32;
// Only one archetype will have each handle,
// so if we have it, we can be sure it's ours.
let removed_obj = Option::take(&mut data_vec[idx]);

if removed_obj.is_some() {
archetype.object_count -= 1;
}
}

fn evaluate<M: Material>(
archetype: &mut ObjectArchetype,
device: &Device,
encoder: &mut CommandEncoder,
scatter: &ScatterCopy,
deferred_removals: &[RawObjectHandle],
) {
let data_vec = archetype.data_vec.downcast_slice_mut::<Option<InternalObject<M>>>().unwrap();

for removal in deferred_removals {
// Only one archetype will have each handle,
// so if we have it, we can be sure it's ours.
let removed_obj = data_vec[removal.idx].take();

if removed_obj.is_some() {
archetype.object_count -= 1;
}
}

archetype.buffer.apply(device, encoder, scatter, |idx| data_vec[idx].as_ref().map(|o| o.inner).unwrap_or_default())
}
4 changes: 1 addition & 3 deletions rend3/src/renderer/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ pub fn evaluate_instructions(renderer: &Renderer) -> InstructionEvaluationOutput

let mut instructions = renderer.instructions.consumer.lock();

let delayed_object_handles = renderer.resource_handle_allocators.object.reclaim_delayed_handles();

// 16 encoders is a reasonable default
let mut cmd_bufs = Vec::with_capacity(16);

Expand Down Expand Up @@ -157,7 +155,7 @@ pub fn evaluate_instructions(renderer: &Renderer) -> InstructionEvaluationOutput

// Do these in dependency order
// Level 3
data_core.object_manager.evaluate(&renderer.device, &mut encoder, &renderer.scatter, &delayed_object_handles);
data_core.object_manager.evaluate(&renderer.device, &mut encoder, &renderer.scatter);

// Level 2
let d2_texture = data_core.d2_texture_manager.evaluate(&renderer.device);
Expand Down
18 changes: 9 additions & 9 deletions rend3/src/renderer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,15 @@ struct HandleAllocators {
impl Default for HandleAllocators {
fn default() -> Self {
Self {
mesh: HandleAllocator::new(false),
skeleton: HandleAllocator::new(false),
d2_texture: HandleAllocator::new(false),
d2c_texture: HandleAllocator::new(false),
material: HandleAllocator::new(false),
object: HandleAllocator::new(true),
directional_light: HandleAllocator::new(false),
point_light: HandleAllocator::new(false),
graph_storage: HandleAllocator::new(false),
mesh: HandleAllocator::new(),
skeleton: HandleAllocator::new(),
d2_texture: HandleAllocator::new(),
d2c_texture: HandleAllocator::new(),
material: HandleAllocator::new(),
object: HandleAllocator::new(),
directional_light: HandleAllocator::new(),
point_light: HandleAllocator::new(),
graph_storage: HandleAllocator::new(),
}
}
}
Expand Down
Loading