1*c8dee2aaSAndroid Build Coastguard Worker/* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2021 Google LLC 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/mtl/MtlGraphicsPipeline.h" 9*c8dee2aaSAndroid Build Coastguard Worker 10*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/graphite/TextureInfo.h" 11*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/Attribute.h" 12*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/ContextUtils.h" 13*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/GraphicsPipelineDesc.h" 14*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/Log.h" 15*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/RenderPassDesc.h" 16*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/RendererProvider.h" 17*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/ShaderInfo.h" 18*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/mtl/MtlGraphiteTypesPriv.h" 19*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/mtl/MtlGraphiteUtilsPriv.h" 20*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/mtl/MtlResourceProvider.h" 21*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/mtl/MtlSharedContext.h" 22*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/mtl/MtlUtilsPriv.h" 23*c8dee2aaSAndroid Build Coastguard Worker#include "src/sksl/SkSLCompiler.h" 24*c8dee2aaSAndroid Build Coastguard Worker#include "src/sksl/SkSLProgramSettings.h" 25*c8dee2aaSAndroid Build Coastguard Worker#include "src/sksl/ir/SkSLProgram.h" 26*c8dee2aaSAndroid Build Coastguard Worker 27*c8dee2aaSAndroid Build Coastguard Workernamespace skgpu::graphite { 28*c8dee2aaSAndroid Build Coastguard Worker 29*c8dee2aaSAndroid Build Coastguard Workernamespace { 30*c8dee2aaSAndroid Build Coastguard Worker 31*c8dee2aaSAndroid Build Coastguard Workerinline MTLVertexFormat attribute_type_to_mtlformat(VertexAttribType type) { 32*c8dee2aaSAndroid Build Coastguard Worker switch (type) { 33*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kFloat: 34*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatFloat; 35*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kFloat2: 36*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatFloat2; 37*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kFloat3: 38*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatFloat3; 39*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kFloat4: 40*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatFloat4; 41*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kHalf: 42*c8dee2aaSAndroid Build Coastguard Worker if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { 43*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatHalf; 44*c8dee2aaSAndroid Build Coastguard Worker } else { 45*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatInvalid; 46*c8dee2aaSAndroid Build Coastguard Worker } 47*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kHalf2: 48*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatHalf2; 49*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kHalf4: 50*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatHalf4; 51*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kInt2: 52*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatInt2; 53*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kInt3: 54*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatInt3; 55*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kInt4: 56*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatInt4; 57*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kUInt2: 58*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatUInt2; 59*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kByte: 60*c8dee2aaSAndroid Build Coastguard Worker if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { 61*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatChar; 62*c8dee2aaSAndroid Build Coastguard Worker } else { 63*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatInvalid; 64*c8dee2aaSAndroid Build Coastguard Worker } 65*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kByte2: 66*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatChar2; 67*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kByte4: 68*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatChar4; 69*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kUByte: 70*c8dee2aaSAndroid Build Coastguard Worker if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { 71*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatUChar; 72*c8dee2aaSAndroid Build Coastguard Worker } else { 73*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatInvalid; 74*c8dee2aaSAndroid Build Coastguard Worker } 75*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kUByte2: 76*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatUChar2; 77*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kUByte4: 78*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatUChar4; 79*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kUByte_norm: 80*c8dee2aaSAndroid Build Coastguard Worker if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { 81*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatUCharNormalized; 82*c8dee2aaSAndroid Build Coastguard Worker } else { 83*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatInvalid; 84*c8dee2aaSAndroid Build Coastguard Worker } 85*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kUByte4_norm: 86*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatUChar4Normalized; 87*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kShort2: 88*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatShort2; 89*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kShort4: 90*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatShort4; 91*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kUShort2: 92*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatUShort2; 93*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kUShort2_norm: 94*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatUShort2Normalized; 95*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kInt: 96*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatInt; 97*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kUInt: 98*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatUInt; 99*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kUShort_norm: 100*c8dee2aaSAndroid Build Coastguard Worker if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { 101*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatUShortNormalized; 102*c8dee2aaSAndroid Build Coastguard Worker } else { 103*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatInvalid; 104*c8dee2aaSAndroid Build Coastguard Worker } 105*c8dee2aaSAndroid Build Coastguard Worker case VertexAttribType::kUShort4_norm: 106*c8dee2aaSAndroid Build Coastguard Worker return MTLVertexFormatUShort4Normalized; 107*c8dee2aaSAndroid Build Coastguard Worker } 108*c8dee2aaSAndroid Build Coastguard Worker SK_ABORT("Unknown vertex attribute type"); 109*c8dee2aaSAndroid Build Coastguard Worker} 110*c8dee2aaSAndroid Build Coastguard Worker 111*c8dee2aaSAndroid Build Coastguard WorkerMTLVertexDescriptor* create_vertex_descriptor(SkSpan<const Attribute> vertexAttrs, 112*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const Attribute> instanceAttrs) { 113*c8dee2aaSAndroid Build Coastguard Worker auto vertexDescriptor = [[MTLVertexDescriptor alloc] init]; 114*c8dee2aaSAndroid Build Coastguard Worker int attributeIndex = 0; 115*c8dee2aaSAndroid Build Coastguard Worker 116*c8dee2aaSAndroid Build Coastguard Worker size_t vertexAttributeOffset = 0; 117*c8dee2aaSAndroid Build Coastguard Worker for (const auto& attribute : vertexAttrs) { 118*c8dee2aaSAndroid Build Coastguard Worker MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex]; 119*c8dee2aaSAndroid Build Coastguard Worker MTLVertexFormat format = attribute_type_to_mtlformat(attribute.cpuType()); 120*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(MTLVertexFormatInvalid != format); 121*c8dee2aaSAndroid Build Coastguard Worker mtlAttribute.format = format; 122*c8dee2aaSAndroid Build Coastguard Worker mtlAttribute.offset = vertexAttributeOffset; 123*c8dee2aaSAndroid Build Coastguard Worker mtlAttribute.bufferIndex = MtlGraphicsPipeline::kVertexBufferIndex; 124*c8dee2aaSAndroid Build Coastguard Worker 125*c8dee2aaSAndroid Build Coastguard Worker vertexAttributeOffset += attribute.sizeAlign4(); 126*c8dee2aaSAndroid Build Coastguard Worker attributeIndex++; 127*c8dee2aaSAndroid Build Coastguard Worker } 128*c8dee2aaSAndroid Build Coastguard Worker 129*c8dee2aaSAndroid Build Coastguard Worker if (vertexAttributeOffset) { 130*c8dee2aaSAndroid Build Coastguard Worker MTLVertexBufferLayoutDescriptor* vertexBufferLayout = 131*c8dee2aaSAndroid Build Coastguard Worker vertexDescriptor.layouts[MtlGraphicsPipeline::kVertexBufferIndex]; 132*c8dee2aaSAndroid Build Coastguard Worker vertexBufferLayout.stepFunction = MTLVertexStepFunctionPerVertex; 133*c8dee2aaSAndroid Build Coastguard Worker vertexBufferLayout.stepRate = 1; 134*c8dee2aaSAndroid Build Coastguard Worker vertexBufferLayout.stride = vertexAttributeOffset; 135*c8dee2aaSAndroid Build Coastguard Worker } 136*c8dee2aaSAndroid Build Coastguard Worker 137*c8dee2aaSAndroid Build Coastguard Worker size_t instanceAttributeOffset = 0; 138*c8dee2aaSAndroid Build Coastguard Worker for (const auto& attribute : instanceAttrs) { 139*c8dee2aaSAndroid Build Coastguard Worker MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex]; 140*c8dee2aaSAndroid Build Coastguard Worker MTLVertexFormat format = attribute_type_to_mtlformat(attribute.cpuType()); 141*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(MTLVertexFormatInvalid != format); 142*c8dee2aaSAndroid Build Coastguard Worker mtlAttribute.format = format; 143*c8dee2aaSAndroid Build Coastguard Worker mtlAttribute.offset = instanceAttributeOffset; 144*c8dee2aaSAndroid Build Coastguard Worker mtlAttribute.bufferIndex = MtlGraphicsPipeline::kInstanceBufferIndex; 145*c8dee2aaSAndroid Build Coastguard Worker 146*c8dee2aaSAndroid Build Coastguard Worker instanceAttributeOffset += attribute.sizeAlign4(); 147*c8dee2aaSAndroid Build Coastguard Worker attributeIndex++; 148*c8dee2aaSAndroid Build Coastguard Worker } 149*c8dee2aaSAndroid Build Coastguard Worker 150*c8dee2aaSAndroid Build Coastguard Worker if (instanceAttributeOffset) { 151*c8dee2aaSAndroid Build Coastguard Worker MTLVertexBufferLayoutDescriptor* instanceBufferLayout = 152*c8dee2aaSAndroid Build Coastguard Worker vertexDescriptor.layouts[MtlGraphicsPipeline::kInstanceBufferIndex]; 153*c8dee2aaSAndroid Build Coastguard Worker instanceBufferLayout.stepFunction = MTLVertexStepFunctionPerInstance; 154*c8dee2aaSAndroid Build Coastguard Worker instanceBufferLayout.stepRate = 1; 155*c8dee2aaSAndroid Build Coastguard Worker instanceBufferLayout.stride = instanceAttributeOffset; 156*c8dee2aaSAndroid Build Coastguard Worker } 157*c8dee2aaSAndroid Build Coastguard Worker return vertexDescriptor; 158*c8dee2aaSAndroid Build Coastguard Worker} 159*c8dee2aaSAndroid Build Coastguard Worker 160*c8dee2aaSAndroid Build Coastguard Worker// TODO: share this w/ Ganesh Metal backend? 161*c8dee2aaSAndroid Build Coastguard Workerstatic MTLBlendFactor blend_coeff_to_mtl_blend(skgpu::BlendCoeff coeff) { 162*c8dee2aaSAndroid Build Coastguard Worker switch (coeff) { 163*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kZero: 164*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorZero; 165*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kOne: 166*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorOne; 167*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kSC: 168*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorSourceColor; 169*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kISC: 170*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorOneMinusSourceColor; 171*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kDC: 172*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorDestinationColor; 173*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kIDC: 174*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorOneMinusDestinationColor; 175*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kSA: 176*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorSourceAlpha; 177*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kISA: 178*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorOneMinusSourceAlpha; 179*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kDA: 180*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorDestinationAlpha; 181*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kIDA: 182*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorOneMinusDestinationAlpha; 183*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kConstC: 184*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorBlendColor; 185*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kIConstC: 186*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorOneMinusBlendColor; 187*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kS2C: 188*c8dee2aaSAndroid Build Coastguard Worker if (@available(macOS 10.12, iOS 11.0, tvOS 11.0, *)) { 189*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorSource1Color; 190*c8dee2aaSAndroid Build Coastguard Worker } else { 191*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorZero; 192*c8dee2aaSAndroid Build Coastguard Worker } 193*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kIS2C: 194*c8dee2aaSAndroid Build Coastguard Worker if (@available(macOS 10.12, iOS 11.0, tvOS 11.0, *)) { 195*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorOneMinusSource1Color; 196*c8dee2aaSAndroid Build Coastguard Worker } else { 197*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorZero; 198*c8dee2aaSAndroid Build Coastguard Worker } 199*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kS2A: 200*c8dee2aaSAndroid Build Coastguard Worker if (@available(macOS 10.12, iOS 11.0, tvOS 11.0, *)) { 201*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorSource1Alpha; 202*c8dee2aaSAndroid Build Coastguard Worker } else { 203*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorZero; 204*c8dee2aaSAndroid Build Coastguard Worker } 205*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kIS2A: 206*c8dee2aaSAndroid Build Coastguard Worker if (@available(macOS 10.12, iOS 11.0, tvOS 11.0, *)) { 207*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorOneMinusSource1Alpha; 208*c8dee2aaSAndroid Build Coastguard Worker } else { 209*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorZero; 210*c8dee2aaSAndroid Build Coastguard Worker } 211*c8dee2aaSAndroid Build Coastguard Worker case skgpu::BlendCoeff::kIllegal: 212*c8dee2aaSAndroid Build Coastguard Worker return MTLBlendFactorZero; 213*c8dee2aaSAndroid Build Coastguard Worker } 214*c8dee2aaSAndroid Build Coastguard Worker 215*c8dee2aaSAndroid Build Coastguard Worker SK_ABORT("Unknown blend coefficient"); 216*c8dee2aaSAndroid Build Coastguard Worker} 217*c8dee2aaSAndroid Build Coastguard Worker 218*c8dee2aaSAndroid Build Coastguard Worker// TODO: share this w/ Ganesh Metal backend? 219*c8dee2aaSAndroid Build Coastguard Workerstatic MTLBlendOperation blend_equation_to_mtl_blend_op(skgpu::BlendEquation equation) { 220*c8dee2aaSAndroid Build Coastguard Worker static const MTLBlendOperation gTable[] = { 221*c8dee2aaSAndroid Build Coastguard Worker MTLBlendOperationAdd, // skgpu::BlendEquation::kAdd 222*c8dee2aaSAndroid Build Coastguard Worker MTLBlendOperationSubtract, // skgpu::BlendEquation::kSubtract 223*c8dee2aaSAndroid Build Coastguard Worker MTLBlendOperationReverseSubtract, // skgpu::BlendEquation::kReverseSubtract 224*c8dee2aaSAndroid Build Coastguard Worker }; 225*c8dee2aaSAndroid Build Coastguard Worker static_assert(std::size(gTable) == (int)skgpu::BlendEquation::kFirstAdvanced); 226*c8dee2aaSAndroid Build Coastguard Worker static_assert(0 == (int)skgpu::BlendEquation::kAdd); 227*c8dee2aaSAndroid Build Coastguard Worker static_assert(1 == (int)skgpu::BlendEquation::kSubtract); 228*c8dee2aaSAndroid Build Coastguard Worker static_assert(2 == (int)skgpu::BlendEquation::kReverseSubtract); 229*c8dee2aaSAndroid Build Coastguard Worker 230*c8dee2aaSAndroid Build Coastguard Worker SkASSERT((unsigned)equation < skgpu::kBlendEquationCnt); 231*c8dee2aaSAndroid Build Coastguard Worker return gTable[(int)equation]; 232*c8dee2aaSAndroid Build Coastguard Worker} 233*c8dee2aaSAndroid Build Coastguard Worker 234*c8dee2aaSAndroid Build Coastguard Workerstatic MTLRenderPipelineColorAttachmentDescriptor* create_color_attachment( 235*c8dee2aaSAndroid Build Coastguard Worker MTLPixelFormat format, 236*c8dee2aaSAndroid Build Coastguard Worker const BlendInfo& blendInfo) { 237*c8dee2aaSAndroid Build Coastguard Worker 238*c8dee2aaSAndroid Build Coastguard Worker skgpu::BlendEquation equation = blendInfo.fEquation; 239*c8dee2aaSAndroid Build Coastguard Worker skgpu::BlendCoeff srcCoeff = blendInfo.fSrcBlend; 240*c8dee2aaSAndroid Build Coastguard Worker skgpu::BlendCoeff dstCoeff = blendInfo.fDstBlend; 241*c8dee2aaSAndroid Build Coastguard Worker bool blendOn = !skgpu::BlendShouldDisable(equation, srcCoeff, dstCoeff); 242*c8dee2aaSAndroid Build Coastguard Worker 243*c8dee2aaSAndroid Build Coastguard Worker // TODO: I *think* this gets cleaned up by the pipelineDescriptor? 244*c8dee2aaSAndroid Build Coastguard Worker auto mtlColorAttachment = [[MTLRenderPipelineColorAttachmentDescriptor alloc] init]; 245*c8dee2aaSAndroid Build Coastguard Worker 246*c8dee2aaSAndroid Build Coastguard Worker mtlColorAttachment.pixelFormat = format; 247*c8dee2aaSAndroid Build Coastguard Worker 248*c8dee2aaSAndroid Build Coastguard Worker mtlColorAttachment.blendingEnabled = blendOn; 249*c8dee2aaSAndroid Build Coastguard Worker 250*c8dee2aaSAndroid Build Coastguard Worker if (blendOn) { 251*c8dee2aaSAndroid Build Coastguard Worker mtlColorAttachment.sourceRGBBlendFactor = blend_coeff_to_mtl_blend(srcCoeff); 252*c8dee2aaSAndroid Build Coastguard Worker mtlColorAttachment.destinationRGBBlendFactor = blend_coeff_to_mtl_blend(dstCoeff); 253*c8dee2aaSAndroid Build Coastguard Worker mtlColorAttachment.rgbBlendOperation = blend_equation_to_mtl_blend_op(equation); 254*c8dee2aaSAndroid Build Coastguard Worker mtlColorAttachment.sourceAlphaBlendFactor = blend_coeff_to_mtl_blend(srcCoeff); 255*c8dee2aaSAndroid Build Coastguard Worker mtlColorAttachment.destinationAlphaBlendFactor = blend_coeff_to_mtl_blend(dstCoeff); 256*c8dee2aaSAndroid Build Coastguard Worker mtlColorAttachment.alphaBlendOperation = blend_equation_to_mtl_blend_op(equation); 257*c8dee2aaSAndroid Build Coastguard Worker } 258*c8dee2aaSAndroid Build Coastguard Worker 259*c8dee2aaSAndroid Build Coastguard Worker mtlColorAttachment.writeMask = blendInfo.fWritesColor ? MTLColorWriteMaskAll 260*c8dee2aaSAndroid Build Coastguard Worker : MTLColorWriteMaskNone; 261*c8dee2aaSAndroid Build Coastguard Worker 262*c8dee2aaSAndroid Build Coastguard Worker return mtlColorAttachment; 263*c8dee2aaSAndroid Build Coastguard Worker} 264*c8dee2aaSAndroid Build Coastguard Worker 265*c8dee2aaSAndroid Build Coastguard Worker} // anonymous namespace 266*c8dee2aaSAndroid Build Coastguard Worker 267*c8dee2aaSAndroid Build Coastguard Workersk_sp<MtlGraphicsPipeline> MtlGraphicsPipeline::Make( 268*c8dee2aaSAndroid Build Coastguard Worker const MtlSharedContext* sharedContext, 269*c8dee2aaSAndroid Build Coastguard Worker MtlResourceProvider* resourceProvider, 270*c8dee2aaSAndroid Build Coastguard Worker const RuntimeEffectDictionary* runtimeDict, 271*c8dee2aaSAndroid Build Coastguard Worker const GraphicsPipelineDesc& pipelineDesc, 272*c8dee2aaSAndroid Build Coastguard Worker const RenderPassDesc& renderPassDesc, 273*c8dee2aaSAndroid Build Coastguard Worker SkEnumBitMask<PipelineCreationFlags> pipelineCreationFlags) { 274*c8dee2aaSAndroid Build Coastguard Worker std::string vsMSL, fsMSL; 275*c8dee2aaSAndroid Build Coastguard Worker SkSL::Program::Interface vsInterface, fsInterface; 276*c8dee2aaSAndroid Build Coastguard Worker 277*c8dee2aaSAndroid Build Coastguard Worker SkSL::ProgramSettings settings; 278*c8dee2aaSAndroid Build Coastguard Worker settings.fSharpenTextures = true; 279*c8dee2aaSAndroid Build Coastguard Worker settings.fForceNoRTFlip = true; 280*c8dee2aaSAndroid Build Coastguard Worker 281*c8dee2aaSAndroid Build Coastguard Worker SkSL::Compiler skslCompiler; 282*c8dee2aaSAndroid Build Coastguard Worker ShaderErrorHandler* errorHandler = sharedContext->caps()->shaderErrorHandler(); 283*c8dee2aaSAndroid Build Coastguard Worker 284*c8dee2aaSAndroid Build Coastguard Worker const RenderStep* step = 285*c8dee2aaSAndroid Build Coastguard Worker sharedContext->rendererProvider()->lookup(pipelineDesc.renderStepID()); 286*c8dee2aaSAndroid Build Coastguard Worker const bool useStorageBuffers = sharedContext->caps()->storageBufferSupport(); 287*c8dee2aaSAndroid Build Coastguard Worker 288*c8dee2aaSAndroid Build Coastguard Worker UniquePaintParamsID paintID = pipelineDesc.paintParamsID(); 289*c8dee2aaSAndroid Build Coastguard Worker 290*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<ShaderInfo> shaderInfo = ShaderInfo::Make(sharedContext->caps(), 291*c8dee2aaSAndroid Build Coastguard Worker sharedContext->shaderCodeDictionary(), 292*c8dee2aaSAndroid Build Coastguard Worker runtimeDict, 293*c8dee2aaSAndroid Build Coastguard Worker step, 294*c8dee2aaSAndroid Build Coastguard Worker paintID, 295*c8dee2aaSAndroid Build Coastguard Worker useStorageBuffers, 296*c8dee2aaSAndroid Build Coastguard Worker renderPassDesc.fWriteSwizzle); 297*c8dee2aaSAndroid Build Coastguard Worker 298*c8dee2aaSAndroid Build Coastguard Worker const std::string& fsSkSL = shaderInfo->fragmentSkSL(); 299*c8dee2aaSAndroid Build Coastguard Worker const BlendInfo& blendInfo = shaderInfo->blendInfo(); 300*c8dee2aaSAndroid Build Coastguard Worker if (!SkSLToMSL(sharedContext->caps()->shaderCaps(), 301*c8dee2aaSAndroid Build Coastguard Worker fsSkSL, 302*c8dee2aaSAndroid Build Coastguard Worker SkSL::ProgramKind::kGraphiteFragment, 303*c8dee2aaSAndroid Build Coastguard Worker settings, 304*c8dee2aaSAndroid Build Coastguard Worker &fsMSL, 305*c8dee2aaSAndroid Build Coastguard Worker &fsInterface, 306*c8dee2aaSAndroid Build Coastguard Worker errorHandler)) { 307*c8dee2aaSAndroid Build Coastguard Worker return nullptr; 308*c8dee2aaSAndroid Build Coastguard Worker } 309*c8dee2aaSAndroid Build Coastguard Worker 310*c8dee2aaSAndroid Build Coastguard Worker const std::string& vsSkSL = shaderInfo->vertexSkSL(); 311*c8dee2aaSAndroid Build Coastguard Worker if (!SkSLToMSL(sharedContext->caps()->shaderCaps(), 312*c8dee2aaSAndroid Build Coastguard Worker vsSkSL, 313*c8dee2aaSAndroid Build Coastguard Worker SkSL::ProgramKind::kGraphiteVertex, 314*c8dee2aaSAndroid Build Coastguard Worker settings, 315*c8dee2aaSAndroid Build Coastguard Worker &vsMSL, 316*c8dee2aaSAndroid Build Coastguard Worker &vsInterface, 317*c8dee2aaSAndroid Build Coastguard Worker errorHandler)) { 318*c8dee2aaSAndroid Build Coastguard Worker return nullptr; 319*c8dee2aaSAndroid Build Coastguard Worker } 320*c8dee2aaSAndroid Build Coastguard Worker 321*c8dee2aaSAndroid Build Coastguard Worker auto vsLibrary = 322*c8dee2aaSAndroid Build Coastguard Worker MtlCompileShaderLibrary(sharedContext, shaderInfo->vsLabel(), vsMSL, errorHandler); 323*c8dee2aaSAndroid Build Coastguard Worker auto fsLibrary = 324*c8dee2aaSAndroid Build Coastguard Worker MtlCompileShaderLibrary(sharedContext, shaderInfo->fsLabel(), fsMSL, errorHandler); 325*c8dee2aaSAndroid Build Coastguard Worker 326*c8dee2aaSAndroid Build Coastguard Worker sk_cfp<id<MTLDepthStencilState>> dss = 327*c8dee2aaSAndroid Build Coastguard Worker resourceProvider->findOrCreateCompatibleDepthStencilState(step->depthStencilSettings()); 328*c8dee2aaSAndroid Build Coastguard Worker 329*c8dee2aaSAndroid Build Coastguard Worker PipelineInfo pipelineInfo{*shaderInfo, pipelineCreationFlags}; 330*c8dee2aaSAndroid Build Coastguard Worker#if defined(GPU_TEST_UTILS) 331*c8dee2aaSAndroid Build Coastguard Worker pipelineInfo.fNativeVertexShader = std::move(vsMSL); 332*c8dee2aaSAndroid Build Coastguard Worker pipelineInfo.fNativeFragmentShader = std::move(fsMSL); 333*c8dee2aaSAndroid Build Coastguard Worker#endif 334*c8dee2aaSAndroid Build Coastguard Worker 335*c8dee2aaSAndroid Build Coastguard Worker std::string pipelineLabel = 336*c8dee2aaSAndroid Build Coastguard Worker GetPipelineLabel(sharedContext->shaderCodeDictionary(), renderPassDesc, step, paintID); 337*c8dee2aaSAndroid Build Coastguard Worker return Make(sharedContext, 338*c8dee2aaSAndroid Build Coastguard Worker pipelineLabel, 339*c8dee2aaSAndroid Build Coastguard Worker pipelineInfo, 340*c8dee2aaSAndroid Build Coastguard Worker {vsLibrary.get(), "vertexMain"}, 341*c8dee2aaSAndroid Build Coastguard Worker step->vertexAttributes(), 342*c8dee2aaSAndroid Build Coastguard Worker step->instanceAttributes(), 343*c8dee2aaSAndroid Build Coastguard Worker {fsLibrary.get(), "fragmentMain"}, 344*c8dee2aaSAndroid Build Coastguard Worker std::move(dss), 345*c8dee2aaSAndroid Build Coastguard Worker step->depthStencilSettings().fStencilReferenceValue, 346*c8dee2aaSAndroid Build Coastguard Worker blendInfo, 347*c8dee2aaSAndroid Build Coastguard Worker renderPassDesc); 348*c8dee2aaSAndroid Build Coastguard Worker} 349*c8dee2aaSAndroid Build Coastguard Worker 350*c8dee2aaSAndroid Build Coastguard Workersk_sp<MtlGraphicsPipeline> MtlGraphicsPipeline::MakeLoadMSAAPipeline( 351*c8dee2aaSAndroid Build Coastguard Worker const MtlSharedContext* sharedContext, 352*c8dee2aaSAndroid Build Coastguard Worker MtlResourceProvider* resourceProvider, 353*c8dee2aaSAndroid Build Coastguard Worker const RenderPassDesc& renderPassDesc) { 354*c8dee2aaSAndroid Build Coastguard Worker static const char* kLoadMSAAShaderText = R"( 355*c8dee2aaSAndroid Build Coastguard Worker #include <metal_stdlib> 356*c8dee2aaSAndroid Build Coastguard Worker #include <simd/simd.h> 357*c8dee2aaSAndroid Build Coastguard Worker using namespace metal; 358*c8dee2aaSAndroid Build Coastguard Worker 359*c8dee2aaSAndroid Build Coastguard Worker typedef struct { 360*c8dee2aaSAndroid Build Coastguard Worker float4 position [[position]]; 361*c8dee2aaSAndroid Build Coastguard Worker } VertexOutput; 362*c8dee2aaSAndroid Build Coastguard Worker 363*c8dee2aaSAndroid Build Coastguard Worker vertex VertexOutput vertexMain(uint vertexID [[vertex_id]]) { 364*c8dee2aaSAndroid Build Coastguard Worker VertexOutput out; 365*c8dee2aaSAndroid Build Coastguard Worker float2 position = float2(float(vertexID >> 1), float(vertexID & 1)); 366*c8dee2aaSAndroid Build Coastguard Worker out.position = float4(2.0 * position - 1.0, 0.0, 1.0); 367*c8dee2aaSAndroid Build Coastguard Worker return out; 368*c8dee2aaSAndroid Build Coastguard Worker } 369*c8dee2aaSAndroid Build Coastguard Worker 370*c8dee2aaSAndroid Build Coastguard Worker fragment float4 fragmentMain(VertexOutput in [[stage_in]], 371*c8dee2aaSAndroid Build Coastguard Worker texture2d<half> colorMap [[texture(0)]]) { 372*c8dee2aaSAndroid Build Coastguard Worker uint2 coords = uint2(in.position.x, in.position.y); 373*c8dee2aaSAndroid Build Coastguard Worker half4 colorSample = colorMap.read(coords); 374*c8dee2aaSAndroid Build Coastguard Worker return float4(colorSample); 375*c8dee2aaSAndroid Build Coastguard Worker } 376*c8dee2aaSAndroid Build Coastguard Worker )"; 377*c8dee2aaSAndroid Build Coastguard Worker 378*c8dee2aaSAndroid Build Coastguard Worker auto mtlLibrary = MtlCompileShaderLibrary(sharedContext, 379*c8dee2aaSAndroid Build Coastguard Worker "LoadMSAAFromResolve", 380*c8dee2aaSAndroid Build Coastguard Worker kLoadMSAAShaderText, 381*c8dee2aaSAndroid Build Coastguard Worker sharedContext->caps()->shaderErrorHandler()); 382*c8dee2aaSAndroid Build Coastguard Worker BlendInfo noBlend{}; // default is equivalent to kSrc blending 383*c8dee2aaSAndroid Build Coastguard Worker sk_cfp<id<MTLDepthStencilState>> ignoreDS = 384*c8dee2aaSAndroid Build Coastguard Worker resourceProvider->findOrCreateCompatibleDepthStencilState({}); 385*c8dee2aaSAndroid Build Coastguard Worker 386*c8dee2aaSAndroid Build Coastguard Worker std::string pipelineLabel = "LoadMSAAFromResolve + "; 387*c8dee2aaSAndroid Build Coastguard Worker pipelineLabel += renderPassDesc.toString().c_str(); 388*c8dee2aaSAndroid Build Coastguard Worker 389*c8dee2aaSAndroid Build Coastguard Worker PipelineInfo pipelineInfo; 390*c8dee2aaSAndroid Build Coastguard Worker pipelineInfo.fNumFragTexturesAndSamplers = 1; 391*c8dee2aaSAndroid Build Coastguard Worker // This is an internal shader, leave off filling out the test-utils shader code 392*c8dee2aaSAndroid Build Coastguard Worker return Make(sharedContext, 393*c8dee2aaSAndroid Build Coastguard Worker pipelineLabel, 394*c8dee2aaSAndroid Build Coastguard Worker pipelineInfo, 395*c8dee2aaSAndroid Build Coastguard Worker {mtlLibrary.get(), "vertexMain"}, 396*c8dee2aaSAndroid Build Coastguard Worker /*vertexAttrs=*/{}, 397*c8dee2aaSAndroid Build Coastguard Worker /*instanceAttrs=*/{}, 398*c8dee2aaSAndroid Build Coastguard Worker {mtlLibrary.get(), "fragmentMain"}, 399*c8dee2aaSAndroid Build Coastguard Worker std::move(ignoreDS), 400*c8dee2aaSAndroid Build Coastguard Worker /*stencilRefValue=*/0, 401*c8dee2aaSAndroid Build Coastguard Worker noBlend, 402*c8dee2aaSAndroid Build Coastguard Worker renderPassDesc); 403*c8dee2aaSAndroid Build Coastguard Worker} 404*c8dee2aaSAndroid Build Coastguard Worker 405*c8dee2aaSAndroid Build Coastguard Workersk_sp<MtlGraphicsPipeline> MtlGraphicsPipeline::Make(const MtlSharedContext* sharedContext, 406*c8dee2aaSAndroid Build Coastguard Worker const std::string& label, 407*c8dee2aaSAndroid Build Coastguard Worker const PipelineInfo& pipelineInfo, 408*c8dee2aaSAndroid Build Coastguard Worker MSLFunction vertexMain, 409*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const Attribute> vertexAttrs, 410*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const Attribute> instanceAttrs, 411*c8dee2aaSAndroid Build Coastguard Worker MSLFunction fragmentMain, 412*c8dee2aaSAndroid Build Coastguard Worker sk_cfp<id<MTLDepthStencilState>> dss, 413*c8dee2aaSAndroid Build Coastguard Worker uint32_t stencilRefValue, 414*c8dee2aaSAndroid Build Coastguard Worker const BlendInfo& blendInfo, 415*c8dee2aaSAndroid Build Coastguard Worker const RenderPassDesc& renderPassDesc) { 416*c8dee2aaSAndroid Build Coastguard Worker id<MTLLibrary> vsLibrary = std::get<0>(vertexMain); 417*c8dee2aaSAndroid Build Coastguard Worker id<MTLLibrary> fsLibrary = std::get<0>(fragmentMain); 418*c8dee2aaSAndroid Build Coastguard Worker if (!vsLibrary || !fsLibrary) { 419*c8dee2aaSAndroid Build Coastguard Worker return nullptr; 420*c8dee2aaSAndroid Build Coastguard Worker } 421*c8dee2aaSAndroid Build Coastguard Worker 422*c8dee2aaSAndroid Build Coastguard Worker sk_cfp<MTLRenderPipelineDescriptor*> psoDescriptor([[MTLRenderPipelineDescriptor alloc] init]); 423*c8dee2aaSAndroid Build Coastguard Worker 424*c8dee2aaSAndroid Build Coastguard Worker NSString* labelName = [NSString stringWithUTF8String: label.c_str()]; 425*c8dee2aaSAndroid Build Coastguard Worker NSString* vsFuncName = [NSString stringWithUTF8String: std::get<1>(vertexMain).c_str()]; 426*c8dee2aaSAndroid Build Coastguard Worker NSString* fsFuncName = [NSString stringWithUTF8String: std::get<1>(fragmentMain).c_str()]; 427*c8dee2aaSAndroid Build Coastguard Worker 428*c8dee2aaSAndroid Build Coastguard Worker (*psoDescriptor).label = labelName; 429*c8dee2aaSAndroid Build Coastguard Worker (*psoDescriptor).vertexFunction = [vsLibrary newFunctionWithName: vsFuncName]; 430*c8dee2aaSAndroid Build Coastguard Worker (*psoDescriptor).fragmentFunction = [fsLibrary newFunctionWithName: fsFuncName]; 431*c8dee2aaSAndroid Build Coastguard Worker 432*c8dee2aaSAndroid Build Coastguard Worker // TODO: I *think* this gets cleaned up by the pipelineDescriptor? 433*c8dee2aaSAndroid Build Coastguard Worker (*psoDescriptor).vertexDescriptor = create_vertex_descriptor(vertexAttrs, instanceAttrs); 434*c8dee2aaSAndroid Build Coastguard Worker 435*c8dee2aaSAndroid Build Coastguard Worker MTLPixelFormat pixelFormat = 436*c8dee2aaSAndroid Build Coastguard Worker TextureInfos::GetMTLPixelFormat(renderPassDesc.fColorAttachment.fTextureInfo); 437*c8dee2aaSAndroid Build Coastguard Worker auto mtlColorAttachment = create_color_attachment(pixelFormat, blendInfo); 438*c8dee2aaSAndroid Build Coastguard Worker (*psoDescriptor).colorAttachments[0] = mtlColorAttachment; 439*c8dee2aaSAndroid Build Coastguard Worker 440*c8dee2aaSAndroid Build Coastguard Worker (*psoDescriptor).rasterSampleCount = 441*c8dee2aaSAndroid Build Coastguard Worker renderPassDesc.fColorAttachment.fTextureInfo.numSamples(); 442*c8dee2aaSAndroid Build Coastguard Worker 443*c8dee2aaSAndroid Build Coastguard Worker MTLPixelFormat depthStencilFormat = 444*c8dee2aaSAndroid Build Coastguard Worker TextureInfos::GetMTLPixelFormat(renderPassDesc.fDepthStencilAttachment.fTextureInfo); 445*c8dee2aaSAndroid Build Coastguard Worker if (MtlFormatIsStencil(depthStencilFormat)) { 446*c8dee2aaSAndroid Build Coastguard Worker (*psoDescriptor).stencilAttachmentPixelFormat = depthStencilFormat; 447*c8dee2aaSAndroid Build Coastguard Worker } else { 448*c8dee2aaSAndroid Build Coastguard Worker (*psoDescriptor).stencilAttachmentPixelFormat = MTLPixelFormatInvalid; 449*c8dee2aaSAndroid Build Coastguard Worker } 450*c8dee2aaSAndroid Build Coastguard Worker if (MtlFormatIsDepth(depthStencilFormat)) { 451*c8dee2aaSAndroid Build Coastguard Worker (*psoDescriptor).depthAttachmentPixelFormat = depthStencilFormat; 452*c8dee2aaSAndroid Build Coastguard Worker } else { 453*c8dee2aaSAndroid Build Coastguard Worker (*psoDescriptor).depthAttachmentPixelFormat = MTLPixelFormatInvalid; 454*c8dee2aaSAndroid Build Coastguard Worker } 455*c8dee2aaSAndroid Build Coastguard Worker 456*c8dee2aaSAndroid Build Coastguard Worker NSError* error; 457*c8dee2aaSAndroid Build Coastguard Worker sk_cfp<id<MTLRenderPipelineState>> pso( 458*c8dee2aaSAndroid Build Coastguard Worker [sharedContext->device() newRenderPipelineStateWithDescriptor:psoDescriptor.get() 459*c8dee2aaSAndroid Build Coastguard Worker error:&error]); 460*c8dee2aaSAndroid Build Coastguard Worker if (!pso) { 461*c8dee2aaSAndroid Build Coastguard Worker SKGPU_LOG_E("Render pipeline creation failure:\n%s", error.debugDescription.UTF8String); 462*c8dee2aaSAndroid Build Coastguard Worker return nullptr; 463*c8dee2aaSAndroid Build Coastguard Worker } 464*c8dee2aaSAndroid Build Coastguard Worker 465*c8dee2aaSAndroid Build Coastguard Worker return sk_sp<MtlGraphicsPipeline>(new MtlGraphicsPipeline(sharedContext, 466*c8dee2aaSAndroid Build Coastguard Worker pipelineInfo, 467*c8dee2aaSAndroid Build Coastguard Worker std::move(pso), 468*c8dee2aaSAndroid Build Coastguard Worker std::move(dss), 469*c8dee2aaSAndroid Build Coastguard Worker stencilRefValue)); 470*c8dee2aaSAndroid Build Coastguard Worker} 471*c8dee2aaSAndroid Build Coastguard Worker 472*c8dee2aaSAndroid Build Coastguard WorkerMtlGraphicsPipeline::MtlGraphicsPipeline(const skgpu::graphite::SharedContext* sharedContext, 473*c8dee2aaSAndroid Build Coastguard Worker const PipelineInfo& pipelineInfo, 474*c8dee2aaSAndroid Build Coastguard Worker sk_cfp<id<MTLRenderPipelineState>> pso, 475*c8dee2aaSAndroid Build Coastguard Worker sk_cfp<id<MTLDepthStencilState>> dss, 476*c8dee2aaSAndroid Build Coastguard Worker uint32_t refValue) 477*c8dee2aaSAndroid Build Coastguard Worker : GraphicsPipeline(sharedContext, pipelineInfo) 478*c8dee2aaSAndroid Build Coastguard Worker , fPipelineState(std::move(pso)) 479*c8dee2aaSAndroid Build Coastguard Worker , fDepthStencilState(std::move(dss)) 480*c8dee2aaSAndroid Build Coastguard Worker , fStencilReferenceValue(refValue) {} 481*c8dee2aaSAndroid Build Coastguard Worker 482*c8dee2aaSAndroid Build Coastguard Workervoid MtlGraphicsPipeline::freeGpuData() { 483*c8dee2aaSAndroid Build Coastguard Worker fPipelineState.reset(); 484*c8dee2aaSAndroid Build Coastguard Worker} 485*c8dee2aaSAndroid Build Coastguard Worker 486*c8dee2aaSAndroid Build Coastguard Worker} // namespace skgpu::graphite 487