directx 11 中的最佳顶点缓冲对象

optional vertexbufferobjects in directx11

我有一些模型(几何)有一些顶点信息。例如位置、法线、颜色、纹理坐标,每个信息都有自己的顶点缓冲区。但是其中一些模型有纹理坐标,有些没有…… 为了管理这些差异,我写了一个顶点着色器,它正在检查常量缓冲区 "hasTextureCoordinates" 中的标志是否 == 1。如果是,它是否使用 texcoord 参数。 但是 Directx 并不真正喜欢这种解决方法并打印出:

D3D11 INFO: ID3D11DeviceContext::Draw: Element [3] in the current Input Layout's declaration references input slot 3, but there is no Buffer bound to this slot. This is OK, as reads from an empty slot are defined to return 0. It is also possible the developer knows the data will not be used anyway. This is only a problem if the developer actually intended to bind an input Buffer here. [ EXECUTION INFO #348: DEVICE_DRAW_VERTEX_BUFFER_NOT_SET]

我不确定每个硬件是否都能正确处理这个问题,而且在输出中看到这个 "warnings" 每帧也不是很好... 我知道我可以写两个着色器,一个有一个没有 texcoods,但问题是这不是唯一可能缺少的参数......有些有颜色,有些没有,有些有颜色和纹理坐标等等。并且为顶点缓冲区输入的每个组合编写一个着色器是极其多余的。这非常糟糕,因为如果我们更改一个着色器,我们也必须更改所有其他着色器。也有可能将部分着色器放入不同的文件并包含它们,但这很混乱。

有没有办法说directx特定的vertexbuffer是可选的? 或者有人知道这个问题的更好解决方案吗?

您可以通过编程方式禁止显示此特定消息。由于它是 INFO 而不是 ERRORCORRUPTION 消息,因此忽略它是安全的。

#include <wrl/client.h>

using Microsoft::WRL::ComPtr;

ComPtr<ID3D11Debug> d3dDebug;
if ( SUCCEEDED( device.As(&d3dDebug) ) )
{
    ComPtr<ID3D11InfoQueue> d3dInfoQueue;
    if ( SUCCEEDED( d3dDebug.As(&d3dInfoQueue) ) )
    {
#ifdef _DEBUG
        d3dInfoQueue->SetBreakOnSeverity( D3D11_MESSAGE_SEVERITY_CORRUPTION, true );
        d3dInfoQueue->SetBreakOnSeverity( D3D11_MESSAGE_SEVERITY_ERROR, true );
#endif
        D3D11_MESSAGE_ID hide[] =
        {
            D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS,
            D3D11_MESSAGE_ID_DEVICE_DRAW_VERTEX_BUFFER_NOT_SET, // <--- Your message here!
            // Add more message IDs here as needed 
        };
        D3D11_INFO_QUEUE_FILTER filter = {};
        filter.DenyList.NumIDs = _countof(hide);
        filter.DenyList.pIDList = hide;
        d3dInfoQueue->AddStorageFilterEntries( &filter );
    }
}

除了抑制 'noise' 消息外,在调试版本中,如果您确实遇到了 ERRORCORRUPTION 消息,因为这些确实需要修复。

Direct3D SDK Debug Layer Tricks

Note I'm using ComPtr here to simplify the QueryInterface chain, and I assume you are keeping your device as a ComPtr<ID3D11Device> device as I do in in Anatomy of Direct3D 11 Create Device

I also assume you are using VS 2013 or later so that D3D11_INFO_QUEUE_FILTER filter = {}; is sufficient to zero-fill the structure.