首先声明,本人是自学DX12,有很多的理解也许不到位,不过都是自己的理解。在很长一段时间里边,我从迷茫到有一天开始能看懂,现在是第三次开始刷DX12了,于是在此表明写作的初衷:

1.有一些DX12的学习心得,希望发出来,有大佬如果愿意指教,万分感谢;

2.如果对于才入门的人来说,这可能是我的白话教程,也许会对你有所帮助,但不可尽信,因为我也不确定我对不对;

3.DX12的概念很多,也是想把这作为自己的学习笔记来做,希望对自己也有帮助,如果有一天我发现哪里错了会及时回来更正。

那么话不多说,现在开始!!!

看过我前边6篇的同志们应该对D3D12的大概流程设置有了一定的了解,能够看懂D3D12的源码了,如果暂时还不是很熟练也没有大问题,毕竟程序员的工作大多数时候还是一些CCVV的工作嘛。开玩笑的啦,能看懂,会粘贴基本来说解决了入门的大问题了。由于本人也是处于一个入门的阶段吧,很多东西都是自己的理解,还要不断的探索,因此之后的文章可能不会再细节到深刻分析整个流程(因为基本的流程就是前边6篇的那点东西),之后更多的是专项的剖析,比如今天,我们好好来谈一下根签名&动态顶点缓冲区。

一、根签名

前边在常量缓冲区构建的时候我们提到过根签名,讲述了它的作用:将常量资源映射到GPU寄存器的特定槽当中,以供着色器取用。之前我们主要是以根描述符表的形式,实际还有根常量,根描述符两种,并且介绍根描述符表也只是只有一个表,今天我们就来详细看看各自的一些特性。

注意区别:

根描述符表逻辑:数据放入上传堆,将上传堆地址作为CBV结构体属性创建一个CBV;建立根签名,将根参数索引与CBV地址建立映射;

根描述符&根常量:不再需要CBV,直接建立根参数索引与上传堆的联系。

空间占用:根描述符表和跟常量都占用1DWORD,可以理解为就是一个地址的占用;根描述符占用2DWORD。但是他们能传递的信息量是不同的,根描述符&根描述符表都可以传递数组类(矩阵等),跟常量只传递一个数据,一般根签名以64DWORD为限。

具体使用:

1.根描述符表:

后边就是从根参数到根签名部分的序列化,创建等代码,与之前常量缓冲相同,不做赘述。

上图展示了定义多个CBV/SRV/UAV时的使用方法,主要通过Init的最后一个参数来进行偏移设置,最后将根参数InitAsDescriptorTable(根参数size,根参数数组,shader中可见性)。之后的工作就是将对应根参数索引与XXV的地址建立映射:

cmdList->SetGraphicsRootDescriptorTable(paramIndex, cbvHandle);

这里有一个技巧可以考虑,Init的最够一个参数是相对起始地址的偏移,一种办法是如上计算偏移,另一种办法是设置为D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,将根据根描述符表中前一个描述符数量来自动计算。

2.根描述符

CD3DX12_ROOT_PARAMETER slotRootParameter[2];

//使用根描述符,直接InitAsConstantBufferView,就没有创建CBV来关联上传堆的部分
    slotRootParameter[0].InitAsConstantBufferView(0);//槽号
    slotRootParameter[1].InitAsConstantBufferView(1);

后边就是从根参数到根签名部分的序列化,创建等代码,与之前常量缓冲相同,不做赘述。

之后使用:

mCommandList->SetGraphicsRootConstantBufferView(0/*ParamIndex*/, objCBAddress/*上传堆地址*/);

mCommandList->SetGraphicsRootConstantBufferView(1, passCB->GetGPUVirtualAddress());

这里直接是与上传堆地址建立映射,不同于根描述符表是与CBV建立映射。

但是要注意这里的根参数一个索引里边只能传单个数据,虽然数据类型没有限制,但是不能像上边一样设置描述符表包含的CBV数目这类。

3.跟常量

CD3DX12_ROOT_PARAMETER slotRootParameter[1];
    //12个数据放在0#槽
    slotRootParameter[0].InitAsConstants(12, 0);

后边就是从根参数到根签名部分的序列化,创建等代码,与之前常量缓冲相同,不做赘述。

std::vector<float> arr(11);
    int num = arr.size()/2;
    //paramIndex,数据数目,数据,偏移
    mCommandList->SetGraphicsRoot32BitConstants(0, 1, &num, 0);
    mCommandList->SetGraphicsRoot32BitConstants(0, arr.size(), arr.data(), 1);

可见三种方法都可以利用特定的槽向shader中映射数据,不同之处在于使用的便捷性(是否依赖创建CBV堆和上传堆),数据量大小。

二、动态顶点缓冲区

这个其实没什么好说的,因为根据目前我们所学习的东西,按道理我们是可以自己实现这个部分了,这里还是叙述一下。

为什么要用动态顶点缓冲:实际上我们用顶点来描述几何体的形态,如果像我们之前那样创建static的物体,那么顶点都是通过上传堆存到默认堆,并不要每帧都更新顶点数据,但是当顶点如果每帧都在修改,比如我们模拟一个起伏的水面,或者受到力作用变形的面,要让顶点数据的改变反映到shader阶段的顶点中来绘制图形,就需要每帧都更新。要实现每帧更新,那就使用上传堆而不是默认堆。为了更好的说明怎么操作,我给出两端代码,来看看具体差异:

绘制static物体的顶点数据传输:一次性将顶点与索引都存储到默认堆。

ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
    CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);

ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
    CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);

geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
        mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);

geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
        mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);

geo->VertexByteStride = sizeof(Vertex);
    geo->VertexBufferByteSize = vbByteSize;
    geo->IndexFormat = DXGI_FORMAT_R16_UINT;
    geo->IndexBufferByteSize = ibByteSize;

使用动态顶点缓冲:

ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
    CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);

geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
        mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);

geo->VertexByteStride = sizeof(Vertex);
    geo->VertexBufferByteSize = vbByteSize;
    geo->IndexFormat = DXGI_FORMAT_R16_UINT;
    geo->IndexBufferByteSize = ibByteSize;

这里只有索引,放到了默认堆,因为数据的拓扑关系不变,如果拓扑关系要改变,那么也要使用上传堆。既然这里没有顶点数据,那顶点数据在哪里设置呢?

currWavesVB->CopyData(i, v);//上传堆通过Map和memcpy得到的数据

geo->VertexBufferGPU = currWavesVB->Resource();

可以看到我们并没有创建顶点数据的默认堆,而是把顶点数据的上传堆地址直接给到默认堆,相当于我们可以理解,输入装配阶段总是从默认堆去拿数据,画static图形的时候直接就拿到数据了,但是动态顶点会通知他到上传堆去拿数据。我们将这个CopyData及地址设置部分放到每帧的循环里,后边DrawCall则都是一样的,因为数据能拿到走流水线都是一个逻辑。

OK了,今天就到这里,加油。

七、D3D12学习笔记——根签名动态顶点缓冲区相关推荐

  1. dx12 龙书第七章学习笔记 -- 利用Direct3D绘制几何体(续)

    1.帧资源 之前,我们在处理CPU和GPU的同步问题时,采取以下方法:在每帧绘制的结尾调用D3DApp::FlushCommandQueue函数,以确保GPU在每一帧都能正确完成所有命令的执行 这样做 ...

  2. 描述性物理海洋学--第七章学习笔记

    第七章学习笔记--海洋环流的动力过程 不稳定理论 判别方法: 大尺度不稳定 中尺度不稳定 控制方程 地流动力学参数 近似简化 正斜压海洋 基本洋流 地转流 风生Ekman 环流 上升流 朗缪尔环流 惯 ...

  3. 【学习笔记11】动态方法调用和使用通配符定义action

    2019独角兽企业重金招聘Python工程师标准>>> 动态方法调用: 如果Action中存在多个方法时,我们可以使用 !+方法名调用指定方法.如下: public class He ...

  4. 二十、D3D12学习笔记——环境光遮蔽

    好多天都没有更新D3D12的学习笔记了,因为最近确实学得有点乏,所以换了个方向,总结了一下之前学习的OpenGL和一些图形渲染的高级话题.那么回到D3D的学习,今天我们要介绍一下龙书对于环境光遮蔽的讲 ...

  5. Android学习笔记——Android 签名机制详解

    Android 签名机制详解 近期由于工作需要在学习 Android 的签名机制,因为没有现成资料,只能通过开发者文档和阅读博客的方式对 Android 签名机制进行大致了解.过程中查阅到的资料相对零 ...

  6. 十、D3D12学习笔记——纹理

    首先声明,本人是自学DX12,有很多的理解也许不到位,不过都是自己的理解.在很长一段时间里边,我从迷茫到有一天开始能看懂,现在是第三次开始刷DX12了,于是在此表明写作的初衷: 1.有一些DX12的学 ...

  7. C++ Primer Plus学习笔记之类和动态内存分配

    前言 个人觉得学习编程最有效的方法是阅读专业的书籍,通过阅读专业书籍可以构建更加系统化的知识体系. 一直以来都很想深入学习一下C++,将其作为自己的主力开发语言.现在为了完成自己这一直以来的心愿,准备 ...

  8. 20135210——信息安全设计基础第七周学习笔记

    第七周(10.19-10.25): 学习计时:共16小时 读书:5 代码:4 作业:4 博客:3 一.学习目标 1. 了解常见的存储技术(RAM.ROM.磁盘.固态硬盘等) 2. 理解局部性原理 3. ...

  9. 一、D3D12学习笔记——初始化Direct3D

    首先声明,本人是自学DX12,有很多的理解也许不到位,不过都是自己的理解.在很长一段时间里边,我从迷茫到有一天开始能看懂,现在是第三次开始刷DX12了,于是在此表明写作的初衷: 1.有一些DX12的学 ...

  10. 【D3D11游戏编程】学习笔记十八:模板缓冲区的使用、镜子的实现

    (注:[D3D11游戏编程]学习笔记系列由CSDN作者BonChoix所写,转载请注明出处:http://blog.csdn.net/BonChoix,谢谢~) 模板缓冲区(Stencil Buffe ...

最新文章

  1. pl/sql developer连接远程数据库
  2. sqli-labs过关笔记(Page-1:1-22关)
  3. C++ 线程池的思想
  4. Ubuntu系统手动安装英伟达驱动程序
  5. mysql 列数据显示转成行数据显示_Mysql的列修改成行并显示数据的简单实现
  6. Maven Helper 安装使用(jar 包管理工具)
  7. 数据列表的分页实现————分页敏捷开发
  8. 以太坊虚拟机 EVM(4)分布式存储架构设计(FISCO BCOS为例)
  9. keras pytorch_使用PyTorch重新创建Keras功能API
  10. 三角形状的点阵模糊效果iOS源码
  11. Swagger2+Apizza接口文档
  12. ArcGIS教程 - 8 空间数据拓扑处理
  13. 无线通信——GSM系统组成
  14. 图像处理之图像质量评价指标SSIM(结构相似性)
  15. 用matlab实现女声变男声步骤,男变女声、女变男声、如何实现变声效果?
  16. java繁体_Java-汉字繁体拼音转换
  17. 如何找到能商用的背景纯音乐
  18. Python17_项目实操关卡-人机PK
  19. layui分页和模板引擎
  20. java获取文件列表,[javaSE] java获取文件列表

热门文章

  1. android捕获按键广播,Android 解决监听home键的几种方法
  2. 在鹅厂工作1到11年的程序媛
  3. 中通快递 | 快递单号查询API
  4. 单片机c51语言实训总结,单片机实训报告
  5. hdu 4939 Stupid Tower Defense 2014多校七 DP
  6. Mybatis实现订单案例的五表联合操作
  7. 华为认证HCNE考试知识点
  8. OSChina 周一乱弹 ——杜牧你个老流氓!
  9. 吴恩达深度学习笔记——改善深层神经网络:超参数调整,正则化,最优化(Hyperparameter Tuning)
  10. 打造自己的域名转向