{"action":"created","issue":{"url":"https://api.github.com/repos/Aeva/m.grl/issues/232","repository_url":"https://api.github.com/repos/Aeva/m.grl","labels_url":"https://api.github.com/repos/Aeva/m.grl/issues/232/labels{/name}","comments_url":"https://api.github.com/repos/Aeva/m.grl/issues/232/comments","events_url":"https://api.github.com/repos/Aeva/m.grl/issues/232/events","html_url":"https://github.com/Aeva/m.grl/issues/232","id":156176337,"number":232,"title":"rendering infrastructure overhaul","user":{"login":"Aeva","id":768449,"avatar_url":"https://avatars.githubusercontent.com/u/768449?v=3","gravatar_id":"","url":"https://api.github.com/users/Aeva","html_url":"https://github.com/Aeva","followers_url":"https://api.github.com/users/Aeva/followers","following_url":"https://api.github.com/users/Aeva/following{/other_user}","gists_url":"https://api.github.com/users/Aeva/gists{/gist_id}","starred_url":"https://api.github.com/users/Aeva/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Aeva/subscriptions","organizations_url":"https://api.github.com/users/Aeva/orgs","repos_url":"https://api.github.com/users/Aeva/repos","events_url":"https://api.github.com/users/Aeva/events{/privacy}","received_events_url":"https://api.github.com/users/Aeva/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/Aeva/m.grl/labels/compositing%20graph","name":"compositing graph","color":"cccccc"},{"url":"https://api.github.com/repos/Aeva/m.grl/labels/enhancement","name":"enhancement","color":"84b6eb"},{"url":"https://api.github.com/repos/Aeva/m.grl/labels/optimization","name":"optimization","color":"baff00"},{"url":"https://api.github.com/repos/Aeva/m.grl/labels/refactoring%20/%20cleanup","name":"refactoring / cleanup","color":"f7c6c7"},{"url":"https://api.github.com/repos/Aeva/m.grl/labels/scene%20graph","name":"scene graph","color":"666666"},{"url":"https://api.github.com/repos/Aeva/m.grl/labels/WebGL","name":"WebGL","color":"ba268f"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/Aeva/m.grl/milestones/1","html_url":"https://github.com/Aeva/m.grl/milestones/Milestone%20One","labels_url":"https://api.github.com/repos/Aeva/m.grl/milestones/1/labels","id":829516,"number":1,"title":"Milestone One","description":"This milestone is complete when the jta model format's file format is stable, and there are enough core features to make this project useful for other people.\r\n\r\nThe estimated completion date is a floating target.","creator":{"login":"Aeva","id":768449,"avatar_url":"https://avatars.githubusercontent.com/u/768449?v=3","gravatar_id":"","url":"https://api.github.com/users/Aeva","html_url":"https://github.com/Aeva","followers_url":"https://api.github.com/users/Aeva/followers","following_url":"https://api.github.com/users/Aeva/following{/other_user}","gists_url":"https://api.github.com/users/Aeva/gists{/gist_id}","starred_url":"https://api.github.com/users/Aeva/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Aeva/subscriptions","organizations_url":"https://api.github.com/users/Aeva/orgs","repos_url":"https://api.github.com/users/Aeva/repos","events_url":"https://api.github.com/users/Aeva/events{/privacy}","received_events_url":"https://api.github.com/users/Aeva/received_events","type":"User","site_admin":false},"open_issues":23,"closed_issues":116,"state":"open","created_at":"2014-10-16T21:22:56Z","updated_at":"2016-05-22T22:12:56Z","due_on":null,"closed_at":null},"comments":3,"created_at":"2016-05-22T22:12:56Z","updated_at":"2016-06-05T22:06:22Z","closed_at":null,"body":"## abstract\r\nM.GRL performs very poorly when a modest number of dynamic objects are in play at once.  But, this is a fixable problem, and I have a much better idea as to what kind of rendering architecture is needed to support this now than I did when I started down the rabbit hole of \"adding WebGL\" a few years ago.\r\n\r\nThe following tickets contain relevant exploratory research on how to resolve the shortcomings of the engine: #189 (consolidated VBOs), #193 (related stress test), #195 (using instancing extension instead), #197 (glsl compiler support for instancing abstraction).\r\n\r\nThe most striking part of pursuing the instancing extension was one of my \"control group\" tests: just flattening out the rendering graph to draw as many of one object as possible.  No extensions, no VBO foolery, just no branching what-so-ever.  The results were good enough (though it seems I didn't feel the need to document them anywhere obvious) that it became evident that I needed to employ code generation for any execution pathway that is time sensitive.  The rendering bottleneck is entirely CPU bound, so that should be made to run as fast as possible, and that means removing unnecessary work at draw time.\r\n\r\nCombined with the alternative API proposed in #230, it should be also possible to create static elements in a scene without creating graph nodes for them, which was the show stopping bottleneck for the instancing demo in terms of startup time as well as extreme memory consumption.\r\n\r\n## the new rendering pipeline\r\nThe way the new rendering pipeline should work is this.\r\n\r\n1. \"Scene graph\" root object is created.  Draw function is an empty stub function.  A simple object called \"cache\" will serve as a mechanism for named access for dynamic memory.\r\n2. graph.attach(\"asset.jta\", etc) is called - if the object is dynamic, a GraphNode is created for it and returned.  Either way, an IR is created for the draw path of this specific object.  If the object is dynamic, cache lines may be reserved on the graph root for the IR to read from.\r\n3. the attach call causes the graph to be marked dirty.  A sort function is called on the IR for all of the associated objects to determine the shortest rendering path.  A new draw function is generated by stepping through the now sorted IR and generating lines of source code for the function constructor.  Redundant calls are removed automatically.\r\n\r\nFor dynamic objects, their IR will at first be generated like static objects with whatever defaults are provided through the attach interface.  If a property changes, the IR will be marked dirty and the property will switch to reading the value from a cache line instead (even if it is a static value).  The assumption here is that if a property is a static value, if it ever changes after the object is instanced, then it is likely the property will change semi-frequently and therefor we will not want to dump the draw function every time.\r\n\r\n## related areas for improvement\r\nThese should probably be forked out into other issues, but are worth mentioning here for now:\r\n\r\nShader program context switching can be made a ton faster by assuming that an asset attach is created with a specific shader in mind, and only has those bindings.  This would allow us to remove a ton of extra work when the shader program needs to be regenerated.  The whole connecting uniforms and enabling / disabling of attributes could also be sped up via code generation\r\n\r\nIt is possible that the compositing graph could also be similarly improved, since its behavior is pretty static once established.\r\n\r\n## fuzzy bits\r\n - [ ] how and where does object picking fit into this? #192 covers some concerns as to what should change in the picking system.  Code generation should also be used here.\r\n\r\n - [ ] how do particle systems work in this new scheme?\r\n\r\n## the IR\r\nThis part is open ended at the moment.  The 'IR' as said elsewhere in this ticket will probably be a list of objects, of which the objects themselves each represent a single statement (I theorize almost entirely GL calls, but there might be other things needed).  The constructor is probably the method name and a list of args - not unlike ```please.format_invocation``` in m.defs - but the args could also be function calls?\r\n\r\nAn IR object should be persistent after a GraphObject is instanced, and also mutable.  It could feature a 'compile' method, which would assign cache lines to unassigned dynamic variables.  The compile method would take a cache object, and output a statement.\r\n\r\n## development plan\r\nThis is going to be a long running task, and will be made easiest if I can break it down into small parts.  Development will happen in the branch ```fast_graph```.  A loose outline of where to start follows:\r\n - [x] remove static draw node functionality entirely\r\n - [x] create the IR object (see section above), add tests\r\n - [x] remove \"manual cache invalidation\" mechanism from GraphNodes\r\n - [x] update m.gl.buffers to generate source for bind and draw functions, mark old paths as deprecated.\r\n - [x] scheme for generating IR for JTA GraphNode instances (use cache lines, no static vars)\r\n - [x] event hook for flagging ir dirty when writing to a driver property\r\n - [x] automatic regeneration of static draw function, \"static first\" strategy for graph nodes IR\r\n - [x] generate combined IR on the graph root\r\n - [x] generate draw function from combined IR\r\n - [ ] testing, profiling\r\n - [ ] fix broken demos\r\n - [ ] backport picking (see #192)\r\n - [ ] backport particles\r\n - [ ] more testing\r\n\r\nAfter that, the following assorted tasks might be approached:\r\n - [ ] scheme for generating IR for image GraphNode instances\r\n - [ ] scheme for generating IR for gani GraphNode instances\r\n\r\nIf the performance is good and the API is still backwards compatible, then this can be merged into master at this point.  **picking should also be accounted for before merging**. Following that:\r\n - [ ] attach API? (see #230)\r\n - [ ] graphless IR generation for static non-animated JTA attaches\r\n - [ ] graphless IR generation for static image attaches\r\n - [ ] throw an error for static attaches of animated assets (some JTA, gani)\r\n - [ ] revise dynamic attaches to use static IR first and use cache lines on subsequent IRs\r\n\r\nWith the graph overhaul done, the following would be the next ideal place to work on:\r\n - [ ] revise GraphNode creation APIs to require the desired shader for bindings to be generated\r\n - [ ] remove rebind event\r\n - [ ] generated code for shader context switches\r\n\r\nFollowing all of the above, the following can be worked on, likely in their own issue tickets:\r\n - [ ] improving performance of rendering static assets in some cases via the instancing extension\r\n - [ ] improving performance of the compositing graph with code generation"},"comment":{"url":"https://api.github.com/repos/Aeva/m.grl/issues/comments/223840745","html_url":"https://github.com/Aeva/m.grl/issues/232#issuecomment-223840745","issue_url":"https://api.github.com/repos/Aeva/m.grl/issues/232","id":223840745,"user":{"login":"Aeva","id":768449,"avatar_url":"https://avatars.githubusercontent.com/u/768449?v=3","gravatar_id":"","url":"https://api.github.com/users/Aeva","html_url":"https://github.com/Aeva","followers_url":"https://api.github.com/users/Aeva/followers","following_url":"https://api.github.com/users/Aeva/following{/other_user}","gists_url":"https://api.github.com/users/Aeva/gists{/gist_id}","starred_url":"https://api.github.com/users/Aeva/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Aeva/subscriptions","organizations_url":"https://api.github.com/users/Aeva/orgs","repos_url":"https://api.github.com/users/Aeva/repos","events_url":"https://api.github.com/users/Aeva/events{/privacy}","received_events_url":"https://api.github.com/users/Aeva/received_events","type":"User","site_admin":false},"created_at":"2016-06-05T22:06:22Z","updated_at":"2016-06-05T22:06:22Z","body":" - [ ] use the dirty signals to trigger more IR objects to be added to the __static_draw path (?)\r\n - [ ] fix regression where properties that should end up static aren't (see 'mode' in demo 6)\r\n - [ ] update unit tests for codegen"}}
{"actor":{"display_login":"Aeva"}}