Jump to content
  • Advertisement
Sign in to follow this  
Wavarian

OpenGL Getting started with D3D in C#: InvalidCallException

This topic is 1505 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

Hey guys, figured I'd finally take a break from OpenGL to look at some Direct3D in C# and stumbled upon this tutorial:

 

http://msdn.microsoft.com/en-us/library/windows/desktop/bb153258%28v=vs.85%29.aspx

 

Works fine except for when you resize the window such that its client-height becomes 0; in which case the device suddenly becomes invalid and throws an InvalidCallException whenever you try to use it again.

 

This is the code I wrote while following the tutorial:

//
// D3DForm.cs
//



//
// Includes
//

using System.Drawing;
using System.Windows.Forms;

using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;



//
// D3DForm class definition
//

class D3DForm : Form
{
	//
	// Used to manage a D3D rendering device
	//

	private Device m_device = null;

	//=========================================================================
	//
	// DESCRIPTION
	//
	//		Constructor
	//
	// PARAMETERS
	//
	// RETURNS
	//
	//=========================================================================

	public D3DForm()
	{
		//
		// Initialize the form
		//

		this.ClientSize = new Size(640, 480);
	}

	//=========================================================================
	//
	// DESCRIPTION
	//
	//		Initializes the D3D rendering device
	//
	// PARAMETERS
	//
	// RETURNS
	//
	//		Returns true if successful
	//
	//=========================================================================

	public bool InitializeGraphics()
	{
		try
		{
			PresentParameters present_params = new PresentParameters();

			present_params.Windowed = true;
			present_params.SwapEffect = SwapEffect.Discard;

			m_device = new Device
			(
				0,
				DeviceType.Hardware,
				this,
				CreateFlags.SoftwareVertexProcessing,
				present_params
			);
		}
		catch(DirectXException)
		{
			return false;
		}

		return true;
	}

	//=========================================================================
	//
	// DESCRIPTION
	//
	//		Renders the scene
	//
	// PARAMETERS
	//
	// RETURNS
	//
	//=========================================================================

	public void Render()
	{
		if(m_device != null)
		{
			m_device.Clear(ClearFlags.Target, Color.Blue, 1.0f, 0); // InvalidCallException thrown
			m_device.BeginScene();

			m_device.EndScene();
			m_device.Present();
		}
	}

	//=========================================================================
	//
	// DESCRIPTION
	//
	//		Application entry point
	//
	// PARAMETERS
	//
	// RETURNS
	//
	//=========================================================================

	private static void Main()
	{
		using(D3DForm form = new D3DForm())
		{
			if(form.InitializeGraphics())
			{
				form.Show();

				//
				// Application loop
				//

				while(form.Created)
				{
					form.Render();

					Application.DoEvents();
				}
			}
		}
	}
}

How do I repair the device once this happens? How do I prevent it from becoming invalid - do I have to prevent the window's client-size from becoming zero?

 

Thanks!

Edited by Wavarian

Share this post


Link to post
Share on other sites
Advertisement

I'm guessing that I'll need to reset the device whenever rendering fails like so:

//
// D3DForm.cs
//



//
// Includes
//

using System.Drawing;
using System.Windows.Forms;

using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;



//
// D3DForm class definition
//

class D3DForm : Form
{
	//
	// Used to manage a D3D rendering device
	//

	private Device m_device = null;

	//=========================================================================
	//
	// DESCRIPTION
	//
	//		Constructor
	//
	// PARAMETERS
	//
	// RETURNS
	//
	//=========================================================================

	public D3DForm()
	{
		//
		// Initialize the form
		//

		this.ClientSize = new Size(640, 480);
	}

	//=========================================================================
	//
	// DESCRIPTION
	//
	//		Initializes the D3D rendering device
	//
	// PARAMETERS
	//
	// RETURNS
	//
	//		Returns true if successful
	//
	//=========================================================================

	public bool InitializeGraphics()
	{
		try
		{
			PresentParameters present_params = new PresentParameters();

			present_params.Windowed = true;
			present_params.SwapEffect = SwapEffect.Discard;

			if(m_device == null)
			{
				m_device = new Device
				(
					0,
					DeviceType.Hardware,
					this,
					CreateFlags.SoftwareVertexProcessing,
					present_params
				);
			}
			else
			{
				m_device.Reset(present_params);
			}
		}
		catch(DirectXException)
		{
			return false;
		}

		return true;
	}

	//=========================================================================
	//
	// DESCRIPTION
	//
	//		Renders the scene
	//
	// PARAMETERS
	//
	// RETURNS
	//
	//=========================================================================

	public void Render()
	{
		if(m_device != null)
		{
			try
			{
				m_device.Clear(ClearFlags.Target, Color.Blue, 1.0f, 0);
				m_device.BeginScene();

				m_device.EndScene();
				m_device.Present();
			}
			catch(DirectXException)
			{
				InitializeGraphics();
			}
		}
	}

	//=========================================================================
	//
	// DESCRIPTION
	//
	//		Application entry point
	//
	// PARAMETERS
	//
	// RETURNS
	//
	//=========================================================================

	private static void Main()
	{
		using(D3DForm form = new D3DForm())
		{
			if(form.InitializeGraphics())
			{
				form.Show();

				//
				// Application loop
				//

				while(form.Created)
				{
					form.Render();

					Application.DoEvents();
				}
			}
		}
	}
}

No idea if this is the proper solution though.

Edited by Wavarian

Share this post


Link to post
Share on other sites

In D3D9 you can have a "Lost Device" scenario, and you have to recover from it by calling Reset on your device. It's a real pain to deal with in a robust way, and is the source of a lot of errors. Fortunately they fixed it for D3D10/D3D11.

I should definitely warn you that the "Managed DirectX" library you're using is very old, and hasn't been updated in many years. Microsoft essentially abandoned it, and left the task of a managed DirectX wrapper up to the community. Earlier on SlimDX was the most popular Managed DX wrapper, but these days SharpDX is much more active and up-to-date with the latest DirectX versions. I would recommend using SharpDX instead if you're looking to actually do any DX app development, and I would also recommend using D3D11 unless you really need to target Windows XP.

Edited by MJP

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!