Skip to content

Commit b5266e7

Browse files
committed
[mtl] better sync and less allocation on the remote sink
1 parent 62d16de commit b5266e7

File tree

1 file changed

+45
-20
lines changed

1 file changed

+45
-20
lines changed

src/backend/metal/src/command.rs

+45-20
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,7 @@ impl CommandPool {
147147
dispatch_queue: match ONLINE_RECORDING {
148148
OnlineRecording::Immediate |
149149
OnlineRecording::Deferred => None,
150-
OnlineRecording::Remote(priority) => Some(
151-
dispatch::Queue::with_target_queue(
152-
"gfx-metal",
153-
dispatch::QueueAttribute::Serial,
154-
&dispatch::Queue::global(priority),
155-
)
156-
),
150+
OnlineRecording::Remote(priority) => Some(dispatch::Queue::global(priority)),
157151
}
158152
};
159153
CommandPool {
@@ -639,6 +633,13 @@ impl StageResources {
639633
}
640634

641635

636+
#[derive(Debug, Default)]
637+
struct Capacity {
638+
render: usize,
639+
compute: usize,
640+
blit: usize,
641+
}
642+
642643
//TODO: make sure to recycle the heap allocation of these commands.
643644
enum EncodePass {
644645
Render(Vec<soft::RenderCommand<soft::Own>>, metal::RenderPassDescriptor),
@@ -677,6 +678,14 @@ impl EncodePass {
677678
}
678679
});
679680
}
681+
682+
fn update(&self, capacity: &mut Capacity) {
683+
match &self {
684+
EncodePass::Render(ref list, _) => capacity.render = capacity.render.max(list.len()),
685+
EncodePass::Compute(ref list) => capacity.compute = capacity.compute.max(list.len()),
686+
EncodePass::Blit(ref list) => capacity.blit = capacity.blit.max(list.len()),
687+
}
688+
}
680689
}
681690

682691

@@ -757,6 +766,7 @@ enum CommandSink {
757766
cmd_buffer: Arc<Mutex<metal::CommandBuffer>>,
758767
token: Token,
759768
pass: Option<EncodePass>,
769+
capacity: Capacity,
760770
},
761771
}
762772

@@ -882,12 +892,14 @@ impl CommandSink {
882892
CommandSink::Remote { pass: Some(EncodePass::Blit(ref mut list)), .. } => {
883893
list.extend(commands.into_iter().map(soft::BlitCommand::own));
884894
}
885-
CommandSink::Remote { ref queue, ref cmd_buffer, ref mut pass, .. } => {
895+
CommandSink::Remote { ref queue, ref cmd_buffer, ref mut pass, ref mut capacity, .. } => {
886896
if let Some(pass) = pass.take() {
897+
pass.update(capacity);
887898
pass.schedule(queue, cmd_buffer);
888899
}
889-
let owned_commands = commands.into_iter().map(soft::BlitCommand::own).collect();
890-
*pass = Some(EncodePass::Blit(owned_commands));
900+
let mut list = Vec::with_capacity(capacity.blit);
901+
list.extend(commands.into_iter().map(soft::BlitCommand::own));
902+
*pass = Some(EncodePass::Blit(list));
891903
}
892904
}
893905
}
@@ -939,8 +951,9 @@ impl CommandSink {
939951
*is_encoding = false;
940952
journal.stop();
941953
}
942-
CommandSink::Remote { ref queue, ref cmd_buffer, ref mut pass, .. } => {
954+
CommandSink::Remote { ref queue, ref cmd_buffer, ref mut pass, ref mut capacity, .. } => {
943955
if let Some(pass) = pass.take() {
956+
pass.update(capacity);
944957
pass.schedule(queue, cmd_buffer);
945958
}
946959
}
@@ -991,14 +1004,15 @@ impl CommandSink {
9911004
}
9921005
journal.passes.push((pass, range))
9931006
}
994-
CommandSink::Remote { ref queue, ref cmd_buffer, ref mut pass, .. } => {
1007+
CommandSink::Remote { ref queue, ref cmd_buffer, ref mut pass, ref capacity, .. } => {
9951008
let desc = unsafe {
9961009
let desc: metal::RenderPassDescriptor = msg_send![descriptor, copy];
9971010
msg_send![desc.as_ptr(), retain];
9981011
desc
9991012
};
1000-
let owned_commands = init_commands.map(soft::RenderCommand::own).collect();
1001-
let new_pass = EncodePass::Render(owned_commands, desc);
1013+
let mut list = Vec::with_capacity(capacity.render);
1014+
list.extend(init_commands.map(soft::RenderCommand::own));
1015+
let new_pass = EncodePass::Render(list, desc);
10021016
match door {
10031017
PassDoor::Open => *pass = Some(new_pass),
10041018
PassDoor::Closed { .. } => new_pass.schedule(queue, cmd_buffer),
@@ -1043,9 +1057,10 @@ impl CommandSink {
10431057
};
10441058
journal.passes.push((soft::Pass::Compute, range))
10451059
}
1046-
CommandSink::Remote { ref queue, ref cmd_buffer, ref mut pass, .. } => {
1047-
let owned_commands = init_commands.map(soft::ComputeCommand::own).collect();
1048-
let new_pass = EncodePass::Compute(owned_commands);
1060+
CommandSink::Remote { ref queue, ref cmd_buffer, ref mut pass, ref capacity, .. } => {
1061+
let mut list = Vec::with_capacity(capacity.compute);
1062+
list.extend(init_commands.map(soft::ComputeCommand::own));
1063+
let new_pass = EncodePass::Compute(list);
10491064
match door {
10501065
PassDoor::Open => *pass = Some(new_pass),
10511066
PassDoor::Closed { .. } => new_pass.schedule(queue, cmd_buffer),
@@ -1065,6 +1080,7 @@ pub struct IndexBuffer<B> {
10651080
pub struct CommandBufferInner {
10661081
sink: Option<CommandSink>,
10671082
backup_journal: Option<Journal>,
1083+
backup_capacity: Option<Capacity>,
10681084
retained_buffers: Vec<metal::Buffer>,
10691085
retained_textures: Vec<metal::Texture>,
10701086
}
@@ -1090,8 +1106,11 @@ impl CommandBufferInner {
10901106
self.backup_journal = Some(journal);
10911107
}
10921108
}
1093-
Some(CommandSink::Remote { token, .. }) => {
1109+
Some(CommandSink::Remote { token, capacity, .. }) => {
10941110
shared.queue.lock().release(token);
1111+
if !release {
1112+
self.backup_capacity = Some(capacity);
1113+
}
10951114
}
10961115
None => {}
10971116
};
@@ -1525,7 +1544,7 @@ impl RawCommandQueue<Backend> for CommandQueue {
15251544
trace!("\tremote {:?}", token);
15261545
cmd_buffer.lock().enqueue();
15271546
let shared_cb = SharedCommandBuffer(Arc::clone(cmd_buffer));
1528-
queue.async(move || {
1547+
queue.sync(move || {
15291548
shared_cb.0.lock().commit();
15301549
});
15311550
}
@@ -1669,6 +1688,7 @@ impl pool::RawCommandPool<Backend> for CommandPool {
16691688
inner: Arc::new(RefCell::new(CommandBufferInner {
16701689
sink: None,
16711690
backup_journal: None,
1691+
backup_capacity: None,
16721692
retained_buffers: Vec::new(),
16731693
retained_textures: Vec::new(),
16741694
})),
@@ -1773,10 +1793,15 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
17731793
OnlineRecording::Remote(_) if oneshot => {
17741794
let (cmd_buffer, token) = self.shared.queue.lock().spawn();
17751795
CommandSink::Remote {
1776-
queue: self.pool_shared.borrow_mut().dispatch_queue.clone().unwrap(),
1796+
queue: dispatch::Queue::with_target_queue(
1797+
"gfx-metal",
1798+
dispatch::QueueAttribute::Serial,
1799+
self.pool_shared.borrow_mut().dispatch_queue.as_ref().unwrap(),
1800+
),
17771801
cmd_buffer: Arc::new(Mutex::new(cmd_buffer)),
17781802
token,
17791803
pass: None,
1804+
capacity: inner.backup_capacity.take().unwrap_or_default(),
17801805
}
17811806
}
17821807
_ => {

0 commit comments

Comments
 (0)