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

news2024/11/15 10:53:43

计算着色器虽然是一种可编程的着色器,但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);

在这里插入图片描述

分派一个规模为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的缩 写)字段就是所指定的计算着色器。下列代码展示了一个将着色器编译为字节码的示例:

	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");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/441362.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ESP32设备驱动-BH1745NUC 亮度和颜色传感器驱动

BH1745NUC 亮度和颜色传感器驱动 文章目录 BH1745NUC 亮度和颜色传感器驱动2、硬件准备3、软件准备4、驱动实现BH1745NUC 是具有 IC 总线接口的数字颜色传感器 IC。 该 IC 感应红光、绿光和蓝光 (RGB) 并将它们转换为数字值。 高灵敏度、宽动态范围和出色的 Ircut 特性使该 IC …

【CSS3】CSS3 伪元素字体图标 ( 生成 icommon 字体文件 | 字体图标基本使用 | 使用伪元素实现 icommon 字体图标显示 )

文章目录 一、icommon 字体图标基本使用1、生成 icommon 字体文件2、字体图标基本使用 二、使用伪元素实现 icommon 字体图标显示 一、icommon 字体图标基本使用 字体图标 指的是 将图标做成字体样式 , 在 放图标的地方 使用 文字 即可实现 图标显示 ; 1、生成 icommon 字体文件…

Vue2-黑马(十三)

目录&#xff1a; &#xff08;1&#xff09;实战-permissions.js-动态路由 &#xff08;2&#xff09;实战-第三方登录-流程分析 &#xff08;3&#xff09;实战-第三方登录-代码解读 &#xff08;1&#xff09;实战-permissions.js-动态路由 在做根据用户角色动态生成路由…

【Unity+MySQL】实现注册登录系统(升级版)

目录 1 UI界面重新设计1.1 注册界面1.2 登录界面1.3 交互实现 2 注册功能完善2.1 判断用户输入的用户名是否与数据库中的重复2.2 将当前时间更新至用户表的当前注册时间列2.3 将用户输入的注册密码使用哈希加密 3 登录功能完善 接着 上篇文章所谈到的系统缺陷&#xff0c;这篇…

==与equals()的理解

java中的数据类型分为基本数据类型、基本数据类型对应的包装类型&#xff08;引用类型&#xff09;&#xff0c;引用类型三种数据类型。 每一个基本类型java都提供了一个与之对应的包装类型&#xff0c;该包装类型是一个引用类型,并且在基本类型与包装类型之间提供了自动拆箱和…

AD21原理图----网络连线(网络线、网络标签、总线、差分对、信号线束)

目录 网络连线 网络线&#xff08;Wire&#xff09; 网络标签 总线 差分对 信号线束 网络连线 网络线&#xff08;Wire&#xff09; 网络标签 可以跨原理图 总线 用于放置同一类数据 使用步骤 第一步&#xff1a;先绘制网络线 第二步&#xff1a;利用网络标签进行连接&a…

虚拟机下Ubuntu系统的Docker部署

虚拟机下Ubuntu系统的微服务项目Docker部署 文章目录 虚拟机下Ubuntu系统的微服务项目Docker部署1、Ubuntu安装 Docker2、修改后端微服务的配置2.1 修改 MySQL 的配置2.2 修改 Redis 的配置2.3 修改 Nacos 的配置 3、生成微服务镜像4、拉取远程镜像5、生成前端镜像5.1 准备文件…

MacOS安装MongoDB与Redis

1.安装MongoDB: brew tap mongodb/brew brew install mongodb-community 后台服务方式运行mongodb: brew services restart mongodb/brew/mongodb-community 直接运行mongodb非后台服务 /usr/local/opt/mongodb-community/bin/mongod --config /usr/local/etc/mongod.con…

化工行业数字化“智能工厂”-解决方案(ppt可编辑)

本资料来源公开网络&#xff0c;仅供个人学习&#xff0c;请勿商用&#xff0c;如有侵权请联系删除。 总体架构 设计理念—数据集成与流转 九大核心价值之一 九大核心价值之二 九大核心价值之三 九大核心价值之四 九大核心价值之五 九大核心价值之六 九大核心价值之七 九大核心…

数据库学习-常用的SQL语句

背景&#xff1a; 汇整一下自己学习数据库过程中常见的题目及语句。 一.实例分析题 二&#xff0e;简单SQL查询&#xff1a; 1&#xff09;:统计每个部门员工的数目select dept,count(*) from employee group by dept;2&#xff09;:统计每个部门员工的数目大于一个的记录se…

3.4 迭代法

4.1 雅克比迭代法&#xff1a; 雅可比迭代法是一种用于求解线性方程组的迭代算法&#xff0c;其基本思想是将线性方程组中的系数矩阵拆分为对角线矩阵和非对角线矩阵两部分&#xff0c;并利用对角线矩阵的逆矩阵来迭代求解方程组。 具体地&#xff0c;设线性方程组为Axb&…

操作系统笔记--虚拟内存的使用

1--背景概念 在计算机系统中&#xff0c;当多道程序同时运行时可能会出现内存不足的情况&#xff0c;一般可通过以下技术进行解决&#xff1a; 覆盖技术&#xff1a; 当程序太大超出内存容量时&#xff0c;可以采用手动覆盖的技术&#xff0c;只把需要的指令和数据保存在内存当…

SSM整合、环境配置以及基础综合测试(单表查询、多表查询和数据分页、前后端分离、Vue3)

SSM整合、环境配置以及基础综合测试 准备&#xff1a;创建maven项目以及项目框架准备 SSM整合简介 介绍: SSM(SpringSpringMVCMyBatis) 整合&#xff0c;就是三个框架协同开发。Spring整合Mybatis就是将Mybatis核心配置文件当中数据源的配置、事务处理、以及工厂的配置&…

Docker的使用说明

目录 第一章什么是Docker 1.1.Docker的概述 1.2.什么是容器 1.3.Docker核心概念 第二章.安装 Docker 2.1.安装环境部署 2.2.安装 Docker-CE并设置为开机自动启动 2.2.Docaker的简单信息查看 第三章.Docker 操作 3.1.Docker的镜像操作 3.2.Docker 容器操作 3.3.容器…

Baumer工业相机堡盟工业相机如何联合BGAPISDK和佳能EF变焦镜头实现相机的自动变焦(C#)

Baumer工业相机堡盟工业相机如何联合BGAPISDK和佳能EF变焦镜头实现相机的自动变焦&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机BGAPISDK中控制变焦镜头的技术背景代码案例分享第一步&#xff1a;开启相机自动调焦功能模块第二步&#xff1a;控制自动变焦镜头电机的…

Delphi DataSnap 流程分析(二)

Delphi DataSnap 流程分析(一)_看那山瞧那水的博客-CSDN博客 粗略分析了 创建传统DataSnap的流程&#xff0c;现在再分析下创建现在更常用的 方式&#xff1a; DataSnap REST Application 这种方式只支持HTTP(普通HTTP和REST HTTP)通信&#xff0c;不支持TCP通信。 这种方式…

详解C语言string.h中常见的13个库函数(上)

我计划讲解C语言string.h这个头文件中&#xff0c;最常见的13个库函数。为了让大家更加深入的理解这些函数&#xff0c;部分函数我会模拟实现。篇幅所限&#xff0c;如果文章太长了&#xff0c;可能会较难坚持读完&#xff0c;所以我会分几篇博客来讲述。本篇博客主要讲解的函数…

什么是全民开发?|概念、技能和优势

注&#xff1a;全民开发的英文是Citizen Development&#xff0c;由咨询公司Gartner在2010年提出的概念&#xff0c;指非专业开发人员使用低代码或无代码平台创建应用程序&#xff0c;无需IT部门的支持&#xff0c;旨在提高生产力并降低开发成本。 国内普遍将Citizen Developme…

【ROS】单目摄像机的标定

在上节: ROS 教程之 vision : 用笔记本摄像头获取图像 能够使用相机后&#xff0c;就需要对相机进行标定&#xff0c;在ROS上使用原始图像校准单目相机。 操作步骤 1、首先将catkin_ws/src/usb_cam/launch/usb_cam-test.launch的文件内容修改掉。 原有内容&#xff1a; <…

docker 使用Dockerfile 部署springboot项目

1、先准备好你的springboot项目jar包。拉取 openjdk docker pull openjdk:8-jdk-alpine 2、上传你的springboot项目&#xff0c;然后配置 Dockerfile&#xff1a; FROM openjdk:8-jdk-alpine ADD ./springbootstudy.jar.jar /app.jar ENTRYPOINT ["java","-jar…