当前位置:网站首页>D3D计算着色器入门
D3D计算着色器入门
2022-07-26 00:27:00 【Freak587】
1.对计算着色器的理解:
计算着色器跟他的名字一样,就是进行计算的着色器。但是它的用途不仅局限于图形的运算,也可以进行通用的运算。计算着色器的计算能力非常强,这就使得在gpu进行通用运算后再传输回cpu,比直接在cpu中运算花费的时间更短。
计算着色器不属于渲染管线,但可以对任意阶段进行读取操作。
2.线程组与线程
计算着色器利用gpu的并行处理器来开启多线程计算,从而达到高性能计算。一个线程组包含多个线程,让多处理器同时来处理两个及以上的线程组会有更好的效果,不至于当有线程组等待资源时导致计算的堵塞。
每个线程组都有共享的内存可供线程访问,但线程组之间不可互相访问。
一个warp对应32个线程,ATI对应下的wavement对应64个线程。
m_pd3dImmediateContext->Dispatch(32, 32, 1);//表示xyz三个维度的线程组为32/32/1
假设上图所示的网格是一个纹理,那么它的线程就是2x2x1,线程组就为3x2x1,所以这个位图就是6x4x1的像素大小。
3.HLSL代码的理解
Texture2D g_TexA : register(t0);
Texture2D g_TexB : register(t1);
RWTexture2D<float4> g_Output : register(u0);
[numthreads(16, 16, 1)]
void CS( uint3 DTid : SV_DispatchThreadID )
{
g_Output[DTid.xy] = g_TexA[DTid.xy] * g_TexB[DTid.xy];
}Texture2D 表明了一个纹理,其包含RGBA,坐标信息等,等价于Texture2D<unorm float4> ,这是因为Texture2D省略了数据格式。
RWTexture2D<float4> 可读可写,不能像那样可以省略数据类型。u0表明无序访问第0个寄存器。
[numthreads(16, 16, 1)] 设置了一个线程组的线程为16x16x1个数目。
SV_DispatchThreadID 线程在3D网格的位置(xyz)。
g_TexA[DTid.xy] * g_TexB[DTid.xy] 取在xy位置的纹理数据分量相乘。
4.C++代码
主要流程:
初始化部分:

UAV unorderAccessView 可无序读写纹理
SRV ShaderResourceView 读取纹理
| 主题 | 说明 |
|---|---|
常量缓冲区包含着色器常量数据。 其优点在于数据持续存在,并且可由任意 GPU 着色器访问,直到需要更改数据。 | |
顶点缓冲区保存顶点列表的数据。 每个顶点的数据都可能包含位置、颜色、法向矢量、纹理坐标等。 索引缓冲区将整数索引(偏移量)保存到顶点缓冲区中,并用于定义和呈现组成完整的顶点列表的一部分的对象。 | |
着色器资源视图通常以方便着色器访问纹理的方式围绕纹理。 无序的访问视图提供类似的功能,但支持以任何顺序读取和写入到纹理(或其他资源)。 | |
采样是读取纹理中的输入值或读取其他资源的过程。 “取样器”是从资源中读取的任何对象。 | |
呈现目标使场景能够呈现到临时中间缓冲区,而不是呈现到要呈现到屏幕的后台缓冲区。 利用此功能,可在图形管道中将可呈现的复杂场景用作反射纹理或用于其他用途,也可将其用于在呈现前向场景添加其他像素着色器效果。 | |
深度模板视图提供用于保存深度和模板信息的格式和缓冲区。 深度缓冲区用于剔除由较近的对象对其进行遮挡时,对查看者不可见的像素的绘制。 模板缓冲区可用于剔除定义的形状外部的所有绘制。 | |
流输出视图支持将顶点、分割和几何图形着色器附带的顶点信息流式传输回应用程序以供进一步使用。 例如,已经由这些着色器导致失真的对象可以写回到应用程序,从而为物理引擎或其他引擎提供更准确的输入。 但在实践中,流输出视图是图形管道中不常使用的功能。 | |
利用光栅器有序视图,可以消除一些深度缓冲区限制,特别是使多个包含透明度的纹理应用于同一像素。 |
参考:视图 - UWP applications | Microsoft Docs
管线部分:

前四个阶段是属于计算着色器阶段。最后的api是将合成的纹理输出到文件中。
代码:
HR(CreateDDSTextureFromFile(m_pd3dDevice.Get(), L"..\\Texture\\flare.dds",
nullptr, m_pTextureInputA.GetAddressOf()));
HR(CreateDDSTextureFromFile(m_pd3dDevice.Get(), L"..\\Texture\\flarealpha.dds",
nullptr, m_pTextureInputB.GetAddressOf()));
// 创建用于UAV的纹理,必须是非压缩格式
D3D11_TEXTURE2D_DESC texDesc;
texDesc.Width = 512;
texDesc.Height = 512;
texDesc.MipLevels = 1;
texDesc.ArraySize = 1;
texDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Usage = D3D11_USAGE_DEFAULT;
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE |
D3D11_BIND_UNORDERED_ACCESS;
texDesc.CPUAccessFlags = 0;
texDesc.MiscFlags = 0;
HR(m_pd3dDevice->CreateTexture2D(&texDesc, nullptr, m_pTextureOutputA.GetAddressOf()));
texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
HR(m_pd3dDevice->CreateTexture2D(&texDesc, nullptr, m_pTextureOutputB.GetAddressOf()));
// 创建无序访问视图
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
uavDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
uavDesc.Texture2D.MipSlice = 0;
HR(m_pd3dDevice->CreateUnorderedAccessView(m_pTextureOutputA.Get(), &uavDesc,
m_pTextureOutputA_UAV.GetAddressOf()));
uavDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
HR(m_pd3dDevice->CreateUnorderedAccessView(m_pTextureOutputB.Get(), &uavDesc,
m_pTextureOutputB_UAV.GetAddressOf()));
// 创建计算着色器
ComPtr<ID3DBlob> blob;
HR(CreateShaderFromFile(L"HLSL\\TextureMul_R32G32B32A32_CS.cso",
L"HLSL\\TextureMul_R32G32B32A32_CS.hlsl", "CS", "cs_5_0", blob.GetAddressOf()));
HR(m_pd3dDevice->CreateComputeShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, m_pTextureMul_R32G32B32A32_CS.GetAddressOf()));
HR(CreateShaderFromFile(L"HLSL\\TextureMul_R8G8B8A8_CS.cso",
L"HLSL\\TextureMul_R8G8B8A8_CS.hlsl", "CS", "cs_5_0", blob.GetAddressOf()));
HR(m_pd3dDevice->CreateComputeShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, m_pTextureMul_R8G8B8A8_CS.GetAddressOf()));
assert(m_pd3dImmediateContext);
//#if defined(DEBUG) | defined(_DEBUG)
// ComPtr<IDXGraphicsAnalysis> graphicsAnalysis;
// HR(DXGIGetDebugInterface1(0, __uuidof(graphicsAnalysis.Get()), reinterpret_cast<void**>(graphicsAnalysis.GetAddressOf())));
// graphicsAnalysis->BeginCapture();
//#endif
m_pd3dImmediateContext->CSSetShaderResources(0, 1, m_pTextureInputA.GetAddressOf());
m_pd3dImmediateContext->CSSetShaderResources(1, 1, m_pTextureInputB.GetAddressOf());
// DXGI Format: DXGI_FORMAT_R32G32B32A32_FLOAT
// Pixel Format: A32B32G32R32
m_pd3dImmediateContext->CSSetShader(m_pTextureMul_R32G32B32A32_CS.Get(), nullptr, 0);
m_pd3dImmediateContext->CSSetUnorderedAccessViews(0, 1, m_pTextureOutputA_UAV.GetAddressOf(), nullptr);
m_pd3dImmediateContext->Dispatch(32, 32, 1);
// DXGI Format: DXGI_FORMAT_R8G8B8A8_SNORM
// Pixel Format: A8B8G8R8
m_pd3dImmediateContext->CSSetShader(m_pTextureMul_R8G8B8A8_CS.Get(), nullptr, 0);
m_pd3dImmediateContext->CSSetUnorderedAccessViews(0, 1, m_pTextureOutputB_UAV.GetAddressOf(), nullptr);
m_pd3dImmediateContext->Dispatch(32, 32, 1);
//#if defined(DEBUG) | defined(_DEBUG)
// graphicsAnalysis->EndCapture();
//#endif
HR(SaveDDSTextureToFile(m_pd3dImmediateContext.Get(), m_pTextureOutputA.Get(), L"..\\Texture\\flareoutputA.dds"));
HR(SaveDDSTextureToFile(m_pd3dImmediateContext.Get(), m_pTextureOutputB.Get(), L"..\\Texture\\flareoutputB.dds"));
MessageBox(nullptr, L"请打开Texture文件夹观察输出文件flareoutputA.dds和flareoutputB.dds", L"运行结束", MB_OK);6.数据格式
C++对应的HLSL中RWTexture2D<T>的数据格式
| DXGI_FORMAT | HLSL类型 |
|---|---|
| DXGI_FORMAT_R32_FLOAT | float |
| DXGI_FORMAT_R32G32_FLOAT | float2 |
| DXGI_FORMAT_R32G32B32A32_FLOAT | float4 |
| DXGI_FORMAT_R32_UINT | uint |
| DXGI_FORMAT_R32G32_UINT | uint2 |
| DXGI_FORMAT_R32G32B32A32_UINT | uint4 |
| DXGI_FORMAT_R32_SINT | int |
| DXGI_FORMAT_R32G32_SINT | int2 |
| DXGI_FORMAT_R32G32B32A32_SINT | int4 |
| DXGI_FORMAT_R16G16B16A16_FLOAT | float4 |
| DXGI_FORMAT_R8G8B8A8_UNORM | unorm float4 |
| DXGI_FORMAT_R8G8B8A8_SNORM | snorm float4 |
参考文章:DirectX11 With Windows SDK--26 计算着色器:入门 - X_Jun - 博客园 (cnblogs.com)
边栏推荐
- 测试7年,面试华为最后面议要薪1万,HR说我不尊重华为,他们没有那么低薪资的岗位~
- markdown写作平台
- Wechat applet dynamic style | parameter transfer
- Hefei approved in advance
- Pinduoduo gets the usage instructions of the product details API according to the ID
- 你还在掐表算时间复杂度?
- The way of understanding JS: what is prototype chain
- 合肥提前批
- This time, thoroughly understand promise principle
- [paper notes] - target attitude estimation Epro PNP 2022 CVPR
猜你喜欢

数据库工具对决:HeidiSQL 与 Navicat

YOLOV2 YOLO9000

数据流通交易场景下数据质量综合管理体系与技术框架研究

Super super super realistic digital people! Keep you on the air 24 hours a day

Pikachu靶机通关和源码分析

Representation and implementation of stack (C language)

Rotate K strings to the left (details)

【无标题】如何实现可插拔配置?

In order to grasp the redis data structure, I drew 40 pictures (full version)

Tid-mop: a comprehensive framework for security management and control under the scenario of data exchange
随机推荐
Introduction of MySQL transactions
The way to understand JS: the principle of object.call and object.create() inheritance
JVM Tri Color marking and read-write barrier
Solid smart contract development - 3.2-solid syntax array, structure, mapping
How much data can a list store?
Jd.com searches for product API instructions by keyword
Solve page refresh without attaching data
Research on visualization method of technology topic map based on clustering information
Multitask programming
基于SEIR模型的网络医疗众筹传播建模与仿真分析
测试7年,面试华为最后面议要薪1万,HR说我不尊重华为,他们没有那么低薪资的岗位~
Research on text classification of e-commerce comments based on mffmb
C语言 预处理详解
Nodejs starts mqtt service with an error schemaerror: expected 'schema' to be an object or Boolean problem solving
redis的使用
牛血清蛋白修饰酚酸类及生物碱类小分子/偶联微球的蛋白/牛红细胞SOD的研究
基于网络分析和文本挖掘的意见领袖影响力研究
Verilog语法基础HDL Bits训练 06
TID-MOP:面向数据交易所场景下的安全管控综合框架
FreeRTOS personal notes - mutex
