Problem with ConstructGSWithSO (D3DX11 Effect)

Started by
5 comments, last by B_old 12 years, 6 months ago
I'm trying to stream out vertex data to two streams from a geometry shader that looks like this:


cbuffer ChangePerSkinnedObject
{
float4x4 g_bones[256];
}


struct SkinnedVertex
{
float3 pos : Position;
float4 normal : Normal;
};


SkinnedVertex skin(float3 pos, float4 weights, uint4 bones, float4 normal)
{
SkinnedVertex output = (SkinnedVertex)0;

//skinning...

return output;
}


SkinnedVertex vertexShader(float3 pos : Position, float4 weights : Weights, uint4 bones : Bones, float4 normal : Normal)
{
return skin(pos, weights, bones, normal);
}


VertexShader VShader = CompileShader(vs_5_0, vertexShader());


GeometryShader GeoShaderSo = ConstructGSWithSO(VShader, "0:Position.xyz", "1:Normal.xyzw", NULL, NULL, 0);


technique11 Skinning
{
pass P0
{
SetVertexShader(VShader);
SetGeometryShader(GeoShaderSo);
SetPixelShader(0);
}
}


When I compile the effect file I get the following error: D3D11: ERROR: ID3D11Device::CreateGeometryShaderWithStreamOutput: Stream Output Declaration Element[1]'s semantic (Normal 0) not found in output signature of shader.
I don't understand it.
Setting the declaration for the second stream to NULL makes it compile. It even works but obviously the second stream does not receive the data I want to have.
Any idea how to configure ConstructGSWithSO() correctly?
Advertisement
Funnily, I can compile that shader with fxc without any problems. Haven't played around with multiple streams yet, but if I get the effect file syntax right from here, maybe this works:


GeometryShader GeoShaderSo = ConstructGSWithSO(VShader, "0:Position.xyz;1:Normal.xyzw", NULL, NULL, NULL, 0);

since you don't have an explicit GS which outputs a second stream.
As you say, I don't get a compile error but the error appears later when the effect framework calls CreateGSWithSO(). The variant suggested by you works but than I end up with an interleaved stream, which I don't want.
I tried this:


//...
struct GS_Output_Pos
{
float3 pos : Position;
};

struct GS_Output_Normal
{
float4 normal : Normal;
};

[maxvertexcount(1)]
void geometryShader(point SkinnedVertex input[1], inout PointStream<GS_Output_Pos> positions, inout PointStream<GS_Output_Normal> normals)
{
GS_Output_Pos pos;
pos.pos = input[0].pos;

GS_Output_Normal normal;
normal.normal = input[0].normal;

positions.Append(pos);
normals.Append(normal);
}

VertexShader VShader = CompileShader(vs_5_0, vertexShader());

GeometryShader GsBase = CompileShader(gs_5_0, geometryShader());
GeometryShader GeoShaderSo = ConstructGSWithSO(GsBase, "0:Position.xyz", "1:Normal.xyzw", NULL, NULL, 0xffffffff);


It doesn't give me any errors but it crashes the video driver. :)

BTW, do you happen to know what the fx equivalent of D3D11_SO_NO_RASTERIZED_STREAM is? I tried 0xffffffff, but this still gives me a warning that the rasterizer is activated unless I manually disable depth-writes.
I'm currently out of clues. Can you show the buffer creation, draw setup and drawing call code, please ?

//buffer creation
D3D11_BUFFER_DESC bd;
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = bytes;
bd.BindFlags = D3D11_BIND_STREAM_OUTPUT | D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
bd.MiscFlags = 0;

ID3D11Buffer *buffer;

m_device->CreateBuffer(&bd, nullptr, &buffer);

//drawing
getContext().setRenderTarget(nullptr, nullptr);
getContext().unbindVertexBuffers();
getContext().setDepthStencilState(&m_dsState);
getContext().setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
getContext().setInputLayout(m_inputLayout);

m_effect->setMatrices("g_bones", skeleton->getBones(), skeleton->getNumBones());
getContext().setVertexBuffers(2, skinningData->m_skinningInputs, inputLayoutDescription());
getContext().setStreamOutTargets(2, skinningData->m_streamOutTargets);
m_effect->getTechnique("Skinning").apply(getContext());
getContext().draw(getModel()->m_numVertices);

The second part is pseudo code:ish but I hope you can still see the d3d11 calls beneath it. As I said earlier that stuff actually works as long as I only write to one stream, but I'd rather have two.
Hot stuff, literally. Experimenting with your setup - manually though, not through the effect framework - I first got a memory corruption when calling CreateGeometryShaderWithStreamOutput and later a freeze of my apps and suddenly some weird rendering with a blue background and white text. Blue screen of death :(

So I'm of little help now, sorry. I'd double check the strides and experiment with buffers with equal strides. But that's just a real shot in the dark.
I managed to get away the errors by specifying [font="Courier New"]uint normal : Normal[/font] as the output for the second stream which matches the stride of my normals, because they are compressed. However whatever I output in the geometry shader it does not seem to end up in the output stream.

EDIT0: I confirmed that the second stream is not being written too, by outputting the same data to both streams. Reading from those streams later the data is not identical.

EDIT1: Had to specify [maxvertexcount(2)]. Now it works! :)

This topic is closed to new replies.

Advertisement