• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Dawn Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "dawn_native/d3d12/RenderPipelineD3D12.h"
16 
17 #include "common/Assert.h"
18 #include "common/Log.h"
19 #include "dawn_native/CreatePipelineAsyncTask.h"
20 #include "dawn_native/d3d12/D3D12Error.h"
21 #include "dawn_native/d3d12/DeviceD3D12.h"
22 #include "dawn_native/d3d12/PipelineLayoutD3D12.h"
23 #include "dawn_native/d3d12/PlatformFunctions.h"
24 #include "dawn_native/d3d12/ShaderModuleD3D12.h"
25 #include "dawn_native/d3d12/TextureD3D12.h"
26 #include "dawn_native/d3d12/UtilsD3D12.h"
27 
28 #include <d3dcompiler.h>
29 
30 namespace dawn_native { namespace d3d12 {
31 
32     namespace {
VertexFormatType(wgpu::VertexFormat format)33         DXGI_FORMAT VertexFormatType(wgpu::VertexFormat format) {
34             switch (format) {
35                 case wgpu::VertexFormat::Uint8x2:
36                     return DXGI_FORMAT_R8G8_UINT;
37                 case wgpu::VertexFormat::Uint8x4:
38                     return DXGI_FORMAT_R8G8B8A8_UINT;
39                 case wgpu::VertexFormat::Sint8x2:
40                     return DXGI_FORMAT_R8G8_SINT;
41                 case wgpu::VertexFormat::Sint8x4:
42                     return DXGI_FORMAT_R8G8B8A8_SINT;
43                 case wgpu::VertexFormat::Unorm8x2:
44                     return DXGI_FORMAT_R8G8_UNORM;
45                 case wgpu::VertexFormat::Unorm8x4:
46                     return DXGI_FORMAT_R8G8B8A8_UNORM;
47                 case wgpu::VertexFormat::Snorm8x2:
48                     return DXGI_FORMAT_R8G8_SNORM;
49                 case wgpu::VertexFormat::Snorm8x4:
50                     return DXGI_FORMAT_R8G8B8A8_SNORM;
51                 case wgpu::VertexFormat::Uint16x2:
52                     return DXGI_FORMAT_R16G16_UINT;
53                 case wgpu::VertexFormat::Uint16x4:
54                     return DXGI_FORMAT_R16G16B16A16_UINT;
55                 case wgpu::VertexFormat::Sint16x2:
56                     return DXGI_FORMAT_R16G16_SINT;
57                 case wgpu::VertexFormat::Sint16x4:
58                     return DXGI_FORMAT_R16G16B16A16_SINT;
59                 case wgpu::VertexFormat::Unorm16x2:
60                     return DXGI_FORMAT_R16G16_UNORM;
61                 case wgpu::VertexFormat::Unorm16x4:
62                     return DXGI_FORMAT_R16G16B16A16_UNORM;
63                 case wgpu::VertexFormat::Snorm16x2:
64                     return DXGI_FORMAT_R16G16_SNORM;
65                 case wgpu::VertexFormat::Snorm16x4:
66                     return DXGI_FORMAT_R16G16B16A16_SNORM;
67                 case wgpu::VertexFormat::Float16x2:
68                     return DXGI_FORMAT_R16G16_FLOAT;
69                 case wgpu::VertexFormat::Float16x4:
70                     return DXGI_FORMAT_R16G16B16A16_FLOAT;
71                 case wgpu::VertexFormat::Float32:
72                     return DXGI_FORMAT_R32_FLOAT;
73                 case wgpu::VertexFormat::Float32x2:
74                     return DXGI_FORMAT_R32G32_FLOAT;
75                 case wgpu::VertexFormat::Float32x3:
76                     return DXGI_FORMAT_R32G32B32_FLOAT;
77                 case wgpu::VertexFormat::Float32x4:
78                     return DXGI_FORMAT_R32G32B32A32_FLOAT;
79                 case wgpu::VertexFormat::Uint32:
80                     return DXGI_FORMAT_R32_UINT;
81                 case wgpu::VertexFormat::Uint32x2:
82                     return DXGI_FORMAT_R32G32_UINT;
83                 case wgpu::VertexFormat::Uint32x3:
84                     return DXGI_FORMAT_R32G32B32_UINT;
85                 case wgpu::VertexFormat::Uint32x4:
86                     return DXGI_FORMAT_R32G32B32A32_UINT;
87                 case wgpu::VertexFormat::Sint32:
88                     return DXGI_FORMAT_R32_SINT;
89                 case wgpu::VertexFormat::Sint32x2:
90                     return DXGI_FORMAT_R32G32_SINT;
91                 case wgpu::VertexFormat::Sint32x3:
92                     return DXGI_FORMAT_R32G32B32_SINT;
93                 case wgpu::VertexFormat::Sint32x4:
94                     return DXGI_FORMAT_R32G32B32A32_SINT;
95                 default:
96                     UNREACHABLE();
97             }
98         }
99 
VertexStepModeFunction(wgpu::VertexStepMode mode)100         D3D12_INPUT_CLASSIFICATION VertexStepModeFunction(wgpu::VertexStepMode mode) {
101             switch (mode) {
102                 case wgpu::VertexStepMode::Vertex:
103                     return D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
104                 case wgpu::VertexStepMode::Instance:
105                     return D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
106             }
107         }
108 
D3D12PrimitiveTopology(wgpu::PrimitiveTopology primitiveTopology)109         D3D12_PRIMITIVE_TOPOLOGY D3D12PrimitiveTopology(wgpu::PrimitiveTopology primitiveTopology) {
110             switch (primitiveTopology) {
111                 case wgpu::PrimitiveTopology::PointList:
112                     return D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
113                 case wgpu::PrimitiveTopology::LineList:
114                     return D3D_PRIMITIVE_TOPOLOGY_LINELIST;
115                 case wgpu::PrimitiveTopology::LineStrip:
116                     return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
117                 case wgpu::PrimitiveTopology::TriangleList:
118                     return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
119                 case wgpu::PrimitiveTopology::TriangleStrip:
120                     return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
121             }
122         }
123 
D3D12PrimitiveTopologyType(wgpu::PrimitiveTopology primitiveTopology)124         D3D12_PRIMITIVE_TOPOLOGY_TYPE D3D12PrimitiveTopologyType(
125             wgpu::PrimitiveTopology primitiveTopology) {
126             switch (primitiveTopology) {
127                 case wgpu::PrimitiveTopology::PointList:
128                     return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
129                 case wgpu::PrimitiveTopology::LineList:
130                 case wgpu::PrimitiveTopology::LineStrip:
131                     return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
132                 case wgpu::PrimitiveTopology::TriangleList:
133                 case wgpu::PrimitiveTopology::TriangleStrip:
134                     return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
135             }
136         }
137 
D3D12CullMode(wgpu::CullMode mode)138         D3D12_CULL_MODE D3D12CullMode(wgpu::CullMode mode) {
139             switch (mode) {
140                 case wgpu::CullMode::None:
141                     return D3D12_CULL_MODE_NONE;
142                 case wgpu::CullMode::Front:
143                     return D3D12_CULL_MODE_FRONT;
144                 case wgpu::CullMode::Back:
145                     return D3D12_CULL_MODE_BACK;
146             }
147         }
148 
D3D12Blend(wgpu::BlendFactor factor)149         D3D12_BLEND D3D12Blend(wgpu::BlendFactor factor) {
150             switch (factor) {
151                 case wgpu::BlendFactor::Zero:
152                     return D3D12_BLEND_ZERO;
153                 case wgpu::BlendFactor::One:
154                     return D3D12_BLEND_ONE;
155                 case wgpu::BlendFactor::Src:
156                     return D3D12_BLEND_SRC_COLOR;
157                 case wgpu::BlendFactor::OneMinusSrc:
158                     return D3D12_BLEND_INV_SRC_COLOR;
159                 case wgpu::BlendFactor::SrcAlpha:
160                     return D3D12_BLEND_SRC_ALPHA;
161                 case wgpu::BlendFactor::OneMinusSrcAlpha:
162                     return D3D12_BLEND_INV_SRC_ALPHA;
163                 case wgpu::BlendFactor::Dst:
164                     return D3D12_BLEND_DEST_COLOR;
165                 case wgpu::BlendFactor::OneMinusDst:
166                     return D3D12_BLEND_INV_DEST_COLOR;
167                 case wgpu::BlendFactor::DstAlpha:
168                     return D3D12_BLEND_DEST_ALPHA;
169                 case wgpu::BlendFactor::OneMinusDstAlpha:
170                     return D3D12_BLEND_INV_DEST_ALPHA;
171                 case wgpu::BlendFactor::SrcAlphaSaturated:
172                     return D3D12_BLEND_SRC_ALPHA_SAT;
173                 case wgpu::BlendFactor::Constant:
174                     return D3D12_BLEND_BLEND_FACTOR;
175                 case wgpu::BlendFactor::OneMinusConstant:
176                     return D3D12_BLEND_INV_BLEND_FACTOR;
177             }
178         }
179 
180         // When a blend factor is defined for the alpha channel, any of the factors that don't
181         // explicitly state that they apply to alpha should be treated as their explicitly-alpha
182         // equivalents. See: https://github.com/gpuweb/gpuweb/issues/65
D3D12AlphaBlend(wgpu::BlendFactor factor)183         D3D12_BLEND D3D12AlphaBlend(wgpu::BlendFactor factor) {
184             switch (factor) {
185                 case wgpu::BlendFactor::Src:
186                     return D3D12_BLEND_SRC_ALPHA;
187                 case wgpu::BlendFactor::OneMinusSrc:
188                     return D3D12_BLEND_INV_SRC_ALPHA;
189                 case wgpu::BlendFactor::Dst:
190                     return D3D12_BLEND_DEST_ALPHA;
191                 case wgpu::BlendFactor::OneMinusDst:
192                     return D3D12_BLEND_INV_DEST_ALPHA;
193 
194                 // Other blend factors translate to the same D3D12 enum as the color blend factors.
195                 default:
196                     return D3D12Blend(factor);
197             }
198         }
199 
D3D12BlendOperation(wgpu::BlendOperation operation)200         D3D12_BLEND_OP D3D12BlendOperation(wgpu::BlendOperation operation) {
201             switch (operation) {
202                 case wgpu::BlendOperation::Add:
203                     return D3D12_BLEND_OP_ADD;
204                 case wgpu::BlendOperation::Subtract:
205                     return D3D12_BLEND_OP_SUBTRACT;
206                 case wgpu::BlendOperation::ReverseSubtract:
207                     return D3D12_BLEND_OP_REV_SUBTRACT;
208                 case wgpu::BlendOperation::Min:
209                     return D3D12_BLEND_OP_MIN;
210                 case wgpu::BlendOperation::Max:
211                     return D3D12_BLEND_OP_MAX;
212             }
213         }
214 
D3D12RenderTargetWriteMask(wgpu::ColorWriteMask writeMask)215         uint8_t D3D12RenderTargetWriteMask(wgpu::ColorWriteMask writeMask) {
216             static_assert(static_cast<D3D12_COLOR_WRITE_ENABLE>(wgpu::ColorWriteMask::Red) ==
217                               D3D12_COLOR_WRITE_ENABLE_RED,
218                           "ColorWriteMask values must match");
219             static_assert(static_cast<D3D12_COLOR_WRITE_ENABLE>(wgpu::ColorWriteMask::Green) ==
220                               D3D12_COLOR_WRITE_ENABLE_GREEN,
221                           "ColorWriteMask values must match");
222             static_assert(static_cast<D3D12_COLOR_WRITE_ENABLE>(wgpu::ColorWriteMask::Blue) ==
223                               D3D12_COLOR_WRITE_ENABLE_BLUE,
224                           "ColorWriteMask values must match");
225             static_assert(static_cast<D3D12_COLOR_WRITE_ENABLE>(wgpu::ColorWriteMask::Alpha) ==
226                               D3D12_COLOR_WRITE_ENABLE_ALPHA,
227                           "ColorWriteMask values must match");
228             return static_cast<uint8_t>(writeMask);
229         }
230 
ComputeColorDesc(const ColorTargetState * state)231         D3D12_RENDER_TARGET_BLEND_DESC ComputeColorDesc(const ColorTargetState* state) {
232             D3D12_RENDER_TARGET_BLEND_DESC blendDesc;
233             blendDesc.BlendEnable = state->blend != nullptr;
234             if (blendDesc.BlendEnable) {
235                 blendDesc.SrcBlend = D3D12Blend(state->blend->color.srcFactor);
236                 blendDesc.DestBlend = D3D12Blend(state->blend->color.dstFactor);
237                 blendDesc.BlendOp = D3D12BlendOperation(state->blend->color.operation);
238                 blendDesc.SrcBlendAlpha = D3D12AlphaBlend(state->blend->alpha.srcFactor);
239                 blendDesc.DestBlendAlpha = D3D12AlphaBlend(state->blend->alpha.dstFactor);
240                 blendDesc.BlendOpAlpha = D3D12BlendOperation(state->blend->alpha.operation);
241             }
242             blendDesc.RenderTargetWriteMask = D3D12RenderTargetWriteMask(state->writeMask);
243             blendDesc.LogicOpEnable = false;
244             blendDesc.LogicOp = D3D12_LOGIC_OP_NOOP;
245             return blendDesc;
246         }
247 
StencilOp(wgpu::StencilOperation op)248         D3D12_STENCIL_OP StencilOp(wgpu::StencilOperation op) {
249             switch (op) {
250                 case wgpu::StencilOperation::Keep:
251                     return D3D12_STENCIL_OP_KEEP;
252                 case wgpu::StencilOperation::Zero:
253                     return D3D12_STENCIL_OP_ZERO;
254                 case wgpu::StencilOperation::Replace:
255                     return D3D12_STENCIL_OP_REPLACE;
256                 case wgpu::StencilOperation::IncrementClamp:
257                     return D3D12_STENCIL_OP_INCR_SAT;
258                 case wgpu::StencilOperation::DecrementClamp:
259                     return D3D12_STENCIL_OP_DECR_SAT;
260                 case wgpu::StencilOperation::Invert:
261                     return D3D12_STENCIL_OP_INVERT;
262                 case wgpu::StencilOperation::IncrementWrap:
263                     return D3D12_STENCIL_OP_INCR;
264                 case wgpu::StencilOperation::DecrementWrap:
265                     return D3D12_STENCIL_OP_DECR;
266             }
267         }
268 
StencilOpDesc(const StencilFaceState & descriptor)269         D3D12_DEPTH_STENCILOP_DESC StencilOpDesc(const StencilFaceState& descriptor) {
270             D3D12_DEPTH_STENCILOP_DESC desc;
271 
272             desc.StencilFailOp = StencilOp(descriptor.failOp);
273             desc.StencilDepthFailOp = StencilOp(descriptor.depthFailOp);
274             desc.StencilPassOp = StencilOp(descriptor.passOp);
275             desc.StencilFunc = ToD3D12ComparisonFunc(descriptor.compare);
276 
277             return desc;
278         }
279 
ComputeDepthStencilDesc(const DepthStencilState * descriptor)280         D3D12_DEPTH_STENCIL_DESC ComputeDepthStencilDesc(const DepthStencilState* descriptor) {
281             D3D12_DEPTH_STENCIL_DESC mDepthStencilDescriptor;
282             mDepthStencilDescriptor.DepthEnable = TRUE;
283             mDepthStencilDescriptor.DepthWriteMask = descriptor->depthWriteEnabled
284                                                          ? D3D12_DEPTH_WRITE_MASK_ALL
285                                                          : D3D12_DEPTH_WRITE_MASK_ZERO;
286             mDepthStencilDescriptor.DepthFunc = ToD3D12ComparisonFunc(descriptor->depthCompare);
287 
288             mDepthStencilDescriptor.StencilEnable = StencilTestEnabled(descriptor) ? TRUE : FALSE;
289             mDepthStencilDescriptor.StencilReadMask =
290                 static_cast<UINT8>(descriptor->stencilReadMask);
291             mDepthStencilDescriptor.StencilWriteMask =
292                 static_cast<UINT8>(descriptor->stencilWriteMask);
293 
294             mDepthStencilDescriptor.FrontFace = StencilOpDesc(descriptor->stencilFront);
295             mDepthStencilDescriptor.BackFace = StencilOpDesc(descriptor->stencilBack);
296             return mDepthStencilDescriptor;
297         }
298 
ComputeIndexBufferStripCutValue(wgpu::PrimitiveTopology primitiveTopology,wgpu::IndexFormat indexFormat)299         D3D12_INDEX_BUFFER_STRIP_CUT_VALUE ComputeIndexBufferStripCutValue(
300             wgpu::PrimitiveTopology primitiveTopology,
301             wgpu::IndexFormat indexFormat) {
302             if (primitiveTopology != wgpu::PrimitiveTopology::TriangleStrip &&
303                 primitiveTopology != wgpu::PrimitiveTopology::LineStrip) {
304                 return D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
305             }
306 
307             switch (indexFormat) {
308                 case wgpu::IndexFormat::Uint16:
309                     return D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF;
310                 case wgpu::IndexFormat::Uint32:
311                     return D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF;
312                 case wgpu::IndexFormat::Undefined:
313                     return D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
314             }
315         }
316 
317     }  // anonymous namespace
318 
CreateUninitialized(Device * device,const RenderPipelineDescriptor * descriptor)319     Ref<RenderPipeline> RenderPipeline::CreateUninitialized(
320         Device* device,
321         const RenderPipelineDescriptor* descriptor) {
322         return AcquireRef(new RenderPipeline(device, descriptor));
323     }
324 
Initialize()325     MaybeError RenderPipeline::Initialize() {
326         Device* device = ToBackend(GetDevice());
327         uint32_t compileFlags = 0;
328 
329         if (!device->IsToggleEnabled(Toggle::UseDXC) &&
330             !device->IsToggleEnabled(Toggle::FxcOptimizations)) {
331             compileFlags |= D3DCOMPILE_OPTIMIZATION_LEVEL0;
332         }
333 
334         if (device->IsToggleEnabled(Toggle::EmitHLSLDebugSymbols)) {
335             compileFlags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
336         }
337 
338         // SPRIV-cross does matrix multiplication expecting row major matrices
339         compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
340 
341         // FXC can miscompile code that depends on special float values (NaN, INF, etc) when IEEE
342         // strictness is not enabled. See crbug.com/tint/976.
343         compileFlags |= D3DCOMPILE_IEEE_STRICTNESS;
344 
345         D3D12_GRAPHICS_PIPELINE_STATE_DESC descriptorD3D12 = {};
346 
347         PerStage<ProgrammableStage> pipelineStages = GetAllStages();
348 
349         PerStage<D3D12_SHADER_BYTECODE*> shaders;
350         shaders[SingleShaderStage::Vertex] = &descriptorD3D12.VS;
351         shaders[SingleShaderStage::Fragment] = &descriptorD3D12.PS;
352 
353         PerStage<CompiledShader> compiledShader;
354 
355         for (auto stage : IterateStages(GetStageMask())) {
356             DAWN_TRY_ASSIGN(
357                 compiledShader[stage],
358                 ToBackend(pipelineStages[stage].module)
359                     ->Compile(pipelineStages[stage], stage, ToBackend(GetLayout()), compileFlags));
360             *shaders[stage] = compiledShader[stage].GetD3D12ShaderBytecode();
361         }
362 
363         mFirstOffsetInfo = compiledShader[SingleShaderStage::Vertex].firstOffsetInfo;
364 
365         PipelineLayout* layout = ToBackend(GetLayout());
366 
367         descriptorD3D12.pRootSignature = layout->GetRootSignature();
368 
369         // D3D12 logs warnings if any empty input state is used
370         std::array<D3D12_INPUT_ELEMENT_DESC, kMaxVertexAttributes> inputElementDescriptors;
371         if (GetAttributeLocationsUsed().any()) {
372             descriptorD3D12.InputLayout = ComputeInputLayout(&inputElementDescriptors);
373         }
374 
375         descriptorD3D12.IBStripCutValue =
376             ComputeIndexBufferStripCutValue(GetPrimitiveTopology(), GetStripIndexFormat());
377 
378         descriptorD3D12.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
379         descriptorD3D12.RasterizerState.CullMode = D3D12CullMode(GetCullMode());
380         descriptorD3D12.RasterizerState.FrontCounterClockwise =
381             (GetFrontFace() == wgpu::FrontFace::CCW) ? TRUE : FALSE;
382         descriptorD3D12.RasterizerState.DepthBias = GetDepthBias();
383         descriptorD3D12.RasterizerState.DepthBiasClamp = GetDepthBiasClamp();
384         descriptorD3D12.RasterizerState.SlopeScaledDepthBias = GetDepthBiasSlopeScale();
385         descriptorD3D12.RasterizerState.DepthClipEnable = TRUE;
386         descriptorD3D12.RasterizerState.MultisampleEnable = (GetSampleCount() > 1) ? TRUE : FALSE;
387         descriptorD3D12.RasterizerState.AntialiasedLineEnable = FALSE;
388         descriptorD3D12.RasterizerState.ForcedSampleCount = 0;
389         descriptorD3D12.RasterizerState.ConservativeRaster =
390             D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
391 
392         if (HasDepthStencilAttachment()) {
393             descriptorD3D12.DSVFormat = D3D12TextureFormat(GetDepthStencilFormat());
394         }
395 
396         for (ColorAttachmentIndex i : IterateBitSet(GetColorAttachmentsMask())) {
397             descriptorD3D12.RTVFormats[static_cast<uint8_t>(i)] =
398                 D3D12TextureFormat(GetColorAttachmentFormat(i));
399             descriptorD3D12.BlendState.RenderTarget[static_cast<uint8_t>(i)] =
400                 ComputeColorDesc(GetColorTargetState(i));
401         }
402         descriptorD3D12.NumRenderTargets = static_cast<uint32_t>(GetColorAttachmentsMask().count());
403 
404         descriptorD3D12.BlendState.AlphaToCoverageEnable = IsAlphaToCoverageEnabled();
405         descriptorD3D12.BlendState.IndependentBlendEnable = TRUE;
406 
407         descriptorD3D12.DepthStencilState = ComputeDepthStencilDesc(GetDepthStencilState());
408 
409         descriptorD3D12.SampleMask = GetSampleMask();
410         descriptorD3D12.PrimitiveTopologyType = D3D12PrimitiveTopologyType(GetPrimitiveTopology());
411         descriptorD3D12.SampleDesc.Count = GetSampleCount();
412         descriptorD3D12.SampleDesc.Quality = 0;
413 
414         mD3d12PrimitiveTopology = D3D12PrimitiveTopology(GetPrimitiveTopology());
415 
416         DAWN_TRY(CheckHRESULT(device->GetD3D12Device()->CreateGraphicsPipelineState(
417                                   &descriptorD3D12, IID_PPV_ARGS(&mPipelineState)),
418                               "D3D12 create graphics pipeline state"));
419 
420         SetLabelImpl();
421 
422         return {};
423     }
424 
425     RenderPipeline::~RenderPipeline() = default;
426 
DestroyImpl()427     void RenderPipeline::DestroyImpl() {
428         RenderPipelineBase::DestroyImpl();
429         ToBackend(GetDevice())->ReferenceUntilUnused(mPipelineState);
430     }
431 
GetD3D12PrimitiveTopology() const432     D3D12_PRIMITIVE_TOPOLOGY RenderPipeline::GetD3D12PrimitiveTopology() const {
433         return mD3d12PrimitiveTopology;
434     }
435 
GetPipelineState() const436     ID3D12PipelineState* RenderPipeline::GetPipelineState() const {
437         return mPipelineState.Get();
438     }
439 
GetFirstOffsetInfo() const440     const FirstOffsetInfo& RenderPipeline::GetFirstOffsetInfo() const {
441         return mFirstOffsetInfo;
442     }
443 
SetLabelImpl()444     void RenderPipeline::SetLabelImpl() {
445         SetDebugName(ToBackend(GetDevice()), GetPipelineState(), "Dawn_RenderPipeline", GetLabel());
446     }
447 
ComputeInputLayout(std::array<D3D12_INPUT_ELEMENT_DESC,kMaxVertexAttributes> * inputElementDescriptors)448     D3D12_INPUT_LAYOUT_DESC RenderPipeline::ComputeInputLayout(
449         std::array<D3D12_INPUT_ELEMENT_DESC, kMaxVertexAttributes>* inputElementDescriptors) {
450         unsigned int count = 0;
451         for (VertexAttributeLocation loc : IterateBitSet(GetAttributeLocationsUsed())) {
452             D3D12_INPUT_ELEMENT_DESC& inputElementDescriptor = (*inputElementDescriptors)[count++];
453 
454             const VertexAttributeInfo& attribute = GetAttribute(loc);
455 
456             // If the HLSL semantic is TEXCOORDN the SemanticName should be "TEXCOORD" and the
457             // SemanticIndex N
458             inputElementDescriptor.SemanticName = "TEXCOORD";
459             inputElementDescriptor.SemanticIndex = static_cast<uint8_t>(loc);
460             inputElementDescriptor.Format = VertexFormatType(attribute.format);
461             inputElementDescriptor.InputSlot = static_cast<uint8_t>(attribute.vertexBufferSlot);
462 
463             const VertexBufferInfo& input = GetVertexBuffer(attribute.vertexBufferSlot);
464 
465             inputElementDescriptor.AlignedByteOffset = attribute.offset;
466             inputElementDescriptor.InputSlotClass = VertexStepModeFunction(input.stepMode);
467             if (inputElementDescriptor.InputSlotClass ==
468                 D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA) {
469                 inputElementDescriptor.InstanceDataStepRate = 0;
470             } else {
471                 inputElementDescriptor.InstanceDataStepRate = 1;
472             }
473         }
474 
475         D3D12_INPUT_LAYOUT_DESC inputLayoutDescriptor;
476         inputLayoutDescriptor.pInputElementDescs = &(*inputElementDescriptors)[0];
477         inputLayoutDescriptor.NumElements = count;
478         return inputLayoutDescriptor;
479     }
480 
InitializeAsync(Ref<RenderPipelineBase> renderPipeline,WGPUCreateRenderPipelineAsyncCallback callback,void * userdata)481     void RenderPipeline::InitializeAsync(Ref<RenderPipelineBase> renderPipeline,
482                                          WGPUCreateRenderPipelineAsyncCallback callback,
483                                          void* userdata) {
484         std::unique_ptr<CreateRenderPipelineAsyncTask> asyncTask =
485             std::make_unique<CreateRenderPipelineAsyncTask>(std::move(renderPipeline), callback,
486                                                             userdata);
487         CreateRenderPipelineAsyncTask::RunAsync(std::move(asyncTask));
488     }
489 
490 }}  // namespace dawn_native::d3d12
491