Tuesday, 11 February 2014

Direction and UI design

Since I didn't posted for quite a bit in my blog, I thought maybe it's time for another post, since I've been pretty busy on many fronts.

First thing, I'm (finally) almost done with this China project, and this was a right pain (for a pretty nice result have to admit). There was a one last bug and I hope the last update will finally tick if off. The result of this update will certainly bring another blog post, but since I don't know yet I'll shut up in the mean time ;)

On other parts, I'm working a lot on reworking my demo tool user interface. I don't want to rewrite from scratch, since I believe it's a bad idea in many cases, but want to shift a bit and try something new.

Main thing, is, at the end of the day, people use a software, so the ui design/functionalities comes as a first. As system programmers, we often will write a kick ass runtime, but forget the utter basics of useability (a basic usability  function might come very late in the pipeline because we found this new super fast code generation technique and focused there instead of any ui part).

This is of course even more apparent when you work with small teams (I mean, under 20 people). In my case and my tool I'm one developer, which also have to do projects for a living, so I can't even dedicate 10% of my full time on this.

So instead, I started to think of it in reverse, eg: this is what I need for my tool:
  • Patch interface
  • Code editor
  • Dock panel (since I want to organize my layout)
  • Node lister
  • Informative elements (logger/project explorer/compilation error report...)
So now the concept is to build the main User Interface without any runtime in there.

By then you might argue that building a shell without any features is at best useless, and by trying it now, I would disagree:
  • By using a ui without being distracted by any fancy looking visual you create, you start to really focus on ui. For example, you will immediately notice you'd like a dock, better undo function, that your ui is not smooth (no reference to 4v here ;) .
  • Since I know how to implement decently good graphics (still need to improve on that area for sure as well ;), The way I implement a particle system (as example) does not matter at this stage. And actually by thinking of this particle system I will see how the user interface can support the feature. Already having this particle system hinders that fact.
  • You WILL modify your user interface to correlate with your runtime (and modify you runtime too, softwares are constantly modified as a fact), but at least by working on UI first, you'll make sure that a rather decent amount of usability features are present and you software is not a bulk of unusable functions.
  • People want to use a software, so working on mockup also allows me to show a proper designer/ui specialist the concepts, and get insights (and programmers should never have the last word on ui design, another fact). What is convenient is what the user finds convenient, not your opinion as a programmer. Having well designed mockups also allows me to send a template find to a friend which will help building a nice menu order, shortcut list. While I delegate that, I suddenly have much more available time to build the core runtime.
So now when you build UI, you're overbloated with APIs, and it's hard to make a choice.

Since I don't plan to port my tool to whatever Android/Mac... (and anyway, as above, if you don't have a team of  20+ programmers or open source your program, don't even remotely think about multiplatform), I have the following choices (which can of course being mixed up, but single API streamlines things a tad).

  • Windows forms: The old good one, integrates super easily with Direct3D, simple to learn, can be extreme clunky and an absolute pain to do theming. Code editors/Dockers already available, good graph component for now I rolled my own (in D2D)
  • Direct2d : Great for building graph and other custom widgets,very good text/strokes rendering, quite fast in general, but complex layouts with d2d on it's own will be for sure cumbersome (not speaking of building a code editor with syntax coloring and other nitfy features).
  • Wpf: Most balanced of all, text can be blurry at times still, but good at shapes, code editor+docker also available, Direct3d integration reasonably easy, but such an overdesigned api that it's really daunting (for writing 2 crappy forms it's more or less ok, but decent builders become much more cumbersome). Theming is not too hard but also badly streamlined. 
  • Direct3d : Same as Direct2d, but you have to do all yourself ;) You could really start to build proper gpu UI, and start to rethink data structures but it's a hell of work. If you'd need intermediate texture integration in your canvas, that will rock performances compared to anything else tho.
So here we go for now, some more info soon ))







Sunday, 12 January 2014

On plugin architecture

I was looking a bit a decoupling my code in a better way, for the moment Dx11 nodes follow the current way:

  • Implement IPluginEvaluate
  • Implement either ResourceProvider or ResourceContextProvider
Then when you Implement ResourceProvider you use : SetDevice(RenderDevice device)

In some way this forces you to register a SetDevice method (so you don't forget to grab device), but this is not ideal in many points.

One thing I don't like with this, you have too much cooking and so much work is wasted on initialization order. Let's take a very basic example:

Code Snippet
  1. [PluginInfo(Name = "CopyCounter", Category = "DX11.Buffer", Version = "", Author = "vux")]
  2. public class CopyCounterNode : IPluginEvaluate,IDxDeviceListener, IDxResourceContextProvider
  3. {
  4.     [Input("Buffer In", DefaultValue = 1,IsSingle=true)]
  5.     protected Pin<DX11Resource<DX11StructuredBuffer>> FInBuffer;
  6.  
  7.     [Output("Buffer Out",IsSingle=true)]
  8.     protected ISpread<DX11Resource<DX11RawBuffer>> FOutBuffer;
  9.  
  10.     private RenderDevice device;
  11.  
  12.     public void SetDevice(RenderDevice device)
  13.     {
  14.         this.device = device;
  15.         this.FOutBuffer[0] = new DX11Resource<DX11RawBuffer>();
  16.     }
  17. }

Please note that I omitted the update/evaluate for clarity.

So what happens is First object constructor is called (here a default constrcutor since none is specified),
then Buffer In and Buffer Out are injected into the node, to finish, once node is ready, SetDevice is called to the node.

Now if I add a constructor, we here have the same:

Code Snippet
  1. [PluginInfo(Name = "CopyCounter", Category = "DX11.Buffer", Version = "", Author = "vux")]
  2. public class CopyCounterNode : IPluginEvaluate,IDxDeviceListener, IDxResourceContextProvider
  3. {
  4.     [Input("Buffer In", DefaultValue = 1,IsSingle=true)]
  5.     protected Pin<DX11Resource<DX11StructuredBuffer>> FInBuffer;
  6.  
  7.     [Output("Buffer Out",IsSingle=true)]
  8.     protected ISpread<DX11Resource<DX11RawBuffer>> FOutBuffer;
  9.  
  10.     private RenderDevice device;
  11.     private IPluginHost host;
  12.  
  13.     [ImportingConstructor()]
  14.     public CopyCounterNode(IPluginHost host)
  15.     {
  16.         this.host = host;
  17.     }
  18.  
  19.     public void SetDevice(RenderDevice device)
  20.     {
  21.         this.device = device;
  22.         this.FOutBuffer[0] = new DX11Resource<DX11RawBuffer>();
  23.     }
  24. }

Please note that first here there's 2 things which are pretty bad:

  • I need to use ImportingConstructor otherwise MEF ignores injection (and plugin creation will fail). This is just really bad. That means I need to add an attribute on every single class of my model. Which, by propagating, would mean I'd need to use MEF even in my standalone library! Even worse, you also need to use attribute in every subclass, since they are not propagated.
  • Using attributes for input/output sounds a good idea, saves some time, but that's reasonably true for simple nodes, where you use inheritance, that creates issue. If I mark my pins as private, I get compiler warning (rightly so), you can use pragma to disable, but then you need to do that on all nodes, really intrusive as well.
Now one cool thing, I can export my DX11 Services, and have them injected, so instead I can do :

Code Snippet
  1. [PluginInfo(Name = "CopyCounter", Category = "DX11.Buffer", Version = "", Author = "vux")]
  2. public class CopyCounterNode : IPluginEvaluate, IDxResourceContextProvider
  3. {
  4.     [Input("Buffer In", DefaultValue = 1,IsSingle=true)]
  5.     protected Pin<DX11Resource<DX11StructuredBuffer>> FInBuffer;
  6.  
  7.     [Output("Buffer Out",IsSingle=true)]
  8.     protected ISpread<DX11Resource<DX11RawBuffer>> FOutBuffer;
  9.  
  10.     private RenderDevice device;
  11.     private IPluginHost host;
  12.  
  13.     [ImportingConstructor()]
  14.     public CopyCounterNode(RenderDevice device, IPluginHost host)
  15.     {
  16.         this.host = host;
  17.         this.device = device;
  18.         this.FOutBuffer[0] = new DX11Resource<DX11RawBuffer>();
  19.     }
  20. }

But this will of course miserably fail.
The simple reason is that FOutBuffer is injected after the constructor. You can't get a proper working object.

2 Solutions for this:

  • Implement IPartImportsSatisfiedNotification , and move the buffer initialization into this. Hurray,one more interface, one more remote method to implement, more intrusion.
  • Create pins by hand in constructor, via IIOFactory. Example below:

Code Snippet
  1.   [PluginInfo(Name = "CopyCounter", Category = "DX11.Buffer", Version = "", Author = "vux")]
  2.   public class CopyCounterNode : IPluginEvaluate, IDxResourceContextProvider, IPartImportsSatisfiedNotification
  3.   {
  4.       private Pin<DX11Resource<DX11StructuredBuffer>> FInBuffer;
  5.       private ISpread<DX11Resource<DX11RawBuffer>> FOutBuffer;
  6.  
  7.       private RenderDevice device;
  8.       [ImportingConstructor()]
  9.       public CopyCounterNode(RenderDevice device, IIOFactory iofactory)
  10.       {
  11.           this.device = device;
  12.           this.FInBuffer = iofactory.CreateResourceInputPin<DX11StructuredBuffer>("Buffer In",true);
  13.           this.FOutBuffer = iofactory.CreateResourceOutputPin<DX11RawBuffer>("Buffer Out",true);
  14.           this.FOutBuffer[0] = new DX11Resource<DX11RawBuffer>();
  15.       }
  16.   }

This feels a little bit more verbose, but now you have something correct (eg : when your object is instanciated it is ready to use, no more dodgy ordering. Initialization is in one place, and you can easily add some extensions methods/static methods to IOFactory to reduce overhead.

Another great advantage, you can create some nicer extensions like :

Code Snippet
  1. public static Pin<DX11Resource<DX11Layer>> CreateDX11LayerOut(
  2.     this IIOFactory iofactory,
  3.     RenderDevice device,
  4.     RenderDelegate<IPluginIO, RenderSettings> rendermethod,
  5.     string name = "Layer Out",
  6.     bool subscribe = true)
  7. {
  8.     var attr = new OutputAttribute(name) { IsSingle = true };
  9.     var pin = iofactory.CreateResourceOutputPin<DX11Layer>(name, subscribe);
  10.     pin[0] = new DX11Resource<DX11Layer>();
  11.     pin[0][device] = new DX11Layer();
  12.     pin[0][device].Render = rendermethod;
  13.     return pin;
  14. }

Now if you call CreateDX11LayerOut, you even took care of the naming by providing a default, which is much easier to mess up with attributes (random typo, no idea of naming...)

Last issue then, this ImportingConstructor is annoying, specially it needs to be everywhere.

So I tried to check If I could get rid of MEF (partly), and build a small plugin interface with a far better container, eg : Autofac

One thing I like is all initialization code is centralized (and not scattered randomly like in MEF so you don't know what exported/imported anymore).

Building container is rather simple:

Code Snippet
  1. ContainerBuilder cb = new ContainerBuilder();
  2. cb.RegisterInstance<IHDEHost>(hdehost).ExternallyOwned();
  3. cb.RegisterInstance<INodeInfoFactory>(ni).ExternallyOwned();
  4. cb.RegisterInstance<IORegistry>(ioreg).ExternallyOwned().As<IIORegistry>();
  5. cb.RegisterInstance<ILogger>(logger).ExternallyOwned();
  6. cb.RegisterInstance(this.RenderDevice).As<DxDevice,RenderDevice>().ExternallyOwned();
  7.  
  8. this.container = cb.Build();

Please note that I didn't added all services here, but you also have a lot of nitfy features, and using AutoFac I can now technically even use composition on my core runtime, which was not possible with MEF (except adding attributes everywhere).

More fun, I can import all vvvv services in one go using their Integration library.

Now to register a plugin:

Code Snippet
  1. container = parent.BeginLifetimeScope
  2. (
  3.     (cb) =>
  4.     {
  5.         cb.Register(c => pluginHost).As<IPluginHost, IPluginHost2, INode>().As<IInternalPluginHost>().ExternallyOwned();
  6.         cb.RegisterType<AutoFacIOFactory>().As<AutoFacIOFactory, IIOFactory>().InstancePerLifetimeScope();
  7.         cb.RegisterType(pluginType).As<IPluginEvaluate>().InstancePerLifetimeScope();
  8.     }
  9. );
  10.  
  11. this.iofactory = container.Resolve<AutoFacIOFactory>();
  12. this.PluginBase = container.Resolve<IPluginEvaluate>();
  13. autoevaluate = nodeInfo.AutoEvaluate;
  14. iofactory.OnCreated(EventArgs.Empty);

Also really simple, and can be even more simplified, but I wanted to do a quick try.

Best of all now, I have proper inheritance support, keeping what I want private/protected and so on:

Code Snippet
  1. [PluginInfo(Name = "CopyCounter", Category = "DX11.Buffer", Version = "", Author = "vux")]
  2. public class CopyCounterNode : IPluginEvaluate, IDxResourceContextProvider
  3. {
  4.     private Pin<DX11Resource<DX11StructuredBuffer>> FInBuffer;
  5.     private ISpread<DX11Resource<DX11RawBuffer>> FOutBuffer;
  6.  
  7.     protected RenderDevice Device { get; private set; }
  8.  
  9.     public CopyCounterNode(RenderDevice device, IIOFactory iofactory)
  10.     {
  11.         this.Device = device;
  12.         this.FInBuffer = iofactory.CreateResourceInputPin<DX11StructuredBuffer>("Buffer In",true);
  13.         this.FOutBuffer = iofactory.CreateResourceOutputPin<DX11RawBuffer>("Buffer Out",true);
  14.         this.FOutBuffer[0] = new DX11Resource<DX11RawBuffer>();
  15.     }
  16. }
  17.  
  18. [PluginInfo(Name = "CopyCounter2", Category = "DX11.Buffer", Version = "", Author = "vux")]
  19. public class CopyCounterNode2 : CopyCounterNode
  20. {
  21.     private ISpread<DX11Resource<DX11RawBuffer>> FOutBuffer2;
  22.  
  23.     public CopyCounterNode2(RenderDevice device, IIOFactory iofactory) : base(device,iofactory)
  24.     {
  25.         this.FOutBuffer2 = iofactory.CreateResourceOutputPin<DX11RawBuffer>("Buffer Out",true);
  26.         this.FOutBuffer2[0] = new DX11Resource<DX11RawBuffer>();
  27.     }
  28. }

No more references to MEF, inheritance is streamlined. Also now you can see that device can't be written by then child class, and no more compiler warning.

Technically class is now perfectly isolated, and node don't know about autofac or using a container. The IOC manages it for you, you can replace it by another one if you want, or make you own barebone version.

Now you also have proper initialization at the place it should be : the constructor.

And as usual one very funny thing, this is MUCH less code than the .NET factory for the same features ;)

Saturday, 11 January 2014

Happy new year, News, and thoughts

First Happy new year!

2013 was pretty great (first DX11 release, Node13, lots of interesting projects, birth of a new tool ;)

Hope 2014 will follow, and to be honest, it's starting quite in many interesting ways.

First thing I'm reasonably happy on adoption for DirectX11, still some parts are missing, but most times people going into it don't go back (which is a good sign).

There's still some nodes missing, but well I'm kinda more or less on my own writing it (thanks to the few people who contributed nodes), on top of various projects, so it's a lot of time (gladly I use it for projects, so at least I can add some bug fixes/Few more nodes, but nodes are generally so specific they not really much point pushing to core).

If a few wannabe c# programmers decide to pop in and help add some of the missing nodes (Text Geometry/XFile writer/Player...), please feel free to ping me, I'll happily help with basics of coding a Dx11 node (it's much easier than writing a DX9 one believe me ;)

Also of course thanks to people who started to post dx11 contributions, I believe that helps adoption, and at least I can spend more efforts on the runtime instead.

On the same way I'd love few people to write help patches and more examples, it also takes time, I rather enjoy to explain routines, but same thing = time.

So now 2014 started on a quite fast paced mode (I spent bit of time between xmas and new year too), let's see what's going on:

  • Port to core runtime to SharpDX is pretty much complete, nicer, faster, simpler. That means support to latest versions, and support up to Win7 is there.
  • Texture was bit of an issue, but thanks to directxtex.codeplex.com , few exports and P/Invoke, now have a portable Texture reader/writer, with tga support on the way, and BC7 encoder, if you survive the "very" slow export, in order to enjoy the very fast import ;)
  • Most of old nodes are also done (i'd say 80% of the nodes are ported)
  • Many type of nodes are now templated (using T4 templates), so most geometry/layer and others, are just reflected and node is generated from that, makes refactoring a hell of a lot easier).
  • Shader nodes have been reasonably revamped.
  • Lot of new interesting/experimental features on the way too ;)
  • Many high level nodes, so non shader experts can start to use their gpu in a reasonable way :)
Now of course there's still work to do, Pin system (once greg will have sorted the convolution issue), will also get some revamp, Resource management is getting along more improvements, and still some more questions about some other bits (see below).

Please note that most work as been done to make API simpler. API now uses less code, is faster, and I find using it is also less code. Writing a node with new API is really simple, there's much less cooking around.

First session of rolling out (pre alpha early bird to not use for production you've been warned) small release is incoming, so will be able to see how things are getting along.

There is still some bits I'd like to work on, in no particular order:
  • Code editor: Time to really start to think as fx files as projects, and just not a window with unusable code completion. 
  • Improve elements decoupling: Some more core, vvvv being so tied to MEF it's gonna be fun, but there's some big rationale behind it, which deserves a post on it's own.
  • Get rid of property injection : So i can really get proper inheritance control , and nodes could even be reused.
  • More high level nodes: No comment, everyone likes high level nodes
  • New transforms : The funny thing is actuallyafter some thoughts, moving transforms to a new type opens a hell of a lot of new doors, more on that later, that deserves another post.
  • Continue to simplify: It doesn't mean lot of small files with 2 lines of code each (no offense to java people, which actually can't since their header is already filled with imports ;) Simpler is better, I don't need the most amazing configurable runtime, I need a lightweight, easy to use and fast runtime!
  • Some more top secret things are also on the way ;)
As usual, thanks for reading and happy new year again !






Sunday, 15 December 2013

SharpDX, refactoring and complexity

I finally was able to spend some proper time to port over SlimDX dx11 to SharpDX (still on quite a few stressful projects, so I try to lock the little amount of spare time I have to test new goodies ;)

Main thing, I didn't redo all from scratch, here is my workflow in that case:

  • Port the core API: This is quite minimal, so I got rid of a lot of the boilerplate, less types, split some parts. API is now much more minimal and easy to work with. 
  • Port of the core: On first instance, I also just replace namespaces/namings. Then I started to refactor parts.
  • Nodes : Since you don't want to break all naming, I keep all very simple. I copy/paste all the nodes and remove the code inside ;) That means I don't have random compile errors, but I got all the in/outs up front (which is kinda similar to test driven development. When I think my core API is ready I push the code again.
So lately I was able to also add improvements, no more multi device helps a lot cleaning codebase, which would help 1 person in a lifetime but makes suffer all the others. Now dx nodes are simpler, easier to write.
There's sill a bit of work polishing API, but foundation seems much nicer for now.

Shader node finally got the improvement it deserved, and is much lighter api wise (eg, also decently faster in many cases).

I also looked to port a few of my high level nodes, and give some decent improvements to the layer system, and all of this is also promising, plan for next release being to provide more low level access to advanced users, while having more high level nodes for general patchers. This is for me a good step forward, but balancing this is hard ;)

On the week end I was able to test a bit API, and results are pretty promising:




Now one major issue with move to SharpDX is the following:

  • You want to support win7
  • You want access to latest DirectX (eg : 11.2)
Luckily, SharpDX makes it relatively easy, only pain part is file load/save. (In win7 you have dxut which makes it easy, in 8/8.1 you hve to do it yourself, or port DirectXTex from c++ to c#).

But that already makes 3 builds to maintain (I'd say ok, 2, 11.1 and 11.2 is not much difference for now).
And since in 4v you need to differenciate x86/x64, that makes 6 builds,uff, just a right pain.

So I looked again a bit more in 4v core, and oh man everything is so overcomplex.

SlimDX is really ultra tied to the core, and it's also the only assembly that forces this 32/64 bits build (90% of the rest could happily be anycpu).
But since it's tied to the core any plugin must choose.

This is a right pain.

I did a few tests, replacing SharpDX by SlimDX also for DX9, but it doesn't scale well, since then you tie yourself to the win7 assembly, which kinda sucks (assembly loading order can create some... interesting errors).

So easiest way ended up to be the brute force, eg, just get rid of SlimDX, and basically just break any plugin with DX9 mesh/layer/texture out.

For me right now it is the best and most sensible solution. I don't have access to the full 4v core, so I'm not able to split a few interfaces, so both of them can live together.

Since I'm really not into dx9/dx11 working in the same 4v instance, it's really not a biggie, but it can bring a few maintenance issues.

So what is the plan now?

Well it would be great to work with devvvvs in order to properly split standard pin logic to render pins, and properly isolate SlimDX (and any architecture dependent code) from he main core. I think it's primordial, but if i have to ship a custom core to avoid this nonsense, then so be it, I will gladly do it.

All those Matrices in 4v are also nonsense, I forgot some of the exact bits, but they add so much complexity to the system, and for me thinking that a simple 16 floats array create such a mess feels kinda bad.
So since I got mostly all of them with a much simpler, custom type, I might introduce that in the next build.
That would be a big thing since it would break backwards compatibility, but at the end I tend to plan for the future not the past.

Rest is to continue into SIMPLIFYING the system. I think most people tend to think too much about a problem, then the most you think of it the more twisted you mind becomes, then you produce a system 10 times more complex than it should be. This is wrong. Not saying that your system should be more flexible, but it needs to be easily testable/debuggable. More complexity never brings any good, over design is bad. 
For example, I looked a lot at code generation, and finally, I will only use it for fx->c# generation.
Doing it for all my types sounds good, but finally I ported all my geometry nodes in 20 minutes, would have taken 2 days to build a generator. For effects with reflection it stays a pretty good idea, since any user can write their own fx, so in that case it makes some sense.

The most fun part of it, you will complain about a system being overcomplex, decide to rewrite all, and makes something 5 times more complex up front (while repeating a lot of mistakes and adding new ones). Not worth it, refactor and improve.

Stop using crappy defaults, and inform user when something is wrong. Crappy defaults sounds a good idea on first instance, but it also makes your system more complex, and when your crappy defaults don't work anymore, you have to know if it comes from the user or yourself, and your user didn't learn anything. A few well placed defaults (with proper information eg : Ok you didn't provided this info, so I used this instead, but please be wary) is a step in the right direction. Choosing silent defaults is a NO GO.

Take more painful decisions if I need to ;) I know users hate changes in some ways (myself included), but then you have to decide and take the risk if you think this is future proof, not stay like ten years ago. I know on programmer side this is also a problem, but finally, changing library if you need is also taking care of users. I could just take AddFlow (the ui library used in 4v), which is now so crap that it's impossible to use vvvv in a live environment anymore (move a few nodes and all your render freezes). I wish they would take the painful path and just switch library, and it doesn't take that much time to do (just bit boring).

Ok stop mumbling, lot of new goodness on the way, be happy ;)







Monday, 2 December 2013

Last DX11 Release...

Using SlimDX ;)

http://vvvv.org/blog/directx-11-beta-31.2-update

Beta31.2 marks a little history as now the plan is to make a full move to SharpDX.

Some people might ask what is the benefits, or if I'm some kind of masochist who like to redo everything again :)

First, a move to SharpDX sounds like the smart option so far, and offers quite a few cool bits:

  • It's quite actively maintained
  • Support for DX11.2
  • Generally API calls are better for performance
  • No more dreaded 32/64 bits builds
And now I'm not rewriting everything, but I feel a lot of things which are already nicer than in old DirectX9 can be done in an even smarter way. Some years of programming in DX taught me a lot as well, and there's definitely some parts that I'm looking forward to improve or rework.

On a first note, writing an API is hard, it takes a lot of time, trial and error, to find a decent compromise between performances/features/ease of programming. So far I consider the first round as a success, there's still a few bugs/features missing, but hey, I'm more or less on my own writing the core, even tho I of course want to thanks people who contributed nodes/shaders ;)

So besides moving to SharpDX, there's of course many plans to improve what is there, in no particular order.

1/Wrapper

New wrapper is almost as fully featured as previous one, but has quite a decent amount of improvements:
  • Clear separation between Device/DeviceContext (multi threaded rendering in mind).
  • Resources are much thinner and much less abstract class/overrides, which should decently help where sometimes it was just a right pain to link 2 elements.
  • Now most of the runtime (not finished yet), is unit tested. So I can quickly see if a change breaks resource creation, pool... This is such a time saver.
  • Resource also have much easier to use creation methods, copies are much more streamlined (only one method to copy to dynamic texture now.
  • Wrapper will mostly manage many addons too (vlc/kinect/geometries...) so most of this can be independently tested in a much cleaner way.
  • Input layout handling is still one of the area for me, it's a bit of a pain to find the right model (for a game engine you can safely build a small hash, but in 4v case, there's so many permutations that it's really not easy).

2/VVVV

Now on the vvvv side, there are also quite some (drastic) changes on the main core. Please don't be afraid as a patcher, on your side it shouldn't be any change.

Death of multi device. Having to handle resource dictionary per device sucks (pain to do anything thread safe), it never got used , and single device works on multi graphics card anyway (tested on a decently fat project). Maybe there's a 0.00001% scenario would pop up where it has a usage, but to be honest I prefer to ease the pain of the 99.9999% of other people ;)

That will mean some performance improvement (specially for large patches) more streamlined coding (less mess up with interfaces).

Layer system is also getting a little improvement, with better stacks for camera, reserved cbuffers, easier rebinding.

Scheduler improvement is also on the way, and small Task based rendering is an area I'm actively looking and experimenting.

3/Shader management

That's the main area where I want to work on, I find shader management in 4v sucks at the moment, you have gazillions of little pieces of code messing around that you can way too easily modify.

Not that modifying shader to fit you needs is bad, but it's just a pain for standard ones. That involves 2 big changes.

Shader package:

basically you have a pack folder and you can compile a library with the following:
  • Precompiled shaders (namespaced as in folder structure)
  • Json content file
So instead of having 200 shaders lying around, you can pack all that lot and easily distribute.

FX Projects

I always found FX projects to be a bit of an issue (an fx project is just a single file, so technically it's not even a project ;)

Also having an extension for each shader type gives some limitations (you don't want to give 50 extensions, but you still want to allow to give a shader a context). Context is for me what is the most missing in vvvv, most stuff is just... stuff.

Giving context to a shader, as selecting host via gui, would allow to create different ways of interpreting it (geometry generator/particle emitter....) in a much easier way, improving quality of contributions.

Ah and on the loop, shader will compile in background, no more massive freeze when you press Ctrl+S on this big fatty compute shader blur :)

I'm not sure if this one will be ready for first release, but it's definitely on decent priority list.

4/Shader API footprint

When you batch like a nutter, Shader API footprint doesn't matter much (you end up <100 draw calls anyway).

But now with compute you can also easily build data structures and manage a decent amount of logic directly in your gpu (on our last project we ended up having most of the processing hosted in there).

So API footprint starts to make sense again, specially on compute side.

There's already some prototypes/experiment done on that side, stay tuned, it rocks believe me ;)

5/Be high (No connotations with any type of substance... )

For now I consider 4v to be fairly low level. 

First part of the plan for DirectX11 was to build a backbone to have people getting used to it. Plan to have high level nodes was always there, but it's not that useful without a decent backbone, now time is getting there.

Many more high level nodes are needed, where people can really do things out of the box.
  • Deffered Renderers
  • Better Light equations
  • Easier to use materials
  • Pluggable particle systems
  • Geometry processors
  • All that wrapped in proper plugins (sandboxed) to also ensure quality API usage.
Some people will claim that it's less tweakable when you sandbox, but for many users they don't write shaders anyway, so some defaults where you can do quality rendering is one thing that is definitely needed.

Resource management, Smart ordering is where normally most user will fail, so giving them a decent start up is not a bad thing (and of course you still have access to the low level API if you feel up for it ;)


And please note that if you want to contribute you are more than welcomed, since doing all that lot takes time and I'm more or less on my own, and I also do projects ;)

That includes mostly:
  • One person to help manage GitHub/Builds (really that would be god send)
  • People to do help patches/examples
  • People for writing some nodes (even tho with new system it will be a bit different).

    So that's it for this post, would say, one chapter closes, one new chapter opens, exciting times ;)