2015-12-01 145 views
1

我是DirectX 12的新手,尝试在DX上渲染网格。到目前为止,我成功地从obj和fbx文件检索顶点和索引,并使用模板通用窗口项目呈现DX 12上的所有顶点。但是,由于三角形列表的渲染结果完全不正确,特别是当输入网格很大(数十万个顶点)时,我遇到了索引缓冲区的一些问题。基本上,索引数据被写成一个指针数组,它似乎是正确的。使用线列表基元拓扑,渲染结果如下所示。 Line list primitive topology rendering resultDirectX 12索引缓冲区

我想知道是否有人可以给出任何建议,哪里可能出现代码错误。对于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

感谢您的建议,我刚刚更新了这个问题。 –

+0

你建议它在成千上万的顶点出现错误,当然如果你只使用不超过65,535的16位索引,它会这样做。但是,您不清楚它是否突破65,535个顶点,是吗? –

+0

我用了一个较小的网格(530个顶点和992个面),但问题仍然存在。 –

回答

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(); 
+0

这不是答案,它只是更多的信息?如果是这样,你应该编辑它的问题,而不是作为答案发布。 – Gimby

0

我实际上与迈克尔合作,所以我知道这个问题的答案:)。我只是在这里发布,让人们在这篇文章中磕磕绊绊。

当超过140000个索引时,问题的确在使用16位(无符号短符号)索引。最大无符号短整型为65535.该解决方案使用格式为DXGI_FORMAT_R32_UINT的32位索引(无符号整型)。