|
||||||||||||||||||
Add Forum to Favorites | Send Topic To a Friend | View Forum FAQ | Track this topic |
Last Thread Next Thread ![]() |
| WPF D3DImage with SlimDx |
|
![]() juergen1969 Member since: 2/27/2008 From: Anrochte, Germany |
||||
|
|
||||
| Hi all, is there a well working sample using SlimDx with .Net Framwork 3.5 (SP1) available? I checked the blog from SteveKr. The sample works very well till I open the Task-Manager in Windows Vista. The Device is lost. Sometims I can recreate it. After the second or third time the program crashes with an exception in SlimDX in "Result.cpp". So I'm searching for a better sample. Best regards, Juergen |
||||
|
||||
![]() jpetrie Moderator - For Beginners Member since: 6/11/2003 From: Redmond, WA, United States |
||||
|
|
||||
| Using SlimDX in Framework 3.5 isn't any different than using it anywhere else. Using it with WPF is another issue altogether though, as you have airspace issues to worry about. What's this sample you're using / what kind of code are we talking about here? Losing the device is expected when you do things like that, it sounds like the code is not handling the reset correctly. But you're going to have to provide more information. Josh Petrie | DirectX/XNA MVP | Scientific Ninja | Twitter | SlimDX |
||||
|
||||
![]() juergen1969 Member since: 2/27/2008 From: Anrochte, Germany |
||||
|
|
||||
| Ok, here is my little sample program. If I try to reset the device (device.Reset) it fails with an exception. If I get an Exception in RenderD3D() I try to create it again. Sometimes it works sometimes not. I want to use the new control D3DImage because it's implemented in WPF and the hole application is written in WPF. At the moment I use a 3D-control written in WinForms inside the WPF-application. Ok, here is the code: using System; using System.Collections.Generic; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using System.Windows.Interop; using System.Drawing; using SlimDX; using SlimDX.Direct3D9; namespace D3DIMageTest { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window { SlimDX.Direct3D9.Direct3D direct3D = new SlimDX.Direct3D9.Direct3D(); Device device; Sprite sprite; Texture texture; public Window1() { InitializeComponent(); Loaded += new RoutedEventHandler(Window_Loaded); } private void Window_Loaded(object sender, RoutedEventArgs e) { InitializeD3D(); CompositionTarget.Rendering += OnRendering; d3dimage.IsFrontBufferAvailableChanged += new DependencyPropertyChangedEventHandler(OnIsFrontBufferAvailableChanged); d3dimage.Lock(); d3dimage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, device.GetBackBuffer(0, 0).ComPointer); d3dimage.Unlock(); } public void InitializeD3D() { HwndSource hwnd = new HwndSource(0, 0, 0, 0, 0, "test", IntPtr.Zero); PresentParameters pp = new PresentParameters(); pp.SwapEffect = SwapEffect.Discard; pp.DeviceWindowHandle = hwnd.Handle; pp.Windowed = true; pp.BackBufferWidth = 400; pp.BackBufferHeight = 400; pp.BackBufferFormat = Format.X8R8G8B8; device = new Device(direct3D, 0, DeviceType.Hardware, hwnd.Handle, CreateFlags.HardwareVertexProcessing, pp); } private void OnRendering(object sender, EventArgs e) { try { d3dimage.Lock(); d3dimage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, device.GetBackBuffer(0, 0).ComPointer); RenderD3D(); d3dimage.AddDirtyRect(new Int32Rect(0, 0, d3dimage.PixelWidth, d3dimage.PixelHeight)); d3dimage.Unlock(); } catch (Direct3D9Exception ex) { string msg = ex.Message; } } void OnIsFrontBufferAvailableChanged(object sender, DependencyPropertyChangedEventArgs e) { if (d3dimage.IsFrontBufferAvailable) { InitializeD3D(); CompositionTarget.Rendering += OnRendering; d3dimage.IsFrontBufferAvailableChanged += new DependencyPropertyChangedEventHandler(OnIsFrontBufferAvailableChanged); d3dimage.Lock(); d3dimage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, device.GetBackBuffer(0, 0).ComPointer); d3dimage.Unlock(); } else { CompositionTarget.Rendering -= OnRendering; } } public void RenderD3D() { Result result; try { if (d3dimage.IsFrontBufferAvailable) { result = device.TestCooperativeLevel(); if (result.IsFailure) { throw new Direct3D9Exception(); } device.Clear(ClearFlags.Target, new Color4(System.Drawing.Color.Yellow), 0, 0); device.BeginScene(); device.EndScene(); device.Present(); } } catch (Exception ex) { string msg = ex.Message; InitializeD3D(); CompositionTarget.Rendering += OnRendering; d3dimage.IsFrontBufferAvailableChanged += new DependencyPropertyChangedEventHandler(OnIsFrontBufferAvailableChanged); d3dimage.Lock(); d3dimage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, device.GetBackBuffer(0, 0).ComPointer); d3dimage.Unlock(); } } } } [Mod edit -- added source tags] [Edited by - Promit on September 10, 2008 5:40:16 PM] |
||||
|
||||
![]() Promit Moderator - Graphics Programming and Theory Member since: 7/29/2001 From: Baltimore, MD, United States |
||||
|
|
||||
| This might be one of those times you have to create an Ex device. Lucky for you, we added support for just this occasion. Switch to using Direct3DEx and DeviceEx, and see if that works out better. |
||||
|
||||
![]() Billr17 Member since: 5/4/2004 From: Pittsburgh, PA, United States |
||||
|
|
||||
Quote: .Net 3.5 SP1 adds the ability to use the D3DImage object. This object allows you to work around the airspace problems that previously made using DirectX with WPF very ugly. The D3DImage object is an ImageSource. Thefore, you can apply an IDirect3DSurface9 as if it was any other WPF brush. I'd recommend checking out the following if you have not done so already. Video outlining .NET 3.5 SP1 Pixel Shader Support and D3DImage Dr WPF's D3DImage article I have had good sucess using the D3DImage object with XNA and a small bit of reflection hackery. :-) |
||||
|
||||
![]() jpetrie Moderator - For Beginners Member since: 6/11/2003 From: Redmond, WA, United States |
||||
|
|
||||
Quote: Right, but that doesn't change how one would use SlimDX itself (which is what I meant by 'another issue'). As for using D3DImage, I don't have much input on that -- looks like it's designed to deal with unmanaged D3D, and SlimDX exposes the unmanaged COM interfaces as IntPtrs, so that's likely what you'd want to use -- as the OP is doing. Beyond that I can't really provide a whole lot of insight... Promit's suggestion of the Ex interface is worth a look, and there may also be issues with the D3DImage doing something to the D3D interface that SlimDX doesn't expect (or vise-versa), but it's hard to tell without more in-depth analysis. Making sure unmanaged debugging is enabled so you can see the native D3D debug spew is also worth doing, if there's just a resource that isn't being released before the reset (a pretty common issue), that'll be easy to see with the output. Josh Petrie | DirectX/XNA MVP | Scientific Ninja | Twitter | SlimDX |
||||
|
||||
![]() juergen1969 Member since: 2/27/2008 From: Anrochte, Germany |
||||
|
|
||||
| I tried the same code with Direct3DEx and DeviceEx and everything works fine. Thank you very much, Jürgen |
||||
|
||||
![]() juergen1969 Member since: 2/27/2008 From: Anrochte, Germany |
||||
|
|
||||
| Now I have a problem with my textures. I get them with Texture.FromFile(). Each time I want to load a texture I get a "D3DERR_INVALIDCALL: Invalid call (-2005530516)". I use now the Direct3D9.DeviceEx. It works with the normal Device. HwndSource hwnd = new HwndSource(0, 0, 0, 0, 0, "test", IntPtr.Zero); PresentParameters pp = new PresentParameters(); pp.SwapEffect = SwapEffect.Discard; pp.DeviceWindowHandle = hwnd.Handle; pp.Windowed = true; pp.BackBufferWidth = 400; pp.BackBufferHeight = 400; pp.BackBufferFormat = Format.X8R8G8B8; device = new DeviceEx(direct3D, 0, DeviceType.Hardware, hwnd.Handle, CreateFlags.HardwareVertexProcessing, pp); sprite = new Sprite(device); texture = Texture.FromFile(device, "pic.jpg"); |
||||
|
||||
![]() Mike.Popoloski GDNet+ Member since: 6/28/2004 From: West Milford, NJ, United States |
||||
|
|
||||
| What do the debug runtimes give you? Mike Popoloski | Journal | SlimDX |
||||
|
||||
![]() Promit Moderator - Graphics Programming and Theory Member since: 7/29/2001 From: Baltimore, MD, United States |
||||
|
|
||||
| FromFile probably defaults to managed pool, which isn't legal on an Ex device. Use the version that specifies the pool explicitly, and pass default. |
||||
|
||||
![]() juergen1969 Member since: 2/27/2008 From: Anrochte, Germany |
||||
|
|
||||
| Promit, I tried this and it works. Thank you. But the problem with the DeviceEx is, that it's not running on WinXP. What do you think? Is it possible to make a SampleFramework depending on a WPF D3DImage working with normal D3D9 Device? |
||||
|
||||
![]() MrSparkle27 Member since: 7/8/2007 From: Leipzig, Germany |
||||
|
|
||||
Quote: Yeah, what about Windows XP? I need the WPF applications to run on WinXP as well, otherwise I could use DirectX 10 instead of DirectX 9. What does the DeviceEx do anyway, I mean what is the difference to the regular Device? Thanks, Christian |
||||
|
||||
![]() Promit Moderator - Graphics Programming and Theory Member since: 7/29/2001 From: Baltimore, MD, United States |
||||
|
|
||||
| Sorry, I have no idea what affects how the normal device works on Vista. |
||||
|
||||
![]() juergen1969 Member since: 2/27/2008 From: Anrochte, Germany |
||||
|
|
||||
| Christian, don't know if it's too late: The only thing you have to do is to try to create a DeviceEx device. If it fails you don't have a Vista system. Then you have to create a normal Device. Here is the code and hope it's not to large: using System; using System.Collections.Generic; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using System.Windows.Interop; using System.Drawing; using SlimDX; using SlimDX.Direct3D9; namespace TriVista.Controls.D3D { /// <summary> /// Description of ControlWPF. /// </summary> public class ControlWPF : DockPanel { // we use it for 3D Direct3D direct3D; Direct3DEx direct3DEx; Device device; DeviceEx deviceEx; PresentParameters pp; // this one is our only child System.Windows.Controls.Image image; D3DImage d3dimage; bool StartThread = false; bool sizeChanged = false; // some public properties public bool useDeviceEx { get; private set; } public Direct3D Direct3D { get { if (useDeviceEx) return direct3DEx; else return direct3D; } } public Device Device { get { if (useDeviceEx) return deviceEx; else return device; } } #region Events /// <summary> /// Occurs once per iteration of the main loop. /// </summary> public event EventHandler MainLoop; /// <summary> /// Occurs when the device is created. /// </summary> public event EventHandler DeviceCreated; /// <summary> /// Occurs when the device is destroyed. /// </summary> public event EventHandler DeviceDestroyed; /// <summary> /// Occurs when the device is lost. /// </summary> public event EventHandler DeviceLost; /// <summary> /// Occurs when the device is reset. /// </summary> public event EventHandler DeviceReset; /// <summary> /// Raises the OnInitialize event. /// </summary> protected virtual void OnInitialize() { } /// <summary> /// Raises the <see cref="E:MainLoop"/> event. /// </summary> protected virtual void OnMainLoop(EventArgs e) { if (MainLoop != null) MainLoop(this, e); } /// <summary> /// Raises the DeviceCreated event. /// </summary> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> protected virtual void OnDeviceCreated(EventArgs e) { if (DeviceCreated != null) DeviceCreated(this, e); } /// <summary> /// Raises the DeviceDestroyed event. /// </summary> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> protected virtual void OnDeviceDestroyed(EventArgs e) { if (DeviceDestroyed != null) DeviceDestroyed(this, e); } /// <summary> /// Raises the DeviceLost event. /// </summary> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> protected virtual void OnDeviceLost(EventArgs e) { if (DeviceLost != null) DeviceLost(this, e); } /// <summary> /// Raises the DeviceReset event. /// </summary> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> protected virtual void OnDeviceReset(EventArgs e) { if (DeviceReset != null) DeviceReset(this, e); } #endregion public ControlWPF() { image = new System.Windows.Controls.Image(); d3dimage = new D3DImage(); image.Source = d3dimage; Children.Clear(); Children.Add(image); } protected override void OnInitialized(EventArgs e) { base.OnInitialized(e); InitializeDirect3D(); } protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) { base.OnRenderSizeChanged(sizeInfo); sizeChanged = true; } void InitializeDirect3D() { try { direct3DEx = new Direct3DEx(); useDeviceEx = true; } catch { direct3D = new Direct3D(); useDeviceEx = false; } } /// <summary> /// Initializes the various Direct3D objects we'll be using. /// </summary> public bool Initialize(bool startThread) { try { StartThread = startThread; ReleaseD3D(); HwndSource hwnd = new HwndSource(0, 0, 0, 0, 0, "test", IntPtr.Zero); pp = new PresentParameters(); pp.SwapEffect = SwapEffect.Discard; pp.DeviceWindowHandle = hwnd.Handle; pp.Windowed = true; pp.BackBufferWidth = (int)ActualWidth; pp.BackBufferHeight = (int)ActualHeight; pp.BackBufferFormat = Format.X8R8G8B8; if (useDeviceEx) { deviceEx = new DeviceEx((Direct3DEx)Direct3D, 0, DeviceType.Hardware, hwnd.Handle, CreateFlags.HardwareVertexProcessing, pp); } else { device = new Device(Direct3D, 0, DeviceType.Hardware, hwnd.Handle, CreateFlags.HardwareVertexProcessing, pp); } // call the users one OnDeviceCreated(EventArgs.Empty); OnDeviceReset(EventArgs.Empty); // only if startThread is true if (StartThread) { CompositionTarget.Rendering += OnRendering; d3dimage.IsFrontBufferAvailableChanged += new DependencyPropertyChangedEventHandler(OnIsFrontBufferAvailableChanged); } d3dimage.Lock(); d3dimage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, Device.GetBackBuffer(0, 0).ComPointer); d3dimage.Unlock(); return true; } catch { return false; } } public void ReleaseD3D() { if (device != null) { if (!device.Disposed) { device.Dispose(); device = null; } } d3dimage.Lock(); d3dimage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, IntPtr.Zero); d3dimage.Unlock(); } private void OnRendering(object sender, EventArgs e) { Result result; try { if (Device == null) Initialize(StartThread); if (sizeChanged) { pp.BackBufferWidth = (int)ActualWidth; pp.BackBufferHeight = (int)ActualHeight; Device.Reset(pp); OnDeviceReset(EventArgs.Empty); } if (d3dimage.IsFrontBufferAvailable) { result = Device.TestCooperativeLevel(); if (result.IsFailure) { throw new Direct3D9Exception(); } d3dimage.Lock(); Device.Clear(ClearFlags.Target, new Color4(System.Drawing.Color.Yellow), 0, 0); Device.BeginScene(); // call the users method OnMainLoop(EventArgs.Empty); Device.EndScene(); Device.Present(); d3dimage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, Device.GetBackBuffer(0, 0).ComPointer); d3dimage.AddDirtyRect(new Int32Rect(0, 0, d3dimage.PixelWidth, d3dimage.PixelHeight)); d3dimage.Unlock(); } } catch (Direct3D9Exception ex) { string msg = ex.Message; Initialize(StartThread); } sizeChanged = false; } void OnIsFrontBufferAvailableChanged(object sender, DependencyPropertyChangedEventArgs e) { if (d3dimage.IsFrontBufferAvailable) { Initialize(StartThread); } else { CompositionTarget.Rendering -= OnRendering; } } } } If someone is interested in a complete working sample, feel free to write. Juergen |
||||
|
||||
All times are ET (US)![]() |
Last Thread Next Thread ![]() |
|