Flaws with Renderer, GLProgram and gl state management

That’s why I implemented a vertex/index data gathering stage. Users can use CustomCommands and flush the pipe without a need to rewrite the buffer because it has been written to before the actual command proccessing.

Thats true. The only problem is that they can’t be batched together in one draw call. That’s one of the main ideas of ArbitraryVertexCommand since they can be batched together in one draw call if they share the same material

You’re right, it looks a lot better. Didn’t see it before, my bad :smile:.

Sounds like a v4.0 thing too me.

Currently I’m working on an improved cocos2dx-AdvancedRenderer that supports static vertex/index data, a more cleaner batching logic and some commands for drawing non-indexed vertex data.

Cheers,
Darinex

I have a counter-proposal:

The current state of the renderer (v3.10) is kind of complex… it has too many commands:

  • QuadCommand: originally thought for 2d sprites (labels included). Batch-able
  • TrianglesCommand: an improved version of QuadCommand that supports a mesh. Batch-able… kind of supersedes QuadCommand
  • MeshCommand: thought for 3d objects. Supports any kind of mesh/primitives. Non batch-able.
  • PrimitivesCommand: Not used internally, but initially thought as an improved QuadCommand but was a bit slower, so decided not to use it. I think this is similar to your ArbitraryVertexCommand.
  • BatchCommand: For legacy code, like SpriteBatchNode… not used very much
  • CustcomCommand: for everything else.

In theory we shouldn’t need more than 3:

  • PrimitivesCommand: for 2d stuff (or single-pass 3d stuff). Batchable
  • MeshCommand: for 3d stuff (multiple-pass stuff). Non-batchable
  • CustomCommand: for everything else

But in practice we can’t remove existing commands due to backward compatibility issues.

So, my counter-proposal is:

  • Let’s use PrimitiveCommand (or improve it in case it doesn’t meet all your needs)
  • Let’s do the “transformation/conversion” in the constructor of of the Command, and not on the renderer.

eg: When you create a QuadCommand, internally it will create PrimitiveCommand… so the renderer will know nothing about QuadCommand.

I think issues 1), 2) and 3) could be fixed with that… (but I could be wrong).

Issue 4): Let’s define an API for that… where should we put it?

Issue 5): Yep… I think this is low priority since I think it doesn’t affect performance… but I could be wrong.

Issue 6): Let’s use (and promote… add documentation and more examples) RenderState

does it make sense? thanks

First of all, thanks for looking into my renderer :).

Hmm I just realised that I never really looked into PrimitivesCommand. But you’re right, they are very similar except that PrimitivesCommands are (currently) not batchable.

Good idea, here’s what I would like it to have/support.

1.) Support for drawing with both glDrawArrays and glDrawElements. Already there.
2.) The PrimitivesCommand only contains the data necessary for drawing, but doesn’t know how to draw itself. The Renderer would be responsible for the drawing then. Kinda like my ArbitraryVertexCommand.
3.) PrimitivesCommands can be batched. Again, just like my ArbitraryVertexCommand :).
4.) PrimitivesCommands would have an option to be transformed on the cpu or not.

Also I really liked the vertex gathering stage, because it allowed you to update the vbos once at the beginning of the frame.

I would also like the Renderer to have control over all vbos used for rendering, and the PrimitvesCommands would only provide the data that they should be filled with. This would have several advantages:

1.) The Renderer could batch buffer updates and submit them all at once before rendering.
2.) The Renderer could implement own backends for updating the vbos (e.g. if the GL_OES_map_buffer extension is accessible, us glMapBuffer or if you support gles3.0 in the future it would use glMapBufferRange/glFlushMappedBufferRange)
3.) The Renderer could take of the issue that I mentioned with large updates via glBufferData on android (using buffer slicing)

So yeah, I would think if PrimitivesCommand would be taken in the direction where ArbitraryVertexCommand is, that would be pretty good.

You’re right with the backward compatibility issues, although I think that if that would be introduced in v4.0, this would not be a too much of a problem.

Issue 1) could be fixed by using a vertex gathering stage and issue 2) could be fixed by having a flag transformOnCpu in PrimitivesCommand like ArbitraryVertexCommand.

A problem here would be that the glsl version on desktop openGL doesn’t mirror the openGLES one. I would use some kind of an enum, with values like GLSL_20_ES and GLSL_30_ES and so on. GLSL_20_ES would be version 100 on opengl es and version 130 (I think?) on desktop opengl. GLSL_30_ES would be version 300 on opengl es and version 330 (I think?) on desktop opengl

You’re right, this would be low priority.

This would be the way too go as it looks a lot more mature than GLStateCache. It could be used along with the new PrimitivesCommand.

So yeah, makes perfectly sense :wink:

1 Like

I’d like to clarify my previous post as it was quite a mess.

I think that the Renderer should have a vbo and ibo for dynamic data, meaning for all TrianglesCommands, QuadCommands and dynamic PrimitivesCommands. The current implementation of PrimitivesCommand is actually not so bad as it allows you to render from a custom vbo/ibo. Again, the only problem is that they aren’t batched currently.

I would add some kind of DynamicPrimitivesCommand that (like my ArbitraryVertexCommand) only contains the data and draw info so that the Renderer would copy the data to it’s internal vbo/ibo. This way, the user doesn’t have to worry about setting up a vbo/ibo and managing the buffer updating logic by himself, but instead let the Renderer take care of it. This would only apply to the DynamicPrimitivesCommand.

The Renderer would not handle all vbo/ibo as I said earlier, he would only have a dynamic vbo for dynamic rendering.

If you don’t like adding a new RenderCommand you could add a second init function to PrimitivesCommand with ArbitraryVertexCommand like input parameters, and set a flag _isDynamic to true so that the Renderer knows that he is responible for the data managing

I didn’t even addressed this one, but yeah, this is a really good idea, as it would make the batching/rendering logic a lot less complex.

So my point is in short, leave the PrimitivesCommand as it is, but add batching and dynamic rendering (just like ArbitraryVertexCommand) logic - as described above - to it.

Edit: @ricardo So you’re main concerns/requests are:

  • ArbitraryVertexCommand should not be a standalone command, but instead should be merged into PrimitivesCommand
  • The conversion from TrianglesCommand or QuadCommand to ArbitraryVertexCommand should be done in the init function of the command

Other than that my Renderer could work with cocos2dx? Did I understand that right?

Hey again,

I updated the cocos2dx-AdvancedRenderer a few day ago. It provides the capability to render non-indexed vertex data, so you don’t have to use indices when rendering a list of points :slight_smile: . I also moved the Triangles/QuadCommand converting logic to the commands constructor, as @ricardo suggested.

While browsing through the source code, I realized that cocos2dx should support newer openGL/openGLES versions as well, for better performance and more features. If I get enough time on my hands, I’m going to improve the cocos2dx-AdvancedRenderer so it supports higher gl versions, in a fashion like the guys from unity3d did (See here). The base is already there as there are classes like VertexBuffer, Framebuffer etc, which can be easily adapted. I do now that opengles 30 support is on the cocos2dx roadmap, however theres no release date, so I’m going to implement it myself :wink:

Cheers,
Darian

2 Likes

nice!
yes, we started adding abstract classes in the v4.0 branch because we wanted to support more platforms.
the thing is that we postponed v4.0… not sure when we are going to continue working on it, but it is needed.
The thing with v4.0 was (is) the backward-compatibility issue.

If you happen to find a way to add (and use) abstract classes without breaking compatibility, we will happily add it in v3.x.

Probably next week I’ll try to improve some parts of the rendered based on the feedback that you sent. thanks

For v4, in case we don’t care about backward compatibility, then I would take a more radical approach: Instead of rewriting everything from scratch ourselves, I would replace our current renderer with an existing one, like BGFX: https://github.com/bkaradzic/bgfx
But I think that is @ShunLin call.

3 Likes

@ricardo

No offence to cocos2d-x team, but because of backward compatibility a lot of features are postponed and code is getting harder and messier to maintain and expand with new features. Engine in current state has some good stuff, but there are a lot of downsides, for example if you want to do something outside engine boundaries you will get in a lot of troubles.

@milos1290 no offense taken and thanks for the feedback. yes. we are aware of that. we are just trying to do our best… we have many users who want to use 100% backward compatible features, and others who don’t care.
Basically v3.x for those who want backward compatibility, and v4 for those who don’t.

1 Like

I would love to see V4 with no backward compatibility (maybe a name change rather than Version Number change) so that it can be the best it can be.

Leave v3 for bug fixes and ‘start again’ in V4

With docco and tools before releasing beyond Beta

If we have docco for V3 V2 and V4 hanging around, it will be even more confusing and difficult for newbies (that’s why I think a name change would be good too!) How about “Ricardos”?

I wouldn’t change the name :)… I would still use the word cocos2d or cocos or cocos2d-x… perhaps “cocos2d-x turbo v4” ? :stuck_out_tongue:

1 Like

The problem with doing this is for users - especially new users.

It is a problem already, if you are looking for info on how best to do something it is too hard to google as every article doesn’t specify exactly which version it was for, and finding what has changed between versions is too hard (I still have horrors about SpriteBatchNode!)

But if there was a completely new product, then it’s simple to look for appropriate documentation and not be confused by older articles and references…

Logically, the 2d can be removed, the -x can also be removed as it would no longer need to differentiate from cocos2d. So we have cocos - but can’t use that because of the tool.

Here are my ideas:
ProCocos
CocosPro
XoXo
Multiply (think about that one!! :smile:

CocosBFG
(Cocos + BGFX + Doom = get it :D)

1 Like

I guess people would then ask things like: “Where is/what is the difference to CocosLite?” :wink:

Rated M, for mature? :smile:

I’m always for the obvious:
TEFKAC (the engine formerly known as cocos).
Fits pretty well with the almighty PEBKAC :wink:

True

Nice!

Or even

CNC (Cocos’s Not Cocos)

I like this one :stuck_out_tongue:

I’ve looked into it some time ago, and took a look at it again. I really like the cross platform shader class and some other things such as the texture handling, BUT what I think is a problem (not really a problem as it works fine, but I don’t like it :stuck_out_tongue: ), is that as an example the gl buffer classes dont use things like glMapBuffer/glUnmapBuffer or glMapBufferRange/glFlushMappedRangeBuffer for updating the buffer, which could be alot faster on devices that supports these functions. In short, my problem with it is that it is - in my opinion - not dynamic enough and I think that a cocos2dx user who wants to do some more low-level graphics stuff - like me - would not be satisfied with it.

Edit: the things that I listed above are linked to BGFX in case you’re wondering

So I would say that it would be better if you write the graphic backends by yourself. You dont’t have to “reinvent the wheel” as you said @ricardo, but reuse parts of BGFX in your implementation. That would make - in my opinion - the render engine in cocos2dx a lot more dynamic, as you can define what features/functions it supports instead of relying on a third-party implementation. Maybe I’m a little biased on this subject as I’m a typical do-it-yourself person :smile:.

So yeah, I hope I made my point clear.

PS: I’m not telling you that you have to do it, I’m just stating that an own implementation may be better.

Is there any reason BGFX couldn’t be updated to better support custom GL or GPU stuff? It feels like so much work in that project could be useful for cocos going forward? Either way I think that the shader compiler, and at minimum the ability to have the engine “progressively enhance” by using GL 3.0 and extensions when available are great things to add in the future. Maybe BGFX is too big in scope or is trying to be too much for too many people, but getting Metal support for free would improve GPU perf (and possibly battery) on a lot on iOS devices, right?

1 Like

I looked at the whole thread again and realised that I was overthinking the whole thing and began to take it personal. That’s my bad, and I apologize for it.

Ricardo is right, instead of having to write and patch an own render engine you should use a third-party one. This way you don’t have to worry about patching stuff and implementing new renderer backends. As for the issues that I mentioned about BGFX above, they could be easily patched in a fork or something like this.

You’re absolutely right, metal support for free would be a big plus.

As I understood from reading the source code, BGFX is kind of a low-level renderer which just takes commands and executes them depending on what rendering backend BGFX is running on, but doesn’t handle batching and stuff like that. Does that means that the cocos2dx Renderer with the render queue design and the render commands is going away, or that the render queue and the renderer are going to stay but issue the graphics stuff through the BGFX renderer?

Not to backtrack away from moving toward BGFX, but thanks for your work, regardless of the future, especially if we can use the advance renderer and combined batch-able custom render command setup in 3.x.

1 Like