Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.
Sign up[metal] Re-usable command buffers #1852
Conversation
kvark
force-pushed the
kvark:mtl-cmd-reuse
branch
from
850e95d
to
d5b639b
Feb 26, 2018
kvark
changed the title
[WIP][mtl] First implementation of software command buffers
[mtl] First implementation of software command buffers
Feb 26, 2018
kvark
changed the title
[mtl] First implementation of software command buffers
[metal] Re-usable command buffers
Feb 27, 2018
mjadczak
reviewed
Feb 27, 2018
|
Nice work! I also like the gradual move to things like |
| }, | ||
| Deferred { | ||
| passes: Vec<soft::Pass>, | ||
| encoding: bool, |
This comment has been minimized.
This comment has been minimized.
mjadczak
Feb 27, 2018
Contributor
Is this supposed to indicate whether the buffer is currently being encoded? If so, maybe change to is_encoding or being_encoded, encoding suggests that there is some sort of encoding to the buffer itself
| }; | ||
| self.reset_resources(); | ||
| } | ||
|
|
||
| fn stop_ecoding(&mut self) { |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@mjadczak thanks for taking a look! Commends are addressed. Nicely spotted |
This comment has been minimized.
This comment has been minimized.
|
One of the things that really bothered me in the old Metal backend is the duplication of state-setting calls: on each state, we'd first modify the local state tracker and then check the current encoder, setting the state on it if available. But then, on starting a render/compute pass we'd go through the current state and set it (Vulkan has state inheritance, Metal does not), which used duplicate code, and it was growing pretty messy. New implementation is straightforward - we compose a list of software commands, and then there are centralized functions that apply them either at the spot or at the beginning on the next relevant pass. Same commands are stored in the re-usable command lists. So, more use cases, but even less code paths :) |
grovesNL
reviewed
Feb 27, 2018
|
Looks great! Seems much easier to read now. |
| } | ||
| Cmd::DrawIndexed { ref index, primitive_type, ref indices, base_vertex, ref instances } => { | ||
| let index_offset = indices.start as pso::BufferOffset * match index.index_type { | ||
| MTLIndexType::UInt16 => 2, |
This comment has been minimized.
This comment has been minimized.
grovesNL
Feb 27, 2018
Member
Not a regression, but I guess we should be careful about byte alignment somewhere here (indexBufferOffset must be aligned to 4 bytes)
| .cloned() | ||
| .enumerate() | ||
| .filter(|&(_, ref resource)| resource.is_some()) | ||
| .map(|(i, texture)| soft::RenderCommand::BindTexture { |
This comment has been minimized.
This comment has been minimized.
grovesNL
Feb 27, 2018
Member
Probably could do filter_map like the above for these cases (and cloning lazily), although this will change when we reuse storage anyway
This comment has been minimized.
This comment has been minimized.
kvark
Feb 27, 2018
Author
Member
I did start off filter_map and then figured that it's not as pretty as the new code, and cloning a None is cheap (for Some resources we need those cloned anyway).
| exec_render(encoder, &command); | ||
| } | ||
| } | ||
| CommandSink::Deferred { ref mut passes, is_encoding: true } => { |
This comment has been minimized.
This comment has been minimized.
grovesNL
Feb 27, 2018
Member
Is there a valid case for Deferred where is_encoding would be false? Just wondering whether this should be an assert instead.
This comment has been minimized.
This comment has been minimized.
| } | ||
|
|
||
| impl CommandSink { | ||
| fn pre_render_commands<I>(&mut self, commands: I) |
This comment has been minimized.
This comment has been minimized.
msiglreith
Feb 27, 2018
Member
Could you add an explanation here what pre-render commands are? It wasn't clear to me until seeing the calls further down. If I understand it correctly this refers to commands which may be outside of the renderpass. Also, a note about the internal state caching would be helpful here IMO, that we only execute commands if we are inside a renderpass else apply them to the internal cache.
| exec_render(encoder, &command); | ||
| } | ||
| } | ||
| CommandSink::Deferred { ref mut passes, is_encoding: true } => { |
This comment has been minimized.
This comment has been minimized.
| encoder.set_render_pipeline_state(pipeline_state); | ||
| } | ||
|
|
||
| fn begin_compute(&mut self) -> MTLSize { |
This comment has been minimized.
This comment has been minimized.
msiglreith
Feb 27, 2018
Member
A note about the return value would be helpful I think, additionally, stating when this will be called as Vulkan doesn't have compute passes so far.
kvark
added some commits
Feb 26, 2018
kvark
force-pushed the
kvark:mtl-cmd-reuse
branch
from
ac6a32f
to
734d48a
Feb 27, 2018
This comment has been minimized.
This comment has been minimized.
|
bors r=msiglreith,grovesNL |
kvark commentedFeb 26, 2018
•
edited
Fixes #1848
PR checklist:
makesucceeds (on *nix)make reftestssucceeds (on Metal, while GL has an unrelated error to be investigated)