Re: [whatwg] Counterproposal for canvas in workers

2013-10-20 Thread Rik Cabanier
On Sun, Oct 20, 2013 at 7:09 PM, Kyle Huey  wrote:

> I think most of these have been said already, but my issues with (my
> understand of?) this proposal are:
>
> 1. It requires defining a new script execution environment different from
> both the main thread and workers.  That seems like a lot of unnecessary
> work.  And this execution environment is either going to duplicate
>
much of web workers or it will lack a lot of functionality that people want.
>

Why would that be a lot of work? It would be almost identical to a worker
environment if not the same apart from some extra interfaces.


> 2. It is mostly stateless, requiring any global one time setup to happen
> per task.  But it also maintains a relatively heavy amount of state (a
> script execution environment and global object for each task on each
> canvas) which will persist for the lifetime of the canvas.  Executing a
> "drawSplashScreen" task at the beginning of a long-running game means you
> would carry that task's memory overhead for the entire game.  Developers
> won't actually want to do that so they'll either have to segregate tasks
> onto different canvases based on task lifetime or they will have to limit
> the number of tasks they use.
>

True, tasks will be carried around by the canvas that created them. I don't
understand why this would be harder than manually managing the state. Could
you not manage this per task?
(A 'detroyTask' function would cover this too)


>  3. 'synchronized' false seems pretty useless.  When would it be useful
> to execute a bunch of tasks out of order and update the screen whenever any
> of them finish?  You would have essentially no guarantees on what appears
> on screen.
>

I had the page that Ken pointed to in mind:
http://www.turbosquid.com/Search/3D-Models/Vehicle/Car
What if you're drawing a bunch of complex models to 1 canvas where you know
that each result is in a separate location? (Could also be used for sprite
sheets)


>  4. I'm not sure whether these tasks are intended to be spawned from the
> main thread or from a worker thread.  If the former, this proposal does not
> solve the "render things without waiting on the main thread at all" goal.
> If the latter, it's unclear how synchronization with main thread DOM
> updates works.
>

both.
I think I went over how the synchronization works in earlier emails.
Basically in a task, everything is queued so if you fire a task B in task
A, all the operations of task B will be inserted atomically in the right
location. (My naive polyfill doesn't do this yet but it would be easy to
implement)


> It seems like we're getting towards consensus on the other thread.  I
> would prefer to drag that proposal over the finish line since this will
> require a lot more work.
>

I don't think it does require a lot more work (although people seem to
disagree).
This is a model that covers the following:
- drawing is synchronized with the main thread (Glenn started this as a new
thread)
- you can use APIs that are resticted for workers (such as text) in a task
- you can use content while is not constructed yet
- you can draw to the same canvas from multiple threads
- no need for triple buffering
- transparent for the author (No need to create workers or figure out how
many workers is optimal. No complicated message passing. No need to change
your use of canvas apart from reading pixels which they shouldn't do for
perf anyway)

Even if my proposal doesn't go anywhere (and it certainly looks like that
:-) ); it will highlight possible issues that need to be addressed or
limitations that authors will have to work around.


Re: [whatwg] Counterproposal for canvas in workers

2013-10-20 Thread Rik Cabanier
On Sun, Oct 20, 2013 at 12:28 AM, Robert O'Callahan wrote:

> On Fri, Oct 18, 2013 at 6:50 AM, Rik Cabanier  wrote:
>
>> Extra methods on the canvas API:
>>
>> Promise setTaskScript(DOMString script); // can error be in promise?
>> Promise executeTask(DOMString id, dictionary json, boolean synchronized =
>> true); // Transferable elements allowed in dictionary
>>
>> Object that is active in the task:
>>
>> interface CanvasTask {
>>
>> HTMLCanvasElement createCanvas(unsigned long width, unsigned long height);
>> attribute Function onTask;
>>
>> }
>>
>> CanvasTask implements HTMLCanvasElement;
>>
>
> It looks like you intend CanvasTask to be the global object for the task
> script? So it's not a Worker and you don't get anything from
> WorkerGlobalScope? That's extremely limiting and also adds a lot of
> complexity by introducing a new kind of script global. You really would
> want to reuse workers here.
>

I have not really given this much thought. CanvasTask could be implemented
on top of a worker (like my naive polyfill)


> Also, making the HTMLCanvasElement API accessible from non-main threads is
> a big no-no. You can't let people do CanvasTask.document.window.whatever
> from non-main threads.
>

Yes, you can with my proposal.
The object that you get back with 'createCanvas' will be different under
the hood than the one you get in the main thread, but its *interface* will
be the same. Since all the calls can be marshalled to the main thread,
features like text and cors keep working. It should also be possible to use
images and canvaselement from the main thread since you don't have to
transfer their data.


Re: [whatwg] Counterproposal for canvas in workers

2013-10-20 Thread Kyle Huey
I think most of these have been said already, but my issues with (my
understand of?) this proposal are:

1. It requires defining a new script execution environment different from
both the main thread and workers.  That seems like a lot of unnecessary
work.  And this execution environment is either going to duplicate much of
web workers or it will lack a lot of functionality that people want.
2. It is mostly stateless, requiring any global one time setup to happen
per task.  But it also maintains a relatively heavy amount of state (a
script execution environment and global object for each task on each
canvas) which will persist for the lifetime of the canvas.  Executing a
"drawSplashScreen" task at the beginning of a long-running game means you
would carry that task's memory overhead for the entire game.  Developers
won't actually want to do that so they'll either have to segregate tasks
onto different canvases based on task lifetime or they will have to limit
the number of tasks they use.
3. 'synchronized' false seems pretty useless.  When would it be useful to
execute a bunch of tasks out of order and update the screen whenever any of
them finish?  You would have essentially no guarantees on what appears on
screen.
4. I'm not sure whether these tasks are intended to be spawned from the
main thread or from a worker thread.  If the former, this proposal does not
solve the "render things without waiting on the main thread at all" goal.
If the latter, it's unclear how synchronization with main thread DOM
updates works.

It seems like we're getting towards consensus on the other thread.  I would
prefer to drag that proposal over the finish line since this will require a
lot more work.

- Kyle


Re: [whatwg] Counterproposal for canvas in workers

2013-10-20 Thread Glenn Maynard
On Sun, Oct 20, 2013 at 2:22 AM, Robert O'Callahan wrote:

> > On Fri, Oct 18, 2013 at 3:10 PM, Glenn Maynard  wrote:
>> >>  Also, with the "transferToImageBuffer" approach, if you want to render
>> >> from a worker into multiple canvases in the UI thread, you have to post
>> >> those ImageBuffers over to the main thread each frame, which has the
>> same
>> >> (potential) synchronization issues as the transferDrawingBufferToCanvas
>> >> proposal.
>>
>
I'm confused here. You said "if you want to render from a worker into
> multiple canvases in the UI thread", which I took to mean that you wanted
> to synchronize canvas updates from workers with DOM changes made by the UI
> thread. But now you're saying you don't want to do that. So I don't know
> what you meant.
>

This has nothing to do with synchronizing to DOM updates.  The point is to
be able to render from a single WebGL context to multiple canvanses,
without having to create multiple WebGL contexts and upload a second copy
of textures, vertex programs, etc. into it, which is very expensive.  Doing
that efficiently and asynchronously is what this is trying to solve.  (The
particular problem I pointed out is specific to doing that from Workers
with canvases in the UI thread, but the goal itself is not.)

-- 
Glenn Maynard


Re: [whatwg] Counterproposal for canvas in workers

2013-10-20 Thread Robert O'Callahan
On Fri, Oct 18, 2013 at 6:50 AM, Rik Cabanier  wrote:

> Extra methods on the canvas API:
>
> Promise setTaskScript(DOMString script); // can error be in promise?
> Promise executeTask(DOMString id, dictionary json, boolean synchronized =
> true); // Transferable elements allowed in dictionary
>
> Object that is active in the task:
>
> interface CanvasTask {
>
> HTMLCanvasElement createCanvas(unsigned long width, unsigned long height);
> attribute Function onTask;
>
> }
>
> CanvasTask implements HTMLCanvasElement;
>

It looks like you intend CanvasTask to be the global object for the task
script? So it's not a Worker and you don't get anything from
WorkerGlobalScope? That's extremely limiting and also adds a lot of
complexity by introducing a new kind of script global. You really would
want to reuse workers here.

Also, making the HTMLCanvasElement API accessible from non-main threads is
a big no-no. You can't let people do CanvasTask.document.window.whatever
from non-main threads.

Rob
-- 
Jtehsauts  tshaei dS,o n" Wohfy  Mdaon  yhoaus  eanuttehrotraiitny  eovni
le atrhtohu gthot sf oirng iyvoeu rs ihnesa.r"t sS?o  Whhei csha iids  teoa
stiheer :p atroa lsyazye,d  'mYaonu,r  "sGients  uapr,e  tfaokreg iyvoeunr,
'm aotr  atnod  sgaoy ,h o'mGee.t"  uTph eann dt hwea lmka'n?  gBoutt  uIp
waanndt  wyeonut  thoo mken.o w  *
*


Re: [whatwg] Counterproposal for canvas in workers

2013-10-20 Thread Robert O'Callahan
On Fri, Oct 18, 2013 at 4:17 PM, Glenn Maynard  wrote:

> On Thu, Oct 17, 2013 at 10:25 PM, Robert O'Callahan  >wrote:
> > On Fri, Oct 18, 2013 at 3:10 PM, Glenn Maynard  wrote:
> >>  Also, with the "transferToImageBuffer" approach, if you want to render
> >> from a worker into multiple canvases in the UI thread, you have to post
> >> those ImageBuffers over to the main thread each frame, which has the
> same
> >> (potential) synchronization issues as the transferDrawingBufferToCanvas
> >> proposal.
> >
> > What are those issues? You can do a single postMessage passing a complete
> > set of ImageBItmaps.
> >
>
> See
> http://lists.w3.org/Archives/Public/public-whatwg-archive/2013Oct/0193.html
> .
> I don't know the answer to this; my feeling is that posting to the UI
> thread and scripts in the UI thread may or may not have
> (performance/smoothness) issues, but doing it all in the worker avoids any
> potential for this issue.
>

I'm confused here. You said "if you want to render from a worker into
multiple canvases in the UI thread", which I took to mean that you wanted
to synchronize canvas updates from workers with DOM changes made by the UI
thread. But now you're saying you don't want to do that. So I don't know
what you meant.

Rob
-- 
Jtehsauts  tshaei dS,o n" Wohfy  Mdaon  yhoaus  eanuttehrotraiitny  eovni
le atrhtohu gthot sf oirng iyvoeu rs ihnesa.r"t sS?o  Whhei csha iids  teoa
stiheer :p atroa lsyazye,d  'mYaonu,r  "sGients  uapr,e  tfaokreg iyvoeunr,
'm aotr  atnod  sgaoy ,h o'mGee.t"  uTph eann dt hwea lmka'n?  gBoutt  uIp
waanndt  wyeonut  thoo mken.o w  *
*


Re: [whatwg] Counterproposal for canvas in workers

2013-10-19 Thread Rik Cabanier
Hi Justin,

I will do reach out to some developers to see if they think it's useful.

As an experiment, I wrote a javascript polyfill that implements a rough
version of my proposal.
I took a box 2d example and ported it over. Since it draws to canvas under
the hood, I didn't have to change any code to make it work.
Original example: http://cabanier.github.io/CanvasWorker/test2.html
Example that uses a worker: http://cabanier.github.io/CanvasWorker/test.html
I added an js-driven animation to show how the original example is hogging
the main thread.

Unfortunately, on Firefox there's a lot of GC overhead so it's better to
use Safari or Chrome.


On Fri, Oct 18, 2013 at 11:30 AM, Justin Novosad  wrote:

>
>
>
> On Fri, Oct 18, 2013 at 12:36 PM, Rik Cabanier  wrote:
>
>> Hi Justin,
>>
>> no, everything is running synchronized and there is no added latency.
>>
>> API calls on canvas will be recorded if there are outstanding tasks.
>> So, for this API call:
>>
>> ctx.drawImage(MinionCanvas, ...)
>>
>> Since it is happening in a task, drawImage will be recorded. It will only
>> execute once the task and its subtasks (ie 
>> MinionCanvas.executeTask("drawMinion",
>> {}) ) are done.
>>
>> It sounds complicated but I think it's much easier for an author than
>> having to send bitmaps and message back and forth.
>>
>
> Ok, got it.  I think this is compelling for many use cases, but I am not
> sure whether it is as generally useful/usable as WorkerCanvas.  It would be
> great to get more web developer feedback.  In particular from graphics
> intensive game and interactive app people.
>
>
>> On Fri, Oct 18, 2013 at 6:48 AM, Justin Novosad  wrote:
>>
>>> Rik, I don't think the nested tasks in your example are a good use case.
>>>  That workflow adds a frame of latency to the sub tasks. This is a problem
>>> because the drawImage call would be drawing from a source canvas that it
>>> out of phase with the mainscene context.  To synchronize the content, I
>>> think the drawImage calls would have to be placed in a Promise resolution
>>> handler that gets invoked once all the executeTask Promises for the
>>> subtasks are resolved.  That means that the drawImage calls necessary for
>>> drawing "mainscene" would end-up executing asynchronously, therefore
>>> outside the scope of the "mainscene" task function, which is a problem.  So
>>> I don't think the executeTask proposal is well suited for sharding
>>> rendering jobs, at least not the way you illustrated it with that example.
>>>
>>>
>>>
>>> On Fri, Oct 18, 2013 at 12:50 AM, Rik Cabanier wrote:
>>>
 Extra methods on the canvas API:

 Promise setTaskScript(DOMString script); // can error be in promise?
 Promise executeTask(DOMString id, dictionary json, boolean synchronized
 = true); // Transferable elements allowed in dictionary

 Object that is active in the task:

 interface CanvasTask {

 HTMLCanvasElement createCanvas(unsigned long width, unsigned long
 height);
 attribute Function onTask;

 }

 CanvasTask implements HTMLCanvasElement;

 Example code:

 var c = document.getElementById("gameCanvas");

 var gameState = {};

 window.addEventListener("load", function(){

 c.setTaskScript("gameLogic.js").then(function(){

 c.executeTask("mainscene", gameState);

 });

 });


 window.requestAnimationFrame(function(){

 c.executeTask("mainscene", gameState);

 }


 Example code for gameLogic.js:

 var ctx = getContext("2d");

 onTask = function(DOMString id, dictionary json) {

 if(id == "mainscene") {

 if(typeof(MinionCanvas)=="Undefined") {

 MinionCanvas = createCanvas(200, 300);

  MinionCanvas.executeTask("drawMinion", {}) // creates promise under
 the hood

 }

 if(typeof(SpaceShipCanvas)=="Undefined")

 SpaceShipCanvas = createCanvas(300, 300);


 SpaceShipCanvas.executeTask("drawSpaceShip", gameState); // redraw
 spaceship


 executeTask("drawBackDrop",  gameState); // in other task

 executeTask("drawBoss", gameState); // lots of js to draw the boss so
 better done in task


 for(...) //for each minion {

  ... // set the matrix
 ctx.drawImage(MinionCanvas, ...); // draw the minion <- note that the
 minion might still be drawing in the other thread

   }
 for(...) //for each spaceship {

 ..// set the matrix

 ctx.drawImage(SpaceShipCanvas); // draw the spaceship <- it might still
 be drawing in the other task

 }

 .. // other drawing commands for score, controls, etc

 } else if(id == "drawMinion") {

 ...

 }  else if(id == "drawSpaceShip") {

 ... // set up tasks to draw parts of the ship?

 } ...

 }



 On Thu, Oct 17, 2013 at 8:10 PM, Rik

Re: [whatwg] Counterproposal for canvas in workers

2013-10-18 Thread Justin Novosad
On Fri, Oct 18, 2013 at 12:36 PM, Rik Cabanier  wrote:

> Hi Justin,
>
> no, everything is running synchronized and there is no added latency.
>
> API calls on canvas will be recorded if there are outstanding tasks.
> So, for this API call:
>
> ctx.drawImage(MinionCanvas, ...)
>
> Since it is happening in a task, drawImage will be recorded. It will only
> execute once the task and its subtasks (ie 
> MinionCanvas.executeTask("drawMinion",
> {}) ) are done.
>
> It sounds complicated but I think it's much easier for an author than
> having to send bitmaps and message back and forth.
>

Ok, got it.  I think this is compelling for many use cases, but I am not
sure whether it is as generally useful/usable as WorkerCanvas.  It would be
great to get more web developer feedback.  In particular from graphics
intensive game and interactive app people.


> On Fri, Oct 18, 2013 at 6:48 AM, Justin Novosad  wrote:
>
>> Rik, I don't think the nested tasks in your example are a good use case.
>>  That workflow adds a frame of latency to the sub tasks. This is a problem
>> because the drawImage call would be drawing from a source canvas that it
>> out of phase with the mainscene context.  To synchronize the content, I
>> think the drawImage calls would have to be placed in a Promise resolution
>> handler that gets invoked once all the executeTask Promises for the
>> subtasks are resolved.  That means that the drawImage calls necessary for
>> drawing "mainscene" would end-up executing asynchronously, therefore
>> outside the scope of the "mainscene" task function, which is a problem.  So
>> I don't think the executeTask proposal is well suited for sharding
>> rendering jobs, at least not the way you illustrated it with that example.
>>
>>
>>
>> On Fri, Oct 18, 2013 at 12:50 AM, Rik Cabanier wrote:
>>
>>> Extra methods on the canvas API:
>>>
>>> Promise setTaskScript(DOMString script); // can error be in promise?
>>> Promise executeTask(DOMString id, dictionary json, boolean synchronized
>>> = true); // Transferable elements allowed in dictionary
>>>
>>> Object that is active in the task:
>>>
>>> interface CanvasTask {
>>>
>>> HTMLCanvasElement createCanvas(unsigned long width, unsigned long
>>> height);
>>> attribute Function onTask;
>>>
>>> }
>>>
>>> CanvasTask implements HTMLCanvasElement;
>>>
>>> Example code:
>>>
>>> var c = document.getElementById("gameCanvas");
>>>
>>> var gameState = {};
>>>
>>> window.addEventListener("load", function(){
>>>
>>> c.setTaskScript("gameLogic.js").then(function(){
>>>
>>> c.executeTask("mainscene", gameState);
>>>
>>> });
>>>
>>> });
>>>
>>>
>>> window.requestAnimationFrame(function(){
>>>
>>> c.executeTask("mainscene", gameState);
>>>
>>> }
>>>
>>>
>>> Example code for gameLogic.js:
>>>
>>> var ctx = getContext("2d");
>>>
>>> onTask = function(DOMString id, dictionary json) {
>>>
>>> if(id == "mainscene") {
>>>
>>> if(typeof(MinionCanvas)=="Undefined") {
>>>
>>> MinionCanvas = createCanvas(200, 300);
>>>
>>>  MinionCanvas.executeTask("drawMinion", {}) // creates promise under
>>> the hood
>>>
>>> }
>>>
>>> if(typeof(SpaceShipCanvas)=="Undefined")
>>>
>>> SpaceShipCanvas = createCanvas(300, 300);
>>>
>>>
>>> SpaceShipCanvas.executeTask("drawSpaceShip", gameState); // redraw
>>> spaceship
>>>
>>>
>>> executeTask("drawBackDrop",  gameState); // in other task
>>>
>>> executeTask("drawBoss", gameState); // lots of js to draw the boss so
>>> better done in task
>>>
>>>
>>> for(...) //for each minion {
>>>
>>>  ... // set the matrix
>>> ctx.drawImage(MinionCanvas, ...); // draw the minion <- note that the
>>> minion might still be drawing in the other thread
>>>
>>>   }
>>> for(...) //for each spaceship {
>>>
>>> ..// set the matrix
>>>
>>> ctx.drawImage(SpaceShipCanvas); // draw the spaceship <- it might still
>>> be drawing in the other task
>>>
>>> }
>>>
>>> .. // other drawing commands for score, controls, etc
>>>
>>> } else if(id == "drawMinion") {
>>>
>>> ...
>>>
>>> }  else if(id == "drawSpaceShip") {
>>>
>>> ... // set up tasks to draw parts of the ship?
>>>
>>> } ...
>>>
>>> }
>>>
>>>
>>>
>>> On Thu, Oct 17, 2013 at 8:10 PM, Rik Cabanier wrote:
>>>



 On Thu, Oct 17, 2013 at 4:01 PM, Robert O'Callahan <
 rob...@ocallahan.org> wrote:

> On Fri, Oct 18, 2013 at 10:56 AM, Justin Novosad wrote:
>
>> On Thu, Oct 17, 2013 at 5:50 PM, Rik Cabanier wrote:
>>
>>> Creating temporary canvases is still possible. I'm unsure how it
>>> would be different from a worker.
>>> An advantage would be that you can draw to the temporary canvases in
>>> parallel to using them. Only PIXEL access is disallowed, you can still 
>>> call
>>> drawImage using a canvas that has outstanding tasks.
>>>
>>
>> Right. The write-only restriction would only apply to canvas contexts
>> that commit (push their tasks) directly down to the compositor. You could
>> still create a canvas that is local to the worker, rasterize it in the
>> 

Re: [whatwg] Counterproposal for canvas in workers

2013-10-18 Thread Rik Cabanier
Hi Justin,

no, everything is running synchronized and there is no added latency.

API calls on canvas will be recorded if there are outstanding tasks.
So, for this API call:

ctx.drawImage(MinionCanvas, ...)

Since it is happening in a task, drawImage will be recorded. It will only
execute once the task and its subtasks (ie
MinionCanvas.executeTask("drawMinion",
{}) ) are done.

It sounds complicated but I think it's much easier for an author than
having to send bitmaps and message back and forth.

On Fri, Oct 18, 2013 at 6:48 AM, Justin Novosad  wrote:

> Rik, I don't think the nested tasks in your example are a good use case.
>  That workflow adds a frame of latency to the sub tasks. This is a problem
> because the drawImage call would be drawing from a source canvas that it
> out of phase with the mainscene context.  To synchronize the content, I
> think the drawImage calls would have to be placed in a Promise resolution
> handler that gets invoked once all the executeTask Promises for the
> subtasks are resolved.  That means that the drawImage calls necessary for
> drawing "mainscene" would end-up executing asynchronously, therefore
> outside the scope of the "mainscene" task function, which is a problem.  So
> I don't think the executeTask proposal is well suited for sharding
> rendering jobs, at least not the way you illustrated it with that example.
>
>
>
> On Fri, Oct 18, 2013 at 12:50 AM, Rik Cabanier  wrote:
>
>> Extra methods on the canvas API:
>>
>> Promise setTaskScript(DOMString script); // can error be in promise?
>> Promise executeTask(DOMString id, dictionary json, boolean synchronized =
>> true); // Transferable elements allowed in dictionary
>>
>> Object that is active in the task:
>>
>> interface CanvasTask {
>>
>> HTMLCanvasElement createCanvas(unsigned long width, unsigned long height);
>> attribute Function onTask;
>>
>> }
>>
>> CanvasTask implements HTMLCanvasElement;
>>
>> Example code:
>>
>> var c = document.getElementById("gameCanvas");
>>
>> var gameState = {};
>>
>> window.addEventListener("load", function(){
>>
>> c.setTaskScript("gameLogic.js").then(function(){
>>
>> c.executeTask("mainscene", gameState);
>>
>> });
>>
>> });
>>
>>
>> window.requestAnimationFrame(function(){
>>
>> c.executeTask("mainscene", gameState);
>>
>> }
>>
>>
>> Example code for gameLogic.js:
>>
>> var ctx = getContext("2d");
>>
>> onTask = function(DOMString id, dictionary json) {
>>
>> if(id == "mainscene") {
>>
>> if(typeof(MinionCanvas)=="Undefined") {
>>
>> MinionCanvas = createCanvas(200, 300);
>>
>>  MinionCanvas.executeTask("drawMinion", {}) // creates promise under the
>> hood
>>
>> }
>>
>> if(typeof(SpaceShipCanvas)=="Undefined")
>>
>> SpaceShipCanvas = createCanvas(300, 300);
>>
>>
>> SpaceShipCanvas.executeTask("drawSpaceShip", gameState); // redraw
>> spaceship
>>
>>
>> executeTask("drawBackDrop",  gameState); // in other task
>>
>> executeTask("drawBoss", gameState); // lots of js to draw the boss so
>> better done in task
>>
>>
>> for(...) //for each minion {
>>
>>  ... // set the matrix
>> ctx.drawImage(MinionCanvas, ...); // draw the minion <- note that the
>> minion might still be drawing in the other thread
>>
>>   }
>> for(...) //for each spaceship {
>>
>> ..// set the matrix
>>
>> ctx.drawImage(SpaceShipCanvas); // draw the spaceship <- it might still
>> be drawing in the other task
>>
>> }
>>
>> .. // other drawing commands for score, controls, etc
>>
>> } else if(id == "drawMinion") {
>>
>> ...
>>
>> }  else if(id == "drawSpaceShip") {
>>
>> ... // set up tasks to draw parts of the ship?
>>
>> } ...
>>
>> }
>>
>>
>>
>> On Thu, Oct 17, 2013 at 8:10 PM, Rik Cabanier  wrote:
>>
>>>
>>>
>>>
>>> On Thu, Oct 17, 2013 at 4:01 PM, Robert O'Callahan >> > wrote:
>>>
 On Fri, Oct 18, 2013 at 10:56 AM, Justin Novosad wrote:

> On Thu, Oct 17, 2013 at 5:50 PM, Rik Cabanier wrote:
>
>> Creating temporary canvases is still possible. I'm unsure how it
>> would be different from a worker.
>> An advantage would be that you can draw to the temporary canvases in
>> parallel to using them. Only PIXEL access is disallowed, you can still 
>> call
>> drawImage using a canvas that has outstanding tasks.
>>
>
> Right. The write-only restriction would only apply to canvas contexts
> that commit (push their tasks) directly down to the compositor. You could
> still create a canvas that is local to the worker, rasterize it in the
> worker and do readbacks in the worker, create ImageBitmaps from it, etc.
>

 I'm not sure that you and Rik are talking about the same thing, since
 he's still talking about "outstanding tasks". If you are talking about the
 same thing, I don't know what it is. I'd like to see some concrete details
 for what you'd change in the current WorkerCanvas proposal. For the sake of
 clarity I've put (my understand of) it here:
 https://wiki.mozilla.org/User:Roc/WorkerCanvasProposal

>>>
>>> I

Re: [whatwg] Counterproposal for canvas in workers

2013-10-18 Thread Glenn Maynard
On Thu, Oct 17, 2013 at 10:25 PM, Robert O'Callahan wrote:

> On Fri, Oct 18, 2013 at 3:10 PM, Glenn Maynard  wrote:
>
>> "transferToImageBuffer" looks like it would create a new ImageBuffer for
>> each frame, so you'd need to add a close() method to make sure they don't
>> accumulate due to GC lag,
>>
>
> That's a good point. We will need something like that. It would only
> neuter that thread's (main thread or worker thread) version of the
> ImageBitmap.
>

But don't forget that this is a cost to authors, who now have to .close()
the object.  If they forget, or don't know they need to do that, or miss
some code paths, then there are no blatant side-effects--things are just
mysteriously slower, and probably with more of an effect in some
implementations than others (which is never good).  With attachToCanvas,
this can't happen.

 and it seems like turning this into a fast buffer swap under the hood
>> would be harder.
>>
>
> I don't see why.
>

To me it seems obviously more complicated, but I guess I'll leave that
evaluation to implementors.


>  Also, with the "transferToImageBuffer" approach, if you want to render
>> from a worker into multiple canvases in the UI thread, you have to post
>> those ImageBuffers over to the main thread each frame, which has the same
>> (potential) synchronization issues as the transferDrawingBufferToCanvas
>> proposal.
>>
>
> What are those issues? You can do a single postMessage passing a complete
> set of ImageBItmaps.
>

See
http://lists.w3.org/Archives/Public/public-whatwg-archive/2013Oct/0193.html.
I don't know the answer to this; my feeling is that posting to the UI
thread and scripts in the UI thread may or may not have
(performance/smoothness) issues, but doing it all in the worker avoids any
potential for this issue.

On Thu, Oct 17, 2013 at 10:48 PM, Rik Cabanier  wrote:

> This proposal implies an extra buffer for the 2d context. My proposal
>>> doesn't require that so it's more memory efficient + you can draw in
>>> parallel.
>>>
>>
>> You always need at least two buffers: a back-buffer for drawing and a
>> front-buffer for display (compositing).  Otherwise, as soon as you start
>> drawing the next frame, the old frame is gone, so you won't be able to
>> recomposite (on reflow, CSS filter changes, etc).  Double-buffering at a
>> minimum is pretty standard, even for native applications (with none of this
>> Web complexity in the way).
>>
>
> Won't you need another front-buffer for the worker to draw to?
>

I don't see why.  You just use double-buffering as always: the worker draws
to the backbuffer, then the drawing buffer (back-buffer) and the buffer
being displayed (front-buffer) are flipped and you start over.   I don't
think there's any difference in this between native OpenGL, today-WebGL,
and WorkerCanvas-WebGL.

(I realize I'm looking at this from a WebGL-biased perspective, which
clears the buffer between presentations unless you tell it not to.  This is
specifically to allow this sort of fast buffer flipping.  2d canvas doesn't
do that, so to allow copy-free display it'd need a flag like WebGL's
preserveDrawingBuffer = false.  This applies to any API trying to get
buffer flipping out of 2d canvas, though--something has to be added or
changed.  We don't need to address this here.)

-- 
Glenn Maynard


Re: [whatwg] Counterproposal for canvas in workers

2013-10-18 Thread Justin Novosad
Rik, I don't think the nested tasks in your example are a good use case.
 That workflow adds a frame of latency to the sub tasks. This is a problem
because the drawImage call would be drawing from a source canvas that it
out of phase with the mainscene context.  To synchronize the content, I
think the drawImage calls would have to be placed in a Promise resolution
handler that gets invoked once all the executeTask Promises for the
subtasks are resolved.  That means that the drawImage calls necessary for
drawing "mainscene" would end-up executing asynchronously, therefore
outside the scope of the "mainscene" task function, which is a problem.  So
I don't think the executeTask proposal is well suited for sharding
rendering jobs, at least not the way you illustrated it with that example.


On Fri, Oct 18, 2013 at 12:50 AM, Rik Cabanier  wrote:

> Extra methods on the canvas API:
>
> Promise setTaskScript(DOMString script); // can error be in promise?
> Promise executeTask(DOMString id, dictionary json, boolean synchronized =
> true); // Transferable elements allowed in dictionary
>
> Object that is active in the task:
>
> interface CanvasTask {
>
> HTMLCanvasElement createCanvas(unsigned long width, unsigned long height);
> attribute Function onTask;
>
> }
>
> CanvasTask implements HTMLCanvasElement;
>
> Example code:
>
> var c = document.getElementById("gameCanvas");
>
> var gameState = {};
>
> window.addEventListener("load", function(){
>
> c.setTaskScript("gameLogic.js").then(function(){
>
> c.executeTask("mainscene", gameState);
>
> });
>
> });
>
>
> window.requestAnimationFrame(function(){
>
> c.executeTask("mainscene", gameState);
>
> }
>
>
> Example code for gameLogic.js:
>
> var ctx = getContext("2d");
>
> onTask = function(DOMString id, dictionary json) {
>
> if(id == "mainscene") {
>
> if(typeof(MinionCanvas)=="Undefined") {
>
> MinionCanvas = createCanvas(200, 300);
>
>  MinionCanvas.executeTask("drawMinion", {}) // creates promise under the
> hood
>
> }
>
> if(typeof(SpaceShipCanvas)=="Undefined")
>
> SpaceShipCanvas = createCanvas(300, 300);
>
>
> SpaceShipCanvas.executeTask("drawSpaceShip", gameState); // redraw
> spaceship
>
>
> executeTask("drawBackDrop",  gameState); // in other task
>
> executeTask("drawBoss", gameState); // lots of js to draw the boss so
> better done in task
>
>
> for(...) //for each minion {
>
>  ... // set the matrix
> ctx.drawImage(MinionCanvas, ...); // draw the minion <- note that the
> minion might still be drawing in the other thread
>
>   }
> for(...) //for each spaceship {
>
> ..// set the matrix
>
> ctx.drawImage(SpaceShipCanvas); // draw the spaceship <- it might still be
> drawing in the other task
>
> }
>
> .. // other drawing commands for score, controls, etc
>
> } else if(id == "drawMinion") {
>
> ...
>
> }  else if(id == "drawSpaceShip") {
>
> ... // set up tasks to draw parts of the ship?
>
> } ...
>
> }
>
>
>
> On Thu, Oct 17, 2013 at 8:10 PM, Rik Cabanier  wrote:
>
>>
>>
>>
>> On Thu, Oct 17, 2013 at 4:01 PM, Robert O'Callahan 
>> wrote:
>>
>>> On Fri, Oct 18, 2013 at 10:56 AM, Justin Novosad wrote:
>>>
 On Thu, Oct 17, 2013 at 5:50 PM, Rik Cabanier wrote:

> Creating temporary canvases is still possible. I'm unsure how it would
> be different from a worker.
> An advantage would be that you can draw to the temporary canvases in
> parallel to using them. Only PIXEL access is disallowed, you can still 
> call
> drawImage using a canvas that has outstanding tasks.
>

 Right. The write-only restriction would only apply to canvas contexts
 that commit (push their tasks) directly down to the compositor. You could
 still create a canvas that is local to the worker, rasterize it in the
 worker and do readbacks in the worker, create ImageBitmaps from it, etc.

>>>
>>> I'm not sure that you and Rik are talking about the same thing, since
>>> he's still talking about "outstanding tasks". If you are talking about the
>>> same thing, I don't know what it is. I'd like to see some concrete details
>>> for what you'd change in the current WorkerCanvas proposal. For the sake of
>>> clarity I've put (my understand of) it here:
>>> https://wiki.mozilla.org/User:Roc/WorkerCanvasProposal
>>>
>>
>> I'll work on drawing up an example of my proposal.
>>
>> With WorkerCanvas and transferToImageBitmap, you can draw multiple layers
>>> in parallel (and actually draw, not just queue drawing commands) by
>>> creating multiple workers, having them each produce an ImageBitmap, and
>>> compositing those ImageBitmaps together by stacking  elements or
>>> drawing them all to a single canvas. It uses more memory but you get more
>>> parallelism.
>>>
>>
>> They would still have to wait for each other so the images are composited
>> in-order. If you don't care about that, the 'synchronized' option would let
>> you draw as soon as you exit the task (which is how Chrome always draws
>> since it's faster)
>>
>> In fact, an implementat

Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Rik Cabanier
Extra methods on the canvas API:

Promise setTaskScript(DOMString script); // can error be in promise?
Promise executeTask(DOMString id, dictionary json, boolean synchronized =
true); // Transferable elements allowed in dictionary

Object that is active in the task:

interface CanvasTask {

HTMLCanvasElement createCanvas(unsigned long width, unsigned long height);
attribute Function onTask;

}

CanvasTask implements HTMLCanvasElement;

Example code:

var c = document.getElementById("gameCanvas");

var gameState = {};

window.addEventListener("load", function(){

c.setTaskScript("gameLogic.js").then(function(){

c.executeTask("mainscene", gameState);

});

});


window.requestAnimationFrame(function(){

c.executeTask("mainscene", gameState);

}


Example code for gameLogic.js:

var ctx = getContext("2d");

onTask = function(DOMString id, dictionary json) {

if(id == "mainscene") {

if(typeof(MinionCanvas)=="Undefined") {

MinionCanvas = createCanvas(200, 300);

MinionCanvas.executeTask("drawMinion", {}) // creates promise under the hood

}

if(typeof(SpaceShipCanvas)=="Undefined")

SpaceShipCanvas = createCanvas(300, 300);


SpaceShipCanvas.executeTask("drawSpaceShip", gameState); // redraw spaceship


executeTask("drawBackDrop",  gameState); // in other task

executeTask("drawBoss", gameState); // lots of js to draw the boss so
better done in task


for(...) //for each minion {

... // set the matrix
ctx.drawImage(MinionCanvas, ...); // draw the minion <- note that the
minion might still be drawing in the other thread

}
for(...) //for each spaceship {

..// set the matrix

ctx.drawImage(SpaceShipCanvas); // draw the spaceship <- it might still be
drawing in the other task

}

.. // other drawing commands for score, controls, etc

} else if(id == "drawMinion") {

...

}  else if(id == "drawSpaceShip") {

... // set up tasks to draw parts of the ship?

} ...

}



On Thu, Oct 17, 2013 at 8:10 PM, Rik Cabanier  wrote:

>
>
>
> On Thu, Oct 17, 2013 at 4:01 PM, Robert O'Callahan 
> wrote:
>
>> On Fri, Oct 18, 2013 at 10:56 AM, Justin Novosad wrote:
>>
>>> On Thu, Oct 17, 2013 at 5:50 PM, Rik Cabanier wrote:
>>>
 Creating temporary canvases is still possible. I'm unsure how it would
 be different from a worker.
 An advantage would be that you can draw to the temporary canvases in
 parallel to using them. Only PIXEL access is disallowed, you can still call
 drawImage using a canvas that has outstanding tasks.

>>>
>>> Right. The write-only restriction would only apply to canvas contexts
>>> that commit (push their tasks) directly down to the compositor. You could
>>> still create a canvas that is local to the worker, rasterize it in the
>>> worker and do readbacks in the worker, create ImageBitmaps from it, etc.
>>>
>>
>> I'm not sure that you and Rik are talking about the same thing, since
>> he's still talking about "outstanding tasks". If you are talking about the
>> same thing, I don't know what it is. I'd like to see some concrete details
>> for what you'd change in the current WorkerCanvas proposal. For the sake of
>> clarity I've put (my understand of) it here:
>> https://wiki.mozilla.org/User:Roc/WorkerCanvasProposal
>>
>
> I'll work on drawing up an example of my proposal.
>
> With WorkerCanvas and transferToImageBitmap, you can draw multiple layers
>> in parallel (and actually draw, not just queue drawing commands) by
>> creating multiple workers, having them each produce an ImageBitmap, and
>> compositing those ImageBitmaps together by stacking  elements or
>> drawing them all to a single canvas. It uses more memory but you get more
>> parallelism.
>>
>
> They would still have to wait for each other so the images are composited
> in-order. If you don't care about that, the 'synchronized' option would let
> you draw as soon as you exit the task (which is how Chrome always draws
> since it's faster)
>
> In fact, an implementation could choose to take the deferred-drawing
>> approach instead. You would queue up drawing commands in the WorkerCanvas
>> (or the drawing context), and then transferToImageBitmap would not
>> immediately render but produce an ImageBitmap implementation encapsulating
>> the list of drawing commands to be drawn later, wherever/whenever that
>> ImageBitmap ended up being used. I think for commit() the implementation
>> would always want to force rasterization on the worker (or possibly some
>> dedicated canvas-rendering thread); you could forward a list of drawing
>> commands to the compositor thread for rasterization but I don't think
>> there's any reason to do that (and some good reasons not to).
>>
>
> Can you tell me how you can ensure that you don't do too much work?
> Drawing in a continuous loop using 'Commit' would waste a lot of resources.
>


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Rik Cabanier
On Thu, Oct 17, 2013 at 8:21 PM, Robert O'Callahan wrote:

> On Fri, Oct 18, 2013 at 4:10 PM, Rik Cabanier  wrote:
>
>> They would still have to wait for each other so the images are composited
>> in-order. If you don't care about that, the 'synchronized' option would
>> let
>> you draw as soon as you exit the task (which is how Chrome always draws
>> since it's faster)
>>
>
> What do you mean "wait for each other"? You only have to wait until
> they're all finished. The cost of actually compositing the images is low.
>

That is true. This would only work for regular source-over operations. If
certain compositing operations are used, they will display incorrectly.


>
>  In fact, an implementation could choose to take the deferred-drawing
>> > approach instead. You would queue up drawing commands in the
>> WorkerCanvas
>> > (or the drawing context), and then transferToImageBitmap would not
>> > immediately render but produce an ImageBitmap implementation
>> encapsulating
>> > the list of drawing commands to be drawn later, wherever/whenever that
>> > ImageBitmap ended up being used. I think for commit() the implementation
>> > would always want to force rasterization on the worker (or possibly some
>> > dedicated canvas-rendering thread); you could forward a list of drawing
>> > commands to the compositor thread for rasterization but I don't think
>> > there's any reason to do that (and some good reasons not to).
>> >
>>
>> Can you tell me how you can ensure that you don't do too much work?
>> Drawing
>> in a continuous loop using 'Commit' would waste a lot of resources.
>>
>
> How to throttle drawing of frames using "commit()" is a completely
> separate issue. Any API that allows direct publishing of frames from
> workers to the compositor will have to deal with it, in roughly the same
> way.
>

Wouldn't it be good to solve that at the same time?


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Rik Cabanier
On Thu, Oct 17, 2013 at 4:32 PM, Glenn Maynard  wrote:

> On Thu, Oct 17, 2013 at 5:14 PM, Rik Cabanier  wrote:
>
>> Compositors are often already threaded, so synchronizing a buffer flip
>>> with the compositor doesn't seem too far out there.)
>>>
>>
>> This proposal implies an extra buffer for the 2d context. My proposal
>> doesn't require that so it's more memory efficient + you can draw in
>> parallel.
>>
>
> You always need at least two buffers: a back-buffer for drawing and a
> front-buffer for display (compositing).  Otherwise, as soon as you start
> drawing the next frame, the old frame is gone, so you won't be able to
> recomposite (on reflow, CSS filter changes, etc).  Double-buffering at a
> minimum is pretty standard, even for native applications (with none of this
> Web complexity in the way).
>

Won't you need another front-buffer for the worker to draw to?


>
> I think WorkerCanvas (as well as CanvasProxy that's in the spec
> today--this isn't new to WorkerCanvas) allows full parallelism in drawing,
> both between the script and the GPU and between the worker and the main UI
> thread.
>
>
>>  I don't remember "multiple workers accessing the same canvas" and I'm
>>> not quite sure what it means.  I do remember "a single (WebGL) context
>>> rendering to multiple canvases".  Is that what you're thinking of?
>>>
>>
>> I went back over the history and that was indeed his use case.
>>
>
> That's a good use case, I've wanted to do that myself.  We haven't tried
> very hard to fit it into the WorkerCanvas approach yet, and it may also be
> that the best way to do that is orthogonal to the whole "canvas in workers"
> use case.
>
> The obvious approach is to add a new method on the context,
> "attachToCanvas(Canvas or WorkerCanvas)", which would just take the context
> and cause its output to be directed to a new Canvas (or WorkerCanvas),
> probably clearing the contents of the new canvas as a side-effect.  (This
> could be added to both CanvasRenderingContext2D and WebGLRenderingContext,
> though I suspect this is only really useful for WebGL.  There's no
> expensive resource loading with 2d canvas.)
>
> var canvas = document.querySelector(".canvas1");
> var gl = canvas.getContext("webgl");
> loadExpensiveResources(gl);
> drawStuff(gl);
> var canvas2 = document.querySelector(".canvas2");
> gl.attachToCanvas(canvas2);
> drawStuff(gl); // don't need to loadExpensiveResources again
>
> I think that's by far the most straightforward approach for users.  Maybe
> there are implementation issues that make this hard, but if so I think they
> would apply to every approach to this use case (they're really all
> different interfaces to the same functionality)...
>
> --
> Glenn Maynard
>
>


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Robert O'Callahan
On Fri, Oct 18, 2013 at 3:10 PM, Glenn Maynard  wrote:

> "transferToImageBuffer" looks like it would create a new ImageBuffer for
> each frame, so you'd need to add a close() method to make sure they don't
> accumulate due to GC lag,
>

That's a good point. We will need something like that. It would only neuter
that thread's (main thread or worker thread) version of the ImageBitmap.

and it seems like turning this into a fast buffer swap under the hood would
> be harder.
>

I don't see why.


> Also, with the "transferToImageBuffer" approach, if you want to render
> from a worker into multiple canvases in the UI thread, you have to post
> those ImageBuffers over to the main thread each frame, which has the same
> (potential) synchronization issues as the transferDrawingBufferToCanvas
> proposal.
>

What are those issues? You can do a single postMessage passing a complete
set of ImageBItmaps.

Rob
-- 
Jtehsauts  tshaei dS,o n" Wohfy  Mdaon  yhoaus  eanuttehrotraiitny  eovni
le atrhtohu gthot sf oirng iyvoeu rs ihnesa.r"t sS?o  Whhei csha iids  teoa
stiheer :p atroa lsyazye,d  'mYaonu,r  "sGients  uapr,e  tfaokreg iyvoeunr,
'm aotr  atnod  sgaoy ,h o'mGee.t"  uTph eann dt hwea lmka'n?  gBoutt  uIp
waanndt  wyeonut  thoo mken.o w  *
*


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Robert O'Callahan
On Fri, Oct 18, 2013 at 4:10 PM, Rik Cabanier  wrote:

> They would still have to wait for each other so the images are composited
> in-order. If you don't care about that, the 'synchronized' option would let
> you draw as soon as you exit the task (which is how Chrome always draws
> since it's faster)
>

What do you mean "wait for each other"? You only have to wait until they're
all finished. The cost of actually compositing the images is low.

In fact, an implementation could choose to take the deferred-drawing
> > approach instead. You would queue up drawing commands in the WorkerCanvas
> > (or the drawing context), and then transferToImageBitmap would not
> > immediately render but produce an ImageBitmap implementation
> encapsulating
> > the list of drawing commands to be drawn later, wherever/whenever that
> > ImageBitmap ended up being used. I think for commit() the implementation
> > would always want to force rasterization on the worker (or possibly some
> > dedicated canvas-rendering thread); you could forward a list of drawing
> > commands to the compositor thread for rasterization but I don't think
> > there's any reason to do that (and some good reasons not to).
> >
>
> Can you tell me how you can ensure that you don't do too much work? Drawing
> in a continuous loop using 'Commit' would waste a lot of resources.
>

How to throttle drawing of frames using "commit()" is a completely separate
issue. Any API that allows direct publishing of frames from workers to the
compositor will have to deal with it, in roughly the same way.

Rob
-- 
Jtehsauts  tshaei dS,o n" Wohfy  Mdaon  yhoaus  eanuttehrotraiitny  eovni
le atrhtohu gthot sf oirng iyvoeu rs ihnesa.r"t sS?o  Whhei csha iids  teoa
stiheer :p atroa lsyazye,d  'mYaonu,r  "sGients  uapr,e  tfaokreg iyvoeunr,
'm aotr  atnod  sgaoy ,h o'mGee.t"  uTph eann dt hwea lmka'n?  gBoutt  uIp
waanndt  wyeonut  thoo mken.o w  *
*


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Rik Cabanier
On Thu, Oct 17, 2013 at 4:01 PM, Robert O'Callahan wrote:

> On Fri, Oct 18, 2013 at 10:56 AM, Justin Novosad  wrote:
>
>> On Thu, Oct 17, 2013 at 5:50 PM, Rik Cabanier  wrote:
>>
>>> Creating temporary canvases is still possible. I'm unsure how it would
>>> be different from a worker.
>>> An advantage would be that you can draw to the temporary canvases in
>>> parallel to using them. Only PIXEL access is disallowed, you can still call
>>> drawImage using a canvas that has outstanding tasks.
>>>
>>
>> Right. The write-only restriction would only apply to canvas contexts
>> that commit (push their tasks) directly down to the compositor. You could
>> still create a canvas that is local to the worker, rasterize it in the
>> worker and do readbacks in the worker, create ImageBitmaps from it, etc.
>>
>
> I'm not sure that you and Rik are talking about the same thing, since he's
> still talking about "outstanding tasks". If you are talking about the same
> thing, I don't know what it is. I'd like to see some concrete details for
> what you'd change in the current WorkerCanvas proposal. For the sake of
> clarity I've put (my understand of) it here:
> https://wiki.mozilla.org/User:Roc/WorkerCanvasProposal
>

I'll work on drawing up an example of my proposal.

With WorkerCanvas and transferToImageBitmap, you can draw multiple layers
> in parallel (and actually draw, not just queue drawing commands) by
> creating multiple workers, having them each produce an ImageBitmap, and
> compositing those ImageBitmaps together by stacking  elements or
> drawing them all to a single canvas. It uses more memory but you get more
> parallelism.
>

They would still have to wait for each other so the images are composited
in-order. If you don't care about that, the 'synchronized' option would let
you draw as soon as you exit the task (which is how Chrome always draws
since it's faster)

In fact, an implementation could choose to take the deferred-drawing
> approach instead. You would queue up drawing commands in the WorkerCanvas
> (or the drawing context), and then transferToImageBitmap would not
> immediately render but produce an ImageBitmap implementation encapsulating
> the list of drawing commands to be drawn later, wherever/whenever that
> ImageBitmap ended up being used. I think for commit() the implementation
> would always want to force rasterization on the worker (or possibly some
> dedicated canvas-rendering thread); you could forward a list of drawing
> commands to the compositor thread for rasterization but I don't think
> there's any reason to do that (and some good reasons not to).
>

Can you tell me how you can ensure that you don't do too much work? Drawing
in a continuous loop using 'Commit' would waste a lot of resources.


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Glenn Maynard
On Thu, Oct 17, 2013 at 8:22 PM, Robert O'Callahan wrote:

> That's not really a use-case. What would you actually be trying to do?
> IIUC Ken agreed that his use-cases that appeared to require a single
> context rendering to multiple canvases would be addressed just as easily
> (or better) by using multiple image elements, a single canvas, and doing
> "image.srcObject = canvas.transferToImageBuffer()".
>

I wasn't arguing a use case, I was agreeing with a feature.  I think the
use cases for rendering to multiple DOM elements (canvases or otherwise)
using WebGL are already well-established (less so for 2d canvas).

"transferToImageBuffer" looks like it would create a new ImageBuffer for
each frame, so you'd need to add a close() method to make sure they don't
accumulate due to GC lag, and it seems like turning this into a fast buffer
swap under the hood would be harder.  If you just point the context at the
final canvas in the first place, it can render directly into that canvas's
backbuffer, so the buffer flipping mechanics are identical to when it isn't
being used at all.

Also, with the "transferToImageBuffer" approach, if you want to render from
a worker into multiple canvases in the UI thread, you have to post those
ImageBuffers over to the main thread each frame, which has the same
(potential) synchronization issues as the transferDrawingBufferToCanvas
proposal.  With attachToCanvas, it's just like WorkerCanvas: the buffer
flipping can happen entirely within the worker.

-- 
Glenn Maynard


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Robert O'Callahan
On Fri, Oct 18, 2013 at 12:32 PM, Glenn Maynard  wrote:

> On Thu, Oct 17, 2013 at 5:14 PM, Rik Cabanier  wrote:
>
> > I don't remember "multiple workers accessing the same canvas" and I'm not
> >> quite sure what it means.  I do remember "a single (WebGL) context
> >> rendering to multiple canvases".  Is that what you're thinking of?
> >>
> >
> > I went back over the history and that was indeed his use case.
> >
>
> That's a good use case, I've wanted to do that myself.  We haven't tried
> very hard to fit it into the WorkerCanvas approach yet, and it may also be
> that the best way to do that is orthogonal to the whole "canvas in workers"
> use case.
>

That's not really a use-case. What would you actually be trying to do? IIUC
Ken agreed that his use-cases that appeared to require a single context
rendering to multiple canvases would be addressed just as easily (or
better) by using multiple image elements, a single canvas, and doing
"image.srcObject = canvas.transferToImageBuffer()".

Rob
-- 
Jtehsauts  tshaei dS,o n" Wohfy  Mdaon  yhoaus  eanuttehrotraiitny  eovni
le atrhtohu gthot sf oirng iyvoeu rs ihnesa.r"t sS?o  Whhei csha iids  teoa
stiheer :p atroa lsyazye,d  'mYaonu,r  "sGients  uapr,e  tfaokreg iyvoeunr,
'm aotr  atnod  sgaoy ,h o'mGee.t"  uTph eann dt hwea lmka'n?  gBoutt  uIp
waanndt  wyeonut  thoo mken.o w  *
*


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Glenn Maynard
On Thu, Oct 17, 2013 at 5:14 PM, Rik Cabanier  wrote:

> Compositors are often already threaded, so synchronizing a buffer flip
>> with the compositor doesn't seem too far out there.)
>>
>
> This proposal implies an extra buffer for the 2d context. My proposal
> doesn't require that so it's more memory efficient + you can draw in
> parallel.
>

You always need at least two buffers: a back-buffer for drawing and a
front-buffer for display (compositing).  Otherwise, as soon as you start
drawing the next frame, the old frame is gone, so you won't be able to
recomposite (on reflow, CSS filter changes, etc).  Double-buffering at a
minimum is pretty standard, even for native applications (with none of this
Web complexity in the way).

I think WorkerCanvas (as well as CanvasProxy that's in the spec today--this
isn't new to WorkerCanvas) allows full parallelism in drawing, both between
the script and the GPU and between the worker and the main UI thread.


> I don't remember "multiple workers accessing the same canvas" and I'm not
>> quite sure what it means.  I do remember "a single (WebGL) context
>> rendering to multiple canvases".  Is that what you're thinking of?
>>
>
> I went back over the history and that was indeed his use case.
>

That's a good use case, I've wanted to do that myself.  We haven't tried
very hard to fit it into the WorkerCanvas approach yet, and it may also be
that the best way to do that is orthogonal to the whole "canvas in workers"
use case.

The obvious approach is to add a new method on the context,
"attachToCanvas(Canvas or WorkerCanvas)", which would just take the context
and cause its output to be directed to a new Canvas (or WorkerCanvas),
probably clearing the contents of the new canvas as a side-effect.  (This
could be added to both CanvasRenderingContext2D and WebGLRenderingContext,
though I suspect this is only really useful for WebGL.  There's no
expensive resource loading with 2d canvas.)

var canvas = document.querySelector(".canvas1");
var gl = canvas.getContext("webgl");
loadExpensiveResources(gl);
drawStuff(gl);
var canvas2 = document.querySelector(".canvas2");
gl.attachToCanvas(canvas2);
drawStuff(gl); // don't need to loadExpensiveResources again

I think that's by far the most straightforward approach for users.  Maybe
there are implementation issues that make this hard, but if so I think they
would apply to every approach to this use case (they're really all
different interfaces to the same functionality)...

-- 
Glenn Maynard


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Robert O'Callahan
On Fri, Oct 18, 2013 at 10:56 AM, Justin Novosad  wrote:

> On Thu, Oct 17, 2013 at 5:50 PM, Rik Cabanier  wrote:
>
>> Creating temporary canvases is still possible. I'm unsure how it would be
>> different from a worker.
>> An advantage would be that you can draw to the temporary canvases in
>> parallel to using them. Only PIXEL access is disallowed, you can still call
>> drawImage using a canvas that has outstanding tasks.
>>
>
> Right. The write-only restriction would only apply to canvas contexts that
> commit (push their tasks) directly down to the compositor. You could still
> create a canvas that is local to the worker, rasterize it in the worker and
> do readbacks in the worker, create ImageBitmaps from it, etc.
>

I'm not sure that you and Rik are talking about the same thing, since he's
still talking about "outstanding tasks". If you are talking about the same
thing, I don't know what it is. I'd like to see some concrete details for
what you'd change in the current WorkerCanvas proposal. For the sake of
clarity I've put (my understand of) it here:
https://wiki.mozilla.org/User:Roc/WorkerCanvasProposal

With WorkerCanvas and transferToImageBitmap, you can draw multiple layers
in parallel (and actually draw, not just queue drawing commands) by
creating multiple workers, having them each produce an ImageBitmap, and
compositing those ImageBitmaps together by stacking  elements or
drawing them all to a single canvas. It uses more memory but you get more
parallelism.

In fact, an implementation could choose to take the deferred-drawing
approach instead. You would queue up drawing commands in the WorkerCanvas
(or the drawing context), and then transferToImageBitmap would not
immediately render but produce an ImageBitmap implementation encapsulating
the list of drawing commands to be drawn later, wherever/whenever that
ImageBitmap ended up being used. I think for commit() the implementation
would always want to force rasterization on the worker (or possibly some
dedicated canvas-rendering thread); you could forward a list of drawing
commands to the compositor thread for rasterization but I don't think
there's any reason to do that (and some good reasons not to).

Rob
-- 
Jtehsauts  tshaei dS,o n" Wohfy  Mdaon  yhoaus  eanuttehrotraiitny  eovni
le atrhtohu gthot sf oirng iyvoeu rs ihnesa.r"t sS?o  Whhei csha iids  teoa
stiheer :p atroa lsyazye,d  'mYaonu,r  "sGients  uapr,e  tfaokreg iyvoeunr,
'm aotr  atnod  sgaoy ,h o'mGee.t"  uTph eann dt hwea lmka'n?  gBoutt  uIp
waanndt  wyeonut  thoo mken.o w  *
*


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Rik Cabanier
On Thu, Oct 17, 2013 at 3:01 PM, Glenn Maynard  wrote:

> On Thu, Oct 17, 2013 at 4:50 PM, Rik Cabanier  wrote:
>
>> It seemed like that proposal was harder. Synchronization with the main
>>
> drawing thread seemed and the continuous committing seemed difficult too.
>>
>
> Have implementors said that synchronizing the flip is (unreasonably) hard
> to implement?  (I'm not an implementor, but this proposal feels
> unimplementable to me, or at least catastrophically difficult for WebGL.
>

That could be. I'm not all that familiar with WebGL.


> Compositors are often already threaded, so synchronizing a buffer flip
> with the compositor doesn't seem too far out there.)
>

This proposal implies an extra buffer for the 2d context. My proposal
doesn't require that so it's more memory efficient + you can draw in
parallel.


>
>
>> In addition, Ken wanted multiple workers access the same canvas which I
>> didn't see addressed (unless I missed it).
>>
>
> I don't remember "multiple workers accessing the same canvas" and I'm not
> quite sure what it means.  I do remember "a single (WebGL) context
> rendering to multiple canvases".  Is that what you're thinking of?
>

I went back over the history and that was indeed his use case.


>
> On Thu, Oct 17, 2013 at 4:51 PM, Rik Cabanier  wrote:
>
>> Thanks Glenn!
>> With that info, will there ever be a way to use WebGL in different
>> workers but going to the same webgl context?
>>
>
> Sorry, which use case is this for?  I'm not sure why you'd want to do
> that, and it sounds like it would expose thread-safety issues to the
> platform.  (I'm not sure if you mean the same thing here and above--they
> sound similar, but you said "canvas" in one place and "WebGL context" in
> the other.)
>
> (Sorry if I'm forgetting things, the subject has been busy and a little
> bit noisy...)
>

Yes. Sorry to add to the noise :-)


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Glenn Maynard
On Thu, Oct 17, 2013 at 4:50 PM, Rik Cabanier  wrote:

> It seemed like that proposal was harder. Synchronization with the main
>
drawing thread seemed and the continuous committing seemed difficult too.
>

Have implementors said that synchronizing the flip is (unreasonably) hard
to implement?  (I'm not an implementor, but this proposal feels
unimplementable to me, or at least catastrophically difficult for WebGL.
 Compositors are often already threaded, so synchronizing a buffer flip
with the compositor doesn't seem too far out there.)


> In addition, Ken wanted multiple workers access the same canvas which I
> didn't see addressed (unless I missed it).
>

I don't remember "multiple workers accessing the same canvas" and I'm not
quite sure what it means.  I do remember "a single (WebGL) context
rendering to multiple canvases".  Is that what you're thinking of?

On Thu, Oct 17, 2013 at 4:51 PM, Rik Cabanier  wrote:

> Thanks Glenn!
> With that info, will there ever be a way to use WebGL in different workers
> but going to the same webgl context?
>

Sorry, which use case is this for?  I'm not sure why you'd want to do that,
and it sounds like it would expose thread-safety issues to the platform.
 (I'm not sure if you mean the same thing here and above--they sound
similar, but you said "canvas" in one place and "WebGL context" in the
other.)

(Sorry if I'm forgetting things, the subject has been busy and a little bit
noisy...)

-- 
Glenn Maynard


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Justin Novosad
On Thu, Oct 17, 2013 at 5:50 PM, Rik Cabanier  wrote:

>
>
>
> On Thu, Oct 17, 2013 at 2:28 PM, Robert O'Callahan 
> wrote:
>
>> On Fri, Oct 18, 2013 at 6:57 AM, Justin Novosad  wrote:
>>
>>> Here is similar concept, but with an API more like WokerCanvas:
>>> The CanvasRenderingContext2D associated with a WorkerCanvas would only
>>> record draw commands, without executing them. The context would be
>>> write-only. When you call commit on the WorkerCanvas, the block of
>>> recorded
>>> draw commands would be posted back to the main thread or directly to the
>>> compositor.
>>
>>
>> Which? They are observably different.
>>
>>
>>> What I like about this approach is that it is always just
>>> pushing data downstream, thus eliminating buffer synchronization issues
>>> as
>>> well as the need for double buffering canvas backing stores.
>>>
>>
>> The write-only restriction is a problem. Also, it's really important that
>> the worker be able to create temporary canvases for its own use (pdf.js for
>> example needs this), and this doesn't really support that.
>>
>
> Creating temporary canvases is still possible. I'm unsure how it would be
> different from a worker.
> An advantage would be that you can draw to the temporary canvases in
> parallel to using them. Only PIXEL access is disallowed, you can still call
> drawImage using a canvas that has outstanding tasks.
>

Right. The write-only restriction would only apply to canvas contexts that
commit (push their tasks) directly down to the compositor. You could still
create a canvas that is local to the worker, rasterize it in the worker and
do readbacks in the worker, create ImageBitmaps from it, etc.

>
>
>>
>> I think we have already converged on a WorkerCanvas design that everyone
>> (on this thread so far) is happy with, using ImageBitmaps to synchronize
>> with the main thread as needed. Is there some problem with that proposal
>> that warrants introducing the complexity of Rik's 'task' system or the
>> limitations of your proposal?
>>
>
> It seemed like that proposal was harder. Synchronization with the main
> drawing thread seemed and the continuous committing seemed difficult too.
> In addition, Ken wanted multiple workers access the same canvas which I
> didn't see addressed (unless I missed it).
>
> If the other proposal is better, we can drop this one.
>


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Rik Cabanier
Thanks Glenn!
With that info, will there ever be a way to use WebGL in different workers
but going to the same webgl context?


On Thu, Oct 17, 2013 at 2:48 PM, Glenn Maynard  wrote:

> On Wed, Oct 16, 2013 at 9:34 PM, Rik Cabanier  wrote:
>
>> When drawing to canvas, Chrome stores the drawing commands in a buffer and
>>
> executes them when the main function returns (or access to pixel data is
>> requested).
>> It occurred to me that this could be re-purposed for canvas workers. A
>> worker could create a list of drawing commands and if the worker is done,
>> this list is executed either on the main thread or the worker or a
>> compositor thread depending on what your architecture supports.
>> The worker would not be allowed to read pixels or resize the canvas but
>> all
>> other operations would be allowed.
>>
>
> This sounds like it serializes setting up the queue, and actually drawing
> the queue.  OpenGL doesn't do that: it starts sending drawing commands to
> the GPU as soon as you make them, so the CPU can be setting up rendering of
> the same scene while the GPU is rendering earlier commands.  It only needs
> to buffer if you send commands faster than the GPU can process them (the
> specific details of this are internal driver magic, but that's the gist).
>  Waiting until all rendering commands have been called before starting to
> render would be catastrophic for performance, since it would prevent
> parallelism between the CPU and GPU.
>
> On Thu, Oct 17, 2013 at 3:35 PM, Rik Cabanier  wrote:
>
> I'm unsure how this would work for WebGL since I'm not all that familiar
>>
> with its architecture. However, it seems that the end result of a webgl
>> application, is a series of commands that are sent to the graphics chip.
>> In
>> theory, this should be compatible.
>>
>
> All of that happens inside the OpenGL driver, which browsers have no
> control over.
>
> --
> Glenn Maynard
>
>


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Rik Cabanier
On Thu, Oct 17, 2013 at 2:28 PM, Robert O'Callahan wrote:

> On Fri, Oct 18, 2013 at 6:57 AM, Justin Novosad  wrote:
>
>> Here is similar concept, but with an API more like WokerCanvas:
>> The CanvasRenderingContext2D associated with a WorkerCanvas would only
>> record draw commands, without executing them. The context would be
>> write-only. When you call commit on the WorkerCanvas, the block of
>> recorded
>> draw commands would be posted back to the main thread or directly to the
>> compositor.
>
>
> Which? They are observably different.
>
>
>> What I like about this approach is that it is always just
>> pushing data downstream, thus eliminating buffer synchronization issues as
>> well as the need for double buffering canvas backing stores.
>>
>
> The write-only restriction is a problem. Also, it's really important that
> the worker be able to create temporary canvases for its own use (pdf.js for
> example needs this), and this doesn't really support that.
>

Creating temporary canvases is still possible. I'm unsure how it would be
different from a worker.
An advantage would be that you can draw to the temporary canvases in
parallel to using them. Only PIXEL access is disallowed, you can still call
drawImage using a canvas that has outstanding tasks.


>
> I think we have already converged on a WorkerCanvas design that everyone
> (on this thread so far) is happy with, using ImageBitmaps to synchronize
> with the main thread as needed. Is there some problem with that proposal
> that warrants introducing the complexity of Rik's 'task' system or the
> limitations of your proposal?
>

It seemed like that proposal was harder. Synchronization with the main
drawing thread seemed and the continuous committing seemed difficult too.
In addition, Ken wanted multiple workers access the same canvas which I
didn't see addressed (unless I missed it).

If the other proposal is better, we can drop this one.


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Glenn Maynard
On Wed, Oct 16, 2013 at 9:34 PM, Rik Cabanier  wrote:

> When drawing to canvas, Chrome stores the drawing commands in a buffer and
>
executes them when the main function returns (or access to pixel data is
> requested).
> It occurred to me that this could be re-purposed for canvas workers. A
> worker could create a list of drawing commands and if the worker is done,
> this list is executed either on the main thread or the worker or a
> compositor thread depending on what your architecture supports.
> The worker would not be allowed to read pixels or resize the canvas but all
> other operations would be allowed.
>

This sounds like it serializes setting up the queue, and actually drawing
the queue.  OpenGL doesn't do that: it starts sending drawing commands to
the GPU as soon as you make them, so the CPU can be setting up rendering of
the same scene while the GPU is rendering earlier commands.  It only needs
to buffer if you send commands faster than the GPU can process them (the
specific details of this are internal driver magic, but that's the gist).
 Waiting until all rendering commands have been called before starting to
render would be catastrophic for performance, since it would prevent
parallelism between the CPU and GPU.

On Thu, Oct 17, 2013 at 3:35 PM, Rik Cabanier  wrote:

> I'm unsure how this would work for WebGL since I'm not all that familiar
>
with its architecture. However, it seems that the end result of a webgl
> application, is a series of commands that are sent to the graphics chip. In
> theory, this should be compatible.
>

All of that happens inside the OpenGL driver, which browsers have no
control over.

-- 
Glenn Maynard


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Robert O'Callahan
On Fri, Oct 18, 2013 at 6:57 AM, Justin Novosad  wrote:

> Here is similar concept, but with an API more like WokerCanvas:
> The CanvasRenderingContext2D associated with a WorkerCanvas would only
> record draw commands, without executing them. The context would be
> write-only. When you call commit on the WorkerCanvas, the block of recorded
> draw commands would be posted back to the main thread or directly to the
> compositor.


Which? They are observably different.


> What I like about this approach is that it is always just
> pushing data downstream, thus eliminating buffer synchronization issues as
> well as the need for double buffering canvas backing stores.
>

The write-only restriction is a problem. Also, it's really important that
the worker be able to create temporary canvases for its own use (pdf.js for
example needs this), and this doesn't really support that.

I think we have already converged on a WorkerCanvas design that everyone
(on this thread so far) is happy with, using ImageBitmaps to synchronize
with the main thread as needed. Is there some problem with that proposal
that warrants introducing the complexity of Rik's 'task' system or the
limitations of your proposal?

Rob
-- 
Jtehsauts  tshaei dS,o n" Wohfy  Mdaon  yhoaus  eanuttehrotraiitny  eovni
le atrhtohu gthot sf oirng iyvoeu rs ihnesa.r"t sS?o  Whhei csha iids  teoa
stiheer :p atroa lsyazye,d  'mYaonu,r  "sGients  uapr,e  tfaokreg iyvoeunr,
'm aotr  atnod  sgaoy ,h o'mGee.t"  uTph eann dt hwea lmka'n?  gBoutt  uIp
waanndt  wyeonut  thoo mken.o w  *
*


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Kenneth Russell
On Thu, Oct 17, 2013 at 2:08 PM, Rik Cabanier  wrote:
>
>
>
> On Thu, Oct 17, 2013 at 2:03 PM, Kenneth Russell  wrote:
>>
>> On Wed, Oct 16, 2013 at 10:26 PM, Robert O'Callahan
>>  wrote:
>> > On Thu, Oct 17, 2013 at 3:34 PM, Rik Cabanier 
>> > wrote:
>> >
>> >> The tasks themselves can also launch synchronized/unsynchronized
>> >> subtasks
>> >> with promises. A task is considered "done" if it exits and all its
>> >> promises
>> >> are fulfilled.
>> >>
>> >
>> > It seems that tasks are like workers, but different, and you'd have to
>> > do a
>> > lot of extra work to precisely define the execution environment of the
>> > task
>> > script.
>> >
>> > It also seems that you have to precisely define how different tasks
>> > interact. For example is the current path left in the canvas by task 1
>> > usable by the code in task 2? You also have to define how this works in
>> > WebGL.
>> >
>> > I don't think this supports a worker/task generating a steady stream of
>> > frames, e.g. for a 3D game. Does it?
>> >
>> > I'm not all that enthusiastic :-)
>>
>> Sorry, neither am I. OpenGL (and WebGL) applications do a lot of
>> one-time setup, and then repeatedly redraw using the previously
>> uploaded objects. This "stateless" drawing model isn't compatible with
>> that structure.
>
>
> Every task per ID and per canvas has access to its own state/VM.
> So, the first time a task is executed (or we could provide an 'init' phase),
> it could do setup which will be maintained between tasks.

OK, I see. Sorry for misinterpreting.

It seems to me that this proposal would restrict even further what the
worker executing the task can do, and be harder to program to than the
existing worker model. I'm interested in pursuing the other discussion
around a WorkerCanvas rather than this one.

-Ken


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Rik Cabanier
On Thu, Oct 17, 2013 at 2:03 PM, Kenneth Russell  wrote:

> On Wed, Oct 16, 2013 at 10:26 PM, Robert O'Callahan
>  wrote:
> > On Thu, Oct 17, 2013 at 3:34 PM, Rik Cabanier 
> wrote:
> >
> >> The tasks themselves can also launch synchronized/unsynchronized
> subtasks
> >> with promises. A task is considered "done" if it exits and all its
> promises
> >> are fulfilled.
> >>
> >
> > It seems that tasks are like workers, but different, and you'd have to
> do a
> > lot of extra work to precisely define the execution environment of the
> task
> > script.
> >
> > It also seems that you have to precisely define how different tasks
> > interact. For example is the current path left in the canvas by task 1
> > usable by the code in task 2? You also have to define how this works in
> > WebGL.
> >
> > I don't think this supports a worker/task generating a steady stream of
> > frames, e.g. for a 3D game. Does it?
> >
> > I'm not all that enthusiastic :-)
>
> Sorry, neither am I. OpenGL (and WebGL) applications do a lot of
> one-time setup, and then repeatedly redraw using the previously
> uploaded objects. This "stateless" drawing model isn't compatible with
> that structure.
>

Every task per ID and per canvas has access to its own state/VM.
So, the first time a task is executed (or we could provide an 'init'
phase), it could do setup which will be maintained between tasks.


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Kenneth Russell
On Wed, Oct 16, 2013 at 10:26 PM, Robert O'Callahan
 wrote:
> On Thu, Oct 17, 2013 at 3:34 PM, Rik Cabanier  wrote:
>
>> The tasks themselves can also launch synchronized/unsynchronized subtasks
>> with promises. A task is considered "done" if it exits and all its promises
>> are fulfilled.
>>
>
> It seems that tasks are like workers, but different, and you'd have to do a
> lot of extra work to precisely define the execution environment of the task
> script.
>
> It also seems that you have to precisely define how different tasks
> interact. For example is the current path left in the canvas by task 1
> usable by the code in task 2? You also have to define how this works in
> WebGL.
>
> I don't think this supports a worker/task generating a steady stream of
> frames, e.g. for a 3D game. Does it?
>
> I'm not all that enthusiastic :-)

Sorry, neither am I. OpenGL (and WebGL) applications do a lot of
one-time setup, and then repeatedly redraw using the previously
uploaded objects. This "stateless" drawing model isn't compatible with
that structure.

-Ken


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Rik Cabanier
On Thu, Oct 17, 2013 at 10:57 AM, Justin Novosad  wrote:

> Here is similar concept, but with an API more like WokerCanvas:
> The CanvasRenderingContext2D associated with a WorkerCanvas would only
> record draw commands, without executing them. The context would be
> write-only. When you call commit on the WorkerCanvas, the block of recorded
> draw commands would be posted back to the main thread or directly to the
> compositor.  What I like about this approach is that it is always just
> pushing data downstream, thus eliminating buffer synchronization issues as
> well as the need for double buffering canvas backing stores.
>

That is basically what I'm proposing, except that the "commit" is a return
for the task.
Continually drawing in a worker seems like it would suck up a lot of power
and cpu resources...


>
>
> On Thu, Oct 17, 2013 at 1:26 AM, Robert O'Callahan 
> wrote:
>
>> On Thu, Oct 17, 2013 at 3:34 PM, Rik Cabanier  wrote:
>>
>> > The tasks themselves can also launch synchronized/unsynchronized
>> subtasks
>> > with promises. A task is considered "done" if it exits and all its
>> promises
>> > are fulfilled.
>> >
>>
>> It seems that tasks are like workers, but different, and you'd have to do
>> a
>> lot of extra work to precisely define the execution environment of the
>> task
>> script.
>>
>> It also seems that you have to precisely define how different tasks
>> interact. For example is the current path left in the canvas by task 1
>> usable by the code in task 2? You also have to define how this works in
>> WebGL.
>>
>> I don't think this supports a worker/task generating a steady stream of
>> frames, e.g. for a 3D game. Does it?
>>
>> I'm not all that enthusiastic :-)
>>
>> Rob
>> --
>> Jtehsauts  tshaei dS,o n" Wohfy  Mdaon  yhoaus  eanuttehrotraiitny  eovni
>> le atrhtohu gthot sf oirng iyvoeu rs ihnesa.r"t sS?o  Whhei csha iids
>>  teoa
>> stiheer :p atroa lsyazye,d  'mYaonu,r  "sGients  uapr,e  tfaokreg
>> iyvoeunr,
>> 'm aotr  atnod  sgaoy ,h o'mGee.t"  uTph eann dt hwea lmka'n?  gBoutt  uIp
>> waanndt  wyeonut  thoo mken.o w  *
>> *
>>
>
>


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Rik Cabanier
On Wed, Oct 16, 2013 at 10:26 PM, Robert O'Callahan wrote:

> On Thu, Oct 17, 2013 at 3:34 PM, Rik Cabanier  wrote:
>
>> The tasks themselves can also launch synchronized/unsynchronized subtasks
>> with promises. A task is considered "done" if it exits and all its
>> promises
>> are fulfilled.
>>
>
> It seems that tasks are like workers, but different, and you'd have to do
> a lot of extra work to precisely define the execution environment of the
> task script.
>

Every task would start with a 'clean' graphics state. We could define ways
to pass other canvas contexts into a task. Those other contexts could even
be drawn in other tasks (so you could use them while they are being drawn)


>
> It also seems that you have to precisely define how different tasks
> interact. For example is the current path left in the canvas by task 1
> usable by the code in task 2? You also have to define how this works in
> WebGL.
>

No. Every task acts like a unique canvas context; there's no sharing of
state.
I'm unsure how this would work for WebGL since I'm not all that familiar
with its architecture. However, it seems that the end result of a webgl
application, is a series of commands that are sent to the graphics chip. In
theory, this should be compatible.


>
> I don't think this supports a worker/task generating a steady stream of
> frames, e.g. for a 3D game. Does it?
>

It should. When the promise of a task if fulfilled, the main thread could
schedule another task. I think the scheduling should be done inside a
requestAnimationFrame for best performance.

Since there can only be 1 task with the same id active at a time, an author
could just continuously schedule tasks in requestAnimationFrame.
In that case if the tasks need to be synchronized, I think the author would
create 1 main task that generates subtasks to draw different parts of a
scene. Otherwise, there wouldn't be a "flush" to the screen since tasks
would be scheduled all the time.


>
> I'm not all that enthusiastic :-)
>

That's OK!


Re: [whatwg] Counterproposal for canvas in workers

2013-10-17 Thread Justin Novosad
Here is similar concept, but with an API more like WokerCanvas:
The CanvasRenderingContext2D associated with a WorkerCanvas would only
record draw commands, without executing them. The context would be
write-only. When you call commit on the WorkerCanvas, the block of recorded
draw commands would be posted back to the main thread or directly to the
compositor.  What I like about this approach is that it is always just
pushing data downstream, thus eliminating buffer synchronization issues as
well as the need for double buffering canvas backing stores.


On Thu, Oct 17, 2013 at 1:26 AM, Robert O'Callahan wrote:

> On Thu, Oct 17, 2013 at 3:34 PM, Rik Cabanier  wrote:
>
> > The tasks themselves can also launch synchronized/unsynchronized subtasks
> > with promises. A task is considered "done" if it exits and all its
> promises
> > are fulfilled.
> >
>
> It seems that tasks are like workers, but different, and you'd have to do a
> lot of extra work to precisely define the execution environment of the task
> script.
>
> It also seems that you have to precisely define how different tasks
> interact. For example is the current path left in the canvas by task 1
> usable by the code in task 2? You also have to define how this works in
> WebGL.
>
> I don't think this supports a worker/task generating a steady stream of
> frames, e.g. for a 3D game. Does it?
>
> I'm not all that enthusiastic :-)
>
> Rob
> --
> Jtehsauts  tshaei dS,o n" Wohfy  Mdaon  yhoaus  eanuttehrotraiitny  eovni
> le atrhtohu gthot sf oirng iyvoeu rs ihnesa.r"t sS?o  Whhei csha iids  teoa
> stiheer :p atroa lsyazye,d  'mYaonu,r  "sGients  uapr,e  tfaokreg iyvoeunr,
> 'm aotr  atnod  sgaoy ,h o'mGee.t"  uTph eann dt hwea lmka'n?  gBoutt  uIp
> waanndt  wyeonut  thoo mken.o w  *
> *
>


Re: [whatwg] Counterproposal for canvas in workers

2013-10-16 Thread Robert O'Callahan
On Thu, Oct 17, 2013 at 3:34 PM, Rik Cabanier  wrote:

> The tasks themselves can also launch synchronized/unsynchronized subtasks
> with promises. A task is considered "done" if it exits and all its promises
> are fulfilled.
>

It seems that tasks are like workers, but different, and you'd have to do a
lot of extra work to precisely define the execution environment of the task
script.

It also seems that you have to precisely define how different tasks
interact. For example is the current path left in the canvas by task 1
usable by the code in task 2? You also have to define how this works in
WebGL.

I don't think this supports a worker/task generating a steady stream of
frames, e.g. for a 3D game. Does it?

I'm not all that enthusiastic :-)

Rob
-- 
Jtehsauts  tshaei dS,o n" Wohfy  Mdaon  yhoaus  eanuttehrotraiitny  eovni
le atrhtohu gthot sf oirng iyvoeu rs ihnesa.r"t sS?o  Whhei csha iids  teoa
stiheer :p atroa lsyazye,d  'mYaonu,r  "sGients  uapr,e  tfaokreg iyvoeunr,
'm aotr  atnod  sgaoy ,h o'mGee.t"  uTph eann dt hwea lmka'n?  gBoutt  uIp
waanndt  wyeonut  thoo mken.o w  *
*


[whatwg] Counterproposal for canvas in workers

2013-10-16 Thread Rik Cabanier
All,

I have another proposal on how we can do canvas in workers. If it's not
practical or too complex, feel free to dismiss it. :-)

When drawing to canvas, Chrome stores the drawing commands in a buffer and
executes them when the main function returns (or access to pixel data is
requested).
It occurred to me that this could be re-purposed for canvas workers. A
worker could create a list of drawing commands and if the worker is done,
this list is executed either on the main thread or the worker or a
compositor thread depending on what your architecture supports.
The worker would not be allowed to read pixels or resize the canvas but all
other operations would be allowed.

The following new API's would be on the 2d context:

void setTaskScript(DOMString); // takes a url that contains the script for
the tasks

Promise executeTask(DOMString id, dictionary json, boolean synchronized =
true);

An author can execute as many tasks as he wants, but there can be only 1
task with the same id active at a time. (Calling executeTask 2 times in a
row with the same id will drop the second task.)
If synchronized is true, the UA will ensure that the drawing commands of
the task are executed in order. For instance:

var p1 = ctx.executeTask("drawBackground");

var p2 = ctx.executeTask("drawScene");
var p3 = ctx.executeTask("drawControls");

will draw a game interface using 3 different tasks


It is up to the UA to determine how many tasks it can run in parallel. It
is also up to the UA on how/where the actual drawing command are resolved,
but the commands of every task (which include the main thread) have to be
executed atomically so there's no interleaving.

Every task has access to a canvas context-like object and the dictionary
that is passed in. It can not read pixel data or resize the canvas. Every
task per canvas and per ID also has access to its own VM.

The main thread can use the canvas as usual. Accessing pixel data or
resizing will block until all tasks are completed.
If 'synchronized' is set to true:
- the canvas bitmap won't be updated until all its tasks are done
- the tasks will execute in order
If 'synchronized' is set to false:
- the canvas bitmap is updated as soon as a task is ready
- tasks can draw out of order

The tasks themselves can also launch synchronized/unsynchronized subtasks
with promises. A task is considered "done" if it exits and all its promises
are fulfilled.

Thoughts?