DirectX11 - 带流输出的几何着色器

DirectX11 - Geometry Shader with Stream Output

我正在尝试从几何着色器流出数据以用作顶点缓冲区以输入到另一个着色器。但是,这似乎不起作用,调试层什么也没告诉我。缓冲区描述有什么问题吗?

以下是我创建输出缓冲区的方式:

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);

第一个着色器的绘制调用:

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);

然后我将信息从该缓冲区复制到第二个缓冲区:

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);

我在其中使用顶点缓冲区设置网格的输入拓扑:

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);

最后,第二个着色器的绘制调用很简单:

deviceContext->DrawAuto();

编辑:正在几何着色器中正确计算几何,但未流出。我在下面包含了几何着色器创建代码:

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);

除了实际的顶点数据之外,用作流输出阶段目标的缓冲区还维护一些内部状态,以跟踪写出的几何体量。 DrawAuto() 依靠此信息来了解要绘制多少几何图形。当您仅将流输出缓冲区中的顶点数据复制到普通 D3D11_BIND_VERTEX_BUFFER 时,此信息将丢失。

来自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.

我不确定是否可以将数据从一个流输出缓冲区复制到另一个流输出缓冲区并从那里 DrawAuto()。我想这可能行得通。但是,根据文档,您目前正在做的事情绝对不应该起作用。理想情况下,您应该避免复制数据。如果你真的必须复制数据(无论出于何种原因),我建议你首先尝试直接从你流式传输到的缓冲区中绘制以确保其他所有内容都设置正确并且只有在工作时尝试复制到另一个同时具有两者的缓冲区顶点和流输出绑定标志集…