diff --git a/src/dawn_native/AttachmentState.cpp b/src/dawn_native/AttachmentState.cpp index a9c23ae741..56a9ba557b 100644 --- a/src/dawn_native/AttachmentState.cpp +++ b/src/dawn_native/AttachmentState.cpp @@ -46,6 +46,20 @@ namespace dawn_native { } } + AttachmentStateBlueprint::AttachmentStateBlueprint(const RenderPipelineDescriptor2* descriptor) + : mSampleCount(descriptor->multisample.count) { + ASSERT(descriptor->fragment->targetCount <= kMaxColorAttachments); + for (ColorAttachmentIndex i(uint8_t(0)); + i < ColorAttachmentIndex(static_cast(descriptor->fragment->targetCount)); + ++i) { + mColorAttachmentsSet.set(i); + mColorFormats[i] = descriptor->fragment->targets[static_cast(i)].format; + } + if (descriptor->depthStencil != nullptr) { + mDepthStencilFormat = descriptor->depthStencil->format; + } + } + AttachmentStateBlueprint::AttachmentStateBlueprint(const RenderPassDescriptor* descriptor) { for (ColorAttachmentIndex i(uint8_t(0)); i < ColorAttachmentIndex(static_cast(descriptor->colorAttachmentCount)); diff --git a/src/dawn_native/AttachmentState.h b/src/dawn_native/AttachmentState.h index ce8b8aaf14..891b15883d 100644 --- a/src/dawn_native/AttachmentState.h +++ b/src/dawn_native/AttachmentState.h @@ -38,6 +38,7 @@ namespace dawn_native { // Note: Descriptors must be validated before the AttachmentState is constructed. explicit AttachmentStateBlueprint(const RenderBundleEncoderDescriptor* descriptor); explicit AttachmentStateBlueprint(const RenderPipelineDescriptor* descriptor); + explicit AttachmentStateBlueprint(const RenderPipelineDescriptor2* descriptor); explicit AttachmentStateBlueprint(const RenderPassDescriptor* descriptor); AttachmentStateBlueprint(const AttachmentStateBlueprint& rhs); diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp index aa71808f92..c146588b73 100644 --- a/src/dawn_native/Device.cpp +++ b/src/dawn_native/Device.cpp @@ -551,6 +551,103 @@ namespace dawn_native { return std::move(result); } + ResultOrError> DeviceBase::GetOrCreateRenderPipeline( + const RenderPipelineDescriptor2* descriptor) { + RenderPipelineBase blueprint(this, descriptor); + + const size_t blueprintHash = blueprint.ComputeContentHash(); + blueprint.SetContentHash(blueprintHash); + + Ref result; + auto iter = mCaches->renderPipelines.find(&blueprint); + if (iter != mCaches->renderPipelines.end()) { + result = *iter; + } else { + // Convert descriptor to the older format it before proceeding. + // TODO: Convert the rest of the code to operate on the newer format. + RenderPipelineDescriptor normalizedDescriptor; + + VertexStateDescriptor vertexState; + normalizedDescriptor.vertexState = &vertexState; + + RasterizationStateDescriptor rasterizationState; + normalizedDescriptor.rasterizationState = &rasterizationState; + + normalizedDescriptor.label = descriptor->label; + normalizedDescriptor.layout = descriptor->layout; + normalizedDescriptor.vertexStage.module = descriptor->vertex.module; + normalizedDescriptor.vertexStage.entryPoint = descriptor->vertex.entryPoint; + normalizedDescriptor.primitiveTopology = descriptor->primitive.topology; + normalizedDescriptor.sampleCount = descriptor->multisample.count; + normalizedDescriptor.sampleMask = descriptor->multisample.mask; + normalizedDescriptor.alphaToCoverageEnabled = + descriptor->multisample.alphaToCoverageEnabled; + + vertexState.vertexBufferCount = descriptor->vertex.bufferCount; + vertexState.vertexBuffers = descriptor->vertex.buffers; + vertexState.indexFormat = descriptor->primitive.stripIndexFormat; + + rasterizationState.frontFace = descriptor->primitive.frontFace; + rasterizationState.cullMode = descriptor->primitive.cullMode; + + DepthStencilStateDescriptor depthStencilState; + if (descriptor->depthStencil) { + const DepthStencilState* depthStencil = descriptor->depthStencil; + normalizedDescriptor.depthStencilState = &depthStencilState; + + depthStencilState.format = depthStencil->format; + depthStencilState.depthWriteEnabled = depthStencil->depthWriteEnabled; + depthStencilState.depthCompare = depthStencil->depthCompare; + depthStencilState.stencilFront = depthStencil->stencilFront; + depthStencilState.stencilBack = depthStencil->stencilBack; + depthStencilState.stencilReadMask = depthStencil->stencilReadMask; + depthStencilState.stencilWriteMask = depthStencil->stencilWriteMask; + rasterizationState.depthBias = depthStencil->depthBias; + rasterizationState.depthBiasSlopeScale = depthStencil->depthBiasSlopeScale; + rasterizationState.depthBiasClamp = depthStencil->depthBiasClamp; + } + + ProgrammableStageDescriptor fragmentStage; + std::vector colorStates; + if (descriptor->fragment) { + const FragmentState* fragment = descriptor->fragment; + normalizedDescriptor.fragmentStage = &fragmentStage; + + fragmentStage.module = fragment->module; + fragmentStage.entryPoint = fragment->entryPoint; + + for (uint32_t i = 0; i < fragment->targetCount; ++i) { + const ColorTargetState& target = fragment->targets[i]; + ColorStateDescriptor colorState; + colorState.format = target.format; + colorState.writeMask = target.writeMask; + + if (target.blend) { + const BlendState* blend = target.blend; + colorState.colorBlend.srcFactor = blend->color.srcFactor; + colorState.colorBlend.dstFactor = blend->color.dstFactor; + colorState.colorBlend.operation = blend->color.operation; + + colorState.alphaBlend.srcFactor = blend->alpha.srcFactor; + colorState.alphaBlend.dstFactor = blend->alpha.dstFactor; + colorState.alphaBlend.operation = blend->alpha.operation; + } + colorStates.push_back(colorState); + } + + normalizedDescriptor.colorStateCount = fragment->targetCount; + normalizedDescriptor.colorStates = colorStates.data(); + } + + DAWN_TRY_ASSIGN(result, CreateRenderPipelineImpl(&normalizedDescriptor)); + result->SetIsCachedReference(); + result->SetContentHash(blueprintHash); + mCaches->renderPipelines.insert(result.Get()); + } + + return std::move(result); + } + void DeviceBase::UncacheRenderPipeline(RenderPipelineBase* obj) { ASSERT(obj->IsCachedReference()); size_t removedCount = mCaches->renderPipelines.erase(obj); @@ -649,6 +746,12 @@ namespace dawn_native { return GetOrCreateAttachmentState(&blueprint); } + Ref DeviceBase::GetOrCreateAttachmentState( + const RenderPipelineDescriptor2* descriptor) { + AttachmentStateBlueprint blueprint(descriptor); + return GetOrCreateAttachmentState(&blueprint); + } + Ref DeviceBase::GetOrCreateAttachmentState( const RenderPassDescriptor* descriptor) { AttachmentStateBlueprint blueprint(descriptor); @@ -1038,92 +1141,20 @@ namespace dawn_native { DAWN_TRY(ValidateRenderPipelineDescriptor(this, descriptor)); } - // Convert descriptor to the older format it before proceeding. - // TODO: Convert the rest of the code to operate on the newer format. - RenderPipelineDescriptor normalizedDescriptor; - - VertexStateDescriptor vertexState; - normalizedDescriptor.vertexState = &vertexState; - - RasterizationStateDescriptor rasterizationState; - normalizedDescriptor.rasterizationState = &rasterizationState; - - normalizedDescriptor.label = descriptor->label; - normalizedDescriptor.layout = descriptor->layout; - normalizedDescriptor.vertexStage.module = descriptor->vertex.module; - normalizedDescriptor.vertexStage.entryPoint = descriptor->vertex.entryPoint; - normalizedDescriptor.primitiveTopology = descriptor->primitive.topology; - normalizedDescriptor.sampleCount = descriptor->multisample.count; - normalizedDescriptor.sampleMask = descriptor->multisample.mask; - normalizedDescriptor.alphaToCoverageEnabled = - descriptor->multisample.alphaToCoverageEnabled; - - vertexState.vertexBufferCount = descriptor->vertex.bufferCount; - vertexState.vertexBuffers = descriptor->vertex.buffers; - vertexState.indexFormat = descriptor->primitive.stripIndexFormat; - - rasterizationState.frontFace = descriptor->primitive.frontFace; - rasterizationState.cullMode = descriptor->primitive.cullMode; - - DepthStencilStateDescriptor depthStencilState; - if (descriptor->depthStencil) { - const DepthStencilState* depthStencil = descriptor->depthStencil; - normalizedDescriptor.depthStencilState = &depthStencilState; - - depthStencilState.format = depthStencil->format; - depthStencilState.depthWriteEnabled = depthStencil->depthWriteEnabled; - depthStencilState.depthCompare = depthStencil->depthCompare; - depthStencilState.stencilFront = depthStencil->stencilFront; - depthStencilState.stencilBack = depthStencil->stencilBack; - depthStencilState.stencilReadMask = depthStencil->stencilReadMask; - depthStencilState.stencilWriteMask = depthStencil->stencilWriteMask; - rasterizationState.depthBias = depthStencil->depthBias; - rasterizationState.depthBiasSlopeScale = depthStencil->depthBiasSlopeScale; - rasterizationState.depthBiasClamp = depthStencil->depthBiasClamp; - } - - ProgrammableStageDescriptor fragmentStage; - std::vector colorStates; - if (descriptor->fragment) { - const FragmentState* fragment = descriptor->fragment; - normalizedDescriptor.fragmentStage = &fragmentStage; - - fragmentStage.module = fragment->module; - fragmentStage.entryPoint = fragment->entryPoint; - - for (uint32_t i = 0; i < fragment->targetCount; ++i) { - const ColorTargetState& target = fragment->targets[i]; - ColorStateDescriptor colorState; - colorState.format = target.format; - colorState.writeMask = target.writeMask; - - if (target.blend) { - const BlendState* blend = target.blend; - colorState.colorBlend.srcFactor = blend->color.srcFactor; - colorState.colorBlend.dstFactor = blend->color.dstFactor; - colorState.colorBlend.operation = blend->color.operation; - - colorState.alphaBlend.srcFactor = blend->alpha.srcFactor; - colorState.alphaBlend.dstFactor = blend->alpha.dstFactor; - colorState.alphaBlend.operation = blend->alpha.operation; - } - colorStates.push_back(colorState); - } - - normalizedDescriptor.colorStateCount = fragment->targetCount; - normalizedDescriptor.colorStates = colorStates.data(); - } - - Ref layoutRef; if (descriptor->layout == nullptr) { + RenderPipelineDescriptor2 descriptorWithDefaultLayout = *descriptor; + // Ref will keep the pipeline layout alive until the end of the function where // the pipeline will take another reference. + Ref layoutRef; DAWN_TRY_ASSIGN(layoutRef, PipelineLayoutBase::CreateDefault(this, GetStages(descriptor))); - normalizedDescriptor.layout = layoutRef.Get(); - } + descriptorWithDefaultLayout.layout = layoutRef.Get(); - return GetOrCreateRenderPipeline(&normalizedDescriptor); + return GetOrCreateRenderPipeline(&descriptorWithDefaultLayout); + } else { + return GetOrCreateRenderPipeline(descriptor); + } } ResultOrError> DeviceBase::CreateRenderPipelineInternal( diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h index 7cbffd6644..f3a3b37afc 100644 --- a/src/dawn_native/Device.h +++ b/src/dawn_native/Device.h @@ -120,6 +120,8 @@ namespace dawn_native { ResultOrError> GetOrCreateRenderPipeline( const RenderPipelineDescriptor* descriptor); + ResultOrError> GetOrCreateRenderPipeline( + const RenderPipelineDescriptor2* descriptor); void UncacheRenderPipeline(RenderPipelineBase* obj); ResultOrError> GetOrCreateSampler(const SamplerDescriptor* descriptor); @@ -134,6 +136,8 @@ namespace dawn_native { Ref GetOrCreateAttachmentState( const RenderBundleEncoderDescriptor* descriptor); Ref GetOrCreateAttachmentState(const RenderPipelineDescriptor* descriptor); + Ref GetOrCreateAttachmentState( + const RenderPipelineDescriptor2* descriptor); Ref GetOrCreateAttachmentState(const RenderPassDescriptor* descriptor); void UncacheAttachmentState(AttachmentState* obj); diff --git a/src/dawn_native/RenderPipeline.cpp b/src/dawn_native/RenderPipeline.cpp index cae708e887..8dbac0b624 100644 --- a/src/dawn_native/RenderPipeline.cpp +++ b/src/dawn_native/RenderPipeline.cpp @@ -674,6 +674,84 @@ namespace dawn_native { // attachment are set? } + RenderPipelineBase::RenderPipelineBase(DeviceBase* device, + const RenderPipelineDescriptor2* descriptor) + : PipelineBase(device, + descriptor->layout, + {{SingleShaderStage::Vertex, descriptor->vertex.module, + descriptor->vertex.entryPoint}, + {SingleShaderStage::Fragment, descriptor->fragment->module, + descriptor->fragment->entryPoint}}), + mAttachmentState(device->GetOrCreateAttachmentState(descriptor)) { + mVertexBufferCount = descriptor->vertex.bufferCount; + const VertexBufferLayout* buffers = descriptor->vertex.buffers; + for (uint8_t slot = 0; slot < mVertexBufferCount; ++slot) { + if (buffers[slot].attributeCount == 0) { + continue; + } + + VertexBufferSlot typedSlot(slot); + + mVertexBufferSlotsUsed.set(typedSlot); + mVertexBufferInfos[typedSlot].arrayStride = buffers[slot].arrayStride; + mVertexBufferInfos[typedSlot].stepMode = buffers[slot].stepMode; + + for (uint32_t i = 0; i < buffers[slot].attributeCount; ++i) { + VertexAttributeLocation location = VertexAttributeLocation( + static_cast(buffers[slot].attributes[i].shaderLocation)); + mAttributeLocationsUsed.set(location); + mAttributeInfos[location].shaderLocation = location; + mAttributeInfos[location].vertexBufferSlot = typedSlot; + mAttributeInfos[location].offset = buffers[slot].attributes[i].offset; + + mAttributeInfos[location].format = + dawn::NormalizeVertexFormat(buffers[slot].attributes[i].format); + } + } + + mPrimitive = descriptor->primitive; + mMultisample = descriptor->multisample; + + if (mAttachmentState->HasDepthStencilAttachment()) { + mDepthStencil = *descriptor->depthStencil; + } 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 + // 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; + mDepthStencil.depthBias = 0; + mDepthStencil.depthBiasSlopeScale = 0.0f; + mDepthStencil.depthBiasClamp = 0.0f; + } + + for (ColorAttachmentIndex i : IterateBitSet(mAttachmentState->GetColorAttachmentsMask())) { + const ColorTargetState* target = + &descriptor->fragment->targets[static_cast(i)]; + mTargets[i] = *target; + + if (target->blend != nullptr) { + mTargetBlend[i] = *target->blend; + mTargets[i].blend = &mTargetBlend[i]; + } + } + + // TODO(cwallez@chromium.org): Check against the shader module that the correct color + // attachment are set? + } + RenderPipelineBase::RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag) : PipelineBase(device, tag) { } diff --git a/src/dawn_native/RenderPipeline.h b/src/dawn_native/RenderPipeline.h index 1302fe3f2b..eb1820ec75 100644 --- a/src/dawn_native/RenderPipeline.h +++ b/src/dawn_native/RenderPipeline.h @@ -58,6 +58,7 @@ namespace dawn_native { class RenderPipelineBase : public PipelineBase { public: RenderPipelineBase(DeviceBase* device, const RenderPipelineDescriptor* descriptor); + RenderPipelineBase(DeviceBase* device, const RenderPipelineDescriptor2* descriptor); ~RenderPipelineBase() override; static RenderPipelineBase* MakeError(DeviceBase* device);