Skip to content

Commit 7ee40d4

Browse files
committed
[mtl] minimize creation of render passes
1 parent 4306768 commit 7ee40d4

File tree

3 files changed

+99
-56
lines changed

3 files changed

+99
-56
lines changed

src/backend/metal/src/command.rs

+94-54
Original file line numberDiff line numberDiff line change
@@ -774,7 +774,11 @@ impl CommandSink {
774774
CommandSink::Deferred { ref mut passes, ref mut is_encoding } => {
775775
*is_encoding = keep_open;
776776
passes.push(soft::Pass::Render {
777-
desc: descriptor.to_owned(),
777+
//Note: the original descriptor belongs to the framebuffer,
778+
// and will me mutated afterwards.
779+
desc: unsafe {
780+
msg_send![descriptor, copy]
781+
},
778782
commands: init_commands.map(soft::RenderCommand::own).collect(),
779783
});
780784
}
@@ -1606,6 +1610,7 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
16061610

16071611
for subresource_range in subresource_ranges {
16081612
let sub = subresource_range.borrow();
1613+
let descriptor = metal::RenderPassDescriptor::new();
16091614

16101615
let num_layers = (sub.layers.end - sub.layers.start) as u64;
16111616
let layers = if CLEAR_IMAGE_ARRAY {
@@ -1633,9 +1638,54 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
16331638
&*image.raw
16341639
};
16351640

1641+
let clear_color_attachment = sub.aspects.contains(Aspects::COLOR);
1642+
if image.format_desc.aspects.contains(Aspects::COLOR) {
1643+
let attachment = descriptor
1644+
.color_attachments()
1645+
.object_at(0)
1646+
.unwrap();
1647+
attachment.set_texture(Some(texture));
1648+
attachment.set_store_action(metal::MTLStoreAction::Store);
1649+
if clear_color_attachment {
1650+
attachment.set_load_action(metal::MTLLoadAction::Clear);
1651+
attachment.set_clear_color(clear_color.clone());
1652+
} else {
1653+
attachment.set_load_action(metal::MTLLoadAction::Load);
1654+
}
1655+
}
1656+
1657+
let clear_depth_attachment = sub.aspects.contains(Aspects::DEPTH);
1658+
if image.format_desc.aspects.contains(Aspects::DEPTH) {
1659+
let attachment = descriptor
1660+
.depth_attachment()
1661+
.unwrap();
1662+
attachment.set_texture(Some(texture));
1663+
attachment.set_store_action(metal::MTLStoreAction::Store);
1664+
if clear_depth_attachment {
1665+
attachment.set_load_action(metal::MTLLoadAction::Clear);
1666+
attachment.set_clear_depth(depth_stencil.depth as _);
1667+
} else {
1668+
attachment.set_load_action(metal::MTLLoadAction::Load);
1669+
}
1670+
}
1671+
1672+
let clear_stencil_attachment = sub.aspects.contains(Aspects::STENCIL);
1673+
if image.format_desc.aspects.contains(Aspects::STENCIL) {
1674+
let attachment = descriptor
1675+
.stencil_attachment()
1676+
.unwrap();
1677+
attachment.set_texture(Some(texture));
1678+
attachment.set_store_action(metal::MTLStoreAction::Store);
1679+
if clear_stencil_attachment {
1680+
attachment.set_load_action(metal::MTLLoadAction::Clear);
1681+
attachment.set_clear_stencil(depth_stencil.stencil);
1682+
} else {
1683+
attachment.set_load_action(metal::MTLLoadAction::Load);
1684+
}
1685+
}
1686+
16361687
for layer in layers {
16371688
for level in sub.levels.clone() {
1638-
let descriptor = metal::RenderPassDescriptor::new();
16391689
if image.extent.depth > 1 {
16401690
assert_eq!(sub.layers.end, 1);
16411691
let depth = image.extent.at_level(level).depth as u64;
@@ -1644,62 +1694,33 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
16441694
descriptor.set_render_target_array_length(num_layers);
16451695
};
16461696

1647-
let clear_color_attachment = sub.aspects.contains(Aspects::COLOR);
1648-
if clear_color_attachment || image.format_desc.aspects.contains(Aspects::COLOR) {
1697+
if clear_color_attachment {
16491698
let attachment = descriptor
16501699
.color_attachments()
16511700
.object_at(0)
16521701
.unwrap();
1653-
attachment.set_texture(Some(texture));
16541702
attachment.set_level(level as _);
1655-
attachment.set_store_action(metal::MTLStoreAction::Store);
16561703
if !CLEAR_IMAGE_ARRAY {
16571704
attachment.set_slice(layer as _);
16581705
}
1659-
if clear_color_attachment {
1660-
attachment.set_load_action(metal::MTLLoadAction::Clear);
1661-
attachment.set_clear_color(clear_color.clone());
1662-
} else {
1663-
attachment.set_load_action(metal::MTLLoadAction::Load);
1664-
}
16651706
}
1666-
1667-
let clear_depth_attachment = sub.aspects.contains(Aspects::DEPTH);
1668-
if clear_depth_attachment || image.format_desc.aspects.contains(Aspects::DEPTH) {
1707+
if clear_depth_attachment {
16691708
let attachment = descriptor
16701709
.depth_attachment()
16711710
.unwrap();
1672-
attachment.set_texture(Some(texture));
16731711
attachment.set_level(level as _);
1674-
attachment.set_store_action(metal::MTLStoreAction::Store);
16751712
if !CLEAR_IMAGE_ARRAY {
16761713
attachment.set_slice(layer as _);
16771714
}
1678-
if clear_depth_attachment {
1679-
attachment.set_load_action(metal::MTLLoadAction::Clear);
1680-
attachment.set_clear_depth(depth_stencil.depth as _);
1681-
} else {
1682-
attachment.set_load_action(metal::MTLLoadAction::Load);
1683-
}
16841715
}
1685-
1686-
let clear_stencil_attachment = sub.aspects.contains(Aspects::STENCIL);
1687-
if clear_stencil_attachment || image.format_desc.aspects.contains(Aspects::STENCIL) {
1716+
if clear_stencil_attachment {
16881717
let attachment = descriptor
16891718
.stencil_attachment()
16901719
.unwrap();
1691-
attachment.set_texture(Some(texture));
16921720
attachment.set_level(level as _);
1693-
attachment.set_store_action(metal::MTLStoreAction::Store);
16941721
if !CLEAR_IMAGE_ARRAY {
16951722
attachment.set_slice(layer as _);
16961723
}
1697-
if clear_stencil_attachment {
1698-
attachment.set_load_action(metal::MTLLoadAction::Clear);
1699-
attachment.set_clear_stencil(depth_stencil.stencil);
1700-
} else {
1701-
attachment.set_load_action(metal::MTLLoadAction::Load);
1702-
}
17031724
}
17041725

17051726
sink.as_mut()
@@ -2019,6 +2040,27 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
20192040
}
20202041
}
20212042

2043+
let descriptor = metal::RenderPassDescriptor::new();
2044+
if src.format_desc.aspects.contains(Aspects::COLOR) {
2045+
descriptor
2046+
.color_attachments()
2047+
.object_at(0)
2048+
.unwrap()
2049+
.set_texture(Some(&dst.raw));
2050+
}
2051+
if src.format_desc.aspects.contains(Aspects::DEPTH) {
2052+
descriptor
2053+
.depth_attachment()
2054+
.unwrap()
2055+
.set_texture(Some(&dst.raw));
2056+
}
2057+
if src.format_desc.aspects.contains(Aspects::STENCIL) {
2058+
descriptor
2059+
.stencil_attachment()
2060+
.unwrap()
2061+
.set_texture(Some(&dst.raw));
2062+
}
2063+
20222064
let mut inner = self.inner.borrow_mut();
20232065
// Note: we don't bother to restore any render states here, since we are currently
20242066
// outside of a render pass, and the state will be reset automatically once
@@ -2062,7 +2104,7 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
20622104
};
20632105

20642106
for ((aspects, level), list) in vertices.drain() {
2065-
let ext = &dst.extent;
2107+
let ext = dst.extent.at_level(level);
20662108

20672109
let extra = [
20682110
//Note: flipping Y coordinate of the destination here
@@ -2097,29 +2139,25 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
20972139
},
20982140
];
20992141

2100-
let descriptor = metal::RenderPassDescriptor::new();
21012142
descriptor.set_render_target_array_length(ext.depth as _);
21022143
if aspects.contains(Aspects::COLOR) {
2103-
let attachment = descriptor
2144+
descriptor
21042145
.color_attachments()
21052146
.object_at(0)
2106-
.unwrap();
2107-
attachment.set_texture(Some(&dst.raw));
2108-
attachment.set_level(level as _);
2147+
.unwrap()
2148+
.set_level(level as _);
21092149
}
21102150
if aspects.contains(Aspects::DEPTH) {
2111-
let attachment = descriptor
2151+
descriptor
21122152
.depth_attachment()
2113-
.unwrap();
2114-
attachment.set_texture(Some(&dst.raw));
2115-
attachment.set_level(level as _);
2153+
.unwrap()
2154+
.set_level(level as _);
21162155
}
21172156
if aspects.contains(Aspects::STENCIL) {
2118-
let attachment = descriptor
2157+
descriptor
21192158
.stencil_attachment()
2120-
.unwrap();
2121-
attachment.set_texture(Some(&dst.raw));
2122-
attachment.set_level(level as _);
2159+
.unwrap()
2160+
.set_level(level as _);
21232161
}
21242162

21252163
let commands = prelude
@@ -2128,7 +2166,7 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
21282166
.chain(&extra)
21292167
.cloned();
21302168

2131-
inner.sink().begin_render_pass(false, descriptor, commands);
2169+
inner.sink().begin_render_pass(false, &descriptor, commands);
21322170
}
21332171
}
21342172

@@ -2292,11 +2330,13 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
22922330
T: IntoIterator,
22932331
T::Item: Borrow<com::ClearValueRaw>,
22942332
{
2295-
let _ap = AutoreleasePool::new();
22962333
// FIXME: subpasses
2297-
let descriptor: metal::RenderPassDescriptor = unsafe {
2298-
msg_send![framebuffer.descriptor, copy]
2299-
};
2334+
let _ap = AutoreleasePool::new();
2335+
2336+
// we are going to modify the RP descriptor here, so
2337+
// locking to avoid data races.
2338+
let descriptor = framebuffer.descriptor.lock().unwrap();
2339+
23002340
let mut num_colors = 0;
23012341
let mut full_aspects = Aspects::empty();
23022342
let mut inner = self.inner.borrow_mut();
@@ -2355,7 +2395,7 @@ impl com::RawCommandBuffer<Backend> for CommandBuffer {
23552395
let init_commands = self.state.make_render_commands(full_aspects);
23562396
inner
23572397
.sink()
2358-
.begin_render_pass(true, &descriptor, init_commands);
2398+
.begin_render_pass(true, &*descriptor, init_commands);
23592399
}
23602400

23612401
fn next_subpass(&mut self, _contents: com::SubpassContents) {

src/backend/metal/src/device.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1168,7 +1168,10 @@ impl hal::Device<Backend> for Device {
11681168
}
11691169
}
11701170

1171-
Ok(n::Framebuffer { descriptor, inner })
1171+
Ok(n::Framebuffer {
1172+
descriptor: Mutex::new(descriptor),
1173+
inner,
1174+
})
11721175
}
11731176

11741177
fn create_shader_module(&self, raw_data: &[u8]) -> Result<n::ShaderModule, ShaderError> {

src/backend/metal/src/native.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub struct FramebufferInner {
5656

5757
#[derive(Debug)]
5858
pub struct Framebuffer {
59-
pub(crate) descriptor: metal::RenderPassDescriptor,
59+
pub(crate) descriptor: Mutex<metal::RenderPassDescriptor>,
6060
pub(crate) inner: FramebufferInner,
6161
}
6262

0 commit comments

Comments
 (0)