当前位置: 首页 > news >正文

编写DX12遇到的坑

编写DX12程序遇到的坑

​ 写DX12每次遇到Bug都会卡好久,结果大部分时候最后都发现是一些小问题导致的,故将自己遇到的坑都写下来,方便后续遇到时回头查阅。

使用ClearDepthStencil清理DepthBuffer的时候把其他资源也清理了

​ 抄MiniEngine对API的封装的时候想试一试封装的效果,故写了个简单的DrawBox程序来测试,创建各个资源的时候都没问题,结果就是绘制不出来。

​ 使用RenderDoc debug才发现是顶点和索引出问题了,然后我又怀疑是资源初始化,也就是先把数据拷贝到上传堆,然后又把上传堆拷贝到默认堆这一步出问题了,结果找了半天也没找到问题。

​ 接着又查看VertexBuffer中的数据,发现拷贝确实成功了,内部的数据也是对的,然后接着往后面的命令翻,同时查看Buffer的数据,结果执行到ClearDepthStencilView这一条命令的时候整个Buffer的值就被清掉了,接着我使用CreateCommittedResource创建深度图,顶点和索引又正常了,因此基本可以断定是深度图创建的时候出问题了。

​ 由于我自己封装了一下D3DResource的分配,所以所有的资源都是通过CreatePlacedResource,而我顶点和索引数据又和深度图在同一个堆中,因此我就怀疑是不是ClearDepthStencilView会把整个堆的数据都清理掉,但是问了AI和其他大佬都说只会清掉特定资源,于是我又去查看了两个Buffer在堆中的偏移,结果发现和我预想中的偏移是一样的,然后又做了一堆无用功。之后在RenderDoc翻两个资源的描述信息的时候发现有DepthBuffer中一个值叫Contents Length,也就是Buffer的内部长度,这和我预想中的不一样,我创建的深度图大小为 1024 x 768,每个单位的大小为4byte,所以总大小应该是3145728,但是上述的那个值却有3932160,远大于我的预想,而我顶点及索引数据在堆中的偏移又真好介于两者之间,因此我断定两个资源在堆中发生了重叠,但是我创建资源的时候都处理了堆中资源的偏移,按理来说不会重叠,于是我又翻找了我创建资源的代码,我获取资源需要的大小所使用的API为GetCopyableFootprints,其参数如下:

void GetCopyableFootprints([in]            const D3D12_RESOURCE_DESC          *pResourceDesc,[in]            UINT                               FirstSubresource,[in]            UINT                               NumSubresources,UINT64                             BaseOffset,[out, optional] D3D12_PLACED_SUBRESOURCE_FOOTPRINT *pLayouts,[out, optional] UINT                               *pNumRows,[out, optional] UINT64                             *pRowSizeInBytes,[out, optional] UINT64                             *pTotalBytes
);

在从上传堆中拷贝到默认堆的时候我所使用的接口也是这个,他最后一个参数为整个资源可拷贝的大小,然后我就理所当然的认为这就是资源的大小了,问了AI之后,得知理应调用的接口为GetResourceAllocationInfo,其参数如下:

D3D12_RESOURCE_ALLOCATION_INFO GetResourceAllocationInfo([in] UINT                      visibleMask,[in] UINT                      numResourceDescs,[in] const D3D12_RESOURCE_DESC *pResourceDescs
);

返回的结构体的参数如下:

typedef struct D3D12_RESOURCE_ALLOCATION_INFO {UINT64 SizeInBytes;UINT64 Alignment;
} D3D12_RESOURCE_ALLOCATION_INFO;

其中SizeInBytes就是分配时需要的大小,Alignment为资源的对齐大小,我该用此接口来创建深度图,结果发现实际需要的大小为4456448,远大于我一开始认为的3145728,而顶点和索引资源是紧跟着深度图创建的,因此其位置在3145728~4456448,而CreatePlacedResource又会把整个深度图清掉,因此顶点和索引数据也一样被清掉了,这就导致数据的异常。

​ 最后我把分配资源时获取大小的接口改为了GetResourceAllocationInfo,问题也就解决了,再堆中多个资源是可以重叠的,这也就是为何创建顶点和索引资源的时候没有报错,但是使用不同资源的时候需要使用ResourceBarrier来进行切换。

http://www.hskmm.com/?act=detail&tid=30437

相关文章:

  • 编写DX12时使用的辅助类
  • HLSL语法
  • DirectX12初始化
  • 实验2
  • CF2159B
  • 登录校验---Filter过滤器
  • 日志|Ajax
  • 环境变量 Path 配置实战指南:从“能用”到“专业”--两种配置环境变量的方法
  • 10月13日
  • Ubuntu22.04安装CH340/CH341驱动
  • 玄机蓝队靶场_应急响应_198:实战Live勒索病毒溯源排查
  • JetBrains Mono字体好看、及其它
  • STM32——UART
  • WebApi 交叉观察者- IntersectionObserver复盘
  • [KaibaMath]1009 关于||a|-|b||≤|a+b|的证明
  • AMPopTip - 优雅的iOS动画提示框库
  • 2026年深度对比值得推荐的10个在线客服系统
  • 文件名中有空格比较烦人
  • 20232421 2024-2025-1 《网络与系统攻防技术》实验一实验报告
  • 十月总结
  • 20251013 之所思 - 人生如梦
  • Markdown 基本语法
  • 简单工单系统的实现-客服系统中增加创建工单功能
  • 日总结 10
  • # 20232421 2024-2025-1 《网络与系统攻防技术》实验一实验报告
  • 20232317 2025-2026-1《网络与系统攻防技术》实验一实验报告
  • 给一个字符串数组,输出不同的部分
  • 连接 USB 设备
  • SpringBoot-day1(快速上手SpringBoot,SpringBoot简介,SpringBoot基础配置,属性配置,yaml文件) - a
  • Chroma私有化:本地部署完整方案