SlimDX WPF No Z-Buffer

Started by
16 comments, last by unbird 12 years, 6 months ago
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?
Advertisement

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?

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();
}

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

If anyone knows anything about this, i'm nervous to get some real answers.
Video:

[media]
[/media]

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 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.
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() ) );
}
}

This topic is closed to new replies.

Advertisement