blob: b2bcf0827eee981d3a7902eae3af4a3c11894dc5 [file] [log] [blame]
Timothy Liang057c3902018-08-08 10:48:45 -04001/*
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
8#include "GrMtlPipelineState.h"
9
Timothy Liang6ed63962018-08-10 09:49:44 -040010#include "GrContext.h"
11#include "GrContextPriv.h"
12#include "GrPipeline.h"
13#include "GrRenderTarget.h"
14#include "GrTexturePriv.h"
Timothy Liang057c3902018-08-08 10:48:45 -040015#include "GrMtlBuffer.h"
16#include "GrMtlGpu.h"
Timothy Liang6ed63962018-08-10 09:49:44 -040017#include "GrMtlSampler.h"
18#include "GrMtlTexture.h"
19#include "glsl/GrGLSLFragmentProcessor.h"
20#include "glsl/GrGLSLGeometryProcessor.h"
21#include "glsl/GrGLSLXferProcessor.h"
Timothy Liang057c3902018-08-08 10:48:45 -040022
Timothy Liang6ed63962018-08-10 09:49:44 -040023GrMtlPipelineState::SamplerBindings::SamplerBindings(const GrSamplerState& state,
24 GrTexture* texture,
25 GrShaderFlags flags,
26 GrMtlGpu* gpu)
27 : fTexture(static_cast<GrMtlTexture*>(texture)->mtlTexture())
28 , fVisibility(flags) {
29 // TODO: use resource provider to get sampler.
30 std::unique_ptr<GrMtlSampler> sampler(
31 GrMtlSampler::Create(gpu, state, texture->texturePriv().maxMipMapLevel()));
32 fSampler = sampler->mtlSamplerState();
33}
34
35GrMtlPipelineState::GrMtlPipelineState(
36 GrMtlGpu* gpu,
37 id<MTLRenderPipelineState> pipelineState,
38 MTLPixelFormat pixelFormat,
39 const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
40 const UniformInfoArray& uniforms,
41 GrMtlBuffer* geometryUniformBuffer,
42 GrMtlBuffer* fragmentUniformBuffer,
43 uint32_t numSamplers,
44 std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
45 std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
46 std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,
47 int fragmentProcessorCnt)
Timothy Liang057c3902018-08-08 10:48:45 -040048 : fGpu(gpu)
49 , fPipelineState(pipelineState)
50 , fPixelFormat(pixelFormat)
Timothy Liang6ed63962018-08-10 09:49:44 -040051 , fBuiltinUniformHandles(builtinUniformHandles)
Timothy Liang057c3902018-08-08 10:48:45 -040052 , fGeometryUniformBuffer(geometryUniformBuffer)
Timothy Liang6ed63962018-08-10 09:49:44 -040053 , fFragmentUniformBuffer(fragmentUniformBuffer)
54 , fNumSamplers(numSamplers)
55 , fGeometryProcessor(std::move(geometryProcessor))
56 , fXferProcessor(std::move(xferProcessor))
57 , fFragmentProcessors(std::move(fragmentProcessors))
58 , fFragmentProcessorCnt(fragmentProcessorCnt)
59 , fDataManager(uniforms, geometryUniformBuffer->sizeInBytes(),
60 fragmentUniformBuffer->sizeInBytes()) {
Timothy Liang057c3902018-08-08 10:48:45 -040061 (void) fPixelFormat; // Suppress unused-var warning.
62}
Timothy Liang6ed63962018-08-10 09:49:44 -040063
64void GrMtlPipelineState::setData(const GrPrimitiveProcessor& primProc,
65 const GrPipeline& pipeline,
66 const GrTextureProxy* const primProcTextures[]) {
67 SkASSERT(primProcTextures || !primProc.numTextureSamplers());
68
69 this->setRenderTargetState(pipeline.proxy());
70 fGeometryProcessor->setData(fDataManager, primProc,
71 GrFragmentProcessor::CoordTransformIter(pipeline));
72 fSamplerBindings.reset();
73 for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
74 const auto& sampler = primProc.textureSampler(i);
75 auto texture = static_cast<GrMtlTexture*>(primProcTextures[i]->peekTexture());
76 fSamplerBindings.emplace_back(sampler.samplerState(), texture, sampler.visibility(), fGpu);
77 }
78
79 GrFragmentProcessor::Iter iter(pipeline);
80 GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
81 const GrFragmentProcessor* fp = iter.next();
82 GrGLSLFragmentProcessor* glslFP = glslIter.next();
83 while (fp && glslFP) {
84 glslFP->setData(fDataManager, *fp);
85 for (int i = 0; i < fp->numTextureSamplers(); ++i) {
86 const auto& sampler = fp->textureSampler(i);
87 fSamplerBindings.emplace_back(sampler.samplerState(), sampler.peekTexture(),
88 kFragment_GrShaderFlag, fGpu);
89 }
90 fp = iter.next();
91 glslFP = glslIter.next();
92 }
93 SkASSERT(!fp && !glslFP);
94
95 {
96 SkIPoint offset;
97 GrTexture* dstTexture = pipeline.peekDstTexture(&offset);
98
99 fXferProcessor->setData(fDataManager, pipeline.getXferProcessor(), dstTexture, offset);
100 }
101
102 if (GrTextureProxy* dstTextureProxy = pipeline.dstTextureProxy()) {
103 fSamplerBindings.emplace_back(GrSamplerState::ClampNearest(),
104 dstTextureProxy->peekTexture(),
105 kFragment_GrShaderFlag,
106 fGpu);
107 }
108
109 SkASSERT(fNumSamplers == fSamplerBindings.count());
110 if (fGeometryUniformBuffer || fFragmentUniformBuffer) {
111 fDataManager.uploadUniformBuffers(fGpu, fGeometryUniformBuffer.get(),
112 fFragmentUniformBuffer.get());
113 }
114}
115
116void GrMtlPipelineState::bind(id<MTLRenderCommandEncoder> renderCmdEncoder) {
117 if (fGeometryUniformBuffer) {
118 [renderCmdEncoder setVertexBuffer: fGeometryUniformBuffer->mtlBuffer()
119 offset: 0
120 atIndex: GrMtlUniformHandler::kGeometryBinding];
121 }
122 if (fFragmentUniformBuffer) {
123 [renderCmdEncoder setFragmentBuffer: fFragmentUniformBuffer->mtlBuffer()
124 offset: 0
125 atIndex: GrMtlUniformHandler::kFragBinding];
126 }
127 SkASSERT(fNumSamplers == fSamplerBindings.count());
128 for (int index = 0; index < fNumSamplers; ++index) {
129 if (fSamplerBindings[index].fVisibility & kVertex_GrShaderFlag) {
130 [renderCmdEncoder setVertexTexture: fSamplerBindings[index].fTexture
131 atIndex: index];
132 [renderCmdEncoder setVertexSamplerState: fSamplerBindings[index].fSampler
133 atIndex: index];
134 }
135 if (fSamplerBindings[index].fVisibility & kFragment_GrShaderFlag) {
136 [renderCmdEncoder setFragmentTexture: fSamplerBindings[index].fTexture
137 atIndex: index];
138 [renderCmdEncoder setFragmentSamplerState: fSamplerBindings[index].fSampler
139 atIndex: index];
140 }
141 }
142}
143
144void GrMtlPipelineState::setRenderTargetState(const GrRenderTargetProxy* proxy) {
145 GrRenderTarget* rt = proxy->peekRenderTarget();
146
147 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
Greg Daniele6ab9982018-08-22 13:56:32 +0000148 if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
149 fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
150 fDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height()));
Timothy Liang6ed63962018-08-10 09:49:44 -0400151 }
152
153 // set RT adjustment
154 SkISize size;
155 size.set(rt->width(), rt->height());
156 SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
157 if (fRenderTargetState.fRenderTargetOrigin != proxy->origin() ||
158 fRenderTargetState.fRenderTargetSize != size) {
159 fRenderTargetState.fRenderTargetSize = size;
160 fRenderTargetState.fRenderTargetOrigin = proxy->origin();
161
162 float rtAdjustmentVec[4];
163 fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
164 fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
165 }
166}
Timothy Liangde0be802018-08-10 13:48:08 -0400167
168static bool blend_coeff_refs_constant(GrBlendCoeff coeff) {
169 switch (coeff) {
170 case kConstC_GrBlendCoeff:
171 case kIConstC_GrBlendCoeff:
172 case kConstA_GrBlendCoeff:
173 case kIConstA_GrBlendCoeff:
174 return true;
175 default:
176 return false;
177 }
178}
179
180void GrMtlPipelineState::setBlendConstants(id<MTLRenderCommandEncoder> renderCmdEncoder,
181 GrPixelConfig config,
182 const GrXferProcessor& xferProcessor) {
183 if (!renderCmdEncoder) {
184 return;
185 }
186
187 GrXferProcessor::BlendInfo blendInfo;
188 xferProcessor.getBlendInfo(&blendInfo);
189 GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
190 GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
191 if (blend_coeff_refs_constant(srcCoeff) || blend_coeff_refs_constant(dstCoeff)) {
192 float floatColors[4];
193 // Swizzle the blend to match what the shader will output.
194 const GrSwizzle& swizzle = fGpu->caps()->shaderCaps()->configOutputSwizzle(config);
195 GrColor blendConst = swizzle.applyTo(blendInfo.fBlendConstant);
196 GrColorToRGBAFloat(blendConst, floatColors);
197
198 [renderCmdEncoder setBlendColorRed: floatColors[0]
199 green: floatColors[1]
200 blue: floatColors[2]
201 alpha: floatColors[3]];
202 }
203}