我是DirectX 12的新用户并尝试在DX上渲染网格物体。到目前为止,我成功地从obj和fbx文件中检索顶点和索引,并使用模板通用窗口项目渲染DX 12上的所有顶点。但是,我遇到了一些index缓冲区的问题,因为三角形列表的渲染结果完全不正确,特别是当输入网格很大(数十万个顶点)时。基本上,索引数据被写为指针数组,似乎是正确的。使用行列表原始拓扑,渲染结果如下所示。 Line list primitive topology rendering result
我想知道是否有人可以提出任何可能在代码中出错的建议。对于IBV设置,我使用模板项目中的确切代码。提前感谢您的帮助。
更新:数据是使用FBX SDK检索的obj文件数据。我确认了obj网格信息和检索到的数据,它们是精确匹配的。所以我认为数据文件是正确的。此外,对于IBV设置传入的数据,例如缓冲区字节大小,也是正确的。对于代码,它来自VS DX 12模板通用窗口项目,如下所示。非常感谢您的帮助。
// Create the index buffer resource in the GPU's default heap and copy index data into it using the upload heap.
// The upload resource must not be released until after the GPU has finished using it.
Microsoft::WRL::ComPtr<ID3D12Resource> indexBufferUpload;
//CD3DX12_RESOURCE_DESC indexBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(indexBufferSize);
DX::ThrowIfFailed(d3dDevice->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(defaultHeapProperties),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(indexBufferSize),
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&m_indexBuffer)));
DX::ThrowIfFailed(d3dDevice->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(indexBufferSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&indexBufferUpload)));
m_indexBuffer->SetName(L"Index Buffer Resource");
indexBufferUpload->SetName(L"Index Buffer Upload Resource");
// Upload the index buffer to the GPU.
{
D3D12_SUBRESOURCE_DATA indexData = {0};
//indexData.pData = cubeIndices;
indexData.pData = reinterpret_cast<BYTE*>(cubeIndices);
indexData.RowPitch = indexBufferSize;
indexData.SlicePitch = indexData.RowPitch;
UpdateSubresources(m_commandList.Get(), m_indexBuffer.Get(), indexBufferUpload.Get(), 0, 0, 1, &indexData);
CD3DX12_RESOURCE_BARRIER indexBufferResourceBarrier =
CD3DX12_RESOURCE_BARRIER::Transition(m_indexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_INDEX_BUFFER);
//CD3DX12_RESOURCE_BARRIER indexBufferResourceBarrier =
// CD3DX12_RESOURCE_BARRIER::Transition(m_indexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
m_commandList->ResourceBarrier(1, &indexBufferResourceBarrier);
}
// Create a descriptor heap for the constant buffers.
{
D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
heapDesc.NumDescriptors = DX::c_frameCount;
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
// This flag indicates that this descriptor heap can be bound to the pipeline and that descriptors contained in it can be referenced by a root table.
heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
DX::ThrowIfFailed(d3dDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&m_cbvHeap)));
m_cbvHeap->SetName(L"Constant Buffer View Descriptor Heap");
}
CD3DX12_RESOURCE_DESC constantBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(DX::c_frameCount * c_alignedConstantBufferSize);
DX::ThrowIfFailed(d3dDevice->CreateCommittedResource(
&uploadHeapProperties,
D3D12_HEAP_FLAG_NONE,
&constantBufferDesc,
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_constantBuffer)));
m_constantBuffer->SetName(L"Constant Buffer");
// Create constant buffer views to access the upload buffer.
D3D12_GPU_VIRTUAL_ADDRESS cbvGpuAddress = m_constantBuffer->GetGPUVirtualAddress();
CD3DX12_CPU_DESCRIPTOR_HANDLE cbvCpuHandle(m_cbvHeap->GetCPUDescriptorHandleForHeapStart());
m_cbvDescriptorSize = d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
for (int n = 0; n < DX::c_frameCount; n++)
{
D3D12_CONSTANT_BUFFER_VIEW_DESC desc;
desc.BufferLocation = cbvGpuAddress;
desc.SizeInBytes = c_alignedConstantBufferSize;
d3dDevice->CreateConstantBufferView(&desc, cbvCpuHandle);
cbvGpuAddress += desc.SizeInBytes;
cbvCpuHandle.Offset(m_cbvDescriptorSize);
}
// Map the constant buffers.
DX::ThrowIfFailed(m_constantBuffer->Map(0, nullptr, reinterpret_cast<void**>(&m_mappedConstantBuffer)));
ZeroMemory(m_mappedConstantBuffer, DX::c_frameCount * c_alignedConstantBufferSize);
// We don't unmap this until the app closes. Keeping things mapped for the lifetime of the resource is okay.
// Close the command list and execute it to begin the vertex/index buffer copy into the GPU's default heap.
DX::ThrowIfFailed(m_commandList->Close());
ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
m_deviceResources->GetCommandQueue()->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
// Create vertex/index buffer views.
m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress();
m_vertexBufferView.StrideInBytes = sizeof(VertexPositionColorTexture);
m_vertexBufferView.SizeInBytes = sizeof(*cubeVertices) * m_VertexNumber;
m_indexBufferView.BufferLocation = m_indexBuffer->GetGPUVirtualAddress();
m_indexBufferView.SizeInBytes = sizeof(*cubeIndices) * m_VertxIndicesNumber;
m_indexBufferView.Format = DXGI_FORMAT_R16_UINT;
// Wait for the command list to finish executing; the vertex/index buffers need to be uploaded to the GPU before the upload resources go out of scope.
m_deviceResources->WaitForGpu();
答案 0 :(得分:1)
数据是使用FBX SDK检索的obj文件数据。我确认了obj网格信息和检索到的数据,它们是精确匹配的。所以我认为数据文件是正确的。此外,对于IBV设置传入的数据,例如缓冲区字节大小,也是正确的。对于代码,它来自VS DX 12模板通用窗口项目,如下所示。非常感谢您的帮助。
// Create the index buffer resource in the GPU's default heap and copy index data into it using the upload heap.
// The upload resource must not be released until after the GPU has finished using it.
Microsoft::WRL::ComPtr<ID3D12Resource> indexBufferUpload;
//CD3DX12_RESOURCE_DESC indexBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(indexBufferSize);
DX::ThrowIfFailed(d3dDevice->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(defaultHeapProperties),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(indexBufferSize),
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&m_indexBuffer)));
DX::ThrowIfFailed(d3dDevice->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(indexBufferSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&indexBufferUpload)));
m_indexBuffer->SetName(L"Index Buffer Resource");
indexBufferUpload->SetName(L"Index Buffer Upload Resource");
// Upload the index buffer to the GPU.
{
D3D12_SUBRESOURCE_DATA indexData = {0};
//indexData.pData = cubeIndices;
indexData.pData = reinterpret_cast<BYTE*>(cubeIndices);
indexData.RowPitch = indexBufferSize;
indexData.SlicePitch = indexData.RowPitch;
UpdateSubresources(m_commandList.Get(), m_indexBuffer.Get(), indexBufferUpload.Get(), 0, 0, 1, &indexData);
CD3DX12_RESOURCE_BARRIER indexBufferResourceBarrier =
CD3DX12_RESOURCE_BARRIER::Transition(m_indexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_INDEX_BUFFER);
//CD3DX12_RESOURCE_BARRIER indexBufferResourceBarrier =
// CD3DX12_RESOURCE_BARRIER::Transition(m_indexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
m_commandList->ResourceBarrier(1, &indexBufferResourceBarrier);
}
// Create a descriptor heap for the constant buffers.
{
D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
heapDesc.NumDescriptors = DX::c_frameCount;
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
// This flag indicates that this descriptor heap can be bound to the pipeline and that descriptors contained in it can be referenced by a root table.
heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
DX::ThrowIfFailed(d3dDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&m_cbvHeap)));
m_cbvHeap->SetName(L"Constant Buffer View Descriptor Heap");
}
CD3DX12_RESOURCE_DESC constantBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(DX::c_frameCount * c_alignedConstantBufferSize);
DX::ThrowIfFailed(d3dDevice->CreateCommittedResource(
&uploadHeapProperties,
D3D12_HEAP_FLAG_NONE,
&constantBufferDesc,
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_constantBuffer)));
m_constantBuffer->SetName(L"Constant Buffer");
// Create constant buffer views to access the upload buffer.
D3D12_GPU_VIRTUAL_ADDRESS cbvGpuAddress = m_constantBuffer->GetGPUVirtualAddress();
CD3DX12_CPU_DESCRIPTOR_HANDLE cbvCpuHandle(m_cbvHeap->GetCPUDescriptorHandleForHeapStart());
m_cbvDescriptorSize = d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
for (int n = 0; n < DX::c_frameCount; n++)
{
D3D12_CONSTANT_BUFFER_VIEW_DESC desc;
desc.BufferLocation = cbvGpuAddress;
desc.SizeInBytes = c_alignedConstantBufferSize;
d3dDevice->CreateConstantBufferView(&desc, cbvCpuHandle);
cbvGpuAddress += desc.SizeInBytes;
cbvCpuHandle.Offset(m_cbvDescriptorSize);
}
// Map the constant buffers.
DX::ThrowIfFailed(m_constantBuffer->Map(0, nullptr, reinterpret_cast<void**>(&m_mappedConstantBuffer)));
ZeroMemory(m_mappedConstantBuffer, DX::c_frameCount * c_alignedConstantBufferSize);
// We don't unmap this until the app closes. Keeping things mapped for the lifetime of the resource is okay.
// Close the command list and execute it to begin the vertex/index buffer copy into the GPU's default heap.
DX::ThrowIfFailed(m_commandList->Close());
ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
m_deviceResources->GetCommandQueue()->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
// Create vertex/index buffer views.
m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress();
m_vertexBufferView.StrideInBytes = sizeof(VertexPositionColorTexture);
m_vertexBufferView.SizeInBytes = sizeof(*cubeVertices) * m_VertexNumber;
m_indexBufferView.BufferLocation = m_indexBuffer->GetGPUVirtualAddress();
m_indexBufferView.SizeInBytes = sizeof(*cubeIndices) * m_VertxIndicesNumber;
m_indexBufferView.Format = DXGI_FORMAT_R16_UINT;
// Wait for the command list to finish executing; the vertex/index buffers need to be uploaded to the GPU before the upload resources go out of scope.
m_deviceResources->WaitForGpu();
答案 1 :(得分:0)
我实际上和Michael一起工作,所以我知道这个问题的答案:)。我会在这里发布,以便让人们绊倒这篇文章。
当有超过140000个指数时,问题确实是使用16位(无符号短指数)。最大无符号短路为65535.解决方案是使用格式为DXGI_FORMAT_R32_UINT的32位索引(unsigned int)。
答案 2 :(得分:0)
对于那些也使用 DirectX 模板并在此问题上苦苦挣扎的人,我建议搜索 DrawIndexedInstanced
。在那里,我不得不根据增加的事件数据量更新 IndexCountPerInstance
参数。
为了使其更灵活,应根据索引计算大小。由于我将 m_indexBufferView.SizeInBytes
设置为以字节为单位的索引大小,因此我必须将其除以 unsigned int
的大小。
std::vector<unsigned int> indices;
...
// Fill vertex data and indices data
//Render one frame
...
DrawIndexedInstanced(m_indexBufferView.SizeInBytes / sizeof(unsigned int), 1, 0, 0, 0);