This is a suggestion for some refactoring we might want to do in the Metal app, to extract an explicit, object-oriented "Command Model" in the Metal app code. I'll outline some what I think we'd do, and why I think it would help.
I also started sketching this out in the Metal code here. So far this is just comments, nothing functional.
The Command Model itself would be a way to capture patterns that are emerging in the code of our mglRenderer. We have a bunch of command codes coming from Matlab, and each seems to be associated with a fairly consistent set of properties and behaviors:
each has its own command code in mglCommandTypes
each can configure an instance of itself, with any necessary params, given an mglCommandInterface to read from
each can influence flow control in the Metal app by reporting success for failure as true/false
each draw command has a particular Metal render pass descriptor that it needs to access
each draw command can add itself to a Metal render pass, given the current view and Metal command encoder
many commands have side-effects on the overall Metal app, affecting things like fullscreen vs windowed mode, stencil state, clear color, etc
many commands can write requested data back to the caller, given an mglCommandInterface to write to
some commands have a handful of little utility functions that go with them, and are not reused by other commands
some commands have state/data that they need to access, and don't necessarily share with other commands, like frame counters or pseudo-random sequences
The Command Model could be a Swift protocol, perhaps mglCommandModel, which would capture these operations as required and optional methods. We'd be able to refactor the mglRenderer to depend on this protocol, but not on the implementation details of each individual command. We'd also be able to move the implementation details of each command into a separate file.
One immediate benefit of this refactoring would be to make the code easier to read an understand. mglRenderer is currently >1000 lines and mixes concerns like flow control, socket/command interface operations, and the state and implementation details of individual commands. Extracting the commands would reduce the code in mglRenderer and clarify its responsibilities. It would also make each individual command easier to understand by grouping related, coupled behaviors into cohesive units/files.
This could also set us up to achieve future goals.
We've started introducing "repeating" commands as in #67. These may be a first step towards other, more complex commands that run "close to the metal" and don't require frame-by-frame socket communications. As these commands grow in complexity it seems likely they will need to maintain data, like texture or vertex buffers, across multiple frames, and may have state that changes between frames, like counters or behavior flags. An mglCommandModel implementation would be a natural place to store these things. Currently we don't have great place for these things, except to add on to mglRenderer.
We've talked about the possibility of making our Metal app extensible by runtime plugins. If we go this way, we'd need to define a protocol/interface against which plugins could be written, and loaded by the app. Something like mglCommandModel could fill this role.
Even if we don't go all they way to runtime plugins, it could be useful to know exactly what it takes to create a new command. A command author/contributor could focus on these things, and not have to think about other moving parts of the app, and could have some confidence that things going on within the new command are not likely to break other existing commands or parts of the app.
Currently, our informal commands "instantiate" themselves by reading from the mglCommandIngerface. We don't currently have another way to instantiate a command, which means it's hard to test the app without mglCommandIngerface and Matlab in the loop. If we had an mglCommandModel and implementations of this protocol, we could instantiate them directly from test code, and add a suite of standalone tests to the Metal app to be run directly in Xcode. This could shorten dev-testing cycles and help isolate issues.
This seems like a really good idea, but I'm going to close for now as I don't think we have to plan to implement in the near future. When we come back to this, we can reopen the issue.
This is a suggestion for some refactoring we might want to do in the Metal app, to extract an explicit, object-oriented "Command Model" in the Metal app code. I'll outline some what I think we'd do, and why I think it would help.
I also started sketching this out in the Metal code here. So far this is just comments, nothing functional.
The Command Model itself would be a way to capture patterns that are emerging in the code of our mglRenderer. We have a bunch of command codes coming from Matlab, and each seems to be associated with a fairly consistent set of properties and behaviors:
The Command Model could be a Swift protocol, perhaps mglCommandModel, which would capture these operations as required and optional methods. We'd be able to refactor the mglRenderer to depend on this protocol, but not on the implementation details of each individual command. We'd also be able to move the implementation details of each command into a separate file.
One immediate benefit of this refactoring would be to make the code easier to read an understand. mglRenderer is currently >1000 lines and mixes concerns like flow control, socket/command interface operations, and the state and implementation details of individual commands. Extracting the commands would reduce the code in mglRenderer and clarify its responsibilities. It would also make each individual command easier to understand by grouping related, coupled behaviors into cohesive units/files.
This could also set us up to achieve future goals.
We've started introducing "repeating" commands as in #67. These may be a first step towards other, more complex commands that run "close to the metal" and don't require frame-by-frame socket communications. As these commands grow in complexity it seems likely they will need to maintain data, like texture or vertex buffers, across multiple frames, and may have state that changes between frames, like counters or behavior flags. An mglCommandModel implementation would be a natural place to store these things. Currently we don't have great place for these things, except to add on to mglRenderer.
We've talked about the possibility of making our Metal app extensible by runtime plugins. If we go this way, we'd need to define a protocol/interface against which plugins could be written, and loaded by the app. Something like mglCommandModel could fill this role.
Even if we don't go all they way to runtime plugins, it could be useful to know exactly what it takes to create a new command. A command author/contributor could focus on these things, and not have to think about other moving parts of the app, and could have some confidence that things going on within the new command are not likely to break other existing commands or parts of the app.
Currently, our informal commands "instantiate" themselves by reading from the mglCommandIngerface. We don't currently have another way to instantiate a command, which means it's hard to test the app without mglCommandIngerface and Matlab in the loop. If we had an mglCommandModel and implementations of this protocol, we could instantiate them directly from test code, and add a suite of standalone tests to the Metal app to be run directly in Xcode. This could shorten dev-testing cycles and help isolate issues.