I'm trying to stream out data from the geometry shader to use as a vertex buffer to be input into another shader. However, this doesn't seem to be working, and the debug layer is telling me nothing. Is there something I'm doing wrong with the buffer descriptions?
Here's how I'm creating the output buffer:
D3D11_BUFFER_DESC outputBufferDesc;
ZeroMemory(&outputBufferDesc, sizeof(outputBufferDesc));
outputBufferDesc.ByteWidth = sizeof(XMFLOAT4) + 2 * sizeof(XMFLOAT3);
outputBufferDesc.Usage = D3D11_USAGE_DEFAULT;
outputBufferDesc.BindFlags = D3D11_BIND_STREAM_OUTPUT;
outputBufferDesc.CPUAccessFlags = 0;
outputBufferDesc.MiscFlags = 0;
outputBufferDesc.StructureByteStride = 0;
result = renderer->CreateBuffer(&outputBufferDesc, NULL, &outputBuffer);
if (result != S_OK)
{
MessageBox(NULL, filename, L"Failed to create stream output buffer", MB_OK);
exit(0);
}
UINT offset[1] = { 0 };
deviceContext->SOSetTargets(1, &outputBuffer, offset);
And the draw call for the first shader:
deviceContext->VSSetShader(vertexShader, NULL, 0);
deviceContext->PSSetShader(pixelShader, NULL, 0);
deviceContext->GSSetShader(streamOutputGeometryShader, NULL, 0);
// Render the triangle.
deviceContext->DrawIndexed(indexCount, 0, 0);
UINT offset[1] = { 0 };
ID3D11Buffer* pNullBuffer = 0;
deviceContext->SOSetTargets(1, &pNullBuffer, offset);
And where I copy the information from that buffer into a second buffer:
D3D11_BUFFER_DESC vertexBufferDesc;
ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc));
vertexBufferDesc.ByteWidth = sizeof(XMFLOAT4) + 2 * sizeof(XMFLOAT3);
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;
vertexBufferDesc.StructureByteStride = 0;
result = renderer->CreateBuffer(&vertexBufferDesc, NULL, &vertexBuffer);
if (result != S_OK)
{
MessageBox(NULL, L"Failed to create output mesh vertex buffer", L"Failed", MB_OK);
exit(0);
}
deviceContext->CopyResource(vertexBuffer, buffer);
And where I set the input topology for the mesh using the vertex buffer:
unsigned int stride;
unsigned int offset;
// Set vertex buffer stride and offset.
stride = sizeof(XMFLOAT4) + 2 * sizeof(XMFLOAT3);
offset = 0;
deviceContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
And finally, the draw call for the second shader is simple:
deviceContext->DrawAuto();
EDIT: The geometry is being computed in the geometry shader correctly, but it's not being streamed out. I've included the geometry shader creation code below:
D3D11_SO_DECLARATION_ENTRY SODeclarationEntry[3] =
{
{ 0, "SV_POSITION", 0, 0, 4, 0 },
{ 0, "NORMAL", 0, 0, 3, 0 },
{ 0, "TEXCOORD", 0, 0, 3, 0 }
};
// Create the geometry shader from the buffer.
result = renderer->CreateGeometryShaderWithStreamOutput(geometryShaderBuffer->GetBufferPointer(), geometryShaderBuffer->GetBufferSize(), SODeclarationEntry, _countof(SODeclarationEntry),
NULL, 0, D3D11_SO_NO_RASTERIZED_STREAM, NULL, &streamOutputGeometryShader);
In addition to just the actual vertex data, buffers used as targets for the Stream Output Stage maintain some internal state to keep track of how much geometry was written out. DrawAuto()
relies on this information to know how much geometry to draw. When you copy just the vertex data out of your stream output buffer into a plain D3D11_BIND_VERTEX_BUFFER
, this information will be lost.
Relevant quote from the documentation:
DrawAuto only works when drawing with one input buffer bound as an input to the IA stage at slot 0. Applications must create the SO buffer resource with both binding flags, D3D11_BIND_VERTEX_BUFFER and D3D11_BIND_STREAM_OUTPUT.
I'm not sure if it's supposed to be possible to copy data from one stream output buffer to another and DrawAuto()
from there. I guess that might work. What you are doing at the moment, however, is definitely not supposed to work according to the documentation. Ideally, you'd just avoid copying the data. If you really must copy the data (for whatever reason), I suggest you nevertheless first try drawing directly from the buffer you streamed into to make sure everything else is set up correctly and only once that works try to copy into another buffer that has both vertex and stream output bind flags set…