Search code examples
c#user-controlsdirectxsharpdx

C# Add UserControl to TabControl then rendering with SharpDX


like in the title said, i add an UserControl to a TabControl. This is just working fine. But when i'm starting to Render to this UserControl using SharpDX.Direct3D11 the tab disappears.

I tried to keep it as simple as possible to get the control working. The code i use to render to the control is from the provided samples. The "MiniCube" sample is working when i build it in the provided solution.

Here is the code i use to render:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using SDX = SharpDX;
using SharpDX.D3DCompiler;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using SharpDX.Windows;
using Buffer = SharpDX.Direct3D11.Buffer;
using Device = SharpDX.Direct3D11.Device;
using OpenTK;


namespace mynamespace.SharpDX
{
   public class SharpDXRenderManager
   {
    private UserControl renderTarget;

    public SharpDXRenderManager(UserControl renderTarget)
    {
        this.renderTarget = renderTarget;
    }

    public void Render()
    {
        var desc = new SDX.DXGI.SwapChainDescription()
        {
            BufferCount = 1,
            ModeDescription = new SDX.DXGI.ModeDescription(this.renderTarget.ClientSize.Width, this.renderTarget.ClientSize.Height, new SDX.DXGI.Rational(60, 1), Format.R8G8B8A8_UNorm),
            IsWindowed = true,
            OutputHandle = this.renderTarget.Handle,
            SampleDescription = new SampleDescription(1, 0),
            SwapEffect = SwapEffect.Discard,
            Usage = Usage.RenderTargetOutput
        };

        Device device;
        SwapChain swapChain;
        Device.CreateWithSwapChain(SDX.Direct3D.DriverType.Hardware, SDX.Direct3D11.DeviceCreationFlags.Debug, desc, out device, out swapChain);
        var context = device.ImmediateContext;

        var factory = swapChain.GetParent<Factory>();
        factory.MakeWindowAssociation(this.renderTarget.Handle, WindowAssociationFlags.IgnoreAll);

        var vertexShaderByteCode = SDX.D3DCompiler.ShaderBytecode.CompileFromFile(mypath, "VS", "vs_4_0");
        var vertexShader = new SDX.Direct3D11.VertexShader(device, vertexShaderByteCode);

        var pixelShaderByteCode = SDX.D3DCompiler.ShaderBytecode.CompileFromFile(mypath, "PS", "ps_4_0");
        var pixelShader = new SDX.Direct3D11.PixelShader(device, pixelShaderByteCode);

        var signature = SDX.D3DCompiler.ShaderSignature.GetInputSignature(vertexShaderByteCode);

        var layout = new SDX.Direct3D11.InputLayout(device, signature, new[]
        {
            new SDX.Direct3D11.InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
            new SDX.Direct3D11.InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0)
        });

        var vertices = Buffer.Create(device, SDX.Direct3D11.BindFlags.VertexBuffer, new[]
        {
            new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), // Front
            new Vector4(-1.0f,  1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
            new Vector4( 1.0f,  1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
            new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
            new Vector4( 1.0f,  1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
            new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),

            new Vector4(-1.0f, -1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), // BACK
            new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
            new Vector4(-1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
            new Vector4(-1.0f, -1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
            new Vector4( 1.0f, -1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
            new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),

            new Vector4(-1.0f, 1.0f, -1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), // Top
            new Vector4(-1.0f, 1.0f,  1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
            new Vector4( 1.0f, 1.0f,  1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
            new Vector4(-1.0f, 1.0f, -1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
            new Vector4( 1.0f, 1.0f,  1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
            new Vector4( 1.0f, 1.0f, -1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),

            new Vector4(-1.0f,-1.0f, -1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), // Bottom
            new Vector4( 1.0f,-1.0f,  1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
            new Vector4(-1.0f,-1.0f,  1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
            new Vector4(-1.0f,-1.0f, -1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
            new Vector4( 1.0f,-1.0f, -1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
            new Vector4( 1.0f,-1.0f,  1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),

            new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), // Left
            new Vector4(-1.0f, -1.0f,  1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
            new Vector4(-1.0f,  1.0f,  1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
            new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
            new Vector4(-1.0f,  1.0f,  1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
            new Vector4(-1.0f,  1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),

            new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), // Right
            new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
            new Vector4( 1.0f, -1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
            new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
            new Vector4( 1.0f,  1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
            new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
        });

        var contantBuffer = new Buffer(device, SDX.Utilities.SizeOf<Matrix4>(), SDX.Direct3D11.ResourceUsage.Default, SDX.Direct3D11.BindFlags.ConstantBuffer, SDX.Direct3D11.CpuAccessFlags.None, SDX.Direct3D11.ResourceOptionFlags.None, 0);

        context.InputAssembler.InputLayout = layout;
        context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
        context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, SDX.Utilities.SizeOf<Vector4>() * 2, 0));
        context.VertexShader.SetConstantBuffer(0, contantBuffer);
        context.VertexShader.Set(vertexShader);
        context.PixelShader.Set(pixelShader);

        var view = Matrix4.LookAt(new Vector3(0, 0, -5), new Vector3(0, 0, 0), Vector3.UnitY);
        var proj = Matrix4.Identity;

        var clock = new Stopwatch();
        clock.Start();

        bool userResized = true;
        Texture2D backBuffer = null;
        RenderTargetView renderView = null;
        Texture2D depthBuffer = null;
        DepthStencilView depthView = null;

        this.renderTarget.Resize += (sender, args) => userResized = true;

        RenderLoop.Run(this.renderTarget, () =>
        {
            if (userResized)
            {
                SDX.Utilities.Dispose(ref backBuffer);
                SDX.Utilities.Dispose(ref renderView);
                SDX.Utilities.Dispose(ref depthBuffer);
                SDX.Utilities.Dispose(ref depthView);

                swapChain.ResizeBuffers(desc.BufferCount, this.renderTarget.ClientSize.Width, renderTarget.ClientSize.Height, Format.Unknown, SwapChainFlags.None);

                backBuffer = Texture2D.FromSwapChain<Texture2D>(swapChain, 0);

                renderView = new RenderTargetView(device, backBuffer);

                depthBuffer = new Texture2D(device, new Texture2DDescription()
                {
                    Format = Format.D32_Float_S8X24_UInt,
                    ArraySize = 1,
                    MipLevels = 1,
                    Width = this.renderTarget.ClientSize.Width,
                    Height = this.renderTarget.ClientSize.Height,
                    SampleDescription = new SampleDescription(1, 0),
                    Usage = ResourceUsage.Default,
                    BindFlags = BindFlags.DepthStencil,
                    CpuAccessFlags = CpuAccessFlags.None,
                    OptionFlags = ResourceOptionFlags.None
                });

                depthView = new DepthStencilView(device, depthBuffer);

                context.Rasterizer.SetViewport(0f, 0f, this.renderTarget.ClientSize.Width, this.renderTarget.ClientSize.Height, 0f, 1f);
                context.OutputMerger.SetTargets(depthView, renderView);

                proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, this.renderTarget.ClientSize.Width / (float)this.renderTarget.ClientSize.Height, 0.1f, 100f);

                userResized = false;
            }

            var time = clock.ElapsedMilliseconds / 1000f;

            var viewProj = Matrix4.Mult(view, proj);

            context.ClearDepthStencilView(depthView, DepthStencilClearFlags.Depth, 1f, 0);
            context.ClearRenderTargetView(renderView, new SDX.Mathematics.Interop.RawColor4(255f, 255f, 255f, 255f));

            var worldViewProj = Matrix4.CreateRotationX(time) * Matrix4.CreateRotationY(time * 2f) * Matrix4.CreateRotationZ(time * 0.7f) * viewProj;
            worldViewProj.Transpose();
            context.UpdateSubresource(ref worldViewProj, contantBuffer);

            swapChain.Present(0, PresentFlags.None);
        });

        signature.Dispose();
        vertexShaderByteCode.Dispose();
        vertexShader.Dispose();
        pixelShaderByteCode.Dispose();
        pixelShader.Dispose();
        vertices.Dispose();
        layout.Dispose();
        contantBuffer.Dispose();
        depthBuffer.Dispose();
        depthView.Dispose();
        renderView.Dispose();
        backBuffer.Dispose();
        context.ClearState();
        context.Flush();
        device.Dispose();
        context.Dispose();
        swapChain.Dispose();
        factory.Dispose();
    }
  }
}

I don't get any Exceptions or anything else. The Tab just disappears and that#s all. As far as i could tell the code is running, this i have checked in a debug session.

The SharpDXRenderManager is only called from the UserControl itself, here the code:

public partial class Planner : UserControl
{
        private SharpDXRenderManager renderManager;

        public Planner()
        {
            InitializeComponent();

            renderManager = new SharpDXRenderManager(this);
            renderManager.Render();
        }
}

Solution

  • The Problem is that i have started the render process straight after the initialization. I solved it by calling the Render() method in the the OnLoad(EventArgs e) Event.