Direct3D 12——计算着色器——计算着色器概念

这篇具有很好参考价值的文章主要介绍了Direct3D 12——计算着色器——计算着色器概念。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

计算着色器虽然是一种可编程的着色器,但Direct3D并没有将它直接归为渲染流水线中的一部分。虽然如此,但位于流水线之外的计算着色器却可以读写GPU资源。从本质上来说,计算着 色器能够使我们访问GPU来实现数据并行算法,而不必渲染出任何图形。由于计算着色器是Direct3D的组成部分,也可以读写Direct3D资源, 由此我们就可以将其输出的数据直接绑定到渲染流水线上。

线程与线程组

在GPU编程的过程中,根据程序具体的执行需求,可将线程划分为由线程组(thread group )构成 的网格(grid )o 一个线程组运行于一个多处理器之上。因此,对于拥有16个多处理器的GPU来说,我 们至少应将任务分解为16个线程组,以此令每个多处理器都充分地运转起来。但是,要获得更佳的性能, 我们还应当令每个多处理器至少拥有两个线程组,使它能够切换到不同的线程组进行处理,以连续不停地 工作[FunglO](线程组在运行的过程中可能会发生停顿,例如,着色器在继续执行下一个指令之前会等待 纹理的处理结果,此时即可切换至另一个线程组)。
每个线程组中都有一块共享内存,供组内的线程访问。但是,线程并不能访问其他组中的共享内存。 同理,同组内的线程间能够进行同步操作,不同组的线程间却不能实现这一点。事实上,我们也无法控 制不同线程组间的处理W序,因为这些线程组可能正运行在不同的多处理器上。
一个线程组中含有n个线程。硬件实际上会将这些线程分为多个warp (每个warp中有32个线程), 而且多处理器会以SIMD32的方式(即32个线程同时执行相同的指令序列)来处理warpo每个CUDA核 心都可处理一个线程,前面也提到了,“Fermi”架构中的每个多处理器都具有32个CUDA核心(因此, CUDA核匚、就像一条专设的SIMD “计算通道” (lane))o在Direct3D中,我们能够以非32的倍数值来指 定线程组的大小。但是出于性能的原因,我们应当总是将线程组的大小设置为warp尺寸的整数倍[FunglO]。
对于各种型号的图形硬件来说,线程数为256的线程组是一种普遍适于工作的初始设置。我们可以 以此值为基础,再根据具体需求尝试将其调整为其他大小。值得注意的是,修改每个线程组中的线程数 量也会对线程组的分派(dispatch,调度)次数产生影响。

NVIDIA公司生产的图形硬件所用的warp单位共有32个线程。而ATI公司(已被AMD公司收购)采用的 "wavefront”单位则具有64个线程,且建议为其分配的线程组大小应总为wavefront尺寸 的整数倍[Bilodeau 10]。另夕卜,值得一提的是,不管是warp还是wavefront,它们的大小在 未来几代中都有可能发生改变。

在Direct3D中可通过调用下列方法来启动线程组:

void ID3D12GraphicsCommandList::Dispatch(
UINT ThreadGroupCountX,
UINT ThreadGroupCountY,
UINT ThreadGroupCountZ);

此方法可开启一个由线程组构成的3D网格,但是我们在本书中仅关注线程组2D网格。下面的调用 示例会分派一个在x方向上为3、y方向上为2,即总数为3x2 = 6个线程组的网格(见图13.3)。

cmdList->Dispatch(3, 2, 1);

Direct3D 12——计算着色器——计算着色器概念

分派一个规模为3x2的线程组。此例假设每个线程组都有8x8条线程

一个简单的计算着色器

以下是将两个纹理进行简单累加的计算着色器示例,假设所有的纹理都具有相同的大小。虽然该着 色器有点索然无味,却五脏俱全,能详细地展示出计算着色器的基本套路语法。

cbuffer cbSettings
{
//计算着色器能访问的常量缓冲区数据
)//数据源及着色器的输出
Texture2D glnputA;
Texture2D glnputB;
RWTexture2D<float4> gOutput;
//线程组中的线程数。组中的线程可以被设置为ID、2D或3D的网格布局
[numthreads(16, 16, 1)]
void CS(int3 dispatchThreadID : SV_DispatchThreadID) // 线程 ID
{
//对两种源像素中横纵坐标分别为x、y处的纹素进行求和,并将结果保存到相应的gOutput纹素中 
gOutput[dispatchThreadID.xy]=glnputA[dispatchThreadID.xy] + glnputB[dispatchThreadlD.xy];
}

可见,一个计算着色器由下列要素构成:

1.通过常量缓冲区访问的全局变量。
2. 输入与输出资源。
3. [numthreads (X, Y, Z)]属性,指定3D线程网格中的线程数量。
4. 每个线程都要执行的着色器指令。
5. 线程ID系统值参数。

不难看出,我们能够根据需求定义岀不同的线程组布局。例如,可以定义一个具有X个线程的单行 线程组[numthreads (X, 1, 1)]或内含Y个线程的单列线程组[numthreads (1 ,Y, 1)]。抑或通 过将维度z设为1来定义规模为X x Y的2D线程组,形如[numthreads (X, Y, 1) ] 。我们应结合所遇到的具体问题来选择适当的线程组布局。如同前一节中提到的那样:针对NVIDIA品牌的显卡来说, 线程组中的总线程数应为warp大小(32 )的整数倍,而ATI公司生产的显卡应为wavefront尺寸(64 ) 的整数倍庁又因wavefront大小的倍数(64x„)必为warp尺寸的倍数(32xm),因此,以前者的线程数 为基础进行设置对两种显卡都适用。

计算流水线状态对象

为了开启计算着色器,我们还需使用其特定的“计算流水线状态描述”。此描述中的字段远少于 D3D12_GRAPHICS_PIPELINE_STATE_DESC结构体。这是因为计算着色器位列图形流水线之外,因 此所有的图形流水线状态都不适用于计算着色器,也就无须以此对它进行设置。下面给岀一个创建计算流水线状态对象的示例:

	D3D12_COMPUTE_PIPELINE_STATE_DESC wavesUpdatePSO = {};
	wavesUpdatePSO.pRootSignature = mWavesRootSignature.Get();
	wavesUpdatePSO.CS =
	{
		reinterpret_cast<BYTE*>(mShaders["wavesUpdateCS"]->GetBufferPointer()),
		mShaders["wavesUpdateCS"]->GetBufferSize()
	};
	wavesUpdatePSO.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
	ThrowIfFailed(md3dDevice->CreateComputePipelineState(&wavesUpdatePSO, IID_PPV_ARGS(&mPSOs["wavesUpdate"])));

根签名定义了什么参数才是着色器所期望的输入(CBV、SRV等)。而cs (即compute shader的缩 写)字段就是所指定的计算着色器。下列代码展示了一个将着色器编译为字节码的示例:文章来源地址https://www.toymoban.com/news/detail-437611.html

	mShaders["wavesUpdateCS"] = d3dUtil::CompileShader(L"Shaders\\WaveSim.hlsl", nullptr, "UpdateWavesCS", "cs_5_0");
	mShaders["wavesDisturbCS"] = d3dUtil::CompileShader(L"Shaders\\WaveSim.hlsl", nullptr, "DisturbWavesCS", "cs_5_0");

到了这里,关于Direct3D 12——计算着色器——计算着色器概念的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • DirectX12_Windows_GameDevelop_3:Direct3D的初始化

    查看龙书时发现, 第四章介绍预备知识的代码不太利于学习 。因为它不像是LearnOpenGL那样从头开始一步一步教你敲代码,导致你没有一种整体感。 如果你把它当作某一块的代码进行学习,你跟着敲会发现,总有几个变量是没有定义的。这是因为书上的代码都是把框架里的某

    2024年02月08日
    浏览(44)
  • Direct3D光照

    光照的组成 环境光:这种类型的光经其他表面反射到达物体表面,并照亮整个场景,要想以较低代价粗略模拟这类反射光,环境光是一个很好的选择 漫射光:这种类型光沿着特定的方向传播。当它到达某一表面时,将沿着各个方向均匀反射,无论从哪个方位观察,表面亮度

    2024年02月09日
    浏览(37)
  • Direct3D融合技术

    该技术能使我们将当前要进行光栅化的像素的颜色与先前已已光栅化并处于同一位置的像素的颜色进行合成,即将正在处理的图元颜色值与存储在后台缓存中的像素颜色值进行合成(混合),利用该技术我们可得到各种各样的效果,尤其是透明效果。 在融合运算时需要遵循:首

    2024年02月07日
    浏览(47)
  • Direct3D绘制旋转立方体例程

    初始化文件见Direct3D的初始化_direct3dcreate9_寂寂寂寂寂蝶丶的博客-CSDN博客 D3DPractice.cpp 运行结果

    2024年02月09日
    浏览(44)
  • Character Animation With Direct3D 读书笔记

    2D动画:循环播放多张图片 3D动画: 骨骼动画、变形动画 Win32 应用程序 Application类:处理主程序循环,图形设备的初始化 Init:加载资源并创建图形设备 Update:更新游戏世界,移动对象,更新物理引擎 Render:渲染所有对象,并将结果呈现给屏幕 Quit Cleanup DirectX 渲染循环:

    2024年02月12日
    浏览(41)
  • 三维引擎基础概述(Direct3D、OpenGL、UE、U3D、threejs等)

    一般而言,三维引擎是在三维底层图形技术的基础上,封装硬件操作与三维图形算法,形成普遍意义上的三维交互引擎,提供给开发者一个简单易用、功能丰富的三维图形环境,在此基础上进行虚拟现实、三维交互、可视化管理平台二次开发等,极大提高开发效率。 【底层图

    2024年02月11日
    浏览(47)
  • web3D三维引擎(Direct3D、OpenGL、UE、U3D、threejs)基础扫盲

    三维引擎是指用于创建和渲染三维图形的软件框架。它们通常提供了图形处理、物理模拟、光照、碰撞检测等功能,帮助开发者构建逼真的三维场景和交互体验。在这里,我将为您详细介绍一些常见的三维引擎,包括Direct3D、OpenGL、Unreal Engine、Unity3D和Three.js。 Direct3D是由微软

    2024年02月11日
    浏览(60)
  • 【C/C++】使用C++和Direct3D (d3d)获取屏幕截图并根据传入分辨率进行缩放图片大小

    目录 一,函数清单 1.Direct3DCreate9 函数 2.IDirect3D9::CreateDevice 方法 3.IDirect3DDevice9::GetDisplayMode 方法 4.IDirect3DDevice9::CreateOffscreenPlainSurface 方法 5.IDirect3DDevice9::GetFrontBufferData 方法 6.IDirect3DDevice9::D3DXLoadSurfaceFromSurface 方法 7. D3DXSaveSurfaceToFile 函数 二,关键代码实现 三,最终实现

    2024年01月18日
    浏览(48)
  • 在direct3D中,透明度处理和D2D1_ALPHA_MODE_PREMULTIPLIED含义?

    D2D1_ALPHA_MODE_PREMULTIPLIED 是 Direct2D 中定义的一种 Alpha 模式,用于描述像素颜色值和其 Alpha 通道(透明度)之间的关系。 在非预乘 Alpha (Straight or Unpremultiplied Alpha) 图像中,每个颜色分量(红、绿、蓝)是独立于 Alpha 值的。而在预乘 Alpha 图像中,每个颜色分量已经被其对应的

    2024年01月25日
    浏览(45)
  • direct3d-msaa-抗锯齿算法-教程-涉及概念解析

    交换链(Swap Chain)在计算机图形学和窗口系统中是一个核心概念,它主要用于管理一组缓冲区(通常是帧缓冲区),这些缓冲区用于存储渲染的图像,并且有序地与屏幕显示进行交替更新。 窗口系统中的交换链: 在Windows、Linux等操作系统上的窗口环境中,交换链与图形API(

    2024年01月24日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包