Skip to content
Open
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
21 changes: 10 additions & 11 deletions crates/redpiler/src/backend/direct/compile.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::backend::direct::Options;
use crate::compile_graph::{CompileGraph, LinkType, NodeIdx};
use crate::{CompilerOptions, TaskMonitor};
use crate::TaskMonitor;
use itertools::Itertools;
use mchprs_blocks::blocks::{Block, Instrument};
use mchprs_blocks::BlockPos;
Expand Down Expand Up @@ -28,6 +29,7 @@ fn compile_node(
nodes_len: usize,
nodes_map: &FxHashMap<NodeIdx, usize>,
noteblock_info: &mut Vec<(BlockPos, Instrument, u32)>,
options: &Options,
stats: &mut FinalGraphStats,
) -> Node {
let node = &graph[node_idx];
Expand Down Expand Up @@ -138,15 +140,14 @@ fn compile_node(
locked: node.state.repeater_locked,
pending_tick: false,
changed: false,
is_io: node.is_input || node.is_output,
is_frozen: !(node.is_input || node.is_output) && options.is_io_only,
}
}

pub fn compile(
backend: &mut DirectBackend,
graph: CompileGraph,
ticks: Vec<TickEntry>,
options: &CompilerOptions,
_monitor: Arc<TaskMonitor>,
) {
// Create a mapping from compile to backend node indices
Expand All @@ -167,6 +168,7 @@ pub fn compile(
nodes_len,
&nodes_map,
&mut backend.noteblock_info,
&backend.options,
&mut stats,
)
})
Expand All @@ -190,15 +192,12 @@ pub fn compile(
// Schedule backend ticks
for entry in ticks {
if let Some(node) = backend.pos_map.get(&entry.pos) {
backend
.scheduler
.schedule_tick(*node, entry.ticks_left as usize, entry.tick_priority);
backend.execution_context.schedule_tick(
*node,
entry.ticks_left as usize,
entry.tick_priority,
);
backend.nodes[*node].pending_tick = true;
}
}

// Dot file output
if options.export_dot_graph {
std::fs::write("backend_graph.dot", format!("{}", backend)).unwrap();
}
}
99 changes: 99 additions & 0 deletions crates/redpiler/src/backend/direct/execution_context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
use super::{node::NodeId, Event};
use mchprs_world::TickPriority;

#[derive(Default, Clone)]
pub struct Queues([Vec<NodeId>; ExecutionContext::NUM_PRIORITIES]);

impl Queues {
pub fn drain_iter(&mut self) -> impl Iterator<Item = NodeId> + '_ {
let [q0, q1, q2, q3] = &mut self.0;
let [q0, q1, q2, q3] = [q0, q1, q2, q3].map(|q| q.drain(..));
q0.chain(q1).chain(q2).chain(q3)
}
}

#[derive(Default)]
pub struct ExecutionContext {
queues_deque: [Queues; Self::NUM_QUEUES],
pos: usize,
events: Vec<Event>,
changes: Vec<NodeId>,
}

impl ExecutionContext {
const NUM_PRIORITIES: usize = 4;
const NUM_QUEUES: usize = 16;

pub(super) fn schedule_tick(&mut self, node: NodeId, delay: usize, priority: TickPriority) {
self.queues_deque[(self.pos + delay) % Self::NUM_QUEUES].0[priority as usize].push(node);
}

pub(super) fn queues_this_tick(&mut self) -> Queues {
self.pos = (self.pos + 1) % Self::NUM_QUEUES;
std::mem::take(&mut self.queues_deque[self.pos])
}

pub(super) fn end_tick(&mut self, mut queues: Queues) {
for queue in &mut queues.0 {
queue.clear();
}
self.queues_deque[self.pos] = queues;
}

fn priorities() -> [TickPriority; Self::NUM_PRIORITIES] {
[
TickPriority::Highest,
TickPriority::Higher,
TickPriority::High,
TickPriority::Normal,
]
}

pub(super) fn has_pending_ticks(&self) -> bool {
for queues in &self.queues_deque {
for queue in &queues.0 {
if !queue.is_empty() {
return true;
}
}
}
false
}

pub(super) fn push_event(&mut self, event: Event) {
self.events.push(event);
}

pub(super) fn drain_events(&mut self) -> impl Iterator<Item = Event> + '_ {
self.events.drain(..)
}

pub(super) fn push_change(&mut self, node_id: NodeId) {
self.changes.push(node_id);
}

pub(super) fn drain_changes(&mut self) -> impl Iterator<Item = NodeId> + '_ {
self.changes.drain(..)
}

pub(super) fn drain_scheduled_ticks(
&mut self,
) -> impl Iterator<Item = (usize, NodeId, TickPriority)> + '_ {
self.queues_deque
.iter_mut()
.enumerate()
.flat_map(|(queue_idx, queues)| {
let delay = (queue_idx + Self::NUM_QUEUES - self.pos) % Self::NUM_QUEUES;

queues
.0
.iter_mut()
.zip(Self::priorities())
.flat_map(move |(queue, priority)| {
queue
.drain(..)
.map(move |node_id| (delay, node_id, priority))
})
})
}
}
50 changes: 50 additions & 0 deletions crates/redpiler/src/backend/direct/flush.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use mchprs_blocks::blocks::Block;
use mchprs_redstone::noteblock;
use mchprs_world::World;

use crate::{
backend::direct::{DirectBackend, Event},
block_powered_mut,
};

impl DirectBackend {
pub(crate) fn flush_events<W: World>(&mut self, world: &mut W) {
for event in self.execution_context.drain_events() {
match event {
Event::NoteBlockPlay { noteblock_id } => {
let (pos, instrument, note) = self.noteblock_info[noteblock_id as usize];
noteblock::play_note(world, pos, instrument, note);
}
}
}
}

pub(crate) fn flush_block_changes<W: World>(&mut self, world: &mut W) {
for i in self.execution_context.drain_changes() {
let node = &mut self.nodes[i];
let Some((pos, block)) = &mut self.blocks[i.index()] else {
continue;
};
if let Some(powered) = block_powered_mut(block) {
*powered = node.powered
}
if let Block::RedstoneWire { wire, .. } = block {
wire.power = node.output_power
};
if let Block::RedstoneRepeater { repeater } = block {
repeater.locked = node.locked;
}
world.set_block(*pos, *block);
node.changed = false;
}
}

pub(super) fn flush_scheduled_ticks<W: World>(&mut self, world: &mut W) {
for (delay, node_id, priority) in self.execution_context.drain_scheduled_ticks() {
let Some((pos, _)) = &self.blocks[node_id.index()] else {
continue;
};
world.schedule_tick(*pos, delay as u32, priority);
}
}
}
Loading