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/RenderPipeline.h" 16 17 #include "common/BitSetIterator.h" 18 #include "common/HashUtils.h" 19 #include "dawn_native/Commands.h" 20 #include "dawn_native/Device.h" 21 #include "dawn_native/ValidationUtils_autogen.h" 22 23 namespace dawn_native { 24 // Helper functions 25 namespace { 26 ValidateVertexAttributeDescriptor(const VertexAttributeDescriptor * attribute,uint64_t vertexBufferStride,std::bitset<kMaxVertexAttributes> * attributesSetMask)27 MaybeError ValidateVertexAttributeDescriptor( 28 const VertexAttributeDescriptor* attribute, 29 uint64_t vertexBufferStride, 30 std::bitset<kMaxVertexAttributes>* attributesSetMask) { 31 DAWN_TRY(ValidateVertexFormat(attribute->format)); 32 33 if (attribute->shaderLocation >= kMaxVertexAttributes) { 34 return DAWN_VALIDATION_ERROR("Setting attribute out of bounds"); 35 } 36 37 // No underflow is possible because the max vertex format size is smaller than 38 // kMaxVertexAttributeEnd. 39 ASSERT(kMaxVertexAttributeEnd >= VertexFormatSize(attribute->format)); 40 if (attribute->offset > kMaxVertexAttributeEnd - VertexFormatSize(attribute->format)) { 41 return DAWN_VALIDATION_ERROR("Setting attribute offset out of bounds"); 42 } 43 44 // No overflow is possible because the offset is already validated to be less 45 // than kMaxVertexAttributeEnd. 46 ASSERT(attribute->offset < kMaxVertexAttributeEnd); 47 if (vertexBufferStride > 0 && 48 attribute->offset + VertexFormatSize(attribute->format) > vertexBufferStride) { 49 return DAWN_VALIDATION_ERROR("Setting attribute offset out of bounds"); 50 } 51 52 if ((*attributesSetMask)[attribute->shaderLocation]) { 53 return DAWN_VALIDATION_ERROR("Setting already set attribute"); 54 } 55 56 attributesSetMask->set(attribute->shaderLocation); 57 return {}; 58 } 59 ValidateVertexBufferDescriptor(const VertexBufferDescriptor * buffer,std::bitset<kMaxVertexAttributes> * attributesSetMask)60 MaybeError ValidateVertexBufferDescriptor( 61 const VertexBufferDescriptor* buffer, 62 std::bitset<kMaxVertexAttributes>* attributesSetMask) { 63 DAWN_TRY(ValidateInputStepMode(buffer->stepMode)); 64 if (buffer->stride > kMaxVertexBufferStride) { 65 return DAWN_VALIDATION_ERROR("Setting input stride out of bounds"); 66 } 67 68 for (uint32_t i = 0; i < buffer->attributeCount; ++i) { 69 DAWN_TRY(ValidateVertexAttributeDescriptor(&buffer->attributes[i], buffer->stride, 70 attributesSetMask)); 71 } 72 73 return {}; 74 } 75 ValidateVertexInputDescriptor(const VertexInputDescriptor * descriptor,std::bitset<kMaxVertexAttributes> * attributesSetMask)76 MaybeError ValidateVertexInputDescriptor( 77 const VertexInputDescriptor* descriptor, 78 std::bitset<kMaxVertexAttributes>* attributesSetMask) { 79 if (descriptor->nextInChain != nullptr) { 80 return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); 81 } 82 DAWN_TRY(ValidateIndexFormat(descriptor->indexFormat)); 83 84 if (descriptor->bufferCount > kMaxVertexBuffers) { 85 return DAWN_VALIDATION_ERROR("Vertex Inputs number exceeds maximum"); 86 } 87 88 uint32_t totalAttributesNum = 0; 89 for (uint32_t i = 0; i < descriptor->bufferCount; ++i) { 90 DAWN_TRY( 91 ValidateVertexBufferDescriptor(&descriptor->buffers[i], attributesSetMask)); 92 totalAttributesNum += descriptor->buffers[i].attributeCount; 93 } 94 95 // Every vertex attribute has a member called shaderLocation, and there are some 96 // requirements for shaderLocation: 1) >=0, 2) values are different across different 97 // attributes, 3) can't exceed kMaxVertexAttributes. So it can ensure that total 98 // attribute number never exceed kMaxVertexAttributes. 99 ASSERT(totalAttributesNum <= kMaxVertexAttributes); 100 101 return {}; 102 } 103 ValidateRasterizationStateDescriptor(const RasterizationStateDescriptor * descriptor)104 MaybeError ValidateRasterizationStateDescriptor( 105 const RasterizationStateDescriptor* descriptor) { 106 if (descriptor->nextInChain != nullptr) { 107 return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); 108 } 109 DAWN_TRY(ValidateFrontFace(descriptor->frontFace)); 110 DAWN_TRY(ValidateCullMode(descriptor->cullMode)); 111 return {}; 112 } 113 ValidateColorStateDescriptor(const DeviceBase * device,const ColorStateDescriptor * descriptor)114 MaybeError ValidateColorStateDescriptor(const DeviceBase* device, 115 const ColorStateDescriptor* descriptor) { 116 if (descriptor->nextInChain != nullptr) { 117 return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); 118 } 119 DAWN_TRY(ValidateBlendOperation(descriptor->alphaBlend.operation)); 120 DAWN_TRY(ValidateBlendFactor(descriptor->alphaBlend.srcFactor)); 121 DAWN_TRY(ValidateBlendFactor(descriptor->alphaBlend.dstFactor)); 122 DAWN_TRY(ValidateBlendOperation(descriptor->colorBlend.operation)); 123 DAWN_TRY(ValidateBlendFactor(descriptor->colorBlend.srcFactor)); 124 DAWN_TRY(ValidateBlendFactor(descriptor->colorBlend.dstFactor)); 125 DAWN_TRY(ValidateColorWriteMask(descriptor->writeMask)); 126 127 const Format* format; 128 DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format)); 129 if (!format->IsColor() || !format->isRenderable) { 130 return DAWN_VALIDATION_ERROR("Color format must be color renderable"); 131 } 132 133 return {}; 134 } 135 ValidateDepthStencilStateDescriptor(const DeviceBase * device,const DepthStencilStateDescriptor * descriptor)136 MaybeError ValidateDepthStencilStateDescriptor( 137 const DeviceBase* device, 138 const DepthStencilStateDescriptor* descriptor) { 139 if (descriptor->nextInChain != nullptr) { 140 return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); 141 } 142 DAWN_TRY(ValidateCompareFunction(descriptor->depthCompare)); 143 DAWN_TRY(ValidateCompareFunction(descriptor->stencilFront.compare)); 144 DAWN_TRY(ValidateStencilOperation(descriptor->stencilFront.failOp)); 145 DAWN_TRY(ValidateStencilOperation(descriptor->stencilFront.depthFailOp)); 146 DAWN_TRY(ValidateStencilOperation(descriptor->stencilFront.passOp)); 147 DAWN_TRY(ValidateCompareFunction(descriptor->stencilBack.compare)); 148 DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.failOp)); 149 DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.depthFailOp)); 150 DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.passOp)); 151 152 const Format* format; 153 DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format)); 154 if (!format->HasDepthOrStencil() || !format->isRenderable) { 155 return DAWN_VALIDATION_ERROR( 156 "Depth stencil format must be depth-stencil renderable"); 157 } 158 159 return {}; 160 } 161 162 } // anonymous namespace 163 164 // Helper functions IndexFormatSize(dawn::IndexFormat format)165 size_t IndexFormatSize(dawn::IndexFormat format) { 166 switch (format) { 167 case dawn::IndexFormat::Uint16: 168 return sizeof(uint16_t); 169 case dawn::IndexFormat::Uint32: 170 return sizeof(uint32_t); 171 default: 172 UNREACHABLE(); 173 } 174 } 175 VertexFormatNumComponents(dawn::VertexFormat format)176 uint32_t VertexFormatNumComponents(dawn::VertexFormat format) { 177 switch (format) { 178 case dawn::VertexFormat::UChar4: 179 case dawn::VertexFormat::Char4: 180 case dawn::VertexFormat::UChar4Norm: 181 case dawn::VertexFormat::Char4Norm: 182 case dawn::VertexFormat::UShort4: 183 case dawn::VertexFormat::Short4: 184 case dawn::VertexFormat::UShort4Norm: 185 case dawn::VertexFormat::Short4Norm: 186 case dawn::VertexFormat::Half4: 187 case dawn::VertexFormat::Float4: 188 case dawn::VertexFormat::UInt4: 189 case dawn::VertexFormat::Int4: 190 return 4; 191 case dawn::VertexFormat::Float3: 192 case dawn::VertexFormat::UInt3: 193 case dawn::VertexFormat::Int3: 194 return 3; 195 case dawn::VertexFormat::UChar2: 196 case dawn::VertexFormat::Char2: 197 case dawn::VertexFormat::UChar2Norm: 198 case dawn::VertexFormat::Char2Norm: 199 case dawn::VertexFormat::UShort2: 200 case dawn::VertexFormat::Short2: 201 case dawn::VertexFormat::UShort2Norm: 202 case dawn::VertexFormat::Short2Norm: 203 case dawn::VertexFormat::Half2: 204 case dawn::VertexFormat::Float2: 205 case dawn::VertexFormat::UInt2: 206 case dawn::VertexFormat::Int2: 207 return 2; 208 case dawn::VertexFormat::Float: 209 case dawn::VertexFormat::UInt: 210 case dawn::VertexFormat::Int: 211 return 1; 212 default: 213 UNREACHABLE(); 214 } 215 } 216 VertexFormatComponentSize(dawn::VertexFormat format)217 size_t VertexFormatComponentSize(dawn::VertexFormat format) { 218 switch (format) { 219 case dawn::VertexFormat::UChar2: 220 case dawn::VertexFormat::UChar4: 221 case dawn::VertexFormat::Char2: 222 case dawn::VertexFormat::Char4: 223 case dawn::VertexFormat::UChar2Norm: 224 case dawn::VertexFormat::UChar4Norm: 225 case dawn::VertexFormat::Char2Norm: 226 case dawn::VertexFormat::Char4Norm: 227 return sizeof(char); 228 case dawn::VertexFormat::UShort2: 229 case dawn::VertexFormat::UShort4: 230 case dawn::VertexFormat::UShort2Norm: 231 case dawn::VertexFormat::UShort4Norm: 232 case dawn::VertexFormat::Short2: 233 case dawn::VertexFormat::Short4: 234 case dawn::VertexFormat::Short2Norm: 235 case dawn::VertexFormat::Short4Norm: 236 case dawn::VertexFormat::Half2: 237 case dawn::VertexFormat::Half4: 238 return sizeof(uint16_t); 239 case dawn::VertexFormat::Float: 240 case dawn::VertexFormat::Float2: 241 case dawn::VertexFormat::Float3: 242 case dawn::VertexFormat::Float4: 243 return sizeof(float); 244 case dawn::VertexFormat::UInt: 245 case dawn::VertexFormat::UInt2: 246 case dawn::VertexFormat::UInt3: 247 case dawn::VertexFormat::UInt4: 248 case dawn::VertexFormat::Int: 249 case dawn::VertexFormat::Int2: 250 case dawn::VertexFormat::Int3: 251 case dawn::VertexFormat::Int4: 252 return sizeof(int32_t); 253 default: 254 UNREACHABLE(); 255 } 256 } 257 VertexFormatSize(dawn::VertexFormat format)258 size_t VertexFormatSize(dawn::VertexFormat format) { 259 return VertexFormatNumComponents(format) * VertexFormatComponentSize(format); 260 } 261 ValidateRenderPipelineDescriptor(const DeviceBase * device,const RenderPipelineDescriptor * descriptor)262 MaybeError ValidateRenderPipelineDescriptor(const DeviceBase* device, 263 const RenderPipelineDescriptor* descriptor) { 264 if (descriptor->nextInChain != nullptr) { 265 return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); 266 } 267 268 DAWN_TRY(device->ValidateObject(descriptor->layout)); 269 270 if (descriptor->vertexInput == nullptr) { 271 return DAWN_VALIDATION_ERROR("Input state must not be null"); 272 } 273 274 std::bitset<kMaxVertexAttributes> attributesSetMask; 275 DAWN_TRY(ValidateVertexInputDescriptor(descriptor->vertexInput, &attributesSetMask)); 276 DAWN_TRY(ValidatePrimitiveTopology(descriptor->primitiveTopology)); 277 DAWN_TRY(ValidatePipelineStageDescriptor(device, descriptor->vertexStage, 278 descriptor->layout, ShaderStage::Vertex)); 279 DAWN_TRY(ValidatePipelineStageDescriptor(device, descriptor->fragmentStage, 280 descriptor->layout, ShaderStage::Fragment)); 281 282 if (descriptor->rasterizationState) { 283 DAWN_TRY(ValidateRasterizationStateDescriptor(descriptor->rasterizationState)); 284 } 285 286 if ((descriptor->vertexStage->module->GetUsedVertexAttributes() & ~attributesSetMask) 287 .any()) { 288 return DAWN_VALIDATION_ERROR( 289 "Pipeline vertex stage uses inputs not in the input state"); 290 } 291 292 if (!IsValidSampleCount(descriptor->sampleCount)) { 293 return DAWN_VALIDATION_ERROR("Sample count is not supported"); 294 } 295 296 if (descriptor->colorStateCount > kMaxColorAttachments) { 297 return DAWN_VALIDATION_ERROR("Color States number exceeds maximum"); 298 } 299 300 if (descriptor->colorStateCount == 0 && !descriptor->depthStencilState) { 301 return DAWN_VALIDATION_ERROR("Should have at least one attachment"); 302 } 303 304 for (uint32_t i = 0; i < descriptor->colorStateCount; ++i) { 305 DAWN_TRY(ValidateColorStateDescriptor(device, descriptor->colorStates[i])); 306 } 307 308 if (descriptor->depthStencilState) { 309 DAWN_TRY(ValidateDepthStencilStateDescriptor(device, descriptor->depthStencilState)); 310 } 311 312 if (descriptor->sampleMask != 0xFFFFFFFF) { 313 return DAWN_VALIDATION_ERROR("sampleMask must be 0xFFFFFFFF (for now)"); 314 } 315 316 if (descriptor->alphaToCoverageEnabled) { 317 return DAWN_VALIDATION_ERROR("alphaToCoverageEnabled isn't supported (yet)"); 318 } 319 320 return {}; 321 } 322 StencilTestEnabled(const DepthStencilStateDescriptor * mDepthStencilState)323 bool StencilTestEnabled(const DepthStencilStateDescriptor* mDepthStencilState) { 324 return mDepthStencilState->stencilBack.compare != dawn::CompareFunction::Always || 325 mDepthStencilState->stencilBack.failOp != dawn::StencilOperation::Keep || 326 mDepthStencilState->stencilBack.depthFailOp != dawn::StencilOperation::Keep || 327 mDepthStencilState->stencilBack.passOp != dawn::StencilOperation::Keep || 328 mDepthStencilState->stencilFront.compare != dawn::CompareFunction::Always || 329 mDepthStencilState->stencilFront.failOp != dawn::StencilOperation::Keep || 330 mDepthStencilState->stencilFront.depthFailOp != dawn::StencilOperation::Keep || 331 mDepthStencilState->stencilFront.passOp != dawn::StencilOperation::Keep; 332 } 333 BlendEnabled(const ColorStateDescriptor * mColorState)334 bool BlendEnabled(const ColorStateDescriptor* mColorState) { 335 return mColorState->alphaBlend.operation != dawn::BlendOperation::Add || 336 mColorState->alphaBlend.srcFactor != dawn::BlendFactor::One || 337 mColorState->alphaBlend.dstFactor != dawn::BlendFactor::Zero || 338 mColorState->colorBlend.operation != dawn::BlendOperation::Add || 339 mColorState->colorBlend.srcFactor != dawn::BlendFactor::One || 340 mColorState->colorBlend.dstFactor != dawn::BlendFactor::Zero; 341 } 342 343 // RenderPipelineBase 344 RenderPipelineBase(DeviceBase * device,const RenderPipelineDescriptor * descriptor,bool blueprint)345 RenderPipelineBase::RenderPipelineBase(DeviceBase* device, 346 const RenderPipelineDescriptor* descriptor, 347 bool blueprint) 348 : PipelineBase(device, 349 descriptor->layout, 350 dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment), 351 mVertexInput(*descriptor->vertexInput), 352 mHasDepthStencilAttachment(descriptor->depthStencilState != nullptr), 353 mPrimitiveTopology(descriptor->primitiveTopology), 354 mSampleCount(descriptor->sampleCount), 355 mSampleMask(descriptor->sampleMask), 356 mAlphaToCoverageEnabled(descriptor->alphaToCoverageEnabled), 357 mVertexModule(descriptor->vertexStage->module), 358 mVertexEntryPoint(descriptor->vertexStage->entryPoint), 359 mFragmentModule(descriptor->fragmentStage->module), 360 mFragmentEntryPoint(descriptor->fragmentStage->entryPoint), 361 mIsBlueprint(blueprint) { 362 for (uint32_t slot = 0; slot < mVertexInput.bufferCount; ++slot) { 363 if (mVertexInput.buffers[slot].attributeCount == 0) { 364 continue; 365 } 366 367 mInputsSetMask.set(slot); 368 mInputInfos[slot].stride = mVertexInput.buffers[slot].stride; 369 mInputInfos[slot].stepMode = mVertexInput.buffers[slot].stepMode; 370 371 uint32_t location = 0; 372 for (uint32_t i = 0; i < mVertexInput.buffers[slot].attributeCount; ++i) { 373 location = mVertexInput.buffers[slot].attributes[i].shaderLocation; 374 mAttributesSetMask.set(location); 375 mAttributeInfos[location].shaderLocation = location; 376 mAttributeInfos[location].inputSlot = slot; 377 mAttributeInfos[location].offset = mVertexInput.buffers[slot].attributes[i].offset; 378 mAttributeInfos[location].format = mVertexInput.buffers[slot].attributes[i].format; 379 } 380 } 381 382 if (descriptor->rasterizationState != nullptr) { 383 mRasterizationState = *descriptor->rasterizationState; 384 } else { 385 mRasterizationState = RasterizationStateDescriptor(); 386 } 387 388 if (mHasDepthStencilAttachment) { 389 mDepthStencilState = *descriptor->depthStencilState; 390 } else { 391 // These default values below are useful for backends to fill information. 392 // The values indicate that depth and stencil test are disabled when backends 393 // set their own depth stencil states/descriptors according to the values in 394 // mDepthStencilState. 395 mDepthStencilState.depthCompare = dawn::CompareFunction::Always; 396 mDepthStencilState.depthWriteEnabled = false; 397 mDepthStencilState.stencilBack.compare = dawn::CompareFunction::Always; 398 mDepthStencilState.stencilBack.failOp = dawn::StencilOperation::Keep; 399 mDepthStencilState.stencilBack.depthFailOp = dawn::StencilOperation::Keep; 400 mDepthStencilState.stencilBack.passOp = dawn::StencilOperation::Keep; 401 mDepthStencilState.stencilFront.compare = dawn::CompareFunction::Always; 402 mDepthStencilState.stencilFront.failOp = dawn::StencilOperation::Keep; 403 mDepthStencilState.stencilFront.depthFailOp = dawn::StencilOperation::Keep; 404 mDepthStencilState.stencilFront.passOp = dawn::StencilOperation::Keep; 405 mDepthStencilState.stencilReadMask = 0xff; 406 mDepthStencilState.stencilWriteMask = 0xff; 407 } 408 409 for (uint32_t i = 0; i < descriptor->colorStateCount; ++i) { 410 mColorAttachmentsSet.set(i); 411 mColorStates[i] = *descriptor->colorStates[i]; 412 } 413 414 // TODO(cwallez@chromium.org): Check against the shader module that the correct color 415 // attachment are set? 416 } 417 RenderPipelineBase(DeviceBase * device,ObjectBase::ErrorTag tag)418 RenderPipelineBase::RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag) 419 : PipelineBase(device, tag) { 420 } 421 422 // static MakeError(DeviceBase * device)423 RenderPipelineBase* RenderPipelineBase::MakeError(DeviceBase* device) { 424 return new RenderPipelineBase(device, ObjectBase::kError); 425 } 426 ~RenderPipelineBase()427 RenderPipelineBase::~RenderPipelineBase() { 428 // Do not uncache the actual cached object if we are a blueprint 429 if (!mIsBlueprint && !IsError()) { 430 GetDevice()->UncacheRenderPipeline(this); 431 } 432 } 433 GetVertexInputDescriptor() const434 const VertexInputDescriptor* RenderPipelineBase::GetVertexInputDescriptor() const { 435 ASSERT(!IsError()); 436 return &mVertexInput; 437 } 438 GetAttributesSetMask() const439 const std::bitset<kMaxVertexAttributes>& RenderPipelineBase::GetAttributesSetMask() const { 440 ASSERT(!IsError()); 441 return mAttributesSetMask; 442 } 443 GetAttribute(uint32_t location) const444 const VertexAttributeInfo& RenderPipelineBase::GetAttribute(uint32_t location) const { 445 ASSERT(!IsError()); 446 ASSERT(mAttributesSetMask[location]); 447 return mAttributeInfos[location]; 448 } 449 GetInputsSetMask() const450 const std::bitset<kMaxVertexBuffers>& RenderPipelineBase::GetInputsSetMask() const { 451 ASSERT(!IsError()); 452 return mInputsSetMask; 453 } 454 GetInput(uint32_t slot) const455 const VertexBufferInfo& RenderPipelineBase::GetInput(uint32_t slot) const { 456 ASSERT(!IsError()); 457 ASSERT(mInputsSetMask[slot]); 458 return mInputInfos[slot]; 459 } 460 GetColorStateDescriptor(uint32_t attachmentSlot) const461 const ColorStateDescriptor* RenderPipelineBase::GetColorStateDescriptor( 462 uint32_t attachmentSlot) const { 463 ASSERT(!IsError()); 464 ASSERT(attachmentSlot < mColorStates.size()); 465 return &mColorStates[attachmentSlot]; 466 } 467 GetDepthStencilStateDescriptor() const468 const DepthStencilStateDescriptor* RenderPipelineBase::GetDepthStencilStateDescriptor() const { 469 ASSERT(!IsError()); 470 return &mDepthStencilState; 471 } 472 GetPrimitiveTopology() const473 dawn::PrimitiveTopology RenderPipelineBase::GetPrimitiveTopology() const { 474 ASSERT(!IsError()); 475 return mPrimitiveTopology; 476 } 477 GetCullMode() const478 dawn::CullMode RenderPipelineBase::GetCullMode() const { 479 ASSERT(!IsError()); 480 return mRasterizationState.cullMode; 481 } 482 GetFrontFace() const483 dawn::FrontFace RenderPipelineBase::GetFrontFace() const { 484 ASSERT(!IsError()); 485 return mRasterizationState.frontFace; 486 } 487 GetColorAttachmentsMask() const488 std::bitset<kMaxColorAttachments> RenderPipelineBase::GetColorAttachmentsMask() const { 489 ASSERT(!IsError()); 490 return mColorAttachmentsSet; 491 } 492 HasDepthStencilAttachment() const493 bool RenderPipelineBase::HasDepthStencilAttachment() const { 494 ASSERT(!IsError()); 495 return mHasDepthStencilAttachment; 496 } 497 GetColorAttachmentFormat(uint32_t attachment) const498 dawn::TextureFormat RenderPipelineBase::GetColorAttachmentFormat(uint32_t attachment) const { 499 ASSERT(!IsError()); 500 return mColorStates[attachment].format; 501 } 502 GetDepthStencilFormat() const503 dawn::TextureFormat RenderPipelineBase::GetDepthStencilFormat() const { 504 ASSERT(!IsError()); 505 ASSERT(mHasDepthStencilAttachment); 506 return mDepthStencilState.format; 507 } 508 GetSampleCount() const509 uint32_t RenderPipelineBase::GetSampleCount() const { 510 ASSERT(!IsError()); 511 return mSampleCount; 512 } 513 ValidateCompatibleWith(const BeginRenderPassCmd * renderPass) const514 MaybeError RenderPipelineBase::ValidateCompatibleWith( 515 const BeginRenderPassCmd* renderPass) const { 516 ASSERT(!IsError()); 517 // TODO(cwallez@chromium.org): This is called on every SetPipeline command. Optimize it for 518 // example by caching some "attachment compatibility" object that would make the 519 // compatibility check a single pointer comparison. 520 521 if (renderPass->colorAttachmentsSet != mColorAttachmentsSet) { 522 return DAWN_VALIDATION_ERROR( 523 "Pipeline doesn't have same color attachments set as renderPass"); 524 } 525 526 for (uint32_t i : IterateBitSet(mColorAttachmentsSet)) { 527 if (renderPass->colorAttachments[i].view->GetFormat().format != 528 mColorStates[i].format) { 529 return DAWN_VALIDATION_ERROR( 530 "Pipeline color attachment format doesn't match renderPass"); 531 } 532 } 533 534 if (renderPass->hasDepthStencilAttachment != mHasDepthStencilAttachment) { 535 return DAWN_VALIDATION_ERROR( 536 "Pipeline depth stencil attachment doesn't match renderPass"); 537 } 538 539 if (mHasDepthStencilAttachment && 540 (renderPass->depthStencilAttachment.view->GetFormat().format != 541 mDepthStencilState.format)) { 542 return DAWN_VALIDATION_ERROR( 543 "Pipeline depth stencil attachment format doesn't match renderPass"); 544 } 545 546 if (renderPass->sampleCount != mSampleCount) { 547 return DAWN_VALIDATION_ERROR("Pipeline sample count doesn't match renderPass"); 548 } 549 550 return {}; 551 } 552 GetAttributesUsingInput(uint32_t slot) const553 std::bitset<kMaxVertexAttributes> RenderPipelineBase::GetAttributesUsingInput( 554 uint32_t slot) const { 555 ASSERT(!IsError()); 556 return attributesUsingInput[slot]; 557 } 558 operator ()(const RenderPipelineBase * pipeline) const559 size_t RenderPipelineBase::HashFunc::operator()(const RenderPipelineBase* pipeline) const { 560 size_t hash = 0; 561 562 // Hash modules and layout 563 HashCombine(&hash, pipeline->GetLayout()); 564 HashCombine(&hash, pipeline->mVertexModule.Get(), pipeline->mFragmentEntryPoint); 565 HashCombine(&hash, pipeline->mFragmentModule.Get(), pipeline->mFragmentEntryPoint); 566 567 // Hash attachments 568 HashCombine(&hash, pipeline->mColorAttachmentsSet); 569 for (uint32_t i : IterateBitSet(pipeline->mColorAttachmentsSet)) { 570 const ColorStateDescriptor& desc = *pipeline->GetColorStateDescriptor(i); 571 HashCombine(&hash, desc.format, desc.writeMask); 572 HashCombine(&hash, desc.colorBlend.operation, desc.colorBlend.srcFactor, 573 desc.colorBlend.dstFactor); 574 HashCombine(&hash, desc.alphaBlend.operation, desc.alphaBlend.srcFactor, 575 desc.alphaBlend.dstFactor); 576 } 577 578 if (pipeline->mHasDepthStencilAttachment) { 579 const DepthStencilStateDescriptor& desc = pipeline->mDepthStencilState; 580 HashCombine(&hash, desc.format, desc.depthWriteEnabled, desc.depthCompare); 581 HashCombine(&hash, desc.stencilReadMask, desc.stencilWriteMask); 582 HashCombine(&hash, desc.stencilFront.compare, desc.stencilFront.failOp, 583 desc.stencilFront.depthFailOp, desc.stencilFront.passOp); 584 HashCombine(&hash, desc.stencilBack.compare, desc.stencilBack.failOp, 585 desc.stencilBack.depthFailOp, desc.stencilBack.passOp); 586 } 587 588 // Hash vertex input state 589 HashCombine(&hash, pipeline->mAttributesSetMask); 590 for (uint32_t i : IterateBitSet(pipeline->mAttributesSetMask)) { 591 const VertexAttributeInfo& desc = pipeline->GetAttribute(i); 592 HashCombine(&hash, desc.shaderLocation, desc.inputSlot, desc.offset, desc.format); 593 } 594 595 HashCombine(&hash, pipeline->mInputsSetMask); 596 for (uint32_t i : IterateBitSet(pipeline->mInputsSetMask)) { 597 const VertexBufferInfo& desc = pipeline->GetInput(i); 598 HashCombine(&hash, desc.stride, desc.stepMode); 599 } 600 601 HashCombine(&hash, pipeline->mVertexInput.indexFormat); 602 603 // Hash rasterization state 604 { 605 const RasterizationStateDescriptor& desc = pipeline->mRasterizationState; 606 HashCombine(&hash, desc.frontFace, desc.cullMode); 607 HashCombine(&hash, desc.depthBias, desc.depthBiasSlopeScale, desc.depthBiasClamp); 608 } 609 610 // Hash other state 611 HashCombine(&hash, pipeline->mSampleCount, pipeline->mPrimitiveTopology, 612 pipeline->mSampleMask, pipeline->mAlphaToCoverageEnabled); 613 614 return hash; 615 } 616 operator ()(const RenderPipelineBase * a,const RenderPipelineBase * b) const617 bool RenderPipelineBase::EqualityFunc::operator()(const RenderPipelineBase* a, 618 const RenderPipelineBase* b) const { 619 // Check modules and layout 620 if (a->GetLayout() != b->GetLayout() || a->mVertexModule.Get() != b->mVertexModule.Get() || 621 a->mVertexEntryPoint != b->mVertexEntryPoint || 622 a->mFragmentModule.Get() != b->mFragmentModule.Get() || 623 a->mFragmentEntryPoint != b->mFragmentEntryPoint) { 624 return false; 625 } 626 627 // Check attachments 628 if (a->mColorAttachmentsSet != b->mColorAttachmentsSet || 629 a->mHasDepthStencilAttachment != b->mHasDepthStencilAttachment) { 630 return false; 631 } 632 633 for (uint32_t i : IterateBitSet(a->mColorAttachmentsSet)) { 634 const ColorStateDescriptor& descA = *a->GetColorStateDescriptor(i); 635 const ColorStateDescriptor& descB = *b->GetColorStateDescriptor(i); 636 if (descA.format != descB.format || descA.writeMask != descB.writeMask) { 637 return false; 638 } 639 if (descA.colorBlend.operation != descB.colorBlend.operation || 640 descA.colorBlend.srcFactor != descB.colorBlend.srcFactor || 641 descA.colorBlend.dstFactor != descB.colorBlend.dstFactor) { 642 return false; 643 } 644 if (descA.alphaBlend.operation != descB.alphaBlend.operation || 645 descA.alphaBlend.srcFactor != descB.alphaBlend.srcFactor || 646 descA.alphaBlend.dstFactor != descB.alphaBlend.dstFactor) { 647 return false; 648 } 649 } 650 651 if (a->mHasDepthStencilAttachment) { 652 const DepthStencilStateDescriptor& descA = a->mDepthStencilState; 653 const DepthStencilStateDescriptor& descB = b->mDepthStencilState; 654 if (descA.format != descB.format || 655 descA.depthWriteEnabled != descB.depthWriteEnabled || 656 descA.depthCompare != descB.depthCompare) { 657 return false; 658 } 659 if (descA.stencilReadMask != descB.stencilReadMask || 660 descA.stencilWriteMask != descB.stencilWriteMask) { 661 return false; 662 } 663 if (descA.stencilFront.compare != descB.stencilFront.compare || 664 descA.stencilFront.failOp != descB.stencilFront.failOp || 665 descA.stencilFront.depthFailOp != descB.stencilFront.depthFailOp || 666 descA.stencilFront.passOp != descB.stencilFront.passOp) { 667 return false; 668 } 669 if (descA.stencilBack.compare != descB.stencilBack.compare || 670 descA.stencilBack.failOp != descB.stencilBack.failOp || 671 descA.stencilBack.depthFailOp != descB.stencilBack.depthFailOp || 672 descA.stencilBack.passOp != descB.stencilBack.passOp) { 673 return false; 674 } 675 } 676 677 // Check vertex input state 678 if (a->mAttributesSetMask != b->mAttributesSetMask) { 679 return false; 680 } 681 682 for (uint32_t i : IterateBitSet(a->mAttributesSetMask)) { 683 const VertexAttributeInfo& descA = a->GetAttribute(i); 684 const VertexAttributeInfo& descB = b->GetAttribute(i); 685 if (descA.shaderLocation != descB.shaderLocation || 686 descA.inputSlot != descB.inputSlot || descA.offset != descB.offset || 687 descA.format != descB.format) { 688 return false; 689 } 690 } 691 692 if (a->mInputsSetMask != b->mInputsSetMask) { 693 return false; 694 } 695 696 for (uint32_t i : IterateBitSet(a->mInputsSetMask)) { 697 const VertexBufferInfo& descA = a->GetInput(i); 698 const VertexBufferInfo& descB = b->GetInput(i); 699 if (descA.stride != descB.stride || descA.stepMode != descB.stepMode) { 700 return false; 701 } 702 } 703 704 if (a->mVertexInput.indexFormat != b->mVertexInput.indexFormat) { 705 return false; 706 } 707 708 // Check rasterization state 709 { 710 const RasterizationStateDescriptor& descA = a->mRasterizationState; 711 const RasterizationStateDescriptor& descB = b->mRasterizationState; 712 if (descA.frontFace != descB.frontFace || descA.cullMode != descB.cullMode) { 713 return false; 714 } 715 if (descA.depthBias != descB.depthBias || 716 descA.depthBiasSlopeScale != descB.depthBiasSlopeScale || 717 descA.depthBiasClamp != descB.depthBiasClamp) { 718 return false; 719 } 720 } 721 722 // Check other state 723 if (a->mSampleCount != b->mSampleCount || a->mPrimitiveTopology != b->mPrimitiveTopology || 724 a->mSampleMask != b->mSampleMask || 725 a->mAlphaToCoverageEnabled != b->mAlphaToCoverageEnabled) { 726 return false; 727 } 728 729 return true; 730 } 731 732 } // namespace dawn_native 733