Open ghost opened 9 years ago
That's interesting idea. I already had plan to add command baking, which would allow you to once set draw state and then recall it over multiple frames with single call. Your idea is similar.
Would be great for the Go bindings as well. +1
Looked into this a bit more, and there is no simple way of exposing raw commands to you. I do some validation and packing internally. Technically I can let you do all that, but it will break every time I want to change any internals.
The best way to do it, is language binding, record stream of invoked commands, and then flush it at some point:
Pseudo code:
func SetTexture(<args>) {
stream.write(ESetTexture, <args...>);
}
func Frame() {
flush(stream);
}
Then on C++ side implement flush interpreter:
void flush(stream)
{
while (true)
{
cmd = stream.read();
switch (cmd)
{
case ESetTexture:
bgfx::setTexture(<args...>);
break;
...
}
}
}
Is this something you were thinking about?
I've considered that in the past, but then you've got an extra layer of buffering, so you're having to make a trade off. But, it is probably the right trade off in the case of non-zero cost bindings with no alternative.
With regard to language bindings, one big area of overhead with JNI and other language binding systems is that each call to native code is much more expensive than than a regular call. For a few calls it's not a big deal, but when you get into thousands+ of calls, the overhead can become significant.
It would be great if we could implement our own command builder in the binding language. It would generate an entire command buffer for a frame (or close) which would be passed over in one native call with something like: bgfx::frame(&mycmdbuf)
This way we can eliminate virtually all of the command generation call overhead for language bindings.
I intend to look into implementing this but just wanted to get feedback on the idea, thanks!