HLSL streamout problems

Started by
3 comments, last by Tsus 12 years, 2 months ago
I have a few problems with streamout and a question about geometry shaders. Currently i'm trying to create something like rain demo in the nvidia direct3d 10 sdk so that is why i need stream out. I have two problems. One of them is about creating stream out with vertex shader and the other is about pix. First of all here is my code.

struct VSIn
{
float3 position : POSITION;
float3 speed : SPEED;
};
struct PSIn
{
float4 position : SV_POSITION;
};

////////////////////////////////////////
//ADVANCE RAIN
////////////////////////////////////////
VSIn PassThroughVS(VSIn vertex)
{
return vertex;
}
VSIn AdvanceRainVS(VSIn vertex)
{
vertex.position.y -= 0.1f;
if(vertex.position.y <= 0)
{
vertex.position.y = 20;
}
return vertex;
}
[maxvertexcount(1)]
void AdvanceRainGS(point VSIn input[1], inout PointStream<VSIn> OutputStream)
{
VSIn output = (VSIn)0;
output = input[0];
output.position += output.speed * 0.001f;
if(output.position.y < 0)
{
output.position.y = 20;
}
OutputStream.Append(output);
};
VertexShader vsShader = CompileShader(vs_5_0, AdvanceRainVS());
GeometryShader gsShader = CompileShader(gs_5_0, AdvanceRainGS());
GeometryShader gsStreamOut = ConstructGSWithSO( gsShader, "0:POSITION.xyz; 0:SPEED.xyz" );
technique11 AdvanceRain
{
pass p0
{
SetVertexShader(CompileShader(vs_5_0, PassThroughVS()));
SetGeometryShader(gsStreamOut);
SetPixelShader(NULL);
SetDepthStencilState(DisableDepth, 0);
}
}


Now if i try ConstructGSWithSO with AdvanceRainVS function rain particles doesn't move but i get no error and it draws rain particles. And if i try with AdvanceRainGS it works correctly. I couldn't find the reason for this problem.

My second question is when i try to debug my code with pix i get error about ConstructGSWithSO. I've added screenshot of the problem. I've searched for this problem and found there are also some other people having the same problem but they couldn't manage to solve it. I tried to debug nvidia rain demo to see if i get the same error but i didn't get any errors. So i think i did something wrong but since it works correctly i couldn't find what.

And my last question is about geometry shaders. For vertex shaders matrices need to be transposed before multiplication. But in the geometry shader they need to be sent without transpose. I don't understand reasoning behind this. So if anyone have knowledge about this i really appreciate. Here is the code where i use matrices in geometry shader.

[maxvertexcount(4)]
void RenderRainGS(point VSIn input[1], inout TriangleStream<PSIn> SpriteStream)
{

PSIn output = (PSIn)0;

float3 pos[4];
GenBillboardSpriteVertices(input[0].position, float3(0, -1, 0), cameraPosition, pos);

matrix viewProjection = mul(viewMatrix, projectionMatrix);

output.position = mul( float4(pos[0],1.0), viewProjection );
SpriteStream.Append(output);

output.position = mul( float4(pos[1],1.0), viewProjection );
SpriteStream.Append(output);

output.position = mul( float4(pos[2],1.0), viewProjection );
SpriteStream.Append(output);

output.position = mul( float4(pos[3],1.0), viewProjection );
SpriteStream.Append(output);

SpriteStream.RestartStrip();
}


Thanks.
Advertisement
I am still looking for the answers. So if anyone knows something about these questions i really appreciate it.
Hi!


Now if i try ConstructGSWithSO with AdvanceRainVS function rain particles doesn't move but i get no error and it draws rain particles. And if i try with AdvanceRainGS it works correctly. I couldn't find the reason for this problem.

You want to bypass the geometry shader and use stream output, right?
Do you create your shader like this?

VertexShader vsShader = CompileShader(vs_5_0, AdvanceRainVS());
GeometryShader gsStreamOut = ConstructGSWithSO(vsShader, "0:POSITION.xyz; 0:SPEED.xyz" );

technique11 AdvanceRain
{
pass p0
{
SetVertexShader(vsShader);
SetGeometryShader(gsStreamOut);
...
}
}



My second question is when i try to debug my code with pix i get error about ConstructGSWithSO. I've added screenshot of the problem. I've searched for this problem and found there are also some other people having the same problem but they couldn't manage to solve it. I tried to debug nvidia rain demo to see if i get the same error but i didn't get any errors. So i think i did something wrong but since it works correctly i couldn't find what.

Unfortunately this appears to be a bug in PIX. Creating geometry shaders with stream output doesn’t work in PIX if you use the Dx11 API (even on Feature Level 10). The Nvidia Demo is fine since it uses the Dx10 API. My hope is that the next DxSDK will remove this bug. Maybe it is already fixed in the Windows 8 Developer Preview. I’ve seen that the new Visual Studio has PIX build in, so it is likely they also have reviewed a few known problems. Maybe it would be worth a try?

One note: When I want to debug stream output stuff in Dx11 then I let my geometry shader write out to stream output, afterwards I switch to a code path without a geometry shader (e.g. by having a button on the UI that sets a flag to skip the execution of the geometry shader with the stream output) and then I capture the frame with PIX. Then PIX will be able to replay the capture and the output buffer of the stream output will still contain the data.


And my last question is about geometry shaders. For vertex shaders matrices need to be transposed before multiplication. But in the geometry shader they need to be sent without transpose. I don't understand reasoning behind this.

That shouldn’t be the case. Do you bind the shaders in a different manner? (For instance at VS with the effect framework and at GS with a constant buffer by yourself?)
You could try to place the row_major / column_major modifiers in front of your matrices and see whether this makes it consistent.
row_major matrix viewMatrix;
row_major matrix projectionMatrix;


If it helps you can try to tell Dx, which matrix packing to use by default by using the compiler switch /Zpr for row_major or /Zpc for column_major with fxc. (According to the documentation column_major should be faster.)

Cheers!
Thank you very much for answers. I didn't know that main vertex shader and stream out shader must be the same vertex shader. I was setting the main vertex shader to empty vertex shader(i mean nothing is done in it by "empty" not null). I changed it now and problem solved :). It is good to know problem is not in my code with pix. And i didn't know that i can tell directx what type of matrix to use so i learned it now :). But for the first question i still have problem. Again thanks for all of the answers. They solved all of my problems. But if you don't mind i would like to know why we need to set both vertex shader and geometry shader to be same vertex shader. I mean when we set both of them to AdvanceRainVS first the code runs for vertex shader and then it runs for geometry shader isn't it? Or directx automatically overrides one of them?
Hi again,


Thank you very much for answers. I didn't know that main vertex shader and stream out shader must be the same vertex shader. I was setting the main vertex shader to empty vertex shader(i mean nothing is done in it by "empty" not null). I changed it now and problem solved . It is good to know problem is not in my code with pix. And i didn't know that i can tell directx what type of matrix to use so i learned it now . But for the first question i still have problem. Again thanks for all of the answers. They solved all of my problems. But if you don't mind i would like to know why we need to set both vertex shader and geometry shader to be same vertex shader. I mean when we set both of them to AdvanceRainVS first the code runs for vertex shader and then it runs for geometry shader isn't it? Or directx automatically overrides one of them?


You’re welcome.
By definition it is the geometry shader stage that writes to stream output, because the stream output should capture primitives, not vertices. If you render a point list primitives and vertices will coincide, though. But if you would render triangles with an index buffer, then the GS would write out the primitives (and thereby duplicate vertices), so the index buffer would be useless when drawing from the streamed out buffer. It would be redundant if we could specify semantics to output at the vertex shader, too, because we could simply pass the data to the geometry shader and write it out there. It can’t be written after the vertex shader anyway until the complete primitive went through the vertex shader stage (because stream out only writes complete primitives). So they made the design decision to only declare the stream output after the geometry shader.

Nevertheless, at times we would like to be able to stream out directly after the vertex shader, because we know that no geometry will be added. Well, and this use case can be defined in this rather unintuitive way.

  1. We bind the VS to the vertex shader stage so that the vertex shader stage knows what to do. (After all this is the stage that receives data from the input assembler, so we can’t skip it.)
  2. We use the VS in ConstructGSWithSO so that the stream output will know what semantics to write out. The “GeometryShader” object returned by this method does not contain a valid geometry shader, because we never compiled one. It is just a way of connecting the vertex shader with the stream output.

Dx will be smart enough to detect that the shader we threw in ConstructGSWithSO was a VS and will thus not enter the GS stage at all.

Cheers! smile.png

This topic is closed to new replies.

Advertisement