这里是SunshineBooming,GPU公司一枚小小的Driver工程师,主要工作是写DirectX12 Driver,我会持续更新这个DX12 Spec系列,可能比较冷门,但是都是干货和工作中的心得体会,有任何GPU相关的问题都可以在评论区互动,知无不言:
目录
1. Pipeline(管线)
1.1 什么是Pipeline?
- DirectX12中的Pipeline主要分为2类,Graphic Pipeline和Compute Pipeline
- 其中Graphic Pipeline的定义如下:A graphics pipeline is the sequential flow of data inputs and outputs as the GPU renders frames。展开来说,就是DirectX12会将渲染画面的整个流程,划分成若干个Stage,每个Stage负责固定的功能,那么一整个流程就概括起来就是一条Pipeline(流水线)。
- 开始GPU只专门用来渲染图形,后来又发展出了专用的计算GPU,DirectX12定义了另一套Pipeline就是Compute Pipeline,这条Pipeline只包含运算模块CS(Compute Shader)。
1.2 Pipeline详细流程
- 关于Graphic Pipeline和Compute Pipeline的详细流程图,可以从微软官网和DirectX11.3的Spec官网找到。
补个冷知识:为啥DirectX12会参考DirectX11.3的Spec呢?因为微软一直在对DirectX11做升级,DirectX11.3的Pipeline模型已经和DirectX12保持一致了,可以将其看成DirectX12的过渡版本。
- 我们可以清晰地看到,如前文所述,Graphic Pipeline专门用来做图形渲染,就像一条工厂的流水线,具体分为了IA、VS、HS、TS、DS、GS、RS、PS、OM、SO,各个Stage的详细功能图中都有详细定义。Compute Pipeline专门用来做数值运算,只包含一个CS Stage。
1.3 Pipeline中Shader简述
1.3.1 Graphic Pipeline
- 如前文所述,Graphic Pipeline中Shader(与前文Stage一个意思,都是指Pipeline中一个阶段)包含IA、VS、HS、TS、DS、GS、RS、PS、OM、SO。
- 其中用户可编程的Shader(Programbled Shader)主要是VS、PS、DS、HS、GS,这几个Shader可以用HLSL(High Level Shader Language)写好计算流程,用户可以自定义对于Vertex Input(顶点数据输入)的计算过程。
补个知识点:提到这里的Vertex Input,在DirectX、OpenGL、Vulkan这些图形驱动框架里面,图形是由n个Vertex(顶点)构建的。例如:输入3个顶点Vertex0、Vertex1、Vertex2,再指定他们之间的Primitive Topology(图元拓扑逻辑)是三角形,就可以用这3个顶点最终画个三角形出来。那么以此类推,将三维图形各个面拆分成n个三角形,将他们的Vertex数据按照一定的顺序输入DirectX12图形,就可以画出这个三维图形。
- 其余还包括IA、TS、SO、RS、OM这几个Shader,被称为Fixed Shader,不可设置计算流程,只能用Pipeline Stage Object结构体设置其中一些特定的状态。
- DirectX12设置Graphic Pipeline主要是通过
ID3D12Device::CreateGraphicsPipelineState()
这个接口完成的,其中用到了D3D12_GRAPHICS_PIPELINE_STATE_DESC
这个结构体。该结构体中就包含了前文提到的可编程Shader如VS、PS、DS、HS、GS - 以及可以设置状态的Shader几个Shader,
StreamOutput
可以设置SO,RasterizerState
可以设置RS,InputLayout
、IBStripCutValue
和PrimitiveTopologyType
可以设置IA,RTVFormats
可以设置OM输出阶段的数据Format。
typedef struct D3D12_GRAPHICS_PIPELINE_STATE_DESC {
ID3D12RootSignature *pRootSignature;
D3D12_SHADER_BYTECODE VS;
D3D12_SHADER_BYTECODE PS;
D3D12_SHADER_BYTECODE DS;
D3D12_SHADER_BYTECODE HS;
D3D12_SHADER_BYTECODE GS;
D3D12_STREAM_OUTPUT_DESC StreamOutput;
D3D12_BLEND_DESC BlendState;
UINT SampleMask;
D3D12_RASTERIZER_DESC RasterizerState;
D3D12_DEPTH_STENCIL_DESC DepthStencilState;
D3D12_INPUT_LAYOUT_DESC InputLayout;
D3D12_INDEX_BUFFER_STRIP_CUT_VALUE IBStripCutValue;
D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType;
UINT NumRenderTargets;
DXGI_FORMAT RTVFormats[8];
DXGI_FORMAT DSVFormat;
DXGI_SAMPLE_DESC SampleDesc;
UINT NodeMask;
D3D12_CACHED_PIPELINE_STATE CachedPSO;
D3D12_PIPELINE_STATE_FLAGS Flags;
} D3D12_GRAPHICS_PIPELINE_STATE_DESC;
1.3.2 Compute Pipeline
- DirectX12设置Compute Pipeline主要是通过
ID3D12Device::CreateComputePipelineState()
这个接口完成的,其中用到了D3D12_COMPUTE_PIPELINE_STATE_DESC
这个结构体
typedef struct D3D12_COMPUTE_PIPELINE_STATE_DESC {
ID3D12RootSignature *pRootSignature;
D3D12_SHADER_BYTECODE CS;
UINT NodeMask;
D3D12_CACHED_PIPELINE_STATE CachedPSO;
D3D12_PIPELINE_STATE_FLAGS Flags;
} D3D12_COMPUTE_PIPELINE_STATE_DESC;
- Compute Pipeline是专用来做数值运算的一条流水线,其中仅包含一个CS Shader,该Shader由用户使用HLSL写好运算流程,然后交给
D3DCompileFromFile()
接口编译成binary,最后给到上面的D3D12_COMPUTE_PIPELINE_STATE_DESC
结构体中。