diff --git a/src/dawn_native/CommandBufferStateTracker.cpp b/src/dawn_native/CommandBufferStateTracker.cpp index 00c8fd0483..7b6d367078 100644 --- a/src/dawn_native/CommandBufferStateTracker.cpp +++ b/src/dawn_native/CommandBufferStateTracker.cpp @@ -127,10 +127,8 @@ namespace dawn_native { } if (aspects[VALIDATION_ASPECT_INDEX_BUFFER] && mIndexBufferSet) { - wgpu::IndexFormat pipelineIndexFormat = - mLastRenderPipeline->GetVertexStateDescriptor()->indexFormat; if (!IsStripPrimitiveTopology(mLastRenderPipeline->GetPrimitiveTopology()) || - mIndexFormat == pipelineIndexFormat) { + mIndexFormat == mLastRenderPipeline->GetStripIndexFormat()) { mAspects.set(VALIDATION_ASPECT_INDEX_BUFFER); } } @@ -142,8 +140,7 @@ namespace dawn_native { } if (aspects[VALIDATION_ASPECT_INDEX_BUFFER]) { - wgpu::IndexFormat pipelineIndexFormat = - mLastRenderPipeline->GetVertexStateDescriptor()->indexFormat; + wgpu::IndexFormat pipelineIndexFormat = mLastRenderPipeline->GetStripIndexFormat(); if (!mIndexBufferSet) { return DAWN_VALIDATION_ERROR("Missing index buffer"); } else if (IsStripPrimitiveTopology(mLastRenderPipeline->GetPrimitiveTopology()) && diff --git a/src/dawn_native/RenderPipeline.cpp b/src/dawn_native/RenderPipeline.cpp index 6cfaccf4c4..2e41888c48 100644 --- a/src/dawn_native/RenderPipeline.cpp +++ b/src/dawn_native/RenderPipeline.cpp @@ -302,15 +302,15 @@ namespace dawn_native { return {}; } - bool StencilTestEnabled(const DepthStencilStateDescriptor* mDepthStencilState) { - return mDepthStencilState->stencilBack.compare != wgpu::CompareFunction::Always || - mDepthStencilState->stencilBack.failOp != wgpu::StencilOperation::Keep || - mDepthStencilState->stencilBack.depthFailOp != wgpu::StencilOperation::Keep || - mDepthStencilState->stencilBack.passOp != wgpu::StencilOperation::Keep || - mDepthStencilState->stencilFront.compare != wgpu::CompareFunction::Always || - mDepthStencilState->stencilFront.failOp != wgpu::StencilOperation::Keep || - mDepthStencilState->stencilFront.depthFailOp != wgpu::StencilOperation::Keep || - mDepthStencilState->stencilFront.passOp != wgpu::StencilOperation::Keep; + bool StencilTestEnabled(const DepthStencilState* mDepthStencil) { + return mDepthStencil->stencilBack.compare != wgpu::CompareFunction::Always || + mDepthStencil->stencilBack.failOp != wgpu::StencilOperation::Keep || + mDepthStencil->stencilBack.depthFailOp != wgpu::StencilOperation::Keep || + mDepthStencil->stencilBack.passOp != wgpu::StencilOperation::Keep || + mDepthStencil->stencilFront.compare != wgpu::CompareFunction::Always || + mDepthStencil->stencilFront.failOp != wgpu::StencilOperation::Keep || + mDepthStencil->stencilFront.depthFailOp != wgpu::StencilOperation::Keep || + mDepthStencil->stencilFront.passOp != wgpu::StencilOperation::Keep; } bool BlendEnabled(const ColorStateDescriptor* mColorState) { @@ -330,71 +330,104 @@ namespace dawn_native { descriptor->layout, {{SingleShaderStage::Vertex, &descriptor->vertexStage}, {SingleShaderStage::Fragment, descriptor->fragmentStage}}), - mAttachmentState(device->GetOrCreateAttachmentState(descriptor)), - mPrimitiveTopology(descriptor->primitiveTopology), - mSampleMask(descriptor->sampleMask), - mAlphaToCoverageEnabled(descriptor->alphaToCoverageEnabled) { + mAttachmentState(device->GetOrCreateAttachmentState(descriptor)) { + mPrimitive.topology = descriptor->primitiveTopology; + + mMultisample.count = descriptor->sampleCount; + mMultisample.mask = descriptor->sampleMask; + mMultisample.alphaToCoverageEnabled = descriptor->alphaToCoverageEnabled; + if (descriptor->vertexState != nullptr) { - mVertexState = *descriptor->vertexState; - } else { - mVertexState = VertexStateDescriptor(); - } + const VertexStateDescriptor& vertexState = *descriptor->vertexState; + mVertexBufferCount = vertexState.vertexBufferCount; + mPrimitive.stripIndexFormat = vertexState.indexFormat; - for (uint8_t slot = 0; slot < mVertexState.vertexBufferCount; ++slot) { - if (mVertexState.vertexBuffers[slot].attributeCount == 0) { - continue; + for (uint8_t slot = 0; slot < mVertexBufferCount; ++slot) { + if (vertexState.vertexBuffers[slot].attributeCount == 0) { + continue; + } + + VertexBufferSlot typedSlot(slot); + + mVertexBufferSlotsUsed.set(typedSlot); + mVertexBufferInfos[typedSlot].arrayStride = + vertexState.vertexBuffers[slot].arrayStride; + mVertexBufferInfos[typedSlot].stepMode = vertexState.vertexBuffers[slot].stepMode; + + for (uint32_t i = 0; i < vertexState.vertexBuffers[slot].attributeCount; ++i) { + VertexAttributeLocation location = VertexAttributeLocation(static_cast( + vertexState.vertexBuffers[slot].attributes[i].shaderLocation)); + mAttributeLocationsUsed.set(location); + mAttributeInfos[location].shaderLocation = location; + mAttributeInfos[location].vertexBufferSlot = typedSlot; + mAttributeInfos[location].offset = + vertexState.vertexBuffers[slot].attributes[i].offset; + + mAttributeInfos[location].format = dawn::NormalizeVertexFormat( + vertexState.vertexBuffers[slot].attributes[i].format); + } } - - VertexBufferSlot typedSlot(slot); - - mVertexBufferSlotsUsed.set(typedSlot); - mVertexBufferInfos[typedSlot].arrayStride = - mVertexState.vertexBuffers[slot].arrayStride; - mVertexBufferInfos[typedSlot].stepMode = mVertexState.vertexBuffers[slot].stepMode; - - for (uint32_t i = 0; i < mVertexState.vertexBuffers[slot].attributeCount; ++i) { - VertexAttributeLocation location = VertexAttributeLocation(static_cast( - mVertexState.vertexBuffers[slot].attributes[i].shaderLocation)); - mAttributeLocationsUsed.set(location); - mAttributeInfos[location].shaderLocation = location; - mAttributeInfos[location].vertexBufferSlot = typedSlot; - mAttributeInfos[location].offset = - mVertexState.vertexBuffers[slot].attributes[i].offset; - - mAttributeInfos[location].format = dawn::NormalizeVertexFormat( - mVertexState.vertexBuffers[slot].attributes[i].format); - } - } - - if (descriptor->rasterizationState != nullptr) { - mRasterizationState = *descriptor->rasterizationState; } else { - mRasterizationState = RasterizationStateDescriptor(); + mVertexBufferCount = 0; + mPrimitive.stripIndexFormat = wgpu::IndexFormat::Undefined; } if (mAttachmentState->HasDepthStencilAttachment()) { - mDepthStencilState = *descriptor->depthStencilState; + const DepthStencilStateDescriptor& depthStencil = *descriptor->depthStencilState; + mDepthStencil.format = depthStencil.format; + mDepthStencil.depthWriteEnabled = depthStencil.depthWriteEnabled; + mDepthStencil.depthCompare = depthStencil.depthCompare; + mDepthStencil.stencilBack = depthStencil.stencilBack; + mDepthStencil.stencilFront = depthStencil.stencilFront; + mDepthStencil.stencilReadMask = depthStencil.stencilReadMask; + mDepthStencil.stencilWriteMask = depthStencil.stencilWriteMask; } else { // These default values below are useful for backends to fill information. // The values indicate that depth and stencil test are disabled when backends // set their own depth stencil states/descriptors according to the values in - // mDepthStencilState. - mDepthStencilState.depthCompare = wgpu::CompareFunction::Always; - mDepthStencilState.depthWriteEnabled = false; - mDepthStencilState.stencilBack.compare = wgpu::CompareFunction::Always; - mDepthStencilState.stencilBack.failOp = wgpu::StencilOperation::Keep; - mDepthStencilState.stencilBack.depthFailOp = wgpu::StencilOperation::Keep; - mDepthStencilState.stencilBack.passOp = wgpu::StencilOperation::Keep; - mDepthStencilState.stencilFront.compare = wgpu::CompareFunction::Always; - mDepthStencilState.stencilFront.failOp = wgpu::StencilOperation::Keep; - mDepthStencilState.stencilFront.depthFailOp = wgpu::StencilOperation::Keep; - mDepthStencilState.stencilFront.passOp = wgpu::StencilOperation::Keep; - mDepthStencilState.stencilReadMask = 0xff; - mDepthStencilState.stencilWriteMask = 0xff; + // mDepthStencil. + mDepthStencil.format = wgpu::TextureFormat::Undefined; + mDepthStencil.depthWriteEnabled = false; + mDepthStencil.depthCompare = wgpu::CompareFunction::Always; + mDepthStencil.stencilBack.compare = wgpu::CompareFunction::Always; + mDepthStencil.stencilBack.failOp = wgpu::StencilOperation::Keep; + mDepthStencil.stencilBack.depthFailOp = wgpu::StencilOperation::Keep; + mDepthStencil.stencilBack.passOp = wgpu::StencilOperation::Keep; + mDepthStencil.stencilFront.compare = wgpu::CompareFunction::Always; + mDepthStencil.stencilFront.failOp = wgpu::StencilOperation::Keep; + mDepthStencil.stencilFront.depthFailOp = wgpu::StencilOperation::Keep; + mDepthStencil.stencilFront.passOp = wgpu::StencilOperation::Keep; + mDepthStencil.stencilReadMask = 0xff; + mDepthStencil.stencilWriteMask = 0xff; + } + + if (descriptor->rasterizationState != nullptr) { + mPrimitive.frontFace = descriptor->rasterizationState->frontFace; + mPrimitive.cullMode = descriptor->rasterizationState->cullMode; + mDepthStencil.depthBias = descriptor->rasterizationState->depthBias; + mDepthStencil.depthBiasSlopeScale = descriptor->rasterizationState->depthBiasSlopeScale; + mDepthStencil.depthBiasClamp = descriptor->rasterizationState->depthBiasClamp; + } else { + mPrimitive.frontFace = wgpu::FrontFace::CCW; + mPrimitive.cullMode = wgpu::CullMode::None; + mDepthStencil.depthBias = 0; + mDepthStencil.depthBiasSlopeScale = 0.0f; + mDepthStencil.depthBiasClamp = 0.0f; } for (ColorAttachmentIndex i : IterateBitSet(mAttachmentState->GetColorAttachmentsMask())) { - mColorStates[i] = descriptor->colorStates[static_cast(i)]; + const ColorStateDescriptor* colorState = + &descriptor->colorStates[static_cast(i)]; + mTargets[i].format = colorState->format; + mTargets[i].writeMask = colorState->writeMask; + + if (BlendEnabled(colorState)) { + mTargetBlend[i].color = colorState->colorBlend; + mTargetBlend[i].alpha = colorState->alphaBlend; + mTargets[i].blend = &mTargetBlend[i]; + } else { + mTargets[i].blend = nullptr; + } } // TODO(cwallez@chromium.org): Check against the shader module that the correct color @@ -416,11 +449,6 @@ namespace dawn_native { } } - const VertexStateDescriptor* RenderPipelineBase::GetVertexStateDescriptor() const { - ASSERT(!IsError()); - return &mVertexState; - } - const ityp::bitset& RenderPipelineBase::GetAttributeLocationsUsed() const { ASSERT(!IsError()); @@ -446,51 +474,61 @@ namespace dawn_native { return mVertexBufferInfos[slot]; } - const ColorStateDescriptor* RenderPipelineBase::GetColorStateDescriptor( - ColorAttachmentIndex attachmentSlot) const { + uint32_t RenderPipelineBase::GetVertexBufferCount() const { ASSERT(!IsError()); - ASSERT(attachmentSlot < mColorStates.size()); - return &mColorStates[attachmentSlot]; + return mVertexBufferCount; } - const DepthStencilStateDescriptor* RenderPipelineBase::GetDepthStencilStateDescriptor() const { + const ColorTargetState* RenderPipelineBase::GetColorTargetState( + ColorAttachmentIndex attachmentSlot) const { ASSERT(!IsError()); - return &mDepthStencilState; + ASSERT(attachmentSlot < mTargets.size()); + return &mTargets[attachmentSlot]; + } + + const DepthStencilState* RenderPipelineBase::GetDepthStencilState() const { + ASSERT(!IsError()); + return &mDepthStencil; } wgpu::PrimitiveTopology RenderPipelineBase::GetPrimitiveTopology() const { ASSERT(!IsError()); - return mPrimitiveTopology; + return mPrimitive.topology; + } + + wgpu::IndexFormat RenderPipelineBase::GetStripIndexFormat() const { + ASSERT(!IsError()); + return mPrimitive.stripIndexFormat; } wgpu::CullMode RenderPipelineBase::GetCullMode() const { ASSERT(!IsError()); - return mRasterizationState.cullMode; + return mPrimitive.cullMode; } wgpu::FrontFace RenderPipelineBase::GetFrontFace() const { ASSERT(!IsError()); - return mRasterizationState.frontFace; + return mPrimitive.frontFace; } bool RenderPipelineBase::IsDepthBiasEnabled() const { ASSERT(!IsError()); - return mRasterizationState.depthBias != 0 || mRasterizationState.depthBiasSlopeScale != 0; + return mDepthStencil.depthBias != 0 || mDepthStencil.depthBiasSlopeScale != 0; } int32_t RenderPipelineBase::GetDepthBias() const { ASSERT(!IsError()); - return mRasterizationState.depthBias; + return mDepthStencil.depthBias; } float RenderPipelineBase::GetDepthBiasSlopeScale() const { ASSERT(!IsError()); - return mRasterizationState.depthBiasSlopeScale; + return mDepthStencil.depthBiasSlopeScale; } float RenderPipelineBase::GetDepthBiasClamp() const { ASSERT(!IsError()); - return mRasterizationState.depthBiasClamp; + return mDepthStencil.depthBiasClamp; } ityp::bitset @@ -507,13 +545,13 @@ namespace dawn_native { wgpu::TextureFormat RenderPipelineBase::GetColorAttachmentFormat( ColorAttachmentIndex attachment) const { ASSERT(!IsError()); - return mColorStates[attachment].format; + return mTargets[attachment].format; } wgpu::TextureFormat RenderPipelineBase::GetDepthStencilFormat() const { ASSERT(!IsError()); ASSERT(mAttachmentState->HasDepthStencilAttachment()); - return mDepthStencilState.format; + return mDepthStencil.format; } uint32_t RenderPipelineBase::GetSampleCount() const { @@ -523,12 +561,12 @@ namespace dawn_native { uint32_t RenderPipelineBase::GetSampleMask() const { ASSERT(!IsError()); - return mSampleMask; + return mMultisample.mask; } bool RenderPipelineBase::IsAlphaToCoverageEnabled() const { ASSERT(!IsError()); - return mAlphaToCoverageEnabled; + return mMultisample.alphaToCoverageEnabled; } const AttachmentState* RenderPipelineBase::GetAttachmentState() const { @@ -549,22 +587,25 @@ namespace dawn_native { // Record attachments for (ColorAttachmentIndex i : IterateBitSet(mAttachmentState->GetColorAttachmentsMask())) { - const ColorStateDescriptor& desc = *GetColorStateDescriptor(i); + const ColorTargetState& desc = *GetColorTargetState(i); recorder.Record(desc.writeMask); - recorder.Record(desc.colorBlend.operation, desc.colorBlend.srcFactor, - desc.colorBlend.dstFactor); - recorder.Record(desc.alphaBlend.operation, desc.alphaBlend.srcFactor, - desc.alphaBlend.dstFactor); + if (desc.blend != nullptr) { + recorder.Record(desc.blend->color.operation, desc.blend->color.srcFactor, + desc.blend->color.dstFactor); + recorder.Record(desc.blend->alpha.operation, desc.blend->alpha.srcFactor, + desc.blend->alpha.dstFactor); + } } if (mAttachmentState->HasDepthStencilAttachment()) { - const DepthStencilStateDescriptor& desc = mDepthStencilState; + const DepthStencilState& desc = mDepthStencil; recorder.Record(desc.depthWriteEnabled, desc.depthCompare); recorder.Record(desc.stencilReadMask, desc.stencilWriteMask); recorder.Record(desc.stencilFront.compare, desc.stencilFront.failOp, desc.stencilFront.depthFailOp, desc.stencilFront.passOp); recorder.Record(desc.stencilBack.compare, desc.stencilBack.failOp, desc.stencilBack.depthFailOp, desc.stencilBack.passOp); + recorder.Record(desc.depthBias, desc.depthBiasSlopeScale, desc.depthBiasClamp); } // Record vertex state @@ -580,17 +621,13 @@ namespace dawn_native { recorder.Record(desc.arrayStride, desc.stepMode); } - recorder.Record(mVertexState.indexFormat); + // Record primitive state + recorder.Record(mPrimitive.topology, mPrimitive.stripIndexFormat, mPrimitive.frontFace, + mPrimitive.cullMode); - // Record rasterization state - { - const RasterizationStateDescriptor& desc = mRasterizationState; - recorder.Record(desc.frontFace, desc.cullMode); - recorder.Record(desc.depthBias, desc.depthBiasSlopeScale, desc.depthBiasClamp); - } - - // Record other state - recorder.Record(mPrimitiveTopology, mSampleMask, mAlphaToCoverageEnabled); + // Record multisample state + // Sample count hashed as part of the attachment state + recorder.Record(mMultisample.mask, mMultisample.alphaToCoverageEnabled); return recorder.GetContentHash(); } @@ -610,44 +647,59 @@ namespace dawn_native { for (ColorAttachmentIndex i : IterateBitSet(a->mAttachmentState->GetColorAttachmentsMask())) { - const ColorStateDescriptor& descA = *a->GetColorStateDescriptor(i); - const ColorStateDescriptor& descB = *b->GetColorStateDescriptor(i); + const ColorTargetState& descA = *a->GetColorTargetState(i); + const ColorTargetState& descB = *b->GetColorTargetState(i); if (descA.writeMask != descB.writeMask) { return false; } - if (descA.colorBlend.operation != descB.colorBlend.operation || - descA.colorBlend.srcFactor != descB.colorBlend.srcFactor || - descA.colorBlend.dstFactor != descB.colorBlend.dstFactor) { + if ((descA.blend == nullptr) != (descB.blend == nullptr)) { return false; } - if (descA.alphaBlend.operation != descB.alphaBlend.operation || - descA.alphaBlend.srcFactor != descB.alphaBlend.srcFactor || - descA.alphaBlend.dstFactor != descB.alphaBlend.dstFactor) { - return false; + if (descA.blend != nullptr) { + if (descA.blend->color.operation != descB.blend->color.operation || + descA.blend->color.srcFactor != descB.blend->color.srcFactor || + descA.blend->color.dstFactor != descB.blend->color.dstFactor) { + return false; + } + if (descA.blend->alpha.operation != descB.blend->alpha.operation || + descA.blend->alpha.srcFactor != descB.blend->alpha.srcFactor || + descA.blend->alpha.dstFactor != descB.blend->alpha.dstFactor) { + return false; + } } } + // Check depth/stencil state if (a->mAttachmentState->HasDepthStencilAttachment()) { - const DepthStencilStateDescriptor& descA = a->mDepthStencilState; - const DepthStencilStateDescriptor& descB = b->mDepthStencilState; - if (descA.depthWriteEnabled != descB.depthWriteEnabled || - descA.depthCompare != descB.depthCompare) { + const DepthStencilState& stateA = a->mDepthStencil; + const DepthStencilState& stateB = b->mDepthStencil; + + ASSERT(!std::isnan(stateA.depthBiasSlopeScale)); + ASSERT(!std::isnan(stateB.depthBiasSlopeScale)); + ASSERT(!std::isnan(stateA.depthBiasClamp)); + ASSERT(!std::isnan(stateB.depthBiasClamp)); + + if (stateA.depthWriteEnabled != stateB.depthWriteEnabled || + stateA.depthCompare != stateB.depthCompare || + stateA.depthBias != stateB.depthBias || + stateA.depthBiasSlopeScale != stateB.depthBiasSlopeScale || + stateA.depthBiasClamp != stateB.depthBiasClamp) { return false; } - if (descA.stencilReadMask != descB.stencilReadMask || - descA.stencilWriteMask != descB.stencilWriteMask) { + if (stateA.stencilFront.compare != stateB.stencilFront.compare || + stateA.stencilFront.failOp != stateB.stencilFront.failOp || + stateA.stencilFront.depthFailOp != stateB.stencilFront.depthFailOp || + stateA.stencilFront.passOp != stateB.stencilFront.passOp) { return false; } - if (descA.stencilFront.compare != descB.stencilFront.compare || - descA.stencilFront.failOp != descB.stencilFront.failOp || - descA.stencilFront.depthFailOp != descB.stencilFront.depthFailOp || - descA.stencilFront.passOp != descB.stencilFront.passOp) { + if (stateA.stencilBack.compare != stateB.stencilBack.compare || + stateA.stencilBack.failOp != stateB.stencilBack.failOp || + stateA.stencilBack.depthFailOp != stateB.stencilBack.depthFailOp || + stateA.stencilBack.passOp != stateB.stencilBack.passOp) { return false; } - if (descA.stencilBack.compare != descB.stencilBack.compare || - descA.stencilBack.failOp != descB.stencilBack.failOp || - descA.stencilBack.depthFailOp != descB.stencilBack.depthFailOp || - descA.stencilBack.passOp != descB.stencilBack.passOp) { + if (stateA.stencilReadMask != stateB.stencilReadMask || + stateA.stencilWriteMask != stateB.stencilWriteMask) { return false; } } @@ -679,34 +731,26 @@ namespace dawn_native { } } - if (a->mVertexState.indexFormat != b->mVertexState.indexFormat) { - return false; - } - - // Check rasterization state + // Check primitive state { - const RasterizationStateDescriptor& descA = a->mRasterizationState; - const RasterizationStateDescriptor& descB = b->mRasterizationState; - if (descA.frontFace != descB.frontFace || descA.cullMode != descB.cullMode) { - return false; - } - - ASSERT(!std::isnan(descA.depthBiasSlopeScale)); - ASSERT(!std::isnan(descB.depthBiasSlopeScale)); - ASSERT(!std::isnan(descA.depthBiasClamp)); - ASSERT(!std::isnan(descB.depthBiasClamp)); - - if (descA.depthBias != descB.depthBias || - descA.depthBiasSlopeScale != descB.depthBiasSlopeScale || - descA.depthBiasClamp != descB.depthBiasClamp) { + const PrimitiveState& stateA = a->mPrimitive; + const PrimitiveState& stateB = b->mPrimitive; + if (stateA.topology != stateB.topology || + stateA.stripIndexFormat != stateB.stripIndexFormat || + stateA.frontFace != stateB.frontFace || stateA.cullMode != stateB.cullMode) { return false; } } - // Check other state - if (a->mPrimitiveTopology != b->mPrimitiveTopology || a->mSampleMask != b->mSampleMask || - a->mAlphaToCoverageEnabled != b->mAlphaToCoverageEnabled) { - return false; + // Check multisample state + { + const MultisampleState& stateA = a->mMultisample; + const MultisampleState& stateB = b->mMultisample; + // Sample count already checked as part of the attachment state. + if (stateA.mask != stateB.mask || + stateA.alphaToCoverageEnabled != stateB.alphaToCoverageEnabled) { + return false; + } } return true; diff --git a/src/dawn_native/RenderPipeline.h b/src/dawn_native/RenderPipeline.h index 7d24b3f0db..5259620aed 100644 --- a/src/dawn_native/RenderPipeline.h +++ b/src/dawn_native/RenderPipeline.h @@ -35,8 +35,7 @@ namespace dawn_native { bool IsStripPrimitiveTopology(wgpu::PrimitiveTopology primitiveTopology); - bool StencilTestEnabled(const DepthStencilStateDescriptor* mDepthStencilState); - bool BlendEnabled(const ColorStateDescriptor* mColorState); + bool StencilTestEnabled(const DepthStencilState* mDepthStencil); struct VertexAttributeInfo { wgpu::VertexFormat format; @@ -57,17 +56,17 @@ namespace dawn_native { static RenderPipelineBase* MakeError(DeviceBase* device); - const VertexStateDescriptor* GetVertexStateDescriptor() const; const ityp::bitset& GetAttributeLocationsUsed() const; const VertexAttributeInfo& GetAttribute(VertexAttributeLocation location) const; const ityp::bitset& GetVertexBufferSlotsUsed() const; const VertexBufferInfo& GetVertexBuffer(VertexBufferSlot slot) const; + uint32_t GetVertexBufferCount() const; - const ColorStateDescriptor* GetColorStateDescriptor( - ColorAttachmentIndex attachmentSlot) const; - const DepthStencilStateDescriptor* GetDepthStencilStateDescriptor() const; + const ColorTargetState* GetColorTargetState(ColorAttachmentIndex attachmentSlot) const; + const DepthStencilState* GetDepthStencilState() const; wgpu::PrimitiveTopology GetPrimitiveTopology() const; + wgpu::IndexFormat GetStripIndexFormat() const; wgpu::CullMode GetCullMode() const; wgpu::FrontFace GetFrontFace() const; bool IsDepthBiasEnabled() const; @@ -96,7 +95,7 @@ namespace dawn_native { RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag); // Vertex state - VertexStateDescriptor mVertexState; + uint32_t mVertexBufferCount; ityp::bitset mAttributeLocationsUsed; ityp::array mAttributeInfos; @@ -105,14 +104,13 @@ namespace dawn_native { // Attachments Ref mAttachmentState; - DepthStencilStateDescriptor mDepthStencilState; - ityp::array mColorStates; + ityp::array mTargets; + ityp::array mTargetBlend; // Other state - wgpu::PrimitiveTopology mPrimitiveTopology; - RasterizationStateDescriptor mRasterizationState; - uint32_t mSampleMask; - bool mAlphaToCoverageEnabled; + PrimitiveState mPrimitive; + DepthStencilState mDepthStencil; + MultisampleState mMultisample; }; } // namespace dawn_native diff --git a/src/dawn_native/d3d12/RenderPipelineD3D12.cpp b/src/dawn_native/d3d12/RenderPipelineD3D12.cpp index 3e39686ae8..371e9a7bc3 100644 --- a/src/dawn_native/d3d12/RenderPipelineD3D12.cpp +++ b/src/dawn_native/d3d12/RenderPipelineD3D12.cpp @@ -207,16 +207,18 @@ namespace dawn_native { namespace d3d12 { return static_cast(writeMask); } - D3D12_RENDER_TARGET_BLEND_DESC ComputeColorDesc(const ColorStateDescriptor* descriptor) { + D3D12_RENDER_TARGET_BLEND_DESC ComputeColorDesc(const ColorTargetState* state) { D3D12_RENDER_TARGET_BLEND_DESC blendDesc; - blendDesc.BlendEnable = BlendEnabled(descriptor); - blendDesc.SrcBlend = D3D12Blend(descriptor->colorBlend.srcFactor); - blendDesc.DestBlend = D3D12Blend(descriptor->colorBlend.dstFactor); - blendDesc.BlendOp = D3D12BlendOperation(descriptor->colorBlend.operation); - blendDesc.SrcBlendAlpha = D3D12Blend(descriptor->alphaBlend.srcFactor); - blendDesc.DestBlendAlpha = D3D12Blend(descriptor->alphaBlend.dstFactor); - blendDesc.BlendOpAlpha = D3D12BlendOperation(descriptor->alphaBlend.operation); - blendDesc.RenderTargetWriteMask = D3D12RenderTargetWriteMask(descriptor->writeMask); + blendDesc.BlendEnable = state->blend != nullptr; + if (blendDesc.BlendEnable) { + blendDesc.SrcBlend = D3D12Blend(state->blend->color.srcFactor); + blendDesc.DestBlend = D3D12Blend(state->blend->color.dstFactor); + blendDesc.BlendOp = D3D12BlendOperation(state->blend->color.operation); + blendDesc.SrcBlendAlpha = D3D12Blend(state->blend->alpha.srcFactor); + blendDesc.DestBlendAlpha = D3D12Blend(state->blend->alpha.dstFactor); + blendDesc.BlendOpAlpha = D3D12BlendOperation(state->blend->alpha.operation); + } + blendDesc.RenderTargetWriteMask = D3D12RenderTargetWriteMask(state->writeMask); blendDesc.LogicOpEnable = false; blendDesc.LogicOp = D3D12_LOGIC_OP_NOOP; return blendDesc; @@ -254,8 +256,7 @@ namespace dawn_native { namespace d3d12 { return desc; } - D3D12_DEPTH_STENCIL_DESC ComputeDepthStencilDesc( - const DepthStencilStateDescriptor* descriptor) { + D3D12_DEPTH_STENCIL_DESC ComputeDepthStencilDesc(const DepthStencilState* descriptor) { D3D12_DEPTH_STENCIL_DESC mDepthStencilDescriptor; mDepthStencilDescriptor.DepthEnable = TRUE; mDepthStencilDescriptor.DepthWriteMask = descriptor->depthWriteEnabled @@ -347,8 +348,8 @@ namespace dawn_native { namespace d3d12 { descriptorD3D12.InputLayout = ComputeInputLayout(&inputElementDescriptors); } - descriptorD3D12.IBStripCutValue = ComputeIndexBufferStripCutValue( - GetPrimitiveTopology(), GetVertexStateDescriptor()->indexFormat); + descriptorD3D12.IBStripCutValue = + ComputeIndexBufferStripCutValue(GetPrimitiveTopology(), GetStripIndexFormat()); descriptorD3D12.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID; descriptorD3D12.RasterizerState.CullMode = D3D12CullMode(GetCullMode()); @@ -372,15 +373,14 @@ namespace dawn_native { namespace d3d12 { descriptorD3D12.RTVFormats[static_cast(i)] = D3D12TextureFormat(GetColorAttachmentFormat(i)); descriptorD3D12.BlendState.RenderTarget[static_cast(i)] = - ComputeColorDesc(GetColorStateDescriptor(i)); + ComputeColorDesc(GetColorTargetState(i)); } descriptorD3D12.NumRenderTargets = static_cast(GetColorAttachmentsMask().count()); descriptorD3D12.BlendState.AlphaToCoverageEnable = descriptor->alphaToCoverageEnabled; descriptorD3D12.BlendState.IndependentBlendEnable = TRUE; - descriptorD3D12.DepthStencilState = - ComputeDepthStencilDesc(GetDepthStencilStateDescriptor()); + descriptorD3D12.DepthStencilState = ComputeDepthStencilDesc(GetDepthStencilState()); descriptorD3D12.SampleMask = GetSampleMask(); descriptorD3D12.PrimitiveTopologyType = D3D12PrimitiveTopologyType(GetPrimitiveTopology()); diff --git a/src/dawn_native/metal/CommandBufferMTL.mm b/src/dawn_native/metal/CommandBufferMTL.mm index a8794d7de1..6c2d3565ce 100644 --- a/src/dawn_native/metal/CommandBufferMTL.mm +++ b/src/dawn_native/metal/CommandBufferMTL.mm @@ -284,7 +284,7 @@ namespace dawn_native { namespace metal { ->GetBufferBindingCount(SingleShaderStage::Vertex); if (enableVertexPulling) { - bufferCount += pipeline->GetVertexStateDescriptor()->vertexBufferCount; + bufferCount += pipeline->GetVertexBufferCount(); } [render setVertexBytes:data[SingleShaderStage::Vertex].data() diff --git a/src/dawn_native/metal/RenderPipelineMTL.mm b/src/dawn_native/metal/RenderPipelineMTL.mm index bea3898cc5..b2f6c8f8da 100644 --- a/src/dawn_native/metal/RenderPipelineMTL.mm +++ b/src/dawn_native/metal/RenderPipelineMTL.mm @@ -201,21 +201,23 @@ namespace dawn_native { namespace metal { } void ComputeBlendDesc(MTLRenderPipelineColorAttachmentDescriptor* attachment, - const ColorStateDescriptor* descriptor, + const ColorTargetState* state, bool isDeclaredInFragmentShader) { - attachment.blendingEnabled = BlendEnabled(descriptor); - attachment.sourceRGBBlendFactor = - MetalBlendFactor(descriptor->colorBlend.srcFactor, false); - attachment.destinationRGBBlendFactor = - MetalBlendFactor(descriptor->colorBlend.dstFactor, false); - attachment.rgbBlendOperation = MetalBlendOperation(descriptor->colorBlend.operation); - attachment.sourceAlphaBlendFactor = - MetalBlendFactor(descriptor->alphaBlend.srcFactor, true); - attachment.destinationAlphaBlendFactor = - MetalBlendFactor(descriptor->alphaBlend.dstFactor, true); - attachment.alphaBlendOperation = MetalBlendOperation(descriptor->alphaBlend.operation); + attachment.blendingEnabled = state->blend != nullptr; + if (attachment.blendingEnabled) { + attachment.sourceRGBBlendFactor = + MetalBlendFactor(state->blend->color.srcFactor, false); + attachment.destinationRGBBlendFactor = + MetalBlendFactor(state->blend->color.dstFactor, false); + attachment.rgbBlendOperation = MetalBlendOperation(state->blend->color.operation); + attachment.sourceAlphaBlendFactor = + MetalBlendFactor(state->blend->alpha.srcFactor, true); + attachment.destinationAlphaBlendFactor = + MetalBlendFactor(state->blend->alpha.dstFactor, true); + attachment.alphaBlendOperation = MetalBlendOperation(state->blend->alpha.operation); + } attachment.writeMask = - MetalColorWriteMask(descriptor->writeMask, isDeclaredInFragmentShader); + MetalColorWriteMask(state->writeMask, isDeclaredInFragmentShader); } MTLStencilOperation MetalStencilOperation(wgpu::StencilOperation stencilOperation) { @@ -239,8 +241,7 @@ namespace dawn_native { namespace metal { } } - NSRef MakeDepthStencilDesc( - const DepthStencilStateDescriptor* descriptor) { + NSRef MakeDepthStencilDesc(const DepthStencilState* descriptor) { NSRef mtlDepthStencilDescRef = AcquireNSRef([MTLDepthStencilDescriptor new]); MTLDepthStencilDescriptor* mtlDepthStencilDescriptor = mtlDepthStencilDescRef.Get(); @@ -340,9 +341,17 @@ namespace dawn_native { namespace metal { ShaderModule* vertexModule = ToBackend(descriptor->vertexStage.module); const char* vertexEntryPoint = descriptor->vertexStage.entryPoint; ShaderModule::MetalFunctionData vertexData; + + const VertexStateDescriptor* vertexStatePtr = descriptor->vertexState; + VertexStateDescriptor vertexState; + if (vertexStatePtr == nullptr) { + vertexState = {}; + vertexStatePtr = &vertexState; + } + DAWN_TRY(vertexModule->CreateFunction(vertexEntryPoint, SingleShaderStage::Vertex, - ToBackend(GetLayout()), &vertexData, 0xFFFFFFFF, - this)); + ToBackend(GetLayout()), &vertexData, 0xFFFFFFFF, this, + vertexStatePtr)); descriptorMTL.vertexFunction = vertexData.function.Get(); if (vertexData.needsStorageBufferLength) { @@ -379,7 +388,7 @@ namespace dawn_native { namespace metal { for (ColorAttachmentIndex i : IterateBitSet(GetColorAttachmentsMask())) { descriptorMTL.colorAttachments[static_cast(i)].pixelFormat = MetalPixelFormat(GetColorAttachmentFormat(i)); - const ColorStateDescriptor* descriptor = GetColorStateDescriptor(i); + const ColorTargetState* descriptor = GetColorTargetState(i); ComputeBlendDesc(descriptorMTL.colorAttachments[static_cast(i)], descriptor, fragmentOutputsWritten[i]); } @@ -403,7 +412,7 @@ namespace dawn_native { namespace metal { // call setDepthStencilState() for a given render pipeline in CommandEncoder, in order to // improve performance. NSRef depthStencilDesc = - MakeDepthStencilDesc(GetDepthStencilStateDescriptor()); + MakeDepthStencilDesc(GetDepthStencilState()); mMtlDepthStencilState = AcquireNSPRef([mtlDevice newDepthStencilStateWithDescriptor:depthStencilDesc.Get()]); diff --git a/src/dawn_native/metal/ShaderModuleMTL.h b/src/dawn_native/metal/ShaderModuleMTL.h index 3d777e94e0..1a4f549cff 100644 --- a/src/dawn_native/metal/ShaderModuleMTL.h +++ b/src/dawn_native/metal/ShaderModuleMTL.h @@ -47,7 +47,8 @@ namespace dawn_native { namespace metal { const PipelineLayout* layout, MetalFunctionData* out, uint32_t sampleMask = 0xFFFFFFFF, - const RenderPipeline* renderPipeline = nullptr); + const RenderPipeline* renderPipeline = nullptr, + const VertexStateDescriptor* vertexState = nullptr); private: ResultOrError TranslateToMSLWithTint(const char* entryPointName, @@ -55,6 +56,7 @@ namespace dawn_native { namespace metal { const PipelineLayout* layout, uint32_t sampleMask, const RenderPipeline* renderPipeline, + const VertexStateDescriptor* vertexState, std::string* remappedEntryPointName, bool* needsStorageBufferLength); ResultOrError TranslateToMSLWithSPIRVCross( @@ -63,6 +65,7 @@ namespace dawn_native { namespace metal { const PipelineLayout* layout, uint32_t sampleMask, const RenderPipeline* renderPipeline, + const VertexStateDescriptor* vertexState, std::string* remappedEntryPointName, bool* needsStorageBufferLength); diff --git a/src/dawn_native/metal/ShaderModuleMTL.mm b/src/dawn_native/metal/ShaderModuleMTL.mm index f678ebd160..9cc493d78b 100644 --- a/src/dawn_native/metal/ShaderModuleMTL.mm +++ b/src/dawn_native/metal/ShaderModuleMTL.mm @@ -56,6 +56,7 @@ namespace dawn_native { namespace metal { // TODO(crbug.com/tint/387): AND in a fixed sample mask in the shader. uint32_t sampleMask, const RenderPipeline* renderPipeline, + const VertexStateDescriptor* vertexState, std::string* remappedEntryPointName, bool* needsStorageBufferLength) { // TODO(crbug.com/tint/256): Set this accordingly if arrayLength(..) is used. @@ -68,8 +69,7 @@ namespace dawn_native { namespace metal { if (stage == SingleShaderStage::Vertex && GetDevice()->IsToggleEnabled(Toggle::MetalEnableVertexPulling)) { transformManager.append( - MakeVertexPullingTransform(*renderPipeline->GetVertexStateDescriptor(), - entryPointName, kPullingBufferBindingSet)); + MakeVertexPullingTransform(*vertexState, entryPointName, kPullingBufferBindingSet)); for (VertexBufferSlot slot : IterateBitSet(renderPipeline->GetVertexBufferSlotsUsed())) { @@ -118,6 +118,7 @@ namespace dawn_native { namespace metal { const PipelineLayout* layout, uint32_t sampleMask, const RenderPipeline* renderPipeline, + const VertexStateDescriptor* vertexState, std::string* remappedEntryPointName, bool* needsStorageBufferLength) { const std::vector* spirv = &GetSpirv(); @@ -128,14 +129,12 @@ namespace dawn_native { namespace metal { stage == SingleShaderStage::Vertex) { if (GetDevice()->IsToggleEnabled(Toggle::UseTintGenerator)) { DAWN_TRY_ASSIGN(pullingSpirv, - GeneratePullingSpirv(GetTintProgram(), - *renderPipeline->GetVertexStateDescriptor(), - entryPointName, kPullingBufferBindingSet)); + GeneratePullingSpirv(GetTintProgram(), *vertexState, entryPointName, + kPullingBufferBindingSet)); } else { - DAWN_TRY_ASSIGN( - pullingSpirv, - GeneratePullingSpirv(GetSpirv(), *renderPipeline->GetVertexStateDescriptor(), - entryPointName, kPullingBufferBindingSet)); + DAWN_TRY_ASSIGN(pullingSpirv, + GeneratePullingSpirv(GetSpirv(), *vertexState, entryPointName, + kPullingBufferBindingSet)); } spirv = &pullingSpirv; } @@ -228,20 +227,29 @@ namespace dawn_native { namespace metal { const PipelineLayout* layout, ShaderModule::MetalFunctionData* out, uint32_t sampleMask, - const RenderPipeline* renderPipeline) { + const RenderPipeline* renderPipeline, + const VertexStateDescriptor* vertexState) { ASSERT(!IsError()); ASSERT(out); + // Vertex stages must specify a renderPipeline and vertexState + if (stage == SingleShaderStage::Vertex) { + ASSERT(renderPipeline != nullptr); + ASSERT(vertexState != nullptr); + } + std::string remappedEntryPointName; std::string msl; if (GetDevice()->IsToggleEnabled(Toggle::UseTintGenerator)) { - DAWN_TRY_ASSIGN(msl, TranslateToMSLWithTint(entryPointName, stage, layout, sampleMask, - renderPipeline, &remappedEntryPointName, - &out->needsStorageBufferLength)); + DAWN_TRY_ASSIGN( + msl, TranslateToMSLWithTint(entryPointName, stage, layout, sampleMask, + renderPipeline, vertexState, &remappedEntryPointName, + &out->needsStorageBufferLength)); } else { - DAWN_TRY_ASSIGN(msl, TranslateToMSLWithSPIRVCross( - entryPointName, stage, layout, sampleMask, renderPipeline, - &remappedEntryPointName, &out->needsStorageBufferLength)); + DAWN_TRY_ASSIGN(msl, TranslateToMSLWithSPIRVCross(entryPointName, stage, layout, + sampleMask, renderPipeline, + vertexState, &remappedEntryPointName, + &out->needsStorageBufferLength)); } // Metal uses Clang to compile the shader as C++14. Disable everything in the -Wall diff --git a/src/dawn_native/opengl/RenderPipelineGL.cpp b/src/dawn_native/opengl/RenderPipelineGL.cpp index 9a5da5c282..c5e9805079 100644 --- a/src/dawn_native/opengl/RenderPipelineGL.cpp +++ b/src/dawn_native/opengl/RenderPipelineGL.cpp @@ -104,43 +104,42 @@ namespace dawn_native { namespace opengl { void ApplyColorState(const OpenGLFunctions& gl, ColorAttachmentIndex attachment, - const ColorStateDescriptor* descriptor) { + const ColorTargetState* state) { GLuint colorBuffer = static_cast(static_cast(attachment)); - if (BlendEnabled(descriptor)) { + if (state->blend != nullptr) { gl.Enablei(GL_BLEND, colorBuffer); - gl.BlendEquationSeparatei(colorBuffer, - GLBlendMode(descriptor->colorBlend.operation), - GLBlendMode(descriptor->alphaBlend.operation)); + gl.BlendEquationSeparatei(colorBuffer, GLBlendMode(state->blend->color.operation), + GLBlendMode(state->blend->alpha.operation)); gl.BlendFuncSeparatei(colorBuffer, - GLBlendFactor(descriptor->colorBlend.srcFactor, false), - GLBlendFactor(descriptor->colorBlend.dstFactor, false), - GLBlendFactor(descriptor->alphaBlend.srcFactor, true), - GLBlendFactor(descriptor->alphaBlend.dstFactor, true)); + GLBlendFactor(state->blend->color.srcFactor, false), + GLBlendFactor(state->blend->color.dstFactor, false), + GLBlendFactor(state->blend->alpha.srcFactor, true), + GLBlendFactor(state->blend->alpha.dstFactor, true)); } else { gl.Disablei(GL_BLEND, colorBuffer); } - gl.ColorMaski(colorBuffer, descriptor->writeMask & wgpu::ColorWriteMask::Red, - descriptor->writeMask & wgpu::ColorWriteMask::Green, - descriptor->writeMask & wgpu::ColorWriteMask::Blue, - descriptor->writeMask & wgpu::ColorWriteMask::Alpha); + gl.ColorMaski(colorBuffer, state->writeMask & wgpu::ColorWriteMask::Red, + state->writeMask & wgpu::ColorWriteMask::Green, + state->writeMask & wgpu::ColorWriteMask::Blue, + state->writeMask & wgpu::ColorWriteMask::Alpha); } - void ApplyColorState(const OpenGLFunctions& gl, const ColorStateDescriptor* descriptor) { - if (BlendEnabled(descriptor)) { + void ApplyColorState(const OpenGLFunctions& gl, const ColorTargetState* state) { + if (state->blend != nullptr) { gl.Enable(GL_BLEND); - gl.BlendEquationSeparate(GLBlendMode(descriptor->colorBlend.operation), - GLBlendMode(descriptor->alphaBlend.operation)); - gl.BlendFuncSeparate(GLBlendFactor(descriptor->colorBlend.srcFactor, false), - GLBlendFactor(descriptor->colorBlend.dstFactor, false), - GLBlendFactor(descriptor->alphaBlend.srcFactor, true), - GLBlendFactor(descriptor->alphaBlend.dstFactor, true)); + gl.BlendEquationSeparate(GLBlendMode(state->blend->color.operation), + GLBlendMode(state->blend->alpha.operation)); + gl.BlendFuncSeparate(GLBlendFactor(state->blend->color.srcFactor, false), + GLBlendFactor(state->blend->color.dstFactor, false), + GLBlendFactor(state->blend->alpha.srcFactor, true), + GLBlendFactor(state->blend->alpha.dstFactor, true)); } else { gl.Disable(GL_BLEND); } - gl.ColorMask(descriptor->writeMask & wgpu::ColorWriteMask::Red, - descriptor->writeMask & wgpu::ColorWriteMask::Green, - descriptor->writeMask & wgpu::ColorWriteMask::Blue, - descriptor->writeMask & wgpu::ColorWriteMask::Alpha); + gl.ColorMask(state->writeMask & wgpu::ColorWriteMask::Red, + state->writeMask & wgpu::ColorWriteMask::Green, + state->writeMask & wgpu::ColorWriteMask::Blue, + state->writeMask & wgpu::ColorWriteMask::Alpha); } bool Equal(const BlendDescriptor& lhs, const BlendDescriptor& rhs) { @@ -170,7 +169,7 @@ namespace dawn_native { namespace opengl { } void ApplyDepthStencilState(const OpenGLFunctions& gl, - const DepthStencilStateDescriptor* descriptor, + const DepthStencilState* descriptor, PersistentPipelineState* persistentPipelineState) { // Depth writes only occur if depth is enabled if (descriptor->depthCompare == wgpu::CompareFunction::Always && @@ -278,7 +277,7 @@ namespace dawn_native { namespace opengl { ApplyFrontFaceAndCulling(gl, GetFrontFace(), GetCullMode()); - ApplyDepthStencilState(gl, GetDepthStencilStateDescriptor(), &persistentPipelineState); + ApplyDepthStencilState(gl, GetDepthStencilState(), &persistentPipelineState); gl.SampleMaski(0, GetSampleMask()); if (IsAlphaToCoverageEnabled()) { @@ -302,21 +301,26 @@ namespace dawn_native { namespace opengl { if (!GetDevice()->IsToggleEnabled(Toggle::DisableIndexedDrawBuffers)) { for (ColorAttachmentIndex attachmentSlot : IterateBitSet(GetColorAttachmentsMask())) { - ApplyColorState(gl, attachmentSlot, GetColorStateDescriptor(attachmentSlot)); + ApplyColorState(gl, attachmentSlot, GetColorTargetState(attachmentSlot)); } } else { - const ColorStateDescriptor* prevDescriptor = nullptr; + const ColorTargetState* prevDescriptor = nullptr; for (ColorAttachmentIndex attachmentSlot : IterateBitSet(GetColorAttachmentsMask())) { - const ColorStateDescriptor* descriptor = GetColorStateDescriptor(attachmentSlot); + const ColorTargetState* descriptor = GetColorTargetState(attachmentSlot); if (!prevDescriptor) { ApplyColorState(gl, descriptor); prevDescriptor = descriptor; - } else if (!Equal(descriptor->alphaBlend, prevDescriptor->alphaBlend) || - !Equal(descriptor->colorBlend, prevDescriptor->colorBlend) || - descriptor->writeMask != prevDescriptor->writeMask) { - // TODO(crbug.com/dawn/582): Add validation to prevent this as it is not - // supported on GLES < 3.2. + } else if ((descriptor->blend == nullptr) != (prevDescriptor->blend == nullptr)) { + // TODO(crbug.com/dawn/582): GLES < 3.2 does not support different blend states + // per color target. Add validation to prevent this as it is not. ASSERT(false); + } else if (descriptor->blend != nullptr) { + if (!Equal(descriptor->blend->alpha, prevDescriptor->blend->alpha) || + !Equal(descriptor->blend->color, prevDescriptor->blend->color) || + descriptor->writeMask != prevDescriptor->writeMask) { + // TODO(crbug.com/dawn/582) + ASSERT(false); + } } } } diff --git a/src/dawn_native/vulkan/RenderPipelineVk.cpp b/src/dawn_native/vulkan/RenderPipelineVk.cpp index 2d9c627d57..2438fde6df 100644 --- a/src/dawn_native/vulkan/RenderPipelineVk.cpp +++ b/src/dawn_native/vulkan/RenderPipelineVk.cpp @@ -222,18 +222,29 @@ namespace dawn_native { namespace vulkan { : static_cast(0); } - VkPipelineColorBlendAttachmentState ComputeColorDesc(const ColorStateDescriptor* descriptor, + VkPipelineColorBlendAttachmentState ComputeColorDesc(const ColorTargetState* state, bool isDeclaredInFragmentShader) { VkPipelineColorBlendAttachmentState attachment; - attachment.blendEnable = BlendEnabled(descriptor) ? VK_TRUE : VK_FALSE; - attachment.srcColorBlendFactor = VulkanBlendFactor(descriptor->colorBlend.srcFactor); - attachment.dstColorBlendFactor = VulkanBlendFactor(descriptor->colorBlend.dstFactor); - attachment.colorBlendOp = VulkanBlendOperation(descriptor->colorBlend.operation); - attachment.srcAlphaBlendFactor = VulkanBlendFactor(descriptor->alphaBlend.srcFactor); - attachment.dstAlphaBlendFactor = VulkanBlendFactor(descriptor->alphaBlend.dstFactor); - attachment.alphaBlendOp = VulkanBlendOperation(descriptor->alphaBlend.operation); + attachment.blendEnable = state->blend != nullptr ? VK_TRUE : VK_FALSE; + if (attachment.blendEnable) { + attachment.srcColorBlendFactor = VulkanBlendFactor(state->blend->color.srcFactor); + attachment.dstColorBlendFactor = VulkanBlendFactor(state->blend->color.dstFactor); + attachment.colorBlendOp = VulkanBlendOperation(state->blend->color.operation); + attachment.srcAlphaBlendFactor = VulkanBlendFactor(state->blend->alpha.srcFactor); + attachment.dstAlphaBlendFactor = VulkanBlendFactor(state->blend->alpha.dstFactor); + attachment.alphaBlendOp = VulkanBlendOperation(state->blend->alpha.operation); + } else { + // Swiftshader's Vulkan implementation appears to expect these values to be valid + // even when blending is not enabled. + attachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + attachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; + attachment.colorBlendOp = VK_BLEND_OP_ADD; + attachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + attachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + attachment.alphaBlendOp = VK_BLEND_OP_ADD; + } attachment.colorWriteMask = - VulkanColorWriteMask(descriptor->writeMask, isDeclaredInFragmentShader); + VulkanColorWriteMask(state->writeMask, isDeclaredInFragmentShader); return attachment; } @@ -259,7 +270,7 @@ namespace dawn_native { namespace vulkan { } VkPipelineDepthStencilStateCreateInfo ComputeDepthStencilDesc( - const DepthStencilStateDescriptor* descriptor) { + const DepthStencilState* descriptor) { VkPipelineDepthStencilStateCreateInfo depthStencilState; depthStencilState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; depthStencilState.pNext = nullptr; @@ -404,7 +415,7 @@ namespace dawn_native { namespace vulkan { multisample.alphaToOneEnable = VK_FALSE; VkPipelineDepthStencilStateCreateInfo depthStencilState = - ComputeDepthStencilDesc(GetDepthStencilStateDescriptor()); + ComputeDepthStencilDesc(GetDepthStencilState()); // Initialize the "blend state info" that will be chained in the "create info" from the data // pre-computed in the ColorState @@ -413,9 +424,8 @@ namespace dawn_native { namespace vulkan { const auto& fragmentOutputsWritten = GetStage(SingleShaderStage::Fragment).metadata->fragmentOutputsWritten; for (ColorAttachmentIndex i : IterateBitSet(GetColorAttachmentsMask())) { - const ColorStateDescriptor* colorStateDescriptor = GetColorStateDescriptor(i); - colorBlendAttachments[i] = - ComputeColorDesc(colorStateDescriptor, fragmentOutputsWritten[i]); + const ColorTargetState* target = GetColorTargetState(i); + colorBlendAttachments[i] = ComputeColorDesc(target, fragmentOutputsWritten[i]); } VkPipelineColorBlendStateCreateInfo colorBlend; colorBlend.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;