I believe that option 1 is what is currently implemented by the task manager ? If I add a task with the same or higher sort value than the current task, it is executed in the same frame after the current task (or after all the tasks with lower sort value). However I noticed that means the new task will always be scheduler after the task that created the new one.
Let me give an example, if a surface patch comes into view, it needs a geom object, a heightmap and a couple of surface textures (albedo, specular, and so on). The engine does not check if any of those data exists or should be loaded or calculated, it just create a new task that will take care of that and when the task is done, the engine knows it can add the patch into the scene (during that time a temporary patch with lower quality data is shown)
The heightmap is either in the cache or must be calculated on the GPU; if it’s in the cache the task has nothing to wait on (the geom is generated on the fly and the textures are also in a cache), that means the task could do all its job before the end of the frame and add the new patch into the scene to be shown on the next frame.
If the heightmap is not in the cache, the engine schedule its rendering on the GPU (if a render buffer is free in the pool) and the calculated heightmap will be available on the next frame.
If I set the sort value of the patch task to a lower value that the engine task, it means it won’t be scheduled before the end of the frame, only at the start of the next frame. But that also means the engine task will be notified of the result also during the next frame.
With option 1, I set the sort value to the same of higher value than the engine task, the patch task will be scheduled later during the same frame slot, but if it has to wait for GPU generation it will be paused until next frame. In that case, the engine task will be executed first and the patch task after, which means the generation result will not be visible to the engine task until the next frame. (It is not usually a problem, except when the camera is moving relatively fast, which mean those two frames old data are no longer useful)
I think the option 2 with a patch task having a lower sort value that the engine task could do the trick, If I understand correctly. That would mean the patch task will always run after being created within the same frame slot, eventually block if some data must be generated or loaded, then, once the data is available, run before the engine task.
Though I would made that mode optional and keep the default behaviour by default, otherwise this would cause havok in app that relies on strict task scheduling
Option 3 scares me too, and thinking about it, is of no use to me. I still need the task to be executed in the right order. Though it might be useful for some people to have such kind of rule free task chain in parallel to more strict task chains.