• 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/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