Microthreads using C# 5.0 async

There has been lot of experiments to bring microthreads to C#. Usual primitive construct to build such a framework are:

  • Leveraging IEnumerable/yield constructs
  • Modifying generated IL (as Second Life is doing)
  • Using custom VM modifications such as Mono.Tasklets.Continuation

  • Miguel de Icaza has an nice summary with lot of interesting thoughts/explanation about this in his blog.

    With the introduction of the C# 5.0 async keyword, it quickly became clear that this feature could also be nicely leveraged to write such a microthread engine.

    Lot of things which were tedious or even impossible to do with other approaches are now possible, just to name a few:

  • Task cancellation
  • Proper exception handling
  • Thread migration & resume in another thread or context
  • Customization of the threading model, by inheriting SynchronizationContext (can easily force specific tasks to run on only one specific thread, or use thread pool, etc…)
  • Access to System.Threading.Tasks: advanced operations such as waiting for multiple tasks (e.g. TaskEx.WhenAll, wait for external operation using TaskCompletionSource, etc…)
  • Can use lot of existing constructs almost directly, such as new async CTP functions in AsyncCtoLibrary (and by extension every BeginXX/EndXX async methods)

  • As a result, I could easily come up with a powerful framework that allows to wait for events (e.g. await Engine.NextFrame()), as well as much more advanced features. Concerning implementation details, most of the scheduling such as await Engine.NextFrame() is built on top of TaskCompletionSource, so that execution can be resumed whenever the scheduler want. Writing such a framework is actually quite easy with the help of System.Threading.Tasks.
    Hopefully scripting and async resource loading will be a breeze using this approach!

    Posted in Uncategorized | Leave a comment

    Writing GPU shaders in… C# (update 3) – Constant buffers, the way they always should have been!

    There has been some good progress over the past few days.

    Now all the Texture2D<T>, Texture2DMS<T>, TextureCube<T>, Buffer<T> etc… have stubs and get converted by the system.

    However, most of my work has been focused on implementing a good system for constant buffer. As 3D pipeline becomes more and more shader-centric, I believe string-driven constant buffer system as it exists in OpenGL and D3D is something that should be avoided.

    Of course, as part of my effort to write shader in C#, there is already constant buffer definitions lying in the assembly. After giving it some thoughts, I ended up with a system for generating optimized proxy from a Constant Buffer C# interface taken from the shader signature.

    As an example, let’s say we have those C# interface being referenced as constant buffer from the shader code in C# (check previous posts for more info):

        public interface IStructTest
        {
            SVector2F Test3 { get; set; }
            SVector2F Test4 { get; set; }
        }
        [ConstantBuffer]
        public interface IConstantBuffer1
        {
            SVector1F Test { get; set; }
            SVector1F Test2 { get; set; }
            IStructTest Struct { get; }
        }
    

    To obtain a constant buffer instance implementing that interface and change its content, user only needs to do something along the line of (this piece of code will probably be simplified later):

                var proxyType = ProxyGenerator.GenerateConstantBufferType<IConstantBuffer1>(shader.ConstantBuffers["cb1"]);
                var cb = (IConstantBuffer1)Activator.CreateInstance(proxyType);
                // Then we can play with our buffer:
                testInstance.Test = new SVector1F(32.321f);
                testInstance.Test2 = new SVector1F(32.321f);
                testInstance.Struct.Test4 = new SVector2F(24.0f, 24.0f);
                testInstance.Struct.Test3 = new SVector2F(12.0f, 24.0f);
    

    What the hell is going on? Under the hood, the proxy generator is using Reflection.Emit to generate optimized code for filling a buffer (byte[]) very efficiently through its auto-generated “set” properties Most of the copy is done directly with memcpy (OpCodes.Cpblk) and offset/size are hardcoded directly into the type, without any backing field. On top of that, the root constant buffer object will have its IsDirty flags updated to know if the buffer needs to be reuploaded (might consider range IsDirty support later, not sure if it is worth it as Constant Buffer should be split depending on their upload frequency). Please note that a constant buffer type generated by the proxy generator is done using information only known at runtime (OpenGL and D3D both have different way to layout data and do padding). However, nothing prevents the implementation of statically defined padding (such as std140 layout in OpenGL). The point is, user doesn’t need to worry about that, all the buffer layout is done from the shader reflection when constructing the type.

    As a result, this system offers an almost optimal (close to hardcoded C) way to fill constant buffer while not writing a single line of code (except the interface). Also, since it maps to a real type, there is no needs for the error-prone GetVariableByName() or glGetUniformLocation() at all. Overhead happens only first time a constant buffer proxy type is requested (then it is cached for future instantiation anyway).

    Overall, as the different part of this shader system are getting in place, I feel very excited about the new possibilities and ease of use for fast shader prototyping (with almost no restriction compared to writing shaders in HLSL). I believe such a system could be the base for writing very powerful 3D middleware. This is still in early stage of development, but I expect to be able to do some rendering with it very soon.

    Posted in Uncategorized | Tagged , , , , | Leave a comment

    Writing GPU shaders in… C# (update 2)

    Good progress is going on.

    I have written some T4 template to generate all of the various scalar, vector (including swizzling i.e. v.xzy = v2.xyy) and matrix types (with their operators) as well as the HLSL functions with their overloads. As generated code is over 30,000 lines, I am pretty happy I went that way (and I will probably do the matrix swizzling operator with a function taking enum constants, since it would otherwise be millions of lines for all the swizzling combinations)!

    I have generated Texture2D<T> type but still need to make stubs for most of others Texture and Buffer types.

    I still need to review the overall thing a little bit more to make sure everything could be later translated to GLSL 4 as well.

    Anyway, as HLSL mapping is almost finished, soon the fun part will begin: architecturing nicely the whole system to operates smoothly with a nice 3D engine (streams and constants mapping — both manual and automatic).

    Posted in Uncategorized | Tagged , , , , | 4 Comments

    Writing GPU shaders in… C#

    I am currently working on some fun project, which transforms a shader written inside a method in your C# assembly (could probably be any .NET language) into HLSL shader (could be extended Cg/GLSL as well).

    For example, this piece of code:

        [ConstantBuffer]
        public interface IConstantBuffer1
        {
            public float Test;
        }
        public struct Vertex
        {
            [StreamSemantic("Position")]
            public float x;
            [StreamSemantic("Position2")]
            public Vector3F v;
        }
        public class Shader
        {
            public Vertex Main(
                Vertex vertex,
                ConstantBuffer1 cb1,
                ConstantBuffer1 cb2
            )
            {
                Vector3F v1 = new Vector3F(1.0f, 0.0f, 0.5f);
                float z = vertex.x;
                Vector3F v2 = vertex.v.Normalize();
                float c = Vector3F.Dot(v2, v2);
                z += vertex.v.X + v2.Z + cb1.Test + cb2.Test;
                return new Vertex { x = z };
            }
        }
    

    Get transformed into:

    struct Vertex
    {
            float x : Position;
            float3 v : Position2;
    }
    
    cbuffer cb1
    {
            float cb1_Test;
    }
    
    cbuffer cb2
    {
            float cb2_Test;
    }
    
    Vertex main(Vertex vertex)
    {
            float3 V_0 = { 1, 0, 0.5 };
            float V_1 = vertex.x;
            float3 V_2 = normalize(vertex.v);
            float V_3 = dot(V_2, V_2);
            V_1 = V_1 + (((vertex.v.X + V_2.Z) + cb1_Test) + cb2_Test);
            Vertex V_4;
            V_4.x = V_1;
            return V_4;
    }
    

    Of course, the process transforms primitive type. For example, Vector3F (internal class in my framework) would become a float3, and v.Normalize() function would become a static normalize(v) when translated in the shader. Also, all the shader specific functions are available through function stubs.

    As a result, users can write GPU shaders directly in their code, in a typesafe way, and can map directly vertex input, output and constant buffer from C# struct. Some Attribute such as [ConstantBuffer] and [StreamMapping("Position")] are used to provides meta information that will be embedded in the generated shader as well. Of course, this allows shader constants to be defined only in one place as a real struct member. This avoids all the mess of using glGetUniformLocation or GetVariable(name), provides type safety and language refactoring (rename, etc…).

    One of the big challenge of modern game engine is their inabilities to allow both the engine and the game developer to have control over the shader code since it is usually just a plain text file. However, with this approach, I believe it is possible to mix the best of both world: customizable shader with features controlled by the engine.

    Seeing a little bit further, I can think lot of cool features could exist with such a system, such as testing shader directly on CPU (since it is real code), automatically upload constant buffers, have placeholders so that user can change some parts, etc…

    I will explain more in the next days (I started it only 2 days ago), but I believe this could really change the way shaders are being used if it is used wisely.

    Posted in Uncategorized | Tagged , , , , | 3 Comments