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?
1 Answers
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 );

- 8,523
- 1
- 27
- 61
-
Those two Microsoft’s DX10 samples don’t use CreateGeometryShaderWithStreamOutput API. While they use output streams, they do so in FX effects, not in C++ code. – Soonts Apr 03 '17 at 04:54
-
nVidia samples do the same. – Soonts Apr 03 '17 at 05:00
-
In my case, the problem was MSDN says “possible values include: POSITION”, bit it gives E_INVALIDARG from CreateGeometryShaderWithStreamOutput API. “SV_Position” worked OK instead. – Soonts Apr 06 '17 at 00:21