Flutter Engine
The Flutter Engine
GrMtlPipelineState.mm
Go to the documentation of this file.
1/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
23
24#if !__has_feature(objc_arc)
25#error This file must be compiled with Arc. Use -fobjc-arc flag
26#endif
27
28GR_NORETAIN_BEGIN
29
30GrMtlPipelineState::SamplerBindings::SamplerBindings(GrSamplerState state,
32 GrMtlGpu* gpu)
33 : fTexture(static_cast<GrMtlTexture*>(texture)->mtlTexture()) {
35 gpu->commandBuffer()->addResource(sk_ref_sp<GrManagedResource>(fSampler));
37 sk_ref_sp<GrSurface>(static_cast<GrMtlTexture*>(texture)->attachment()));
38}
39
41 GrMtlGpu* gpu,
43 MTLPixelFormat pixelFormat,
44 const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
45 const UniformInfoArray& uniforms,
46 uint32_t uniformBufferSize,
47 uint32_t numSamplers,
48 std::unique_ptr<GrGeometryProcessor::ProgramImpl> gpImpl,
49 std::unique_ptr<GrXferProcessor::ProgramImpl> xpImpl,
50 std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fpImpls)
51 : fGpu(gpu)
52 , fPipeline(std::move(pipeline))
53 , fPixelFormat(pixelFormat)
54 , fBuiltinUniformHandles(builtinUniformHandles)
55 , fNumSamplers(numSamplers)
56 , fGPImpl(std::move(gpImpl))
57 , fXPImpl(std::move(xpImpl))
58 , fFPImpls(std::move(fpImpls))
59 , fDataManager(uniforms, uniformBufferSize) {
60 (void) fPixelFormat; // Suppress unused-var warning.
61}
62
64 const GrProgramInfo& programInfo) {
65 SkISize colorAttachmentDimensions = framebuffer->colorAttachment()->dimensions();
66
67 this->setRenderTargetState(colorAttachmentDimensions, programInfo.origin());
68 fGPImpl->setData(fDataManager, *fGpu->caps()->shaderCaps(), programInfo.geomProc());
69
70 for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) {
71 const auto& fp = programInfo.pipeline().getFragmentProcessor(i);
72 fp.visitWithImpls([&](const GrFragmentProcessor& fp,
74 impl.setData(fDataManager, fp);
75 }, *fFPImpls[i]);
76 }
77
78 programInfo.pipeline().setDstTextureUniforms(fDataManager, &fBuiltinUniformHandles);
79 fXPImpl->setData(fDataManager, programInfo.pipeline().getXferProcessor());
80
81 fDataManager.resetDirtyBits();
82
83#ifdef SK_DEBUG
84 if (programInfo.isStencilEnabled()) {
85 SkDEBUGCODE(const GrAttachment* stencil = framebuffer->stencilAttachment());
86 SkASSERT(stencil);
87 SkASSERT(GrBackendFormatStencilBits(stencil->backendFormat()) == 8);
88 }
89#endif
90
91 fStencil = programInfo.nonGLStencilSettings();
92 fGpu->commandBuffer()->addResource(fPipeline);
93}
94
96 const GrPipeline& pipeline,
97 const GrSurfaceProxy* const geomProcTextures[]) {
98 fSamplerBindings.clear();
99 for (int i = 0; i < geomProc.numTextureSamplers(); ++i) {
100 SkASSERT(geomProcTextures[i]->asTextureProxy());
101 const auto& sampler = geomProc.textureSampler(i);
102 auto texture = static_cast<GrMtlTexture*>(geomProcTextures[i]->peekTexture());
103 fSamplerBindings.emplace_back(sampler.samplerState(), texture, fGpu);
104 }
105
106 if (GrTextureProxy* dstTextureProxy = pipeline.dstProxyView().asTextureProxy()) {
107 fSamplerBindings.emplace_back(
108 GrSamplerState::Filter::kNearest, dstTextureProxy->peekTexture(), fGpu);
109 }
110
111 pipeline.visitTextureEffects([&](const GrTextureEffect& te) {
112 fSamplerBindings.emplace_back(te.samplerState(), te.texture(), fGpu);
113 });
114
115 SkASSERT(fNumSamplers == fSamplerBindings.size());
116}
117
119 const skgpu::Swizzle& writeSwizzle,
120 const GrXferProcessor& xferProcessor) {
121 this->bindUniforms(renderCmdEncoder);
122 this->setBlendConstants(renderCmdEncoder, writeSwizzle, xferProcessor);
123 this->setDepthStencilState(renderCmdEncoder);
124}
125
126void GrMtlPipelineState::bindUniforms(GrMtlRenderCommandEncoder* renderCmdEncoder) {
127 fDataManager.uploadAndBindUniformBuffers(fGpu, renderCmdEncoder);
128}
129
131 SkASSERT(fNumSamplers == fSamplerBindings.size());
132 for (int index = 0; index < fNumSamplers; ++index) {
133 renderCmdEncoder->setFragmentTexture(fSamplerBindings[index].fTexture, index);
134 renderCmdEncoder->setFragmentSamplerState(fSamplerBindings[index].fSampler, index);
135 }
136}
137
138void GrMtlPipelineState::setRenderTargetState(SkISize colorAttachmentDimensions,
139 GrSurfaceOrigin origin) {
140 SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
141 if (fRenderTargetState.fRenderTargetOrigin != origin ||
142 fRenderTargetState.fRenderTargetSize != colorAttachmentDimensions) {
143 fRenderTargetState.fRenderTargetSize = colorAttachmentDimensions;
144 fRenderTargetState.fRenderTargetOrigin = origin;
145
146 // The client will mark a swap buffer as kTopLeft when making a SkSurface because
147 // Metal's framebuffer space has (0, 0) at the top left. This agrees with Skia's device
148 // coords. However, in NDC (-1, -1) is the bottom left. So we flip when origin is kTopLeft.
149 bool flip = (origin == kTopLeft_GrSurfaceOrigin);
150 std::array<float, 4> v = SkSL::Compiler::GetRTAdjustVector(colorAttachmentDimensions, flip);
151 fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, v.data());
152 if (fBuiltinUniformHandles.fRTFlipUni.isValid()) {
153 // Note above that framebuffer space has origin top left. So we need !flip here.
154 std::array<float, 2> d =
155 SkSL::Compiler::GetRTFlipVector(colorAttachmentDimensions.height(), !flip);
156 fDataManager.set2fv(fBuiltinUniformHandles.fRTFlipUni, 1, d.data());
157 }
158 }
159}
160
161void GrMtlPipelineState::setBlendConstants(GrMtlRenderCommandEncoder* renderCmdEncoder,
162 const skgpu::Swizzle& swizzle,
163 const GrXferProcessor& xferProcessor) {
164 if (!renderCmdEncoder) {
165 return;
166 }
167
168 const skgpu::BlendInfo& blendInfo = xferProcessor.getBlendInfo();
169 skgpu::BlendCoeff srcCoeff = blendInfo.fSrcBlend;
170 skgpu::BlendCoeff dstCoeff = blendInfo.fDstBlend;
172 // Swizzle the blend to match what the shader will output.
173 SkPMColor4f blendConst = swizzle.applyTo(blendInfo.fBlendConstant);
174
175 renderCmdEncoder->setBlendColor(blendConst);
176 }
177}
178
179void GrMtlPipelineState::setDepthStencilState(GrMtlRenderCommandEncoder* renderCmdEncoder) {
180 const GrSurfaceOrigin& origin = fRenderTargetState.fRenderTargetOrigin;
183 if (!fStencil.isDisabled()) {
184 if (fStencil.isTwoSided()) {
185 if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) {
186 renderCmdEncoder->setStencilFrontBackReferenceValues(
187 fStencil.postOriginCCWFace(origin).fRef,
188 fStencil.postOriginCWFace(origin).fRef);
189 } else {
190 // Two-sided stencil not supported on older versions of iOS
191 // TODO: Find a way to recover from this
192 SkASSERT(false);
193 }
194 } else {
195 renderCmdEncoder->setStencilReferenceValue(fStencil.singleSidedFace().fRef);
196 }
197 }
198 renderCmdEncoder->setDepthStencilState(state->mtlDepthStencil());
199 fGpu->commandBuffer()->addResource(sk_ref_sp<GrManagedResource>(state));
200}
201
203 SkISize colorAttachmentDimensions,
204 GrSurfaceOrigin rtOrigin,
205 SkIRect scissorRect) {
206 if (!scissorRect.intersect(SkIRect::MakeWH(colorAttachmentDimensions.width(),
207 colorAttachmentDimensions.height()))) {
208 scissorRect.setEmpty();
209 }
210
211 MTLScissorRect scissor;
212 scissor.x = scissorRect.fLeft;
213 scissor.width = scissorRect.width();
214 if (kTopLeft_GrSurfaceOrigin == rtOrigin) {
215 scissor.y = scissorRect.fTop;
216 } else {
218 scissor.y = colorAttachmentDimensions.height() - scissorRect.fBottom;
219 }
220 scissor.height = scissorRect.height();
221
222 SkASSERT(scissor.x >= 0);
223 SkASSERT(scissor.y >= 0);
224
225 renderCmdEncoder->setScissorRect(scissor);
226}
227
229 const MTLRenderPassAttachmentDescriptor* attachment) const {
230 for (int i = 0; i < fSamplerBindings.size(); ++i) {
231 if (attachment.texture == fSamplerBindings[i].fTexture ||
232 attachment.resolveTexture == fSamplerBindings[i].fTexture) {
233 return false;
234 }
235 }
236 return true;
237}
238
239GR_NORETAIN_END
int GrBackendFormatStencilBits(const GrBackendFormat &format)
GrSurfaceOrigin
Definition: GrTypes.h:147
@ kBottomLeft_GrSurfaceOrigin
Definition: GrTypes.h:149
@ kTopLeft_GrSurfaceOrigin
Definition: GrTypes.h:148
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
const GrShaderCaps * shaderCaps() const
Definition: GrCaps.h:63
void setData(const GrGLSLProgramDataManager &pdman, const GrFragmentProcessor &processor)
const TextureSampler & textureSampler(int index) const
const GrCaps * caps() const
Definition: GrGpu.h:73
void addResource(const sk_sp< const GrManagedResource > &resource)
void addGrSurface(sk_sp< const GrSurface > surface)
GrMtlAttachment * stencilAttachment()
GrMtlAttachment * colorAttachment()
GrMtlCommandBuffer * commandBuffer()
Definition: GrMtlGpu.mm:187
GrMtlResourceProvider & resourceProvider()
Definition: GrMtlGpu.h:51
void set2fv(UniformHandle, int arrayCount, const float v[]) const override
void uploadAndBindUniformBuffers(GrMtlGpu *gpu, GrMtlRenderCommandEncoder *renderCmdEncoder) const
void setDrawState(GrMtlRenderCommandEncoder *, const skgpu::Swizzle &writeSwizzle, const GrXferProcessor &)
GrMtlPipelineState(GrMtlGpu *, sk_sp< GrMtlRenderPipeline > pipeline, MTLPixelFormat, const GrGLSLBuiltinUniformHandles &builtinUniformHandles, const UniformInfoArray &uniforms, uint32_t uniformBufferSize, uint32_t numSamplers, std::unique_ptr< GrGeometryProcessor::ProgramImpl >, std::unique_ptr< GrXferProcessor::ProgramImpl >, std::vector< std::unique_ptr< GrFragmentProcessor::ProgramImpl > > fpImpls)
static void SetDynamicScissorRectState(GrMtlRenderCommandEncoder *renderCmdEncoder, SkISize colorAttachmentDimensions, GrSurfaceOrigin rtOrigin, SkIRect scissorRect)
bool doesntSampleAttachment(const MTLRenderPassAttachmentDescriptor *) const
void bindTextures(GrMtlRenderCommandEncoder *renderCmdEncoder)
void setTextures(const GrGeometryProcessor &, const GrPipeline &, const GrSurfaceProxy *const geomProcTextures[])
void setData(GrMtlFramebuffer *, const GrProgramInfo &)
const sk_sp< GrMtlRenderPipeline > & pipeline() const
void setDepthStencilState(id< MTLDepthStencilState > depthStencilState)
void setBlendColor(SkPMColor4f blendConst)
void setFragmentTexture(id< MTLTexture > texture, NSUInteger index)
void setScissorRect(const MTLScissorRect &scissorRect)
void setFragmentSamplerState(GrMtlSampler *sampler, NSUInteger index)
void setStencilReferenceValue(uint32_t referenceValue)
void setStencilFrontBackReferenceValues(uint32_t frontReferenceValue, uint32_t backReferenceValue) SK_API_AVAILABLE(macos(10.11)
GrMtlDepthStencil * findOrCreateCompatibleDepthStencilState(const GrStencilSettings &, GrSurfaceOrigin)
GrMtlSampler * findOrCreateCompatibleSampler(GrSamplerState)
void setDstTextureUniforms(const GrGLSLProgramDataManager &pdm, GrGLSLBuiltinUniformHandles *fBuiltinUniformHandles) const
Definition: GrPipeline.cpp:115
const GrFragmentProcessor & getFragmentProcessor(int idx) const
Definition: GrPipeline.h:157
const GrXferProcessor & getXferProcessor() const
Definition: GrPipeline.h:116
GrSurfaceOrigin origin() const
Definition: GrProgramInfo.h:38
const GrPipeline & pipeline() const
Definition: GrProgramInfo.h:39
const GrGeometryProcessor & geomProc() const
Definition: GrProgramInfo.h:40
bool isStencilEnabled() const
Definition: GrProgramInfo.h:31
GrStencilSettings nonGLStencilSettings() const
bool isTwoSided() const
const Face & postOriginCCWFace(GrSurfaceOrigin origin) const
bool isDisabled() const
const Face & singleSidedFace() const
const Face & postOriginCWFace(GrSurfaceOrigin origin) const
GrTexture * peekTexture() const
SkISize dimensions() const
Definition: GrSurface.h:27
GrTexture * texture() const
GrSamplerState samplerState() const
void set4fv(UniformHandle, int arrayCount, const float v[]) const override
skgpu::BlendInfo getBlendInfo() const
static std::array< float, 2 > GetRTFlipVector(int rtHeight, bool flipY)
Definition: SkSLCompiler.h:99
static std::array< float, 4 > GetRTAdjustVector(SkISize rtDims, bool flipY)
Definition: SkSLCompiler.h:82
constexpr std::array< float, 4 > applyTo(std::array< float, 4 > color) const
Definition: Swizzle.h:101
int size() const
Definition: SkTArray.h:421
T & emplace_back(Args &&... args)
Definition: SkTArray.h:248
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
AtkStateType state
FlTexture * texture
const uint32_t fp
static constexpr bool BlendCoeffRefsConstant(const BlendCoeff coeff)
Definition: Blend.h:141
BlendCoeff
Definition: Blend.h:60
Definition: ref_ptr.h:256
GrGLSLProgramDataManager::UniformHandle fRTFlipUni
GrGLSLProgramDataManager::UniformHandle fRTAdjustmentUni
Definition: SkRect.h:32
bool intersect(const SkIRect &r)
Definition: SkRect.h:513
int32_t fBottom
larger y-axis bounds
Definition: SkRect.h:36
constexpr int32_t height() const
Definition: SkRect.h:165
int32_t fTop
smaller y-axis bounds
Definition: SkRect.h:34
constexpr int32_t width() const
Definition: SkRect.h:158
void setEmpty()
Definition: SkRect.h:242
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
Definition: SkRect.h:56
int32_t fLeft
smaller x-axis bounds
Definition: SkRect.h:33
Definition: SkSize.h:16
constexpr int32_t width() const
Definition: SkSize.h:36
constexpr int32_t height() const
Definition: SkSize.h:37
skgpu::BlendCoeff fDstBlend
Definition: Blend.h:96
SkPMColor4f fBlendConstant
Definition: Blend.h:97
skgpu::BlendCoeff fSrcBlend
Definition: Blend.h:95