Combining XAML and DirectX together in a WinRT application

With the release of Windows 8, Microsoft introduced a grate technology for combining XAML and DirectX together, letting us to place XAML controls over intensive real-time graphics, see DirectX and XAML interop (Windows Runtime apps using DirectX with C++) for more details.

You can easily download and build sample XAML SwapChainPanel DirectX interop sample demonstrating how it works. All that you need is Visual Studio 2013 with installed license. After the license is installed Visual Studio 2013 shows the following dialog:

Visual Studio 2013 license

Open the solution in Visual Studio 2013, and open Configuration Manger:

Visual Studio 2013 Configuration Manger

And from here select x86 as the active configuration:

Visual Studio 2013 Configuration Manger

Start the application pressing F5. The first deployment should produce the following output:

1>------ Deploy started: Project: SwapChainPanel, Configuration: Debug x86 ------
1>Creating a new clean layout...
1>Copying files: Total 2 mb to layout...
1>Checking whether required frameworks are installed...
1>Framework: Microsoft.VCLibs.120.00.Debug/x86, app package version 12.0.21005.1 is not currently installed.
1>Installing missing frameworks...
1>Registering the application to run from layout...

Probably it is something specific to Microsoft Store applications.

Some antivirus can cause an exception at the first application start, but in common I do not see anything that can prevent the application from work except problems with the license. Below I provided some a screen shot of the application window:

Combining XAML and DirectX together in a WinRT application

Also an application of this kind can be created in Visual Studio 2013 by clicking File->New->Project and selecting corresponding template in the opened dialog:

New Windows App

It generates simple XAML with SwapChainPanel  that shows rotating cube and at the same time acts as a usual WPF Grid with columns and rows, so I easily added some simple controls to SwapChainPanel :

<Page
    x:Class="DirectXApp.DirectXPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:DirectXApp"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" FontSize="30">

  <SwapChainPanel x:Name="swapChainPanel">
        <SwapChainPanel.ColumnDefinitions>
            <ColumnDefinition Width="50*"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="50*"/>
        </SwapChainPanel.ColumnDefinitions>
        <SwapChainPanel.RowDefinitions>
            <RowDefinition Height="50*"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="50*"/>
        </SwapChainPanel.RowDefinitions>
        <StackPanel Orientation="Vertical" Margin="100, 100, 10, 10">
            <TextBlock Text="Opacity:"/>
            <Slider Name="opacitySlider" Minimum="0.0" Maximum="1.0" Value="0.5" Width="500" SmallChange="0.1" LargeChange="0.1" StepFrequency="0.1" TickFrequency="0.1" TickPlacement="BottomRight" />
        </StackPanel>  
        <StackPanel Grid.Column="1" Grid.Row="1" Orientation="Vertical">
            <Border BorderBrush="Green" Background="Yellow" BorderThickness="1" Opacity="{Binding Path=Value, ElementName=opacitySlider, Mode=OneWay}" CornerRadius="15" Margin="5">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="400"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <TextBlock Grid.Column="0" Grid.Row="0" Text="123°" Margin="7, 3, 1, 3"/>
                    <TextBlock Grid.Column="1" Grid.Row="0" Text="15kn°" Margin="7, 3, 1, 3"/>
                    <TextBox Grid.Column="2" Grid.Row="0" Grid.RowSpan="2" Margin="3, 3, 7, 3" FontSize="25" TextWrapping="Wrap" IsSpellCheckEnabled="True" AcceptsReturn="True" Text="This is a something like a target label with course and speed. We can move it over the chart panel."/>
                    <TextBox Grid.Column="0" Grid.Row="1" Text="127°" Margin="7, 3, 3, 7" FontSize="30"/>
                    <TextBox Grid.Column="1" Grid.Row="1" Text="10kn°" Margin="7, 3, 3, 7" FontSize="30"/>
                </Grid>
            </Border>
        </StackPanel>
    </SwapChainPanel>

  <Page.BottomAppBar>
    <AppBar x:Name="bottomAppBar" Padding="10,0,10,0">
      <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
        <AppBarButton AutomationProperties.Name="Sample Button"
                      AutomationProperties.AutomationId="SampleAppBarButton"
                      Click="AppBarButton_Click"/>
      </StackPanel>
    </AppBar>
  </Page.BottomAppBar>
</Page>

1 Response to Combining XAML and DirectX together in a WinRT application

  1. superadmin says:

    They removed the following call from StartRenderLoop() in VS2015 DirectX and XAML interop template:

    // Halt the thread until the next vblank is reached.
    // This ensures the app isn’t updating and rendering faster than the display can refresh,
    // which would unnecessarily spend extra CPU and GPU resources. This helps improve battery life.
    m_dxgiOutput->WaitForVBlank();

    of cause it makes live easier, but not so interesting.

    m_dxgiOutput is an interface obtained from dxgiFactory:

    Microsoft::WRL::ComPtr m_dxgiOutput;

    // Retrieve DXGIOutput representing the main adapter output.
    ComPtr dxgiFactory;
    ThrowIfFailed(
    CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory))
    );

    ComPtr dxgiAdapter;
    ThrowIfFailed(
    dxgiFactory->EnumAdapters(0, &dxgiAdapter)
    );

    ThrowIfFailed(
    dxgiAdapter->EnumOutputs(0, &m_dxgiOutput)
    );

    but in all the cases the both samples use m_swapChain->Present1(1, 0, &parameters) that instructs DXGI to block until VSync, putting the application to sleep until the next VSync

Leave a Reply

Your email address will not be published. Required fields are marked *