D3D11 Debug Layer的bug

在開發D3D應用程序時,咱們會使用Debug Layer來調試應用程序,以確保咱們的程序在最終發佈時沒有warnings和errors。不過最近在開發應用程序時遇到了這樣的問題,就是我把多個網格模型的頂點數據放在一個vertex buffer中,與此同時也把它們的索引數據放在一個index buffer中,而後在繪製不一樣的網格模型時就須要設置相應的偏移量,代碼看上去是這樣的:ide

首先我建立了一個box和一個grid:函數

CGeometryGenerator::CreateBox( 1.0f, 1.0f, 1.0f, box );
CGeometryGenerator::CreateGrid( 20.0f, 30.0f, 50, 40, grid );

接着我記錄下每一個網格模型的頂點偏移量和索引偏移量:ui

g_uBoxVertexOffset = 0;
g_uGridVertexOffset = g_uBoxVertexOffset + box.vertices.size();

g_uBoxIndexCount = box.indices.size();
g_uGridIndexCount = grid.indices.size();

g_uBoxIndexOffset = 0;
g_uGridIndexOffset = g_uBoxIndexOffset + g_uBoxIndexCount;

最後我將box和grid的頂點數據與索引數據存放在一個vertex buffer和index buffer中:spa

// Copy vertices
UINT uVertexCount = box.vertices.size() + grid.vertices.size() + sphere.vertices.size() + cylinder.vertices.size();
std::vector<VertexPositionNormal> vVertices( uVertexCount );
UINT uVertexIndex = 0;

for ( UINT vertexIndex = 0; vertexIndex < box.vertices.size(); ++vertexIndex, ++uVertexIndex )
{
    VertexPositionNormal &vertex = vVertices[uVertexIndex];
    VertexPositionNormalTangentColorTexture &boxVertex = box.vertices[vertexIndex];
        
    vertex.position = boxVertex.position;
    vertex.normal = boxVertex.normal;
}

for ( UINT vertexIndex = 0; vertexIndex < grid.vertices.size(); ++vertexIndex, ++uVertexIndex )
{
    VertexPositionNormal &vertex = vVertices[uVertexIndex];
    VertexPositionNormalTangentColorTexture &gridVertex = grid.vertices[vertexIndex];
        
    vertex.position = gridVertex.position;
    vertex.normal = gridVertex.normal;
}

// Create vertex buffer
{
    D3D11_BUFFER_DESC vertexBufferDesc;
    vertexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
    vertexBufferDesc.ByteWidth = sizeof(VertexPositionNormal) * uVertexCount;
    vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vertexBufferDesc.CPUAccessFlags = 0;
    vertexBufferDesc.MiscFlags = 0;
    vertexBufferDesc.StructureByteStride = 0;

    D3D11_SUBRESOURCE_DATA subresourceData;
    subresourceData.pSysMem = &vVertices[0];
    subresourceData.SysMemPitch = 0;
    subresourceData.SysMemSlicePitch = 0;

    HRESULT hr;
    V( pD3DDevice->CreateBuffer(&vertexBufferDesc, &subresourceData, g_pShapeVertexBuffer.ReleaseAndGetAddressOf()) );
}

// Create indices
UINT uIndexCount = g_uBoxIndexCount + g_uGridIndexCount;

std::vector<UINT> vIndices;
vIndices.insert( vIndices.end(), box.indices.begin(), box.indices.end() );
vIndices.insert( vIndices.end(), grid.indices.begin(), grid.indices.end() );

// Create index buffer
{
    D3D11_BUFFER_DESC indexBufferDesc;
    indexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
    indexBufferDesc.ByteWidth = sizeof(UINT) * uIndexCount;
    indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
    indexBufferDesc.CPUAccessFlags = 0;
    indexBufferDesc.MiscFlags = 0;
    indexBufferDesc.StructureByteStride = 0;

    D3D11_SUBRESOURCE_DATA subresourceData;
    subresourceData.pSysMem = &vIndices[0];
    subresourceData.SysMemPitch = 0;
    subresourceData.SysMemSlicePitch = 0;

    HRESULT hr;
    V( pD3DDevice->CreateBuffer(&indexBufferDesc, &subresourceData, g_pShapeIndexBuffer.ReleaseAndGetAddressOf()) );
}

所以,在繪製grid時,我就須要設置相應的偏移量來保證讀取的頂點和索引數據是正確的,代碼以下:調試

pD3DImmediateContext->DrawIndexed( g_uGridIndexCount, g_uGridIndexOffset, g_uGridVertexOffset );

這個時候,D3D Debug Layer就會出現錯誤:code

起初覺得是偏移量設置出錯,可是仔細檢查了代碼,發現沒有任何問題,同時渲染結果也是正確的。因而,嘗試採用另外一種方式,就是在設置vertex buffer時設置偏移量:orm

UINT stride = sizeof( VertexPositionNormal );
UINT offset = g_uGridVertexOffset * sizeof(VertexPositionNormal);
pD3DImmediateContext->IASetVertexBuffers( 0, 1, g_pShapeVertexBuffer.GetAddressOf(), &stride, &offset );

pD3DImmediateContext->DrawIndexed( g_uGridIndexCount, g_uGridIndexOffset, 0 );

此時錯誤就消失了,渲染也是正確的,也就是說,代碼中的偏移量計算是正確的。blog

因而上網翻閱了一些資料,發現有很多朋友遇到過這個問題,同時確認這個是D3D Debug Layer的bug,也就是當DrawIndexed函數中的StartIndexLocation和BaseVertexLocation參數同時不爲0時,就會出現上圖的warning。
既然程序是正確的,那麼有什麼辦法能夠不讓它打印這個warning呢?一個方法就是上面我提到的,在設置vertex buffer時設置偏移量。還有個辦法就是通知Debug Layer隱藏這個消息:索引

// Hide warning: DEVICE_DRAW_INDEX_BUFFER_TOO_SMALL which is a bug of D3D11 Debug Layer
#if defined(DEBUG) | defined(_DEBUG)
ID3D11Debug *pD3DDebug = NULL;
if( SUCCEEDED(pD3DDevice->QueryInterface(__uuidof(ID3D11Debug), reinterpret_cast<VOID**>(&pD3DDebug))) )
{
    ID3D11InfoQueue *pD3DInfoQueue = NULL;
    if( SUCCEEDED(pD3DDebug->QueryInterface(__uuidof(ID3D11InfoQueue), reinterpret_cast<VOID**>(&pD3DInfoQueue))) )
    {
        D3D11_MESSAGE_ID arrHiddenMessageID[] =
        {
            D3D11_MESSAGE_ID_DEVICE_DRAW_INDEX_BUFFER_TOO_SMALL,
        };
            
        D3D11_INFO_QUEUE_FILTER filter;
        memset( &filter, 0, sizeof(filter) );
        filter.DenyList.NumIDs = ARRAYSIZE( arrHiddenMessageID );
        filter.DenyList.pIDList = arrHiddenMessageID;
        
        pD3DInfoQueue->AddStorageFilterEntries( &filter );
        SAFE_RELEASE( pD3DInfoQueue );
    }
    SAFE_RELEASE( pD3DDebug );
}
#endif
相關文章
相關標籤/搜索