在开发D3D应用程序时,我们会使用Debug Layer来调试应用程序,以确保我们的程序在最终发布时没有warnings和errors。不过最近在开发应用程序时遇到了这样的问题,就是我把多个网格模型的顶点数据放在一个vertex buffer中,与此同时也把它们的索引数据放在一个index buffer中,然后在绘制不同的网格模型时就需要设置相应的偏移量,代码看上去是这样的:

首先我创建了一个box和一个grid:

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

接着我记录下每个网格模型的顶点偏移量和索引偏移量:

g_uBoxVertexOffset = ;
g_uGridVertexOffset = g_uBoxVertexOffset + box.vertices.size(); g_uBoxIndexCount = box.indices.size();
g_uGridIndexCount = grid.indices.size(); g_uBoxIndexOffset = ;
g_uGridIndexOffset = g_uBoxIndexOffset + g_uBoxIndexCount;

最后我将box和grid的顶点数据与索引数据存放在一个vertex buffer和index buffer中:

// Copy vertices
UINT uVertexCount = box.vertices.size() + grid.vertices.size() + sphere.vertices.size() + cylinder.vertices.size();
std::vector<VertexPositionNormal> vVertices( uVertexCount );
UINT uVertexIndex = ; for ( UINT vertexIndex = ; 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 = ; 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 = ;
vertexBufferDesc.MiscFlags = ;
vertexBufferDesc.StructureByteStride = ; D3D11_SUBRESOURCE_DATA subresourceData;
subresourceData.pSysMem = &vVertices[];
subresourceData.SysMemPitch = ;
subresourceData.SysMemSlicePitch = ; 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 = ;
indexBufferDesc.MiscFlags = ;
indexBufferDesc.StructureByteStride = ; D3D11_SUBRESOURCE_DATA subresourceData;
subresourceData.pSysMem = &vIndices[];
subresourceData.SysMemPitch = ;
subresourceData.SysMemSlicePitch = ; HRESULT hr;
V( pD3DDevice->CreateBuffer(&indexBufferDesc, &subresourceData, g_pShapeIndexBuffer.ReleaseAndGetAddressOf()) );
}

因此,在绘制grid时,我就需要设置相应的偏移量来保证读取的顶点和索引数据是正确的,代码如下:

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

这个时候,D3D Debug Layer就会出现错误:

起初以为是偏移量设置出错,但是仔细检查了代码,发现没有任何问题,同时渲染结果也是正确的。于是,尝试采用另一种方式,就是在设置vertex buffer时设置偏移量:

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

此时错误就消失了,渲染也是正确的,也就是说,代码中的偏移量计算是正确的。

于是上网翻阅了一些资料,发现有不少朋友遇到过这个问题,同时确认这个是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, , sizeof(filter) );
filter.DenyList.NumIDs = ARRAYSIZE( arrHiddenMessageID );
filter.DenyList.pIDList = arrHiddenMessageID; pD3DInfoQueue->AddStorageFilterEntries( &filter );
SAFE_RELEASE( pD3DInfoQueue );
}
SAFE_RELEASE( pD3DDebug );
}
#endif

D3D11 Debug Layer的bug的更多相关文章

  1. VS2015+Win10 调试DirectX 报错

    安装完Win10调试程序突然在这个地方报错: #if (defined(DEBUG) || defined(_DEBUG)) deviceFlags |= D3D11_CREATE_DEVICE_DE ...

  2. Using an open debug interconnect model to simplify embedded systems design

    Using an open debug interconnect model to simplify embedded systems design Tom Cunningham, Freescale ...

  3. Node程序debug小记

    有时候,所见并不是所得,有些包,你需要去翻他的源码才知道为什么会这样. 背景 今天调试一个程序,用到了一个很久之前的NPM包,名为formstream,用来将form表单数据转换为流的形式进行接口调用 ...

  4. maven项目在eclipse中debug

    作为新手,出现bug后,debug找出bug还是很重要的,能节约大量找bug的时间 1.选中项目,右键点击-->run as -->run configurations 2.在run co ...

  5. 脑法之中的一个 --- DEBUG与搜索算法

    前年闲的蛋疼的时候,看过天津卫视的一档节目<非你莫属>,就来一堆面试者,上面几个壕.选人.记得有一期是给程序猿做的.当中有一个程序猿(好像是媛)傻不啦叽的说,哎呀,我每次DEBUG找到程序 ...

  6. 利用delve(dlv)在Visual Code中进行go程序的远程调试-debug方式

    最近碰到一个问题,如何在Windows的IDE或者文本编辑器上,远程调试Linux服务器上的golang程序. 虽然想说gdb走你,但既然go有dlv这样的类似Java的jdwp的原生方案,而且我用的 ...

  7. Linux 启动参数介绍

    Linux 启动参数介绍 取自2.6.18 kernel Documentation/i386/boot.txt 文件中介绍 vga= 这里的不是一个整数(在C语言表示法中,应是十进制,八进制或者十六 ...

  8. blade 已开源

    https://github.com/crazii 开源的主要原因是一个人写不动了, 而且已经很久没更新代码了. 希望有人能够感兴趣, 提供贡献. 距离上次更新日志已经很久了, 中间大概加了以下fea ...

  9. Kernel boot options

    There are three ways to pass options to the kernel and thus control its behavior: When building the ...

随机推荐

  1. 共享内存shared pool (6):追踪sql语句

    构建实验数据 --使用NC50用户查询(会话1) SQL> conn NC50/NC50 Connected. SQL> create table emp as select * from ...

  2. 第十二章 管理类型(In .net4.5) 之 操作字符串

    1. 概述 本章包括 字符串基本操作 以及 查找.遍历.格式化字符串. 2. 主要内容 2.1 在.net平台中使用字符串 C#中,string是用来保存文本信息的.是一个被当做值类型使用的引用类型. ...

  3. iOS反射机制

    iOS属性反射:说白了,就是将两个对象的所有属性,用动态的方式取出来,并根据属性名,自动绑值.(注意:对象的类,如果是派生类,就得靠其他方式来实现了,因为得到不该基类的属性.) 本人常用的反射方式,有 ...

  4. NFC Forum : Frequently Asked Questions (NFC 论坛:FAQ)

    NFC for Business What is the NFC Forum? The NFC Forum is a not-for-profit industry organization whos ...

  5. 菜鸟学习Struts——总结

    一.原理 客户端请求到ActionSeverlet,ActionSeverlet负责截URL进行分发分发到每一个Action上,Action负责和Model打交道然后把相关信息返回到ActionSev ...

  6. sqlserver中查找长时间未提交事务

    无论是有意无意,如果事务在数据库中保持打开,则它会阻塞其他进程对修改后的数据进行操作.同样,对事务日志进行备份也只会截断不活动事务的那部分事务日志,所以打开的事务会导致日志变多(甚至达到物理限制),直 ...

  7. SystemServer相关

    SystemServer分析 由Zygote通过Zygote.forkSystemServer函数fork出来的.此函数是一个JNI函数,实现在dalvik_system_Zygote.c中. 1.S ...

  8. 转载:监控每个节点(jvm部分)

    操作系统和进程部分 操作系统和进程部分的含义是很清楚的,这里不会描述的很详细.他们列出了基本的资源统计,例如CPU和负载.操作系统部分描述了整个操作系统的情况,进程部分只是描述了Elasticsear ...

  9. Mysql 更改最大连接数

    方法一: 进入MySQL安装目录 打开MySQL配置文件 my.ini 或 my.cnf查找 max_connections=100 修改为 max_connections=1000 服务里重起MyS ...

  10. 2.2孙鑫C++

    1.继承 动物有 吃 睡 呼吸的方法 当然 鱼也有    不用重复再定义 1)public 那里都可以访问 #include <iostream.h> class Animal //类 基 ...