blob: 018f3dff98b5aaf8b37d67c91c58a71e9801f6d0 [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,
Timothy Liang6ed63962018-08-10 09:49:44 -040025 GrMtlGpu* gpu)
Greg Daniel0f70be82018-10-08 17:35:08 +000026 : fTexture(static_cast<GrMtlTexture*>(texture)->mtlTexture()) {
Timothy Liang6ed63962018-08-10 09:49:44 -040027 // TODO: use resource provider to get sampler.
28 std::unique_ptr<GrMtlSampler> sampler(
29 GrMtlSampler::Create(gpu, state, texture->texturePriv().maxMipMapLevel()));
30 fSampler = sampler->mtlSamplerState();
31}
32
33GrMtlPipelineState::GrMtlPipelineState(
34 GrMtlGpu* gpu,
35 id<MTLRenderPipelineState> pipelineState,
36 MTLPixelFormat pixelFormat,
37 const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
38 const UniformInfoArray& uniforms,
39 GrMtlBuffer* geometryUniformBuffer,
40 GrMtlBuffer* fragmentUniformBuffer,
41 uint32_t numSamplers,
42 std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
43 std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
44 std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,
45 int fragmentProcessorCnt)
Timothy Liang057c3902018-08-08 10:48:45 -040046 : fGpu(gpu)
47 , fPipelineState(pipelineState)
48 , fPixelFormat(pixelFormat)
Timothy Liang6ed63962018-08-10 09:49:44 -040049 , fBuiltinUniformHandles(builtinUniformHandles)
Timothy Liang057c3902018-08-08 10:48:45 -040050 , fGeometryUniformBuffer(geometryUniformBuffer)
Timothy Liang6ed63962018-08-10 09:49:44 -040051 , fFragmentUniformBuffer(fragmentUniformBuffer)
52 , fNumSamplers(numSamplers)
53 , fGeometryProcessor(std::move(geometryProcessor))
54 , fXferProcessor(std::move(xferProcessor))
55 , fFragmentProcessors(std::move(fragmentProcessors))
56 , fFragmentProcessorCnt(fragmentProcessorCnt)
57 , fDataManager(uniforms, geometryUniformBuffer->sizeInBytes(),
58 fragmentUniformBuffer->sizeInBytes()) {
Timothy Liang057c3902018-08-08 10:48:45 -040059 (void) fPixelFormat; // Suppress unused-var warning.
60}
Timothy Liang6ed63962018-08-10 09:49:44 -040061
62void GrMtlPipelineState::setData(const GrPrimitiveProcessor& primProc,
63 const GrPipeline& pipeline,
64 const GrTextureProxy* const primProcTextures[]) {
65 SkASSERT(primProcTextures || !primProc.numTextureSamplers());
66
67 this->setRenderTargetState(pipeline.proxy());
68 fGeometryProcessor->setData(fDataManager, primProc,
69 GrFragmentProcessor::CoordTransformIter(pipeline));
70 fSamplerBindings.reset();
71 for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
72 const auto& sampler = primProc.textureSampler(i);
73 auto texture = static_cast<GrMtlTexture*>(primProcTextures[i]->peekTexture());
Greg Daniel0f70be82018-10-08 17:35:08 +000074 fSamplerBindings.emplace_back(sampler.samplerState(), texture, fGpu);
Timothy Liang6ed63962018-08-10 09:49:44 -040075 }
76
77 GrFragmentProcessor::Iter iter(pipeline);
78 GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
79 const GrFragmentProcessor* fp = iter.next();
80 GrGLSLFragmentProcessor* glslFP = glslIter.next();
81 while (fp && glslFP) {
Michael Ludwigd3a357d2018-09-27 17:31:08 -040082 glslFP->setData(fDataManager, *fp);
Timothy Liang6ed63962018-08-10 09:49:44 -040083 for (int i = 0; i < fp->numTextureSamplers(); ++i) {
84 const auto& sampler = fp->textureSampler(i);
Greg Daniel0f70be82018-10-08 17:35:08 +000085 fSamplerBindings.emplace_back(sampler.samplerState(), sampler.peekTexture(), fGpu);
Timothy Liang6ed63962018-08-10 09:49:44 -040086 }
87 fp = iter.next();
88 glslFP = glslIter.next();
89 }
90 SkASSERT(!fp && !glslFP);
91
92 {
93 SkIPoint offset;
94 GrTexture* dstTexture = pipeline.peekDstTexture(&offset);
95
96 fXferProcessor->setData(fDataManager, pipeline.getXferProcessor(), dstTexture, offset);
97 }
98
99 if (GrTextureProxy* dstTextureProxy = pipeline.dstTextureProxy()) {
100 fSamplerBindings.emplace_back(GrSamplerState::ClampNearest(),
101 dstTextureProxy->peekTexture(),
Timothy Liang6ed63962018-08-10 09:49:44 -0400102 fGpu);
103 }
104
105 SkASSERT(fNumSamplers == fSamplerBindings.count());
106 if (fGeometryUniformBuffer || fFragmentUniformBuffer) {
107 fDataManager.uploadUniformBuffers(fGpu, fGeometryUniformBuffer.get(),
108 fFragmentUniformBuffer.get());
109 }
110}
111
112void GrMtlPipelineState::bind(id<MTLRenderCommandEncoder> renderCmdEncoder) {
113 if (fGeometryUniformBuffer) {
114 [renderCmdEncoder setVertexBuffer: fGeometryUniformBuffer->mtlBuffer()
115 offset: 0
116 atIndex: GrMtlUniformHandler::kGeometryBinding];
117 }
118 if (fFragmentUniformBuffer) {
119 [renderCmdEncoder setFragmentBuffer: fFragmentUniformBuffer->mtlBuffer()
120 offset: 0
121 atIndex: GrMtlUniformHandler::kFragBinding];
122 }
123 SkASSERT(fNumSamplers == fSamplerBindings.count());
124 for (int index = 0; index < fNumSamplers; ++index) {
Greg Daniel0f70be82018-10-08 17:35:08 +0000125 [renderCmdEncoder setFragmentTexture: fSamplerBindings[index].fTexture
126 atIndex: index];
127 [renderCmdEncoder setFragmentSamplerState: fSamplerBindings[index].fSampler
128 atIndex: index];
Timothy Liang6ed63962018-08-10 09:49:44 -0400129 }
130}
131
132void GrMtlPipelineState::setRenderTargetState(const GrRenderTargetProxy* proxy) {
133 GrRenderTarget* rt = proxy->peekRenderTarget();
134
135 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
Greg Daniele6ab9982018-08-22 13:56:32 +0000136 if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
137 fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
138 fDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height()));
Timothy Liang6ed63962018-08-10 09:49:44 -0400139 }
140
141 // set RT adjustment
142 SkISize size;
143 size.set(rt->width(), rt->height());
144 SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
145 if (fRenderTargetState.fRenderTargetOrigin != proxy->origin() ||
146 fRenderTargetState.fRenderTargetSize != size) {
147 fRenderTargetState.fRenderTargetSize = size;
148 fRenderTargetState.fRenderTargetOrigin = proxy->origin();
149
150 float rtAdjustmentVec[4];
151 fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
152 fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
153 }
154}
Timothy Liangde0be802018-08-10 13:48:08 -0400155
156static bool blend_coeff_refs_constant(GrBlendCoeff coeff) {
157 switch (coeff) {
158 case kConstC_GrBlendCoeff:
159 case kIConstC_GrBlendCoeff:
160 case kConstA_GrBlendCoeff:
161 case kIConstA_GrBlendCoeff:
162 return true;
163 default:
164 return false;
165 }
166}
167
168void GrMtlPipelineState::setBlendConstants(id<MTLRenderCommandEncoder> renderCmdEncoder,
169 GrPixelConfig config,
170 const GrXferProcessor& xferProcessor) {
171 if (!renderCmdEncoder) {
172 return;
173 }
174
175 GrXferProcessor::BlendInfo blendInfo;
176 xferProcessor.getBlendInfo(&blendInfo);
177 GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
178 GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
179 if (blend_coeff_refs_constant(srcCoeff) || blend_coeff_refs_constant(dstCoeff)) {
180 float floatColors[4];
181 // Swizzle the blend to match what the shader will output.
182 const GrSwizzle& swizzle = fGpu->caps()->shaderCaps()->configOutputSwizzle(config);
183 GrColor blendConst = swizzle.applyTo(blendInfo.fBlendConstant);
184 GrColorToRGBAFloat(blendConst, floatColors);
185
186 [renderCmdEncoder setBlendColorRed: floatColors[0]
187 green: floatColors[1]
188 blue: floatColors[2]
189 alpha: floatColors[3]];
190 }
191}