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