[SlimDX] Need help from Native/Managed Interop Expert

Started by
8 comments, last by gradbot 11 years, 8 months ago
SlimDX is great but there are some parts of the library that are not complete. In particular there seems to be a problem with pointer handling and pointer type conversion. The particular SlimDX code in question is in the GetBuffer method of the SwapChain (D3D10): generic< class T > where T : ComObject, ref class T SwapChain::GetBuffer( int index ) { IUnknown* unknown = 0; GUID guid = Utilities::GetNativeGuidForType( T::typeid ); RECORD_DXGI( InternalPointer->GetBuffer( index, guid, reinterpret_cast<void**>( &unknown ) ) ); if( Result::Last.IsFailure ) return T(); BindingFlags flags = BindingFlags::Static | BindingFlags::InvokeMethod | BindingFlags::NonPublic; array<Object^>^ args = gcnew array<Object^>( 1 ); args[ 0 ] = IntPtr( unknown ); // Trying to invoke "FromPointer" directly will choose the IntPtr overload since it's more // cumbersome to pass a native pointer as an argument here. The IntPtr overload is intended // to be the user-pointer overload, however, which isn't what we want; thus the thunk. T result = safe_cast<T>( T::typeid->InvokeMember( "FromPointerReflectionThunk", flags, nullptr, nullptr, args, CultureInfo::InvariantCulture ) ); return result; } I need to call GetBuffer with the Surface class as well as the Resource class. Are there any SlimDX experts that have time to help? Why isn't this code base something used often by the SlimDX community?
Advertisement
I don't understand what you believe is "missing" here? What is the actual problem you are having? What happens when you called GetBuffer<DXGI.Resource>()?

You may be indirectly referring to the fact that you cannot create a Direct3D10.Resource object directly, which means you cannot use it as the GetBuffer result. This is (thus far) by design, as there is nothing really useful you could do with that resulting interface (it is not actually the derived type, so you cannot downcast it) except ask about its eviction priority.

What are you actually trying to do?

[Edited by - jpetrie on July 23, 2009 11:00:34 AM]
The error I get when trying to use GetBuffer with *any* class is that method "FromPointerReflectionThunk" does not exist. And after searching the code base the method is no where to be found. I guess it's meant to be a placeholder?

I'm trying to write SlimDX code that would be equivalent to the Direct2D / Direct3D interop example that Microsoft has posted:

http://msdn.microsoft.com/en-us/library/dd371004(VS.85).aspx

Here's my C# code:
//Referencesusing SlimDX.Direct2D;using D3D10 = SlimDX.Direct3D10;using DXGI = SlimDX.DXGI;//Declarations        DXGI.SwapChain m_swapChain;        D3D10.Device m_device;        D3D10.RenderTargetView m_renderTarget;        SlimDX.Direct2D.Factory m_direct2DFactory;        SlimDX.DirectWrite.Factory m_directWriteFactory;        RenderTarget m_windowRenderTarget;//Execution code            //Setup Direct3D            DXGI.SwapChainDescription swapChainDescription = new SlimDX.DXGI.SwapChainDescription();            DXGI.ModeDescription modeDescription = new DXGI.ModeDescription();            DXGI.SampleDescription sampleDescription = new DXGI.SampleDescription();            modeDescription.Format = DXGI.Format.R8G8B8A8_UNorm;            modeDescription.RefreshRate = new Rational(60, 1);            modeDescription.Scaling = DXGI.DisplayModeScaling.Unspecified;            modeDescription.ScanlineOrdering = DXGI.DisplayModeScanlineOrdering.Unspecified;            modeDescription.Width = this.ClientRectangle.Width;            modeDescription.Height = this.ClientRectangle.Height;            sampleDescription.Count = 1;            sampleDescription.Quality = 0;            swapChainDescription.ModeDescription = modeDescription;            swapChainDescription.SampleDescription = sampleDescription;            swapChainDescription.BufferCount = 1;            swapChainDescription.Flags = DXGI.SwapChainFlags.None;            swapChainDescription.IsWindowed = true;            swapChainDescription.OutputHandle = this.Handle;            swapChainDescription.SwapEffect = DXGI.SwapEffect.Discard;            swapChainDescription.Usage = DXGI.Usage.RenderTargetOutput;            D3D10.Device.CreateWithSwapChain(null, D3D10.DriverType.Hardware,D3D10.DeviceCreationFlags.Debug | D3D10.DeviceCreationFlags.BgraSupport, swapChainDescription, out m_device, out m_swapChain);            D3D10.Texture2DDescription t2d = new D3D10.Texture2DDescription();            t2d.ArraySize = 1;            t2d.BindFlags = SlimDX.Direct3D10.BindFlags.DepthStencil;            t2d.CpuAccessFlags = SlimDX.Direct3D10.CpuAccessFlags.None;            t2d.Format = SlimDX.DXGI.Format.D16_UNorm;            t2d.Height = this.ClientRectangle.Height;            t2d.Width = this.ClientRectangle.Width;            t2d.MipLevels = 1;            t2d.SampleDescription = new SlimDX.DXGI.SampleDescription(1, 0);            t2d.Usage = SlimDX.Direct3D10.ResourceUsage.Default;            D3D10.Texture2D m_depthStencil = new D3D10.Texture2D(m_device, t2d);            //m_resource = new D3D10.RenderTargetView(m_device, m_depthStencil);            D3D10.RenderTargetViewDescription renderDesc = new SlimDX.Direct3D10.RenderTargetViewDescription();            renderDesc.Format = SlimDX.DXGI.Format.R8G8B8A8_UNorm;            renderDesc.Dimension = SlimDX.Direct3D10.RenderTargetViewDimension.Texture2D;            renderDesc.MipSlice = 0;            D3D10.Resource m_resource = m_swapChain.GetBuffer<D3D10.Resource>(0);            D3D10.RenderTargetView m_renderTargetView = new SlimDX.Direct3D10.RenderTargetView(m_device, m_resource, renderDesc);            D3D10.DepthStencilViewDescription depthViewDesc = new SlimDX.Direct3D10.DepthStencilViewDescription();            depthViewDesc.Format = SlimDX.DXGI.Format.D16_UNorm;            depthViewDesc.Dimension = SlimDX.Direct3D10.DepthStencilViewDimension.Texture2D;            depthViewDesc.MipSlice = 0;            D3D10.DepthStencilView m_depthStencilView = new SlimDX.Direct3D10.DepthStencilView(m_device, m_depthStencil, depthViewDesc);            m_device.OutputMerger.SetTargets(m_depthStencilView);            D3D10.Viewport m_viewArea = new D3D10.Viewport();            m_viewArea.X = 0;            m_viewArea.Y = 0;            m_viewArea.Width = this.ClientRectangle.Width;            m_viewArea.Height = this.ClientRectangle.Height;            m_viewArea.MinZ = 0.0f;            m_viewArea.MaxZ = 1.0f;            m_device.Rasterizer.SetViewports(m_viewArea);            DXGI.Surface m_surface = m_swapChain.GetBuffer<DXGI.Surface>(0);            RenderTargetProperties rp = new RenderTargetProperties();            rp.HorizontalDpi = 96;            rp.VerticalDpi = 96;            rp.MinimumFeatureLevel = FeatureLevel.Default;            rp.PixelFormat = new PixelFormat(){ AlphaMode = AlphaMode.Premultiplied, Format = SlimDX.DXGI.Format.R8G8B8A8_UNorm };            rp.Type = RenderTargetType.Default;            rp.Usage = RenderTargetUsage.None;            m_windowRenderTarget = RenderTarget.FromDXGI(m_direct2DFactory, m_surface, rp);


[Edited by - jpetrie on July 23, 2009 4:02:02 PM]
D3D10.Resource is an abstract type, so it can't be created, which is also why it doesn't have a FromPointerReflectionThunk. Is there a reason why you can't use the most derived type of resource in that spot?

Also, in the future use the [ source ] tags to condense code postings.
Mike Popoloski | Journal | SlimDX
Quote:
The error I get when trying to use GetBuffer with *any* class is that method "FromPointerReflectionThunk" does not exist. And after searching the code base the method is no where to be found. I guess it's meant to be a placeholder?

The method exists; its supplied via the COM object macros. GetBuffer() works as intended (see MiniTri10). Are you using the latest SVN revision? The method wasn't always available to the beta DLL (where all the D2D, D3D11, DWrite stuff is).

As I said, you can't create a D3D10.Resource because the (managed) object is, effectively, sliced. This was an intentional design decision. I will look into what it would take to move FromPointerReflectionThunk into the abstract class macro, since it does make some degree of sense to acquire the base interface in this fashion -- so long as you understand that it is not an instance of the actual most-derived type and casting it will always fail.
Thanks for your response. I've tried removing the GetBuffer call with the Resource class and then I end up with memory issues down the road. As a newbie to DirectX I've been able to extend SlimDX D3D examples just fine... and SlimDX D2D samples just fine. I just can't get D3D and D2D interop (w/SlimDX) working... so frustrating. I'm willing to offer up a bounty on it...is anyone willing to put together an example for me? I'm good for $35 (paypal).
Could you explain in a little more detail what sort of interop you're trying to do exactly? This is valuable information for us and may let us give you hints on alternate approaches as well.
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
I'm creating a graphical foundation for a primarily 2D application (porting some basic GDI+ code as well). I want the ability to use all of the D3D features that are out of reach if I use Direct2D alone.

So an example might be:
1. Draw geometry with D2D
2. Draw 3D geometry with D3D
3. Blur the buffer with a D3D Effect (there is a gaussian blur effect file in the DirectX "PostProcess" sample)
4. Draw some text with DirectWrite

My preference is to create SlimDX code that is equivalent to the native code in Microsoft's example:

http://msdn.microsoft.com/en-us/library/dd371004(VS.85).aspx

I'd be wary of any alternative approaches because that would likely mean a significantly larger memory footprint. I'm a bit on the bleeding edge but I think a SlimDX code example in this spirit would be beneficial to a wide audience... especially when Windows 7 starts to pick up.

I looked into it, and we can't make this work without unrolling the changes to the abstract classes (making them nonabstract again) -- which is a big change we'll have to have a discussion about when at least two-thirds of us are on IRC.
I ran into a similar error while using SlimDX with F#. For those of you who don't know what F# is, it's a type inferred functional .net language. Type inference is normally awesome but in this case caused an error. I'm posting this here so others can find this solution.

let result, device, swapChain = Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, swapChainDescription)
let resource = Resource.FromSwapChain(swapChain, 0)


Causes System.MissingMethodException to be thrown. Building from source I found it dying at this line.


T result = safe_cast<T>( T::typeid->InvokeMember( "FromPointerReflectionThunk", flags, nullptr, nullptr, args, CultureInfo::InvariantCulture ) );


Which again tells me that the method is missing. Finally I realized (thanks to this thread) that I needed to specify a type that did have the method. Adding <Texture2D> to the return type of FromSwapChain fixed the problem. F# was inferring the type to be Resource. The following works.

let result, device, swapChain = Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, swapChainDescription)
let resource = Resource.FromSwapChain<Texture2D>(swapChain, 0)

This topic is closed to new replies.

Advertisement