blob: e10780d15d0def1c1c26e1fa67be85cdd50dfb4d [file] [log] [blame]
jvanverth992ad362016-02-26 09:21:02 -08001/*
2* Copyright 2016 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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/gpu/GrContext.h"
9#include "include/gpu/GrRenderTarget.h"
10#include "src/core/SkMipMap.h"
11#include "src/gpu/GrContextPriv.h"
12#include "src/gpu/GrPipeline.h"
13#include "src/gpu/GrTexturePriv.h"
14#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
15#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
16#include "src/gpu/glsl/GrGLSLXferProcessor.h"
17#include "src/gpu/vk/GrVkBufferView.h"
18#include "src/gpu/vk/GrVkCommandBuffer.h"
19#include "src/gpu/vk/GrVkDescriptorPool.h"
20#include "src/gpu/vk/GrVkDescriptorSet.h"
21#include "src/gpu/vk/GrVkGpu.h"
22#include "src/gpu/vk/GrVkImageView.h"
23#include "src/gpu/vk/GrVkMemory.h"
24#include "src/gpu/vk/GrVkPipeline.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050025#include "src/gpu/vk/GrVkPipelineState.h"
26#include "src/gpu/vk/GrVkSampler.h"
27#include "src/gpu/vk/GrVkTexture.h"
28#include "src/gpu/vk/GrVkUniformBuffer.h"
jvanverth992ad362016-02-26 09:21:02 -080029
Brian Salomon1471df92018-06-08 10:49:00 -040030GrVkPipelineState::GrVkPipelineState(
31 GrVkGpu* gpu,
Brian Salomon4d3f5172018-06-07 14:42:52 -040032 GrVkPipeline* pipeline,
Brian Salomon4d3f5172018-06-07 14:42:52 -040033 const GrVkDescriptorSetManager::Handle& samplerDSHandle,
Brian Salomon1471df92018-06-08 10:49:00 -040034 const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
Brian Salomon4d3f5172018-06-07 14:42:52 -040035 const UniformInfoArray& uniforms,
36 uint32_t geometryUniformSize,
37 uint32_t fragmentUniformSize,
Greg Daniel7a82edf2018-12-04 10:54:34 -050038 const UniformInfoArray& samplers,
Brian Salomon4d3f5172018-06-07 14:42:52 -040039 std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
40 std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
41 std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,
42 int fragmentProcessorCnt)
43 : fPipeline(pipeline)
Brian Salomon4d3f5172018-06-07 14:42:52 -040044 , fUniformDescriptorSet(nullptr)
45 , fSamplerDescriptorSet(nullptr)
Brian Salomon4d3f5172018-06-07 14:42:52 -040046 , fSamplerDSHandle(samplerDSHandle)
Brian Salomon4d3f5172018-06-07 14:42:52 -040047 , fBuiltinUniformHandles(builtinUniformHandles)
48 , fGeometryProcessor(std::move(geometryProcessor))
49 , fXferProcessor(std::move(xferProcessor))
50 , fFragmentProcessors(std::move(fragmentProcessors))
51 , fFragmentProcessorCnt(fragmentProcessorCnt)
Brian Salomon4d3f5172018-06-07 14:42:52 -040052 , fDataManager(uniforms, geometryUniformSize, fragmentUniformSize) {
egdanielc2dc1b22016-03-18 13:18:23 -070053 fDescriptorSets[0] = VK_NULL_HANDLE;
54 fDescriptorSets[1] = VK_NULL_HANDLE;
Greg Daniel31ec1442017-05-08 10:30:59 -040055 fDescriptorSets[2] = VK_NULL_HANDLE;
jvanverth992ad362016-02-26 09:21:02 -080056
Greg Daniel18f96022017-05-04 15:09:03 -040057 fGeometryUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, geometryUniformSize));
jvanverth4c6e47a2016-07-22 10:34:52 -070058 fFragmentUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, fragmentUniformSize));
jvanverth992ad362016-02-26 09:21:02 -080059
Greg Daniel7a82edf2018-12-04 10:54:34 -050060 fNumSamplers = samplers.count();
61
62 for (int i = 0; i < fNumSamplers; ++i) {
63 // We store the immutable samplers here and take ownership of the ref from the
64 // GrVkUnformHandler.
65 fImmutableSamplers.push_back(samplers[i].fImmutableSampler);
66 }
jvanverth992ad362016-02-26 09:21:02 -080067}
68
egdaniel22281c12016-03-23 13:49:40 -070069GrVkPipelineState::~GrVkPipelineState() {
Ethan Nicholas87f340e2017-01-03 14:32:01 -050070 // Must have freed all GPU resources before this is destroyed
jvanverth992ad362016-02-26 09:21:02 -080071 SkASSERT(!fPipeline);
jvanverth992ad362016-02-26 09:21:02 -080072}
73
Ethan Nicholas8e265a72018-12-12 16:22:40 -050074void GrVkPipelineState::freeGPUResources(GrVkGpu* gpu) {
jvanverth992ad362016-02-26 09:21:02 -080075 if (fPipeline) {
76 fPipeline->unref(gpu);
77 fPipeline = nullptr;
78 }
egdanielc2dc1b22016-03-18 13:18:23 -070079
Greg Daniel18f96022017-05-04 15:09:03 -040080 if (fGeometryUniformBuffer) {
81 fGeometryUniformBuffer->release(gpu);
Greg Danieladb4bfe2018-08-23 16:15:05 -040082 fGeometryUniformBuffer.reset();
jvanverth992ad362016-02-26 09:21:02 -080083 }
84
85 if (fFragmentUniformBuffer) {
86 fFragmentUniformBuffer->release(gpu);
Greg Danieladb4bfe2018-08-23 16:15:05 -040087 fFragmentUniformBuffer.reset();
jvanverth992ad362016-02-26 09:21:02 -080088 }
egdanielc2dc1b22016-03-18 13:18:23 -070089
egdaniela95220d2016-07-21 11:50:37 -070090 if (fUniformDescriptorSet) {
91 fUniformDescriptorSet->recycle(const_cast<GrVkGpu*>(gpu));
92 fUniformDescriptorSet = nullptr;
egdaniel778555c2016-05-02 06:50:36 -070093 }
egdanielc2dc1b22016-03-18 13:18:23 -070094
egdaniel707bbd62016-07-26 07:19:47 -070095 if (fSamplerDescriptorSet) {
96 fSamplerDescriptorSet->recycle(const_cast<GrVkGpu*>(gpu));
97 fSamplerDescriptorSet = nullptr;
98 }
jvanverth992ad362016-02-26 09:21:02 -080099}
100
egdaniel22281c12016-03-23 13:49:40 -0700101void GrVkPipelineState::abandonGPUResources() {
Greg Daniel7d918fd2018-06-19 15:22:01 -0400102 if (fPipeline) {
103 fPipeline->unrefAndAbandon();
104 fPipeline = nullptr;
105 }
egdanielc2dc1b22016-03-18 13:18:23 -0700106
Greg Danieladb4bfe2018-08-23 16:15:05 -0400107 if (fGeometryUniformBuffer) {
108 fGeometryUniformBuffer->abandon();
109 fGeometryUniformBuffer.reset();
110 }
111
112 if (fFragmentUniformBuffer) {
113 fFragmentUniformBuffer->abandon();
114 fFragmentUniformBuffer.reset();
115 }
jvanverth992ad362016-02-26 09:21:02 -0800116
egdaniela95220d2016-07-21 11:50:37 -0700117 if (fUniformDescriptorSet) {
118 fUniformDescriptorSet->unrefAndAbandon();
119 fUniformDescriptorSet = nullptr;
egdaniel778555c2016-05-02 06:50:36 -0700120 }
egdaniel707bbd62016-07-26 07:19:47 -0700121
122 if (fSamplerDescriptorSet) {
123 fSamplerDescriptorSet->unrefAndAbandon();
124 fSamplerDescriptorSet = nullptr;
125 }
jvanverth992ad362016-02-26 09:21:02 -0800126}
127
Brian Salomonf7232642018-09-19 08:58:08 -0400128void GrVkPipelineState::setAndBindUniforms(GrVkGpu* gpu,
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500129 const GrRenderTarget* renderTarget,
130 GrSurfaceOrigin origin,
Brian Salomonf7232642018-09-19 08:58:08 -0400131 const GrPrimitiveProcessor& primProc,
132 const GrPipeline& pipeline,
133 GrVkCommandBuffer* commandBuffer) {
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500134 this->setRenderTargetState(renderTarget, origin);
jvanverth992ad362016-02-26 09:21:02 -0800135
Brian Salomonf7232642018-09-19 08:58:08 -0400136 fGeometryProcessor->setData(fDataManager, primProc,
137 GrFragmentProcessor::CoordTransformIter(pipeline));
138 GrFragmentProcessor::Iter iter(pipeline);
139 GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
140 const GrFragmentProcessor* fp = iter.next();
141 GrGLSLFragmentProcessor* glslFP = glslIter.next();
142 while (fp && glslFP) {
143 glslFP->setData(fDataManager, *fp);
144 fp = iter.next();
145 glslFP = glslIter.next();
146 }
147 SkASSERT(!fp && !glslFP);
148
149 {
150 SkIPoint offset;
151 GrTexture* dstTexture = pipeline.peekDstTexture(&offset);
152
153 fXferProcessor->setData(fDataManager, pipeline.getXferProcessor(), dstTexture, offset);
154 }
155
156 // Get new descriptor set
157 if (fGeometryUniformBuffer || fFragmentUniformBuffer) {
158 int uniformDSIdx = GrVkUniformHandler::kUniformBufferDescSet;
159 if (fDataManager.uploadUniformBuffers(
160 gpu, fGeometryUniformBuffer.get(), fFragmentUniformBuffer.get()) ||
161 !fUniformDescriptorSet) {
162 if (fUniformDescriptorSet) {
163 fUniformDescriptorSet->recycle(gpu);
164 }
165 fUniformDescriptorSet = gpu->resourceProvider().getUniformDescriptorSet();
166 fDescriptorSets[uniformDSIdx] = fUniformDescriptorSet->descriptorSet();
167 this->writeUniformBuffers(gpu);
168 }
Greg Danieleecc6872019-07-29 13:21:37 -0400169 commandBuffer->bindDescriptorSets(gpu, this, fPipeline->layout(), uniformDSIdx, 1,
Brian Salomonf7232642018-09-19 08:58:08 -0400170 &fDescriptorSets[uniformDSIdx], 0, nullptr);
171 if (fUniformDescriptorSet) {
172 commandBuffer->addRecycledResource(fUniformDescriptorSet);
173 }
174 if (fGeometryUniformBuffer) {
175 commandBuffer->addRecycledResource(fGeometryUniformBuffer->resource());
176 }
177 if (fFragmentUniformBuffer) {
178 commandBuffer->addRecycledResource(fFragmentUniformBuffer->resource());
179 }
180 }
181}
182
183void GrVkPipelineState::setAndBindTextures(GrVkGpu* gpu,
184 const GrPrimitiveProcessor& primProc,
185 const GrPipeline& pipeline,
186 const GrTextureProxy* const primProcTextures[],
187 GrVkCommandBuffer* commandBuffer) {
188 SkASSERT(primProcTextures || !primProc.numTextureSamplers());
189
190 struct SamplerBindings {
191 GrSamplerState fState;
192 GrVkTexture* fTexture;
193 };
Brian Salomon5e81a122018-08-23 16:46:07 -0400194 SkAutoSTMalloc<8, SamplerBindings> samplerBindings(fNumSamplers);
195 int currTextureBinding = 0;
196
197 fGeometryProcessor->setData(fDataManager, primProc,
198 GrFragmentProcessor::CoordTransformIter(pipeline));
199 for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
200 const auto& sampler = primProc.textureSampler(i);
201 auto texture = static_cast<GrVkTexture*>(primProcTextures[i]->peekTexture());
202 samplerBindings[currTextureBinding++] = {sampler.samplerState(), texture};
203 }
204
205 GrFragmentProcessor::Iter iter(pipeline);
206 GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
207 const GrFragmentProcessor* fp = iter.next();
208 GrGLSLFragmentProcessor* glslFP = glslIter.next();
209 while (fp && glslFP) {
210 for (int i = 0; i < fp->numTextureSamplers(); ++i) {
211 const auto& sampler = fp->textureSampler(i);
212 samplerBindings[currTextureBinding++] =
213 {sampler.samplerState(), static_cast<GrVkTexture*>(sampler.peekTexture())};
214 }
215 fp = iter.next();
216 glslFP = glslIter.next();
217 }
218 SkASSERT(!fp && !glslFP);
219
Robert Phillipsbb581ce2017-05-29 15:05:15 -0400220 if (GrTextureProxy* dstTextureProxy = pipeline.dstTextureProxy()) {
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400221 samplerBindings[currTextureBinding++] = {
222 GrSamplerState::ClampNearest(),
223 static_cast<GrVkTexture*>(dstTextureProxy->peekTexture())};
Brian Salomon18dfa982017-04-03 16:57:43 -0400224 }
jvanverth992ad362016-02-26 09:21:02 -0800225
Brian Salomonf7232642018-09-19 08:58:08 -0400226 // Get new descriptor set
Brian Salomone782f842018-07-31 13:53:11 -0400227 SkASSERT(fNumSamplers == currTextureBinding);
egdanielc2dc1b22016-03-18 13:18:23 -0700228 if (fNumSamplers) {
egdaniel707bbd62016-07-26 07:19:47 -0700229 if (fSamplerDescriptorSet) {
230 fSamplerDescriptorSet->recycle(gpu);
231 }
232 fSamplerDescriptorSet = gpu->resourceProvider().getSamplerDescriptorSet(fSamplerDSHandle);
233 int samplerDSIdx = GrVkUniformHandler::kSamplerDescSet;
234 fDescriptorSets[samplerDSIdx] = fSamplerDescriptorSet->descriptorSet();
Brian Salomonf7232642018-09-19 08:58:08 -0400235 for (int i = 0; i < fNumSamplers; ++i) {
236 const GrSamplerState& state = samplerBindings[i].fState;
237 GrVkTexture* texture = samplerBindings[i].fTexture;
egdanielb4aa3622016-04-06 13:47:08 -0700238
Brian Salomonf7232642018-09-19 08:58:08 -0400239 const GrVkImageView* textureView = texture->textureView();
Greg Daniel7a82edf2018-12-04 10:54:34 -0500240 const GrVkSampler* sampler = nullptr;
241 if (fImmutableSamplers[i]) {
242 sampler = fImmutableSamplers[i];
243 } else {
244 sampler = gpu->resourceProvider().findOrCreateCompatibleSampler(
Greg Daniel7e000222018-12-03 10:08:21 -0500245 state, texture->ycbcrConversionInfo());
Greg Daniel7a82edf2018-12-04 10:54:34 -0500246 }
247 SkASSERT(sampler);
Brian Salomonf7232642018-09-19 08:58:08 -0400248
249 VkDescriptorImageInfo imageInfo;
250 memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo));
251 imageInfo.sampler = sampler->sampler();
252 imageInfo.imageView = textureView->imageView();
253 imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
254
255 VkWriteDescriptorSet writeInfo;
256 memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet));
257 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
258 writeInfo.pNext = nullptr;
259 writeInfo.dstSet = fDescriptorSets[GrVkUniformHandler::kSamplerDescSet];
260 writeInfo.dstBinding = i;
261 writeInfo.dstArrayElement = 0;
262 writeInfo.descriptorCount = 1;
263 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
264 writeInfo.pImageInfo = &imageInfo;
265 writeInfo.pBufferInfo = nullptr;
266 writeInfo.pTexelBufferView = nullptr;
267
268 GR_VK_CALL(gpu->vkInterface(),
269 UpdateDescriptorSets(gpu->device(), 1, &writeInfo, 0, nullptr));
270 commandBuffer->addResource(sampler);
Greg Daniel7a82edf2018-12-04 10:54:34 -0500271 if (!fImmutableSamplers[i]) {
272 sampler->unref(gpu);
273 }
Brian Salomonf7232642018-09-19 08:58:08 -0400274 commandBuffer->addResource(samplerBindings[i].fTexture->textureView());
275 commandBuffer->addResource(samplerBindings[i].fTexture->resource());
egdaniel7cbffda2016-04-08 13:27:53 -0700276 }
Brian Salomonf7232642018-09-19 08:58:08 -0400277
Greg Danieleecc6872019-07-29 13:21:37 -0400278 commandBuffer->bindDescriptorSets(gpu, this, fPipeline->layout(), samplerDSIdx, 1,
Brian Salomonf7232642018-09-19 08:58:08 -0400279 &fDescriptorSets[samplerDSIdx], 0, nullptr);
280 commandBuffer->addRecycledResource(fSamplerDescriptorSet);
egdanielb4aa3622016-04-06 13:47:08 -0700281 }
jvanverth992ad362016-02-26 09:21:02 -0800282}
283
Greg Daniel18f96022017-05-04 15:09:03 -0400284void set_uniform_descriptor_writes(VkWriteDescriptorSet* descriptorWrite,
285 VkDescriptorBufferInfo* bufferInfo,
286 const GrVkUniformBuffer* buffer,
287 VkDescriptorSet descriptorSet,
288 uint32_t binding) {
289
290 memset(bufferInfo, 0, sizeof(VkDescriptorBufferInfo));
291 bufferInfo->buffer = buffer->buffer();
292 bufferInfo->offset = buffer->offset();
293 bufferInfo->range = buffer->size();
294
295 memset(descriptorWrite, 0, sizeof(VkWriteDescriptorSet));
296 descriptorWrite->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
297 descriptorWrite->pNext = nullptr;
Greg Daniel783c4362017-05-04 17:29:09 -0400298 descriptorWrite->dstSet = descriptorSet;
Greg Daniel18f96022017-05-04 15:09:03 -0400299 descriptorWrite->dstBinding = binding;
300 descriptorWrite->dstArrayElement = 0;
301 descriptorWrite->descriptorCount = 1;
302 descriptorWrite->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
303 descriptorWrite->pImageInfo = nullptr;
304 descriptorWrite->pBufferInfo = bufferInfo;
305 descriptorWrite->pTexelBufferView = nullptr;
306}
307
egdaniel22281c12016-03-23 13:49:40 -0700308void GrVkPipelineState::writeUniformBuffers(const GrVkGpu* gpu) {
Greg Daniel18f96022017-05-04 15:09:03 -0400309 VkWriteDescriptorSet descriptorWrites[3];
310 VkDescriptorBufferInfo bufferInfos[3];
jvanverth992ad362016-02-26 09:21:02 -0800311
Greg Daniel18f96022017-05-04 15:09:03 -0400312 uint32_t writeCount = 0;
jvanverth992ad362016-02-26 09:21:02 -0800313
Greg Daniel18f96022017-05-04 15:09:03 -0400314 // Geometry Uniform Buffer
315 if (fGeometryUniformBuffer.get()) {
316 set_uniform_descriptor_writes(&descriptorWrites[writeCount],
317 &bufferInfos[writeCount],
318 fGeometryUniformBuffer.get(),
319 fDescriptorSets[GrVkUniformHandler::kUniformBufferDescSet],
320 GrVkUniformHandler::kGeometryBinding);
321 ++writeCount;
jvanverth992ad362016-02-26 09:21:02 -0800322 }
323
324 // Fragment Uniform Buffer
325 if (fFragmentUniformBuffer.get()) {
Greg Daniel18f96022017-05-04 15:09:03 -0400326 set_uniform_descriptor_writes(&descriptorWrites[writeCount],
327 &bufferInfos[writeCount],
328 fFragmentUniformBuffer.get(),
329 fDescriptorSets[GrVkUniformHandler::kUniformBufferDescSet],
330 GrVkUniformHandler::kFragBinding);
331 ++writeCount;
jvanverth992ad362016-02-26 09:21:02 -0800332 }
333
Greg Daniel18f96022017-05-04 15:09:03 -0400334 if (writeCount) {
jvanverth992ad362016-02-26 09:21:02 -0800335 GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(),
Greg Daniel18f96022017-05-04 15:09:03 -0400336 writeCount,
337 descriptorWrites,
jvanverth992ad362016-02-26 09:21:02 -0800338 0, nullptr));
339 }
340}
341
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500342void GrVkPipelineState::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin) {
Robert Phillips2890fbf2017-07-26 15:48:41 -0400343
jvanverth992ad362016-02-26 09:21:02 -0800344 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
Greg Daniele6ab9982018-08-22 13:56:32 +0000345 if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
346 fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
347 fDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height()));
jvanverth992ad362016-02-26 09:21:02 -0800348 }
349
350 // set RT adjustment
jvanverth992ad362016-02-26 09:21:02 -0800351 SkISize size;
352 size.set(rt->width(), rt->height());
353 SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500354 if (fRenderTargetState.fRenderTargetOrigin != origin ||
jvanverth992ad362016-02-26 09:21:02 -0800355 fRenderTargetState.fRenderTargetSize != size) {
356 fRenderTargetState.fRenderTargetSize = size;
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500357 fRenderTargetState.fRenderTargetOrigin = origin;
jvanverth992ad362016-02-26 09:21:02 -0800358
359 float rtAdjustmentVec[4];
360 fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
egdaniel22281c12016-03-23 13:49:40 -0700361 fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
jvanverth992ad362016-02-26 09:21:02 -0800362 }
363}
364
Brian Salomonf7232642018-09-19 08:58:08 -0400365void GrVkPipelineState::bindPipeline(const GrVkGpu* gpu, GrVkCommandBuffer* commandBuffer) {
jvanverth992ad362016-02-26 09:21:02 -0800366 commandBuffer->bindPipeline(gpu, fPipeline);
egdanielc2dc1b22016-03-18 13:18:23 -0700367}