Jump to content
  • Advertisement
Sign in to follow this  
Quat

SlimDX and UserControl

This topic is 3045 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have created a new control that derives from UserControl. In that control, I add the D3D device, swapchain, etc, and that control will present a 3D display. I am having some repainting issues in that the control does not seem to like when Invalidate() is called to repaint itself. Inside the repaint I have:
protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            if(_d3dDevice != null)
            {
                _d3dDevice.ClearRenderTargetView(_renderTargetView, Color.Blue);
                _d3dDevice.ClearDepthStencilView(_depthStencilView, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1.0f, 0);

                _swapChain.Present(0, PresentFlags.None);
            }
        }
However, on the first paint something is not working because the control is painted gray and not Blue. If I resize the window (not having overridden OnResize, it turns Blue). If I override OnResize, and call Invalidate from it, it turns gray. What is strange is I have copy and paste the same D3D initialization code into a Form, and it works correctly. Anyone know why a UserControl might be throwing it off?
private void InitDirect3D()
        {
            SwapChainDescription sd = new SwapChainDescription();
            sd.ModeDescription = new ModeDescription(Width, Height, new SlimDX.Rational(60, 1), Format.R8G8B8A8_UNorm);
            sd.SampleDescription = new SampleDescription(1, 0);
            sd.Usage = Usage.RenderTargetOutput;
            sd.BufferCount = 1;
            sd.OutputHandle = Handle;
            sd.IsWindowed = true;
            sd.SwapEffect = SwapEffect.Discard;
            sd.Flags = SwapChainFlags.None;

            // Create the device.

            DeviceCreationFlags createDeviceFlags = DeviceCreationFlags.None;
#if DEBUG
            createDeviceFlags |= DeviceCreationFlags.Debug;
#endif

            SlimDX.Direct3D10.Device.CreateWithSwapChain(null, DriverType.Hardware,
                createDeviceFlags, sd, out _d3dDevice, out _swapChain);

            ResizeBackBuffer();
        }

        private void ResizeBackBuffer()
        {
            // Release the old views, as they hold references to the buffers we
            // will be destroying.  Also release the old depth/stencil buffer.

            if(_renderTargetView != null)
                _renderTargetView.Dispose();

            if(_depthStencilView != null)
                _depthStencilView.Dispose();

            if(_depthStencilBuffer != null)
                _depthStencilBuffer.Dispose();


            _swapChain.ResizeBuffers(1, ClientSize.Width, ClientSize.Height, Format.R8G8B8A8_UNorm, SwapChainFlags.None);

            Texture2D backBuffer = Texture2D.FromSwapChain<Texture2D>(_swapChain, 0);
            _renderTargetView = new RenderTargetView(_d3dDevice, backBuffer);
            backBuffer.Dispose();

            // Create the depth/stencil buffer and view.

            Texture2DDescription depthStencilDesc = new Texture2DDescription();
            depthStencilDesc.Width = ClientSize.Width;
            depthStencilDesc.Height = ClientSize.Height;
            depthStencilDesc.MipLevels = 1;
            depthStencilDesc.ArraySize = 1;
            depthStencilDesc.Format = Format.D24_UNorm_S8_UInt;
            depthStencilDesc.SampleDescription = new SampleDescription(1, 0);
            depthStencilDesc.Usage = ResourceUsage.Default;
            depthStencilDesc.BindFlags = BindFlags.DepthStencil;
            depthStencilDesc.CpuAccessFlags = 0;
            depthStencilDesc.OptionFlags = ResourceOptionFlags.None;

            _depthStencilBuffer = new Texture2D(_d3dDevice, depthStencilDesc);
            _depthStencilView = new DepthStencilView(_d3dDevice, _depthStencilBuffer);

            // Bind the render target view and depth/stencil view to the pipeline.

            _d3dDevice.OutputMerger.SetTargets(_depthStencilView, _renderTargetView);


            // Set the viewport transform.

            Viewport vp = new Viewport(0, 0, ClientSize.Width, ClientSize.Height, 0.0f, 1.0f);
            _d3dDevice.Rasterizer.SetViewports(vp);
        }

protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (!DesignMode)
            {
                InitDirect3D();
            }
        }

private SlimDX.Direct3D10.Device _d3dDevice;
        private SwapChain _swapChain;

        private Texture2D _depthStencilBuffer;
        private RenderTargetView _renderTargetView;
        private DepthStencilView _depthStencilView;

Share this post


Link to post
Share on other sites
Advertisement
You'll want to also override OnPaintBackground and have it do nothing, since by default that method will clear the client area to the control's background color.

Share this post


Link to post
Share on other sites
Quote:

You'll want to also override OnPaintBackground and have it do nothing, since by default that method will clear the client area to the control's background color.


I tried that already, and still no luck. By the way, I don't think that is needed except to avoid flicker. In the Form version that does work, I added

Quote:

protected override void OnPaintBackground(PaintEventArgs e)
{

}


and it prevents flicker when I resize the window, for example. If I add it to the version that uses the UserControl (form with my UserControl with Fill docking), then I get the situation I originally described but the color is black instead of gray on the first paint.

Share this post


Link to post
Share on other sites
I am still working on this. Here is the simple code to show the problem.


New UserControl:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using SlimDX;
using SlimDX.Direct3D10;
using SlimDX.DXGI;

namespace SkyConfig
{
public partial class Direct3DControl : UserControl
{
#region Private Fields

private SlimDX.Direct3D10.Device _d3dDevice;
private SwapChain _swapChain;

private Texture2D _depthStencilBuffer;
private RenderTargetView _renderTargetView;
private DepthStencilView _depthStencilView;

#endregion

#region Public Methods

public Direct3DControl()
{
InitializeComponent();

}


#endregion

#region Protected Methods

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
Effects.DisposeAll();
InputLayouts.DisposeAll();

if( _renderTargetView != null )
_renderTargetView.Dispose();

if (_depthStencilView != null)
_depthStencilView.Dispose();

if (_depthStencilBuffer != null)
_depthStencilBuffer.Dispose();

if (_swapChain != null)
_swapChain.Dispose();

if (_d3dDevice != null)
_d3dDevice.Dispose();

if(disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);

if (!DesignMode)
{
InitDirect3D();
}
}

protected override void OnResize(EventArgs e)
{
base.OnResize(e);

if( _d3dDevice != null && (Width > 0) && (Height > 0) )
{
ResizeBackBuffer();
//SetProjection();

// The control is not repainted when we size down, but we need it to.
Invalidate();
}
}

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);

// Don't use Direct3D in design mode.
if (DesignMode || _d3dDevice == null)
{
e.Graphics.Clear(Color.White);
}
else
{
if (_d3dDevice != null)
{
_d3dDevice.ClearRenderTargetView(_renderTargetView, Color.Blue);
_d3dDevice.ClearDepthStencilView(_depthStencilView, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1.0f, 0);

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

protected override void OnPaintBackground(PaintEventArgs e)
{

}

#endregion


#region Private Methods

private void InitDirect3D()
{
SwapChainDescription sd = new SwapChainDescription();
sd.ModeDescription = new ModeDescription(Width, Height, new SlimDX.Rational(60, 1), Format.R8G8B8A8_UNorm);
sd.SampleDescription = new SampleDescription(1, 0);
sd.Usage = Usage.RenderTargetOutput;
sd.BufferCount = 1;
sd.OutputHandle = Handle;
sd.IsWindowed = true;
sd.SwapEffect = SwapEffect.Discard;
sd.Flags = SwapChainFlags.None;

// Create the device.

DeviceCreationFlags createDeviceFlags = DeviceCreationFlags.None;
#if DEBUG
createDeviceFlags |= DeviceCreationFlags.Debug;
#endif

SlimDX.Direct3D10.Device.CreateWithSwapChain(null, DriverType.Hardware,
createDeviceFlags, sd, out _d3dDevice, out _swapChain);

ResizeBackBuffer();
}

private void ResizeBackBuffer()
{
// Release the old views, as they hold references to the buffers we
// will be destroying. Also release the old depth/stencil buffer.

if(_renderTargetView != null)
_renderTargetView.Dispose();

if(_depthStencilView != null)
_depthStencilView.Dispose();

if(_depthStencilBuffer != null)
_depthStencilBuffer.Dispose();


_swapChain.ResizeBuffers(1, ClientSize.Width, ClientSize.Height, Format.R8G8B8A8_UNorm, SwapChainFlags.None);

Texture2D backBuffer = Texture2D.FromSwapChain<Texture2D>(_swapChain, 0);
_renderTargetView = new RenderTargetView(_d3dDevice, backBuffer);
backBuffer.Dispose();

// Create the depth/stencil buffer and view.

Texture2DDescription depthStencilDesc = new Texture2DDescription();
depthStencilDesc.Width = ClientSize.Width;
depthStencilDesc.Height = ClientSize.Height;
depthStencilDesc.MipLevels = 1;
depthStencilDesc.ArraySize = 1;
depthStencilDesc.Format = Format.D24_UNorm_S8_UInt;
depthStencilDesc.SampleDescription = new SampleDescription(1, 0);
depthStencilDesc.Usage = ResourceUsage.Default;
depthStencilDesc.BindFlags = BindFlags.DepthStencil;
depthStencilDesc.CpuAccessFlags = 0;
depthStencilDesc.OptionFlags = ResourceOptionFlags.None;

_depthStencilBuffer = new Texture2D(_d3dDevice, depthStencilDesc);
_depthStencilView = new DepthStencilView(_d3dDevice, _depthStencilBuffer);

// Bind the render target view and depth/stencil view to the pipeline.

_d3dDevice.OutputMerger.SetTargets(_depthStencilView, _renderTargetView);


// Set the viewport transform.

Viewport vp = new Viewport(0, 0, ClientSize.Width, ClientSize.Height, 0.0f, 1.0f);
_d3dDevice.Rasterizer.SetViewports(vp);
}

#endregion

}
}




For the main form, I only do the following. I add a menu strip, I add a panel docked to the right, and I add the Direct3DControl above docked with "Fill".

Share this post


Link to post
Share on other sites
It seems like a SlimDX issue because I rewrote the UserControl in C++/CLI and dropped it into the C# Form, and it is working as expected. I would like to use SlimDX still, so hopefully someone knows the solution.

Share this post


Link to post
Share on other sites
Very weird, I copy and paste your code and is working. Also I comment the lines:

Effects.DisposeAll();
InputLayouts.DisposeAll();

Do you have the lastes release? (feb. 2010)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!