Lloyd.NET

Programing experiments

D2D Progress

For my DirectX WinRT wrapper (now on CodePlex http://directwinrt.codeplex.com/) I took a break of D3D as I had some problem with it (more on that later) and implemented most of D2D, it was easy! ^^

And I also made the initialization even easier and more flexible.

Screenshot of Sample_D2D

So today I will write a quick how to start (with D2D) and about my latest D3D breakthrough (which is just some  C++/CX – C# technicality)

 

Initializing DirectX Graphics

To start DirectX graphic (with my API) one just initialize a DXContext and set a target, like so

var ctxt = new DXContext();
ctxt.Target = (IRenderTarget) ...;

There are 3 types of target to choose from (so far):

DXTargetSwapPanelOrWindow;
DXTargetImageSource;
Texture2D;

Target can even be changed while drawing (for example draw first on a Texture2D, which then can be used in the final scene).

DXTargetSwapPanelOrWindow wrap a SwapChainBackgroundPanel in XAML application.
Of interest DXUtils.Scenes.ScenePanel initialize DirectX, create a Target and call render on every frame.

Then one can draw, for each frame, with pseudo code like that

void Draw(DXContext ctxt)
{
    ctxt.Render = true;
    ctxt.Clear(Colors.White);

    var g3 = new D3DGraphic(ctxt)
    g3.DrawSomething(...);

    var g2 = new D2DGraphic(ctxt);
    g2.DrawSomething(...);

    ctxt.Render = false;
}

 

D2D

Remark at this stage one can download the source (http://directwinrt.codeplex.com/) and have a look at the D2D sample: Sample2_D2D.

 

This weekend and week I wrapped most of D2D API. To be precise I wrapped the following:
- geometries, brushes, bitmap, stroke style, text format, text layout, transforms

(Missing, from the top of my head, would be 2d effects, glyph run and lots of DWrite)

 

Initialization

When drawing a scene (whether D2D or D3D), for performance reason, one should initialize all items first and just call the draw primitives while rendering.

For example lets create a few geometry and brushes

public MyD2DScene()
{
    bImage = new BitmapBrush { Bitmap = new Bitmap(), };
    bImage.Bitmap.CreateWic("Assets\\space-background.jpg");

    bYRB = new LinearGradientBrush
    {
        StartPoint = new Point(100, 100),
        EndPoint = new Point(800, 800),
        GradientStops = new []
        {
            new GradientStop { position = 0, color = Colors.Yellow },
            new GradientStop { position = 0.4f, color = Colors.Red },
            new GradientStop { position = 1, color = Colors.Blue},
        },
    };

    gPath = new PathGeometry();
    using (var sink = gPath.Open())
    {
        sink.BeginFigure(new Point(), FIGURE_BEGIN.FILLED);
        sink.AddLines(new[] {
            new Point(25, 200),
            new Point(275, 175),
            new Point(50, 30),
        });
        sink.EndFigure(FIGURE_END.OPEN);
    }

    //......
}

 

In that scene snippet I created an image brush from a resource image, a gradient brush and a simple path geometry.

 

Rendering

Now I can just render all my items with just few drawing command, like so (for the geometry):

public void Render(DXContext ctxt)
{
    var g = new D2DGraphics(ctxt);
    g.Clear(Colors.Beige);

    g.Transform = DXMath.translate2d(pSkewedRect);
    g.FillGeometry(gPath, bImage);
    g.DrawGeometry(gPath, bYRB, 12, null);
}

 

D3D

Now that was easy and I got back to try to solve my dissatisfaction with my current implementation of D3D. Mostly that the C# developer is (currently) limited to the vertex buffer that I hard coded in the API.

And then I had a breakthrough. Let’s create a native pointer wrapper and write some code on the C# side that make it strongly typed.

My first attempt looked like that:

public ref class NativePointer sealed
{
private:
    uint32 sizeoft, capacity;
    void* data;

internal:
    property void* Ptr { void* get(); }

public:
    NativePointer(uint32 sizeOfT);
    virtual ~NativePointer();

    property Platform::IntPtr Data { Platform::IntPtr get(); }
    property uint32 SizeOfT { uint32 get(); }
    property uint32 Capacity;
    void Insert(uint32 offset, uint32 count);
    void Remove(uint32 offset, uint32 count);
};

That look promising, it even compiled! But then… WTF!!! Platform::IntPtr doesn’t cross ABI!!
Damn you Microsoft!

Then I had a breakthrough, what about… size_t ?!

It’s a perfectly ordinary type, except for the little twist that it projects to int32 when compiling for x86 and int64 when compiling for x64! It worked just fine, sweet!

So this is the change:

property size_t Data { size_t get(); }

On the C# side I was originally hoping to have a generic Pointer<T> class and finally use some unsafe C#.

Well I did use the unsafe C#, but I couldn’t compile code like that

public unsafe static T Get<T>(IntPtr p, int pos)
{
    T* pp = (T*)p;
    return pp[pos];
}

The compiler returns the error

Cannot take the address of, get the size of, or declare a pointer to a managed type ('T')

But it did accepts

public unsafe static int GetInt(IntPtr p, int pos)
{
    int* pp = (int*)p;
    return pp[pos];
}

Sweet…

In the end I create an abstract BasePointer<T> and a .tt template that generate all the template that I need!

Now I just have to implement a class like XNA’s VertexDeclaration and I will get a (reasonably?) solid base to go on…

And also rewrite all my buffers to use this native pointer class.

That’s it for today!
And remember: http://directwinrt.codeplex.com/


Tags: , , ,
Categories: .NET | DirectX | WinRT | C#
Permalink | Comments (0) | Post RSSRSS comment feed

Silverlight Menu

Recently I needed a Silverlight menu. I found the following implementations:

But none behave like an ordinary HeaderedItemsControl and all did impose some constraint which make using databinding, templating or MVVM more awkward than it should be. So here is my take on this control.

 image

Implementation:

 

Below I’m going to quickly explain the salient point of the implementation and then show some usage samples.

 

Implementation

 

Basic ItemsControl

The main class is MenuItem. Inspired by WinForm, WPF, I did create a Menu class but it’s just an optional container with a different layout (and it also hide the arrow on the side).

The UI, at its most basic is defined as follows (non necessary styling element removed)

<Style TargetType="local:MenuItem">
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Vertical"/>
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:MenuItem">
                <Grid Background="Transparent">
                    <Border x:Name="PART_HighlightBg" Margin="2" Opacity="0"
                            Background="{Binding HighlightBrush, Source={StaticResource SystemBrushes}}"
                        />
                    <ContentPresenter
                        Margin="4"
                        Content="{TemplateBinding Header}"
                        ContentTemplate="{TemplateBinding HeaderTemplate}"
                            />
                    <Popup x:Name="PART_Popup" IsOpen="False">
                        <ItemsPresenter />
                    </Popup>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

There is a Transparent Grid background grid for hit testing, a border at lowest Z order for highlight, the content presenter for the header and an ItemsPresenter in a Popup for children.

 

Now the most basic implementation of an ItemsControl just setup children.
I also copy the style in PrepareContainerForItemOverride, as MenuItem’s children item are whole new MenuItem with the default style. This code make sure all children and children’s children and so on looks the same as the top level MenuItem, in case it has been styled.

public class MenuItem : HeaderedItemsControl
{
    public MenuItem()
    {
        this.DefaultStyleKey = typeof(MenuItem);
        ((INotifyCollectionChanged)Items).CollectionChanged += delegate { HasChildren = Items.Count > 0; };
    }

    #region ItemsControl override

    protected override DependencyObject GetContainerForItemOverride()
    {
        return new MenuItem();
    }
    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return item is MenuItem;
    }
    protected override void ClearContainerForItemOverride(DependencyObject element, object item)
    {
        base.ClearContainerForItemOverride(element, item);
    }
    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        // copy import UI value to child element automatically...
        // copy first in case something is set in the template (would be set in base.XXX())
        var mi = (MenuItem)element;
        mi.Style = Style;
        mi.Background = Background;
        mi.Foreground = Foreground;
        mi.BorderBrush = BorderBrush;
        mi.BorderThickness = BorderThickness;

        base.PrepareContainerForItemOverride(element, item);
    }

    #endregion
}

 

To manage the popup by code I added an IsOpen property

#region IsOpen

internal Popup GetPopup()
{
    return this.GetTemplateChild("PART_Popup") as Popup;
}

public bool IsOpen
{
    get
    {
        var p = GetPopup();
        return p != null && p.IsOpen;
    }
    set
    {
        // separator don't open
        value = value && !IsSeparator;

        var p = GetPopup();
        if (p == null)
            return;

        if (p.IsOpen == value)
            return;

        p.IsOpen = value && Items.Count() > 0;
        MenuPopupManager.OnOpen(this, value);
    }
}

#endregion

 

Mouse Handling

Now all is needed is to overrides OnMouseEnter, OnMouseLeave, OnMouseLeftButtonDown, OnMouseLeftButtonUp.

Most of them do little and delegate the thinking to the class MenuPopupManager. This class maintains a list of all open popup, position the Popup appropriately, hide those Popup that need be hidden and close all MenuItem after a timeout.

Ideally it should close all menu when the user click outside the MenuItem but I could not get it to work reliably.

A skeleton implementation looks like that

public static class MenuPopupManager
{
    #region PopupData, CurrentPopupData

    internal class PopupData
    {
        public PopupData()
        {
        }

        public List<MenuItem> Items = new List<MenuItem>();
        public Timer Timer;
        public Dictionary<MenuItem, PlacementMode> Placements = new Dictionary<MenuItem, PlacementMode>();

        public MenuItem Hovering;
    }

    static PopupData CurrentPopupData;

    #endregion

    #region PlacePopup

    internal static void PlacePopup(MenuItem mi, Popup p)
    {
        Action place = delegate
        {
            // placement logi
        };

        // placement needs size calculation, need be done after being shown
        // otherwise DesiredSize will always be {0,0}, despite calls to Measure() !!??
        if (mi.IsOpen)
        {
            place();
        }
        else
        {
            EventHandler onOpen = null;
            onOpen = delegate
            {
                place();
                p.Opened -= onOpen;
            };
            p.Opened += onOpen;
        }
    }

    #endregion

    #region OnMouseEnter(), OnMouseLeave(), OnOpen(), OnFinish(),

    internal static void OnMouseEnter(MenuItem item)
    {
        var pd = CurrentPopupData;
        if (pd == null)
            return;
        pd.Hovering = item;
    }
    internal static void OnMouseLeave(MenuItem item)
    {
        var pd = CurrentPopupData;
        if (pd == null)
            return;
        pd.Hovering = null;
    }
    internal static void OnOpen(MenuItem item, bool open)
    {
        var pd = CurrentPopupData;
        var pi = item.GetParentItem();
        // update CurrentPopupData and close popup that should be closed
    }
    internal static void OnFinish(MenuItem item)
    {
        // close everything and update CurrentPopupData
    }

    #endregion
}

 

Obviously MenuItem implement Click and triggering an ICommand and hiding itself after that. If no Click event handler or Command is defined it will do nothing (including not closing the menu), making it easy to embed advanced control in popup menu.

#region Command

public ICommand Command
{
    get { return (ICommand)GetValue(CommandProperty); }
    set { SetValue(CommandProperty, value); }
}

public static readonly DependencyProperty CommandProperty =
    DependencyProperty.Register("Command", typeof(ICommand), typeof(MenuItem), new PropertyMetadata(null));

#endregion

#region CommandParameter

public object CommandParameter
{
    get { return (object)GetValue(CommandParameterProperty); }
    set { SetValue(CommandParameterProperty, value); }
}

// Using a DependencyProperty as the backing store for CommandParameter.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty CommandParameterProperty =
    DependencyProperty.Register("CommandParameter", typeof(object), typeof(MenuItem), new PropertyMetadata(null));

#endregion

#region Click, OnClick()

public event RoutedEventHandler Click;

protected virtual void OnClick(RoutedEventArgs e)
{
    if (IsSeparator)
        return;

    var c = Command;
    var p = CommandParameter;
    if (c != null && c.CanExecute(p))
    {
        c.Execute(p);
        MenuPopupManager.OnFinish(this);
    }

    var he = Click;
    if (he != null)
    {
        he.Invoke(this, e);
        MenuPopupManager.OnFinish(this);
    }
}

#endregion

 

Styling

And lastly I added a bit of Styling. I downloaded the Silverlight toolkit and took the SystemBrushes class from the SystemColor theme’s source code. Used various SystemBrushes’s Brush for styling the Menu and MenuItem.

The nice silverish background brush of the Menu is SystemBrushes.ButtonGradient
image

 

For the mouse hover effect where an highlight color (quickly but progressively) appears I finally took the time to use animation and view state. It proved to be real easy!

First I setup 2 states. One which progressively increased the opacity of  the background control (PART_HighlightBg). The second state does nothing, in effect reverting the opacity change instantly. I could have used an animation too but I liked the shorter template and result is good too.

<ControlTemplate TargetType="local:MenuItem">
    <Grid Background="Transparent">
        <vsm:VisualStateManager.VisualStateGroups>
            <vsm:VisualStateGroup x:Name="Highlight">
                <vsm:VisualState x:Name="HighlightOn">
                    <Storyboard>
                        <DoubleAnimation
                            Duration="0:0:0.3" To="0.4"
                            Storyboard.TargetName="PART_HighlightBg" Storyboard.TargetProperty="Opacity">
                            <DoubleAnimation.EasingFunction>
                                <ExponentialEase Exponent="3" EasingMode="EaseInOut"/>
                            </DoubleAnimation.EasingFunction>
                        </DoubleAnimation>
                    </Storyboard>
                </vsm:VisualState>
                <vsm:VisualState x:Name="HighlightOff"/>
            </vsm:VisualStateGroup>
        </vsm:VisualStateManager.VisualStateGroups>
        <Border x:Name="PART_HighlightBg"
            Margin="2" Opacity="0"
            Background="{Binding HighlightBrush, Source={StaticResource SystemBrushes}}"
            BorderBrush="{Binding ControlDarkBrush, Source={StaticResource SystemBrushes}}"
            BorderThickness="{TemplateBinding BorderThickness}"
            />
        <!-- other controls -->
    </Grid>
</ControlTemplate>

 

Then I simply setup the state in mouse handler

protected override void OnMouseEnter(MouseEventArgs e)
{
    base.OnMouseEnter(e);
    MenuPopupManager.OnMouseEnter(this);
    VisualStateManager.GoToState(this, "HighlightOn", true);
}
protected override void OnMouseLeave(MouseEventArgs e)
{
    base.OnMouseLeave(e);
    MenuPopupManager.OnMouseLeave(this);
    VisualStateManager.GoToState(this, "HighlightOff", true);
}

 

Examples

And now some example on how to use this control.

 

Inline definition

image

<Grid x:Name="LayoutRoot" Background="White">

    <local:Menu Margin="10,0">
        <local:MenuItem Header="File lala">
            <local:MenuItem Header="Foo">
                <local:MenuItem Header="tadat"/>
                <local:MenuItem Header="Footaise">
                    <local:MenuItem Header="tadat"/>
                    <local:MenuItem Header="tadat"/>
                    <local:MenuItem Header="tadat"/>
                </local:MenuItem>
                <local:MenuItem Header="tadat"/>
                <local:MenuItem Header="tadat"/>
            </local:MenuItem>
            <local:MenuItem IsSeparator="True"/>
            <local:MenuItem Header="tadat"/>
            <local:MenuItem Header="tadat"/>
        </local:MenuItem>
    </local:Menu>
    
</Grid>

 

MVVM - databinding

First I’ll define a data model used for my MVVM usage

public class ModelCommand : ICommand
{
    ModelItem item;
    public ModelCommand(ModelItem item) { this.item = item; }
    public bool CanExecute(object parameter) { return true; }
    public event EventHandler CanExecuteChanged;
    public void Execute(object parameter) { MessageBox.Show("Clicked: " + item.Name); }
}
public class ModelItem
{
    public ModelItem()
    {
        Items = new List<ModelItem>();
        Command = new ModelCommand(this);
    }
    public string Name { get; set; }
    public List<ModelItem> Items { get; private set; }
    public ICommand Command { get; private set; }
}
public class Model
{
    public Model()
    {
        // initialize a recursive list of Items and their children
        // and their children and their children's children and so on...
    }
    public List<ModelItem> Items { get; private set; }
}

 

Then I can do some simple binding

image

<local:Menu Margin="10,0" HorizontalAlignment="Right">
    <local:MenuItem Header="Persons" ItemsSource="{Binding Items, Source={StaticResource MM}}">
        <local:MenuItem.ItemContainerStyle>
            <Style TargetType="local:MenuItem">
                <Setter Property="Command" Value="{Binding Command}"/>
            </Style>
        </local:MenuItem.ItemContainerStyle>
        <local:MenuItem.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}"/>
            </DataTemplate>
        </local:MenuItem.ItemTemplate>
    </local:MenuItem>
</local:Menu>

Remark to setup the Command on the MenuItem I should use the ItemContainerStyle property.

 

Hierarchical binding

image

<local:Menu
    Margin="10,0" HorizontalAlignment="Right" VerticalAlignment="Bottom" PopupPlacement="Top" CornerRadius="5,5,0,0" BorderThickness="1,1,1,0">
    <local:MenuItem Header="Persons" Command="{Binding Command}" ItemsSource="{Binding Items, Source={StaticResource MM}}">
        <local:MenuItem.ItemContainerStyle>
            <Style TargetType="local:MenuItem">
                <Setter Property="Command" Value="{Binding Command}"/>
            </Style>
        </local:MenuItem.ItemContainerStyle>
        <local:MenuItem.ItemTemplate>
            <sdk:HierarchicalDataTemplate ItemsSource="{Binding Items}">
                <TextBlock Text="{Binding Name}"/>
            </sdk:HierarchicalDataTemplate>
        </local:MenuItem.ItemTemplate>
    </local:MenuItem>
</local:Menu>

 

Styling

I can also add a single parentless MenuItem anywhere. And I can style it too, setup the background brush for instance (whether it’s parentless or not) and the value will flow down.

image

<local:MenuItem
    Margin="100,0" HorizontalAlignment="Right" VerticalAlignment="Bottom" PopupPlacement="Top" BorderThickness="1,1,1,0"
    Background="Aquamarine" Header="Persons" ItemsSource="{Binding Items, Source={StaticResource MM}}">
    <local:MenuItem.ItemContainerStyle>
        <Style TargetType="local:MenuItem">
            <Setter Property="Command" Value="{Binding Command}"/>
        </Style>
    </local:MenuItem.ItemContainerStyle>
    <local:MenuItem.ItemTemplate>
        <sdk:HierarchicalDataTemplate ItemsSource="{Binding Items}">
            <TextBlock Text="{Binding Name}"/>
        </sdk:HierarchicalDataTemplate>
    </local:MenuItem.ItemTemplate>
</local:MenuItem>

Permalink | Comments (0) | Post RSSRSS comment feed

OData with async

Today I watched this video about using OData in a WinRT app:
http://blog.jerrynixon.com/2012/08/new-episode-devradio-let-odata-make.html

To summarize he (Jerry Nixon) add a service reference to the Netflix OData API at:
http://odata.netflix.com/Catalog/

 

and then proceed to do something like that

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    var _uri = new Uri("http://odata.netflix.com/Catalog/");
    var ctxt = new NetFlixService.NetflixCatalog(_uri);
    var data = new DataServiceCollection<NetFlixService.Title>(ctxt);

    var query = from t in ctxt.Titles
                where t.Name.Contains("Star Trek")
                select t;
    data.LoadCompleted += delegate 
    {
        this.DataContext = data;
    };
    data.LoadAsync(query);
}

Basically he create an OData service reference, run a database query against it and show the results.

 

What I wanted to change is, use the new async / await keyword in .NET4.5 instead of the LoadCompleted delegate.

There seem to be no obvious way of doing that!
Time to Google!

From the await (C# Reference) reference it seems that await can (only) be applied to a method returning a Task, and a Task (from Googling) can be created from IAsyncResult.

 

So first I started by creating a very simple and reusable IAsyncResult implementation class:

public class SimpleAsyncResult : IAsyncResult, IDisposable
{
    ManualResetEvent waitHandle = new ManualResetEvent(false);

    public void Finish()
    {
        IsCompleted = true;
        waitHandle.Set();
        waitHandle.Dispose();
    }

    public void Dispose() { waitHandle.Dispose(); }

    public bool IsCompleted { get; private set; }
    public object AsyncState { get; set; }
    public bool CompletedSynchronously { get; set; }

    public WaitHandle AsyncWaitHandle { get { return waitHandle; } }
}

 

With that I can easily create an extension method for my OData classes returning a Task:

public static class OData
{
    public static Task<DataServiceCollection<T>> AsyncQuery<T>(this DataServiceCollection<T> data, IQueryable<T> query = null)
    {
        var asyncr = new SimpleAsyncResult();
        Exception exResult = null;
        data.LoadCompleted += delegate(object sender, LoadCompletedEventArgs e)
        {
            exResult = e.Error;
            asyncr.Finish();
        };

        if (query == null)
            data.LoadAsync();
        else
            data.LoadAsync(query);

        return Task<DataServiceCollection<T>>.Factory.FromAsync(asyncr
            , r =>
            {
                if (exResult != null)
                    throw new AggregateException("Async call problem", exResult);
                return data;
            }
        );
    }
}

Remark here I wrap the exception because I don’t want to lose the stack trace (with “throw exResult”)

 

And voila I can update my NavigatedTo method to be async friendly!

protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    var _uri = new Uri("http://odata.netflix.com/Catalog/");
    var ctxt = new NetFlixService.NetflixCatalog(_uri);
    var data = new DataServiceCollection<NetFlixService.Title>(ctxt);

    var query = from t in ctxt.Titles
                where t.Name.Contains("Star Trek")
                select t;
    await data.AsyncQuery(query);
    this.DataContext = data;
}

Tags:
Categories: .NET
Permalink | Comments (0) | Post RSSRSS comment feed

Bulk SQL Update and Delete with LINQ to EF

The more I use EF to SQL the more I like it and get rid of stored procedures. It really ease maintenance and development!

There is one major area where EF is lacking though, and stored proc still absolutely required, and it is bulk update and delete. Wouldn’t it be nice to be able to do that with just some strongly typed nice C# code?

Come to think about it, it might be possible… and Google helping I found a blog which provided an implementation for just that!

Yoohoo!
Just to be safe I downloaded his C# source code file and provide it here as well (untested and unread yet… will do that tomorrow at work…)


Tags: ,
Categories: .NET | Database
Permalink | Comments (0) | Post RSSRSS comment feed

The Content Stream sample

Today I mostly finished porting the Content Stream DirectX sample from MSDN to WPF. About 4300 lines of C++ to C#.

Get it on CodePlex!

I kind of lost track of the big picture while translating C++ to C# method after method, each of them being far remote from doing any DirectX work. Anyhow I did learn a few things…

But first a screen shot of the result: a huge (and empty) free roaming world:

image

 

And here are a few things that I learn while porting the sample

 

Interop lessons

The PackedFile class is reading / writing a lot of structures (directly, as opposed to parsing the bytes) from a terrain file.

Writing a structure to a file in C++ is quite straight forward, define your structure and use WriteFile as in

struct CHUNK_HEADER
{
    UINT64 ChunkOffset;
    UINT64 ChunkSize;
};

CHUNK_HEADER* pChunkHeader = TempHeaderList.GetAt( i );
if( !WriteFile( hFile, pChunkHeader, sizeof( CHUNK_HEADER ), &dwWritten, NULL ) )
    goto Error;

 

The same operation can, in fact, be done in C#. Here is a code that will write any structure (property tagged) to a byte[] array (i.e. any stream)

public static T ToValue<T>(byte[] buf, ref int offset)
    where T : struct
{
    int n = Marshal.SizeOf(typeof(T));
    if (offset < 0 || offset + n > buf.Length)
        throw new ArgumentException();

    fixed (byte* pbuf = &buf[offset])
    {
        var result = (T)Marshal.PtrToStructure((IntPtr)pbuf, typeof(T));
        offset += n;
        return result;
    }
}

(This method can be found in Week02Samples\BufferEx.cs)

The structure should be properly tagged though. Here is one which contains a fixed size string!

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode/*, Pack = 4*/)]
public struct FILE_INDEX
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = WinAPI.MAX_PATH)]
    public string szFileName;
    public long FileSize;
    public long ChunkIndex;
    public long OffsetIntoChunk;
    public Vector3 vCenter;
}

If all the type are supported by Interop it will end-up with the same content as a C++ reader / writer.

 

Sharing DirectX texture with CPU memory

The Textures and buffers of DirectX most of the time lies in the GPU memory. Meaning:

  • That they are a precious resource! There is only that much video memory and if the application need more, the GPU will be considerably slowed swapping some of them with the main memory!
  • There are a few key way of passing the memory around:
  • With D3D.Buffer, a call to UpdateSubresource() will do it

 

With D3D.Texture2D, a mix and match of Map(), write to a Staged resource, Unmap(), CopyResource()

In the samples 2 files help to do that: ResourceReuseCache.cs and ContentLoader.cs

 

In ResourceReuseCache.cs there is a cache of indices buffers, vertices buffer and textures. 

Of particular interest each texture cache item contains a pair of objects (because updating texture is trickier than buffer): a ShaderResourceView and a (staging) Texture2D.

Here is how they are created:

var desc = new Texture2DDescription
{
    Width = Width,
    Height = Height,
    MipLevels = MipLevels,
    ArraySize = 1,
    Format = FormatEx.ToDXGI(( D3DFORMAT )Format),
    SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),
    Usage = ResourceUsage.Default,
    BindFlags = BindFlags.ShaderResource,
    CpuAccessFlags = CpuAccessFlags.None,
    OptionFlags = ResourceOptionFlags.None,
};

using (Texture2D pTex2D = new Texture2D(m_Device, desc))
{
    var SRVDesc = new ShaderResourceViewDescription
    {
        Format = desc.Format,
        Dimension = SharpDX.Direct3D.ShaderResourceViewDimension.Texture2D,
        Texture2D = { MipLevels = desc.MipLevels, }
    };
    tex.pRV10 = new ShaderResourceView(m_Device, pTex2D, SRVDesc);
}

desc.Usage = ResourceUsage.Staging;
desc.BindFlags = BindFlags.None;
desc.CpuAccessFlags = CpuAccessFlags.Write;
tex.pStaging10 = new Texture2D(m_Device, desc);

in maroon bold the 2 paired objects created by this code snipped (note the desc.Usage = ResourceUsage.Staging)

 

Later data is written to those buffer and communicated to the DirectX memory though IDataLoader(s) and IDataProcessor(s) found in ContentLoader.cs. The loading / updating code being split into 5 methods it might be trick to follow.

 

For buffer, this method (from DXUtils) show how to write a Stream to a Buffer:

public static void UpdateSubresource(this Direct3D10.Device device, Stream source, Direct3D10.Resource resource, int subresource)
{
    byte[] buf = new byte[source.Length];
    source.Position = 0;
    source.Read(buf, 0, buf.Length);

    using (var ds = new DataStream(buf, true, true))
    {
        var db = new DataBox(0, 0, ds);
        device.UpdateSubresource(db, resource, subresource);
    }
}

(note sure what the subresource is for, though…)

 

For Texture it’s a bit more involved:

void CopyTexture(Stream textdata)
{
    Device device = ...;
    ShaderResourceView texture = ...;
    Texture2D staging = ...;
var sdata = staging.Map(0, MapMode.Write, MapFlags.None); // WARNING copy should pay attention to row pitch, // i.e. a row length (in byte) might be more than num pixel * pixel size int NumBytes, RowBytes, NumRows; FormatEx.GetSurfaceInfo(250, 250, D3DFORMAT.A8R8G8B8, out NumBytes, out RowBytes, out NumRows); var buff = new BufferEx(); long srcpos = textdata.Position, dstpos = sdata.Data.Position; for (int h = 0; h < NumRows; h++) { textdata.Position = srcpos; sdata.Data.Position = dstpos; buff.CopyMemory(sdata.Data, textdata, RowBytes, buff.CurrentLength); dstpos += m_pLockedRects10[i].Pitch; srcpos += RowBytes; } // send the data to the GPU memory staging.Unmap(0); using (Resource pDest = texture.Resource) device.CopyResource(staging, pDest); }

(again, not sure what the 1st argument of Map() / Unmap() is …)

 

Rendering pipeline and shader bytecode signature

In Direct3D input data, i.e. the vertices with their (optional) texture coordinate, normal and color go through what’s called a rendering pipeline. Having trouble finding an explanation about it again here is a Wikipedia article about it:

 

The Microsoft Direct3D 10 API defines a process to convert a group of vertices, textures, buffers, and state into an image on the screen. This process is described as a rendering pipeline with several distinct stages. The different stages of the Direct3D 10 pipeline[29] are:[30]

  1. Input Assembler: Reads in vertex data from an application supplied vertex buffer and feeds them down the pipeline.
  2. Vertex Shader: Performs operations on a single vertex at a time, such as transformations, skinning, or lighting.
  3. Geometry Shader: Processes entire primitives such as triangles, points, or lines. Given a primitive, this stage discards it, or generates one or more new primitives.
  4. Stream Output: Can write out the previous stage's results to memory. This is useful to recirculate data back into the pipeline.
  5. Rasterizer: Converts primitives into pixels, feeding these pixels into the pixel shader. The Rasterizer may also perform other tasks such as clipping what is not visible, or interpolating vertex data into per-pixel data.
  6. Pixel Shader: Determines the final pixel colour to be written to the render target and can also calculate a depth value to be written to the depth buffer.
  7. Output Merger: Merges various types of output data (pixel shader values, alpha blending, depth/stencil...) to build the final result.

The pipeline stages illustrated with a round box are fully programmable. The application provides a shader program that describes the exact operations to be completed for that stage. Many stages are optional and can be disabled altogether.

 

Another thing I understood is what is this signature thing is all about!

When drawing you should set the input layout of the data. This input layout need some sort of byte code signature, as in:

 

// initialization
var inputSignature = ShaderSignature.GetInputSignature(pVSBlob);
var layout = new InputLayout(Device, inputSignature, new[]{
    new InputElement("VERTEX", 0, Format.R32G32B32_Float, 0),
});

// rendering
Device.InputAssembler.SetInputLayout(layout);
//......

In here signature is not about signing your code / security. It’s about checking that the InputLayout defined in code matches the input of the vertex shader (i.e. the entry point of the rendering pipeline). It’s why the signature always from the vertex shader definition.

 

Effects

Somehow I found the declaration of the various shaders involved in your rendering pipelines quite cumbersome. Now apparently there is a way to do it all in the HLSL file by using effects. An effect (in your HLSL file) look like that:

technique10 RenderTileDiff10
{
    pass p0
    {
        SetVertexShader( CompileShader( vs_4_0, VSBasic() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PSTerrain(false) ) ); 
        
        SetDepthStencilState( EnableDepth, 0 );
        SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
        SetRasterizerState( CullBack );  
    }  
}

It looks like the C++ / C# code for setting up your pipeline, just much more compact!

Once you created a few effects, to use them you got to: compiler your shader file and get a point to the technique of choice.

To create the layout you will need to get the effect’s vertex shader (for the signature)

Here is some pseudo code that use the above effect and do initialization and rendering

//====== Initialization =============
// compile the shader and get the effect
var sbytecode = ShaderBytecode.CompileFromFile(
    "ContentStream\\ContentStream.fx",
    "fx_4_0",
    sFlags, EffectFlags.None, null, null);
var myEffect = new Effect(Device, sbcfile);

// get the technique(s) of interest
var myTechnique = myEffect.GetTechniqueByName("RenderTileDiff10");

// define input data layout
var inputdesc = new InputElement[]
{
    // Lloyd: watch out! trap! offset and slot are swapped between C++ and C#
    new InputElement ( "POSITION", 0, Format.R32G32B32_Float,  0, 0, InputClassification.PerVertexData, 0 ),
    new InputElement ( "NORMAL",   0, Format.R32G32B32_Float, 12, 0, InputClassification.PerVertexData, 0 ),
    new InputElement ( "TEXCOORD", 0, Format.R32G32_Float,    24, 0, InputClassification.PerVertexData, 0 ),
};
var PassDesc = myTechnique.GetPassByIndex(0).Description;
var vertexsignature = PassDesc.Signature;
var inputlayout = new InputLayout(Device, vertexsignature, inputdesc);

// ======== Rendering ===
// set a shader variable
var mWorld = myEffect.GetVariableByName("g_mView").AsMatrix();
mWorld.SetMatrix(CurrentCamera.View);

// render with a technique
var Desc = myTechnique.Description;
for (int iPass = 0; iPass < Desc.PassCount; iPass++)
{
    myTechnique.GetPassByIndex(iPass).Apply();
    Device.DrawIndexed(g_Terrain.NumIndices, 0, 0);
}

Still not sure what the passes are about though.

 

 

Direct3D 9, 10, 11

There is 2 sides to Direct3D. There is the runtime API installed on your computer and there is the feature level (as it is called since D3D 10.1) supported by the video card. So while you might have DirectX 11 installed on your system, your video card might only support Direct3D 10.0 perhaps.

One thing with the D3D 10.1 runtime and up (if it’s installed, by your installer for example) is that you can use whatever version of D3D you like, but target (or use) a given feature level. The difference between each feature level is summarized there.

 

Anyhow I had various problem and success with each version of D3D.

I’m working on those sample at home and everything works fine. At work it doesn’t though, due to my work video card only supporting D3D10 (and maybe some incorrect initialization, hardware testing on my part).

Also, first, to be rendered in D3DImage the render targets should be compatible with D3D9 surface. In the case of D3D 10 and 11 that means they should be defined with ResourceOptionFlags.Shared. But this is not supported by D3D10! (only D3D10.1). It’s hard for me to test as my computer has a D3D11 compatible card, I still have some initialization issue on low end computer for lack of testing machine.

Secondly, while D3D11 include some new amazing features such as computing shader! (talk about parallel processing!), geometry shader with which you can do realistic fur or high performance software renderer the WARP device, it has no support for text and font at all! Although (I have to test) supposedly one can render part of the scene with D3D10 (the text for example) and use the resulting texture in D3D11 directly as the surface have a compatible format.

 

Camera

I learn I need a camera class to describe and manipulate the world, view and projection matrices! I was inspired by DXUTCamera.h and write class very similar to the sample.

Camera has the following interesting methods

public abstract partial class BaseCamera
{
    public BaseCamera()


public void SetViewParams(Vector3 eye, Vector3 lookAt) public virtual void SetViewParams(Vector3 eye, Vector3 lookAt, Vector3 vUp) public void Reset() public Vector3 Position public Vector3 LookAt public Vector3 Up public Matrix View { get { return mView; } } public void SetProjParams(float fFOV, float fAspect, float fNearPlane, float fFarPlane) public float NearPlane public float FarPlane public float AspectRatio public float FieldOfView public Matrix Projection { get { return mProj; } } public void FrameMove(TimeSpan elapsed) } public partial class FirstPersonCamera : BaseCamera
public partial class ModelViewerCamera : BaseCamera

Remark lookAt is the point the camera is looking at, not the direction it’s gazing at!

 

It contains the current view and project matrix. Handle key and mouse input by changing the view matrix. It also can change the view matrix with an elapsed time (for changing the view between each frame, when keys are down).

It’s imperfect (I think I will write a better one once I start porting Babylon from XNA to DirectX+WPF) though.

Ha, well, when experimenting with camera I had to read about… quaternions! Which I only feared by name until now.

I won’t say I master quaternion yet! Ho no!

But I understand enough to be dangerous. Here is some good introductory links on Quaternions


Tags: , ,
Categories: .NET | DirectX | WPF
Permalink | Comments (0) | Post RSSRSS comment feed

Introduction to COM

Found this excellent introduction to COM by Jeremiah Morill on his blog there.

Here is the introduction (follow the link for the full post!)

To some .NET developers, COM is a dirty little turd that no matter how hard they try, it won’t flush.   Microsoft and other vendors keep on pumping out new COM based SDKs year after year.  Sometimes these APIs are directly consumable by .NET and in the case they are not, you can visibly see developers’ anxiety rise at the thought of working directly with COM.  There’s a lot of beef with a lot of developers about COM.  Where does it all come from?

image

“I did XYZ in COM and I couldn’t make it work, so COM sucks”, “I used ABC COM technology and it was way too overcomplicated” and the variations are things that have been heard and are wide spread.  While the fact that so many developers have these grievances about COM is generally relevant, it is also not very fair.  Imagine looking at .NET for the first time and diving right into WCF or Workflow and saying “I got burned by it, so .NET blows”.

… (continued on Jeremiah’s blog)…


Tags: ,
Categories: .NET | link
Permalink | Comments (0) | Post RSSRSS comment feed