C# 将 UserControl 添加到 TabControl 然后使用 SharpDX 渲染

C# Add UserControl to TabControl then rendering with SharpDX

如标​​题所述,我将 UserControl 添加到 TabControl。这很好用。但是当我开始使用 SharpDX.Direct3D11 渲染到这个 UserControl 时,选项卡消失了。

我试图让它尽可能简单,以使控件正常工作。我用来呈现给控件的代码来自提供的示例。 当我在提供的解决方案中构建 "MiniCube" 示例时,它正在运行。

这是我用来渲染的代码:

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();
    }
  }
}

我没有收到任何异常或其他任何信息。选项卡就消失了,仅此而已。据我所知,代码是 运行,这是我在调试会话中检查过的。

SharpDXRenderManager 仅从 UserControl 本身调用,此处代码:

public partial class Planner : UserControl
{
        private SharpDXRenderManager renderManager;

        public Planner()
        {
            InitializeComponent();

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

问题是我在初始化后立即开始了渲染过程。我通过调用 OnLoad(EventArgs e) 事件中的 Render() 方法解决了这个问题。