# SlimDX WPF No Z-Buffer

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

## Recommended Posts

I spend a lot of time to find why z-buffer don't work in my modified WpfSample10 and then founded information from microsoft site(http://msdn.microsof...4(v=vs.85).aspx):

[color="#2A2A2A"]When a buffer is used as a render target, depth-stencil testing and multiple render targets are not supported.[/quote].

And the only way to use SlimDX in WPF is to use texture as render target?
Is there any way to make Z-buffer working in SlimDX WPF?

##### Share on other sites

I spend a lot of time to find why z-buffer don't work in my modified WpfSample10 and then founded information from microsoft site(http://msdn.microsof...4(v=vs.85).aspx):

[color="#2A2A2A"]When a buffer is used as a render target, depth-stencil testing and multiple render targets are not supported.
.

And the only way to use SlimDX in WPF is to use texture as render target?
Is there any way to make Z-buffer working in SlimDX WPF?
[/quote]
As I understand it, the documentation says that a plain d3d10 buffer (and not a texture) can be bound as a RenderTargetView (though I have never tested this kind of bindings) but then you cannot bind any depthstencilviews.

Have you tried in the WPF sample to create a separate render target/depth stencil buffer, render your d3d10 scene to it, and then copy the resulting rendertarget to the shared d3d9 surface?

##### Share on other sites

Have you tried in the WPF sample to create a separate render target/depth stencil buffer, render your d3d10 scene to it, and then copy the resulting rendertarget to the shared d3d9 surface?

Yes, I do in such way, this part of code left from sample and it works pretty well except Z-Buffer.

RenderTarget Texture initialization:
 var renderTexDesc = new Texture2DDescription() { BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource, Format = Format.B8G8R8A8_UNorm, Width = WindowWidth, Height = WindowHeight, MipLevels = 1, SampleDescription = new SampleDescription(1, 0), Usage = ResourceUsage.Default, OptionFlags = ResourceOptionFlags.Shared, CpuAccessFlags = CpuAccessFlags.None, ArraySize = 1 }; SharedTexture = new Texture2D(device, renderTexDesc); sampleRenderView = new RenderTargetView(device, SharedTexture);

DepthStencil initialization:

var depthDesc = new Texture2DDescription() { BindFlags = BindFlags.DepthStencil, Format = Format.D32_Float, Width = WindowWidth, Height = WindowHeight, MipLevels = 1, SampleDescription = new SampleDescription(1, 0), Usage = ResourceUsage.Default, OptionFlags = ResourceOptionFlags.None, CpuAccessFlags = CpuAccessFlags.None, ArraySize = 1 }; DepthTexture = new Texture2D(device, depthDesc); depthStencilView = new DepthStencilView(device, DepthTexture); var dsDesc = new DepthStencilStateDescription { IsDepthEnabled = true, IsStencilEnabled = false, DepthWriteMask = DepthWriteMask.All, DepthComparison = Comparison.Less }; depthStencilState = DepthStencilState.FromDescription(device, dsDesc);

Rasterizer initialization:

var rasterizerState = new RasterizerStateDescription() { CullMode = CullMode.None, FillMode = FillMode.Solid, IsFrontCounterclockwise = false, DepthBias = 0, DepthBiasClamp = 0, SlopeScaledDepthBias = 0, IsDepthClipEnabled = true, IsScissorEnabled = false, IsMultisampleEnabled = true, IsAntialiasedLineEnabled = true }; device.Rasterizer.State = RasterizerState.FromDescription(device, rasterizerState);

Render:

 public void Render(int arg) { device.OutputMerger.DepthStencilState = depthStencilState; device.OutputMerger.SetTargets(depthStencilView, sampleRenderView); device.Rasterizer.SetViewports(new Viewport(0, 0, WindowWidth, WindowHeight, 0.0f, 1.0f)); device.ClearRenderTargetView(sampleRenderView, new Color4(0.0f, 0.0f, 0.0f)); device.ClearDepthStencilView(depthStencilView, DepthStencilClearFlags.Depth, 1.0f, 0); Matrix worldMatrix = GetWorldViewProj(arg); DataStream ds = new DataStream(worldMatrix.ToArray(), true, false); SampleEffect.GetVariableByName("WorldViewProj").AsMatrix().SetMatrix(worldMatrix); EffectTechnique technique = SampleEffect.GetTechniqueByIndex(0); EffectPass pass = technique.GetPassByIndex(0); for (int i = 0; i < technique.Description.PassCount; ++i) { pass.Apply(); renderDataManager.Render(worldMatrix); } device.Flush(); OnSceneRender(); }

##### Share on other sites

[quote name='AlexandreMutel' timestamp='1317818122' post='4869367']
Have you tried in the WPF sample to create a separate render target/depth stencil buffer, render your d3d10 scene to it, and then copy the resulting rendertarget to the shared d3d9 surface?

Yes, I do in such way, this part of code left from sample and it works pretty well except Z-Buffer.
[/quote]
Seems not exactly. What I was suggesting is that you create 2 render target buffer: one used with the z-buffer, but that is not shared (no ResourceOptionFlags.Shared on it). One that is shared, and receive a copy of the 1st render target (device.CopyResource between them)

##### Share on other sites
In such way?

Initialization:

 var renderTexDescShared = new Texture2DDescription() { BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource, Format = Format.B8G8R8A8_UNorm, Width = WindowWidth, Height = WindowHeight, MipLevels = 1, SampleDescription = new SampleDescription(1, 0), Usage = ResourceUsage.Default, OptionFlags = ResourceOptionFlags.Shared, CpuAccessFlags = CpuAccessFlags.None, ArraySize = 1 }; SharedTexture = new Texture2D(device, renderTexDescShared); sampleRenderViewShared = new RenderTargetView(device, SharedTexture); var renderTexDesc = new Texture2DDescription() { BindFlags = BindFlags.RenderTarget, Format = Format.B8G8R8A8_UNorm, Width = WindowWidth, Height = WindowHeight, MipLevels = 1, SampleDescription = new SampleDescription(1, 0), Usage = ResourceUsage.Default, OptionFlags = ResourceOptionFlags.None, CpuAccessFlags = CpuAccessFlags.None, ArraySize = 1 }; renderTexture = new Texture2D(device, renderTexDesc); sampleRenderView = new RenderTargetView(device, renderTexture);

Render:
public void Render(int arg) { device.OutputMerger.DepthStencilState = depthStencilState; device.OutputMerger.SetTargets(depthStencilView, sampleRenderView); device.Rasterizer.SetViewports(new Viewport(0, 0, WindowWidth, WindowHeight, 0.0f, 1.0f)); device.ClearRenderTargetView(sampleRenderView, new Color4(0.0f, 0.0f, 0.0f)); device.ClearDepthStencilView(depthStencilView, DepthStencilClearFlags.Depth, 1.0f, 0); Matrix worldMatrix = GetWorldViewProj(arg); DataStream ds = new DataStream(worldMatrix.ToArray(), true, false); SampleEffect.GetVariableByName("WorldViewProj").AsMatrix().SetMatrix(worldMatrix); EffectTechnique technique = SampleEffect.GetTechniqueByIndex(0); EffectPass pass = technique.GetPassByIndex(0); for (int i = 0; i < technique.Description.PassCount; ++i) { pass.Apply(); renderDataManager.Render(worldMatrix); } device.Flush(); device.CopyResource(renderTexture, SharedTexture); OnSceneRender(); }

The same problems I'll prepare video in several minutes

##### Share on other sites
I ran into the exact same problem. Spent nearly a week to resolve this (using DX11) and utterly failed.
Looking forward to a solution.

EDIT:
I'm using a deferred renderer, thus i already tried the solution that Alexander proposed (copy non-shared mainbuffer to shared surface). No dice. Something screws up the z-buffer. I was already suspecting WPF to somehow interfere with the device. But then again, i have no idea...

EDIT cont:
I just recalled that i tested this without a shared texture. Instead of D3DImage, i used the WinFormsHost control in WPF and rendered directly to the handle (using a swapchain as usual). Now guess what, z-buffer is still broken. That's when i gave up, suspecting WPF to screw with my DX11 device.

Video:

[media]
[/media]

##### Share on other sites

EDIT cont:
I just recalled that i tested this without a shared texture. Instead of D3DImage, i used the WinFormsHost control in WPF and rendered directly to the handle (using a swapchain as usual). Now guess what, z-buffer is still broken. That's when i gave up, suspecting WPF to screw with my DX11 device.

It was my last hope

##### Share on other sites

[quote name='chlerub' timestamp='1317821467' post='4869399']
EDIT cont:
I just recalled that i tested this without a shared texture. Instead of D3DImage, i used the WinFormsHost control in WPF and rendered directly to the handle (using a swapchain as usual). Now guess what, z-buffer is still broken. That's when i gave up, suspecting WPF to screw with my DX11 device.

It was my last hope
[/quote]

Yeah, it was my last hope too. And it's extremely puzzling to say the least. Also there's virtually no information about this to be found anywhere.
I wonder if the creators of (for example) SlimDXControl ever tested their code with anything else than a simple triangle - cause it appears they most certainly have not.
(along with a number of other devs that have blogged about WPF/DX10-11 interop)

After testing the hell out of this topic for a week i put in on the shelf with a big sign saying "FUTILE".
I guess there's no need to state how frustrating this is, especially since WPF and DirectX are developed by the same company.

##### Share on other sites
I have just tested my code in WinForms, the same result, Z-Buffer do not work. May be any problems with shader?

struct VS_IN { float4 pos : POSITION; float4 col : COLOR; }; struct PS_IN { float4 pos : SV_POSITION; float4 col : COLOR; }; float4x4 WorldViewProj : WORLDVIEWPROJECTION; PS_IN VS( VS_IN input ) { PS_IN output = (PS_IN)0; output.pos = mul(input.pos, WorldViewProj); output.col = input.col; return output; } float4 PS( PS_IN input ) : SV_Target { return input.col; } technique10 Render { pass P0 { SetGeometryShader( 0 ); SetVertexShader( CompileShader( vs_4_0, VS() ) ); SetPixelShader( CompileShader( ps_4_0, PS() ) ); } }

##### Share on other sites
Shader looks fine. Could you attach a minimal project (Edit: The WinForms variant, WPF doesn't seem to work with PIX here, please) ?

Also: Check against the reference device, I begin to suspect you have a driver issue.

##### Share on other sites

Shader looks fine. Could you attach a minimal project (Edit: The WinForms variant, WPF doesn't seem to work with PIX here, please) ?

Also: Check against the reference device, I begin to suspect you have a driver issue.

WinForms sources:
http://www.rush.by/source.zip

System config:
i5-2500, Win7 x64, nVidia GTS450 with latest drivers and updates.

When I change in DepthStencilStateDescription

DepthComparison = Comparison.Less

to

DepthComparison = Comparison.LessEqual

I see that something changed, when peak(as on video) is in far side of scene Z-buffer is ok, but if peak is in near side - z-buffer fault. On video "DepthComparison = Comparison.Less".

##### Share on other sites
I'm missing the Atomicus.Chart.Axis project to compile it (referenced in Atomicus.Chart.Interface).

EDIT: Sorry, my bad, had some other troubles (was still working with the older version of SlimDX). I can debug now...

##### Share on other sites

I'm missing the Atomicus.Chart.Axis project to compile it (referenced in Atomicus.Chart.Interface).

i forgot to remove reference, sorry, it is not used, can be removed.

##### Share on other sites
Ok, first your error was the perspective projection (in DXRenderer.GetWorldViewProj()):
 Matrix.PerspectiveFovLH((float)Math.PI / 4f, 1f, 100f, 0f) 
Rather use something like (switching near and far, and yeah, a near of 0 isn't good either)
 Matrix.PerspectiveFovLH((float)Math.PI / 4f, 1f, 0.1f, 100f) 
Then I had a hell of a detour. It really looked stubborn, just as if depth wasn't written ever. Played around with swapping calls and setting everything again prior to drawing. That did not help. Unfortunately I could not PIX it either, so my next steps were to compare and re-incorporate stuff from a test project I did two days ago (WPF sample with a working depth).

Comparing all descriptions/flags: Everything looked fine.

I changed the resized logic: You recreate almost everything - including the device (InitD3D is called twice at startup!). I suspected a forgotten/wrongly bound view or a backbuffer/depth size mismatch or something. So I used SwapChain.ResizeTarget/ResizeBuffers instead, grabbing the dimensions once only (with the needed texture and view recreation). Did not help either.

Suspecting your mesh, I used my grid mesh. Same behaviour.

 struct PS_OUT { float4 col: SV_Target; float dep: SV_Depth; }; //... PS_OUT PS( PS_IN input ) { PS_OUT output = (PS_OUT)0; output.col = input.col; output.col.g = 0; return output; } 

This is not the one you provided two posts ago . The (PS_OUT)0 cast will overwrite all your real depth values with zero. That's the problem.

Omitting SV_Depth output in the pixelshader finally gave a correct result.

I think you owe me a favor

##### Share on other sites
yes, here was my first mistake: Matrix.PerspectiveFovLH((float)Math.PI / 4f, 1f, 100f, 0f)

the result of this mistake was like Z-Buffer not work and i tried everything about Z-Buffer, but nothing about projection matrices.

And my last hope was to make depth calculations manually in shader(or something like this) and I started write something in shader

Now everything works fine, even in WPF. Thanks to unbird.

P.S. Really I see that DirectX/SlimDX rendering cannot depend on WPF, because rendering to shared texture is made just in .Net, not in WPF or WinForms. So I think chlerub can also solve his problem.

##### Share on other sites
I have a different problem, since my code works just fine in WinForms but not in WPF. Also mind i'm using DirectX11.
I'll upload a sample project asap.

##### Share on other sites

I wanted to add something, though it's a bit off topic. I see this pretty often (Output being some struct)

 Output result = (Output)0; //... 

I wonder why. I don't do this, because...

If you do this:
 Output result; // ... // fill result with values // ... return result; 

... and then forget to fill all entries of result the compiler will scream with an error:

 error X4000: variable 'result' used without having been completely initialized 

This is pretty useful information, so why mute it ? Shader debugging is hard enough.