Jump to content

  • Log In with Google      Sign In   
  • Create Account


[SlimDX] Need help from Native/Managed Interop Expert


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
9 replies to this topic

#1 fox2   Members   -  Reputation: 100

Like
0Likes
Like

Posted 23 July 2009 - 02:41 AM

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?

Sponsor:

#2 Josh Petrie   Moderators   -  Reputation: 2954

Like
0Likes
Like

Posted 23 July 2009 - 04:00 AM

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]

Josh Petrie | Core Tools Engineer, 343i | Microsoft C++ MVP


#3 fox2   Members   -  Reputation: 100

Like
0Likes
Like

Posted 23 July 2009 - 09:02 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:

//References
using 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]

#4 Mike.Popoloski   Crossbones+   -  Reputation: 2852

Like
0Likes
Like

Posted 23 July 2009 - 09:24 AM

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

#5 Josh Petrie   Moderators   -  Reputation: 2954

Like
0Likes
Like

Posted 23 July 2009 - 10:56 AM

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.

Josh Petrie | Core Tools Engineer, 343i | Microsoft C++ MVP


#6 fox2   Members   -  Reputation: 100

Like
0Likes
Like

Posted 24 July 2009 - 02:16 AM

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).

#7 Promit   Moderators   -  Reputation: 6096

Like
0Likes
Like

Posted 24 July 2009 - 02:53 AM

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.

#8 fox2   Members   -  Reputation: 100

Like
0Likes
Like

Posted 24 July 2009 - 07:45 AM

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.



#9 Josh Petrie   Moderators   -  Reputation: 2954

Like
0Likes
Like

Posted 25 July 2009 - 09:25 AM

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.

Josh Petrie | Core Tools Engineer, 343i | Microsoft C++ MVP


#10 gradbot   Members   -  Reputation: 113

Like
0Likes
Like

Posted 27 July 2012 - 10:28 AM

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)





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS