user1700893
user1700893

Reputation: 21

How do you use Geometry Shader with Output Stream?

It seems that this feature is very poorly documented.In the Geometry Shader tutorials in the DirectX SDK there is no example of using CreateGeometryShaderWithStreamOutput and there are no threads anywhere that explain the basics of it.In msdn they say what functions to use to create it,but not how and what it's used for.Is there anyone who has successfully used it,can you share a small example or a link to a tutorial for it?What's it used for and is it good performance wise?As far as I understood,it's used for GPU-based frustum culling?

Upvotes: 2

Views: 5431

Answers (1)

mrvux
mrvux

Reputation: 8963

You can find 2 examples in the DirectX SDK (In the directX 10 section)

  • PipesGS
  • ParticlesGS

You can also check the NVidia samples: http://developer.download.nvidia.com/SDK/10/direct3d/samples.html

Rain and Metaballs are using stream out

All those samples are on dx10, but they fairly easy to port to dx11 (just few bits to replace).

There's quite several usages for it (non exhaustive list):

  • Dynamic particles
  • Model pre-processing (skinning, displacement,tesselation). So you can apply displacement on your model once, then rebind the displaced model to several passes (shadow map/material...)
  • Model export: generate some geometry in shader, get stream output content back in cpu and export as 3d model.

In case you want to use raw pipeline instead of stream output, you need to perform the following (this is a summary from Microsoft Stream Output documentation)

FX Framework does the same under the hood.

Your Geometry shader must be created with CreateGeometryShaderWithStreamOutput

instead of CreateGeometryShader

You need to set D3D11_SO_DECLARATION_ENTRY to match your geometry shader output layout (This works the same as Input Assembler)

Next make sure your buffer is created with stream output access:

D3D11_BUFFER_DESC bufferDesc;
bufferDesc.BindFlags = otherBindFlags | D3D11_BIND_STREAM_OUTPUT;
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
bufferDesc.CPUAccessFlags = 0;

Please note that otherBindFlags cannot be D3D11_BIND_UNORDERED_ACCESS at the same time (Shader View and Raw Views are allowed tho).

Finally, before to perform your draw, assign your stream output buffer with SOSetTargets:

UINT offset[1] = 0;
ID3D11Buffer* m_pBuffer (your buffer created before)
deviceContext->SOSetTargets( 1, &m_pBuffer, offset );

Once you are done with your draw call, don't forget to clean using:

UINT offset[1] = 0;
ID3D11Buffer* pNullBuffer = 0;
deviceContext->SOSetTargets( 1, &pNullBuffer, offset );

Upvotes: 3

Related Questions