blob: df85c42cda727e84f3972aca5aa541d2bd255e74 [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
egdaniel22281c12016-03-23 13:49:40 -07008#include "GrVkPipelineState.h"
Robert Phillips9bee2e52017-05-29 12:37:20 -04009#include "GrContext.h"
Robert Phillips6be756b2018-01-16 15:07:54 -050010#include "GrContextPriv.h"
jvanverth992ad362016-02-26 09:21:02 -080011#include "GrPipeline.h"
Brian Salomon1471df92018-06-08 10:49:00 -040012#include "GrRenderTarget.h"
jvanverth62340062016-04-26 08:01:44 -070013#include "GrTexturePriv.h"
Greg Daniel31ec1442017-05-08 10:30:59 -040014#include "GrVkBufferView.h"
jvanverth992ad362016-02-26 09:21:02 -080015#include "GrVkCommandBuffer.h"
16#include "GrVkDescriptorPool.h"
egdaniela95220d2016-07-21 11:50:37 -070017#include "GrVkDescriptorSet.h"
jvanverth992ad362016-02-26 09:21:02 -080018#include "GrVkGpu.h"
19#include "GrVkImageView.h"
20#include "GrVkMemory.h"
21#include "GrVkPipeline.h"
Greg Daniel7d918fd2018-06-19 15:22:01 -040022#include "GrVkPipelineLayout.h"
jvanverth992ad362016-02-26 09:21:02 -080023#include "GrVkSampler.h"
24#include "GrVkTexture.h"
25#include "GrVkUniformBuffer.h"
Brian Salomon1471df92018-06-08 10:49:00 -040026#include "SkMipMap.h"
jvanverth992ad362016-02-26 09:21:02 -080027#include "glsl/GrGLSLFragmentProcessor.h"
28#include "glsl/GrGLSLGeometryProcessor.h"
29#include "glsl/GrGLSLXferProcessor.h"
30
Brian Salomon1471df92018-06-08 10:49:00 -040031GrVkPipelineState::GrVkPipelineState(
32 GrVkGpu* gpu,
Brian Salomon4d3f5172018-06-07 14:42:52 -040033 GrVkPipeline* pipeline,
34 VkPipelineLayout layout,
35 const GrVkDescriptorSetManager::Handle& samplerDSHandle,
Brian Salomon1471df92018-06-08 10:49:00 -040036 const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
Brian Salomon4d3f5172018-06-07 14:42:52 -040037 const UniformInfoArray& uniforms,
38 uint32_t geometryUniformSize,
39 uint32_t fragmentUniformSize,
40 uint32_t numSamplers,
Brian Salomon4d3f5172018-06-07 14:42:52 -040041 std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
42 std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
43 std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,
44 int fragmentProcessorCnt)
45 : fPipeline(pipeline)
Greg Daniel7d918fd2018-06-19 15:22:01 -040046 , fPipelineLayout(new GrVkPipelineLayout(layout))
Brian Salomon4d3f5172018-06-07 14:42:52 -040047 , fUniformDescriptorSet(nullptr)
48 , fSamplerDescriptorSet(nullptr)
Brian Salomon4d3f5172018-06-07 14:42:52 -040049 , fSamplerDSHandle(samplerDSHandle)
Brian Salomon4d3f5172018-06-07 14:42:52 -040050 , fBuiltinUniformHandles(builtinUniformHandles)
51 , fGeometryProcessor(std::move(geometryProcessor))
52 , fXferProcessor(std::move(xferProcessor))
53 , fFragmentProcessors(std::move(fragmentProcessors))
54 , fFragmentProcessorCnt(fragmentProcessorCnt)
Brian Salomon4d3f5172018-06-07 14:42:52 -040055 , fDataManager(uniforms, geometryUniformSize, fragmentUniformSize) {
egdanielc2dc1b22016-03-18 13:18:23 -070056 fDescriptorSets[0] = VK_NULL_HANDLE;
57 fDescriptorSets[1] = VK_NULL_HANDLE;
Greg Daniel31ec1442017-05-08 10:30:59 -040058 fDescriptorSets[2] = VK_NULL_HANDLE;
jvanverth992ad362016-02-26 09:21:02 -080059
Greg Daniel18f96022017-05-04 15:09:03 -040060 fGeometryUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, geometryUniformSize));
jvanverth4c6e47a2016-07-22 10:34:52 -070061 fFragmentUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, fragmentUniformSize));
jvanverth992ad362016-02-26 09:21:02 -080062
jvanverth992ad362016-02-26 09:21:02 -080063 fNumSamplers = numSamplers;
jvanverth992ad362016-02-26 09:21:02 -080064}
65
egdaniel22281c12016-03-23 13:49:40 -070066GrVkPipelineState::~GrVkPipelineState() {
Ethan Nicholas87f340e2017-01-03 14:32:01 -050067 // Must have freed all GPU resources before this is destroyed
jvanverth992ad362016-02-26 09:21:02 -080068 SkASSERT(!fPipeline);
jvanverth992ad362016-02-26 09:21:02 -080069 SkASSERT(!fPipelineLayout);
jvanverth992ad362016-02-26 09:21:02 -080070}
71
egdaniel22281c12016-03-23 13:49:40 -070072void GrVkPipelineState::freeGPUResources(const GrVkGpu* gpu) {
jvanverth992ad362016-02-26 09:21:02 -080073 if (fPipeline) {
74 fPipeline->unref(gpu);
75 fPipeline = nullptr;
76 }
egdanielc2dc1b22016-03-18 13:18:23 -070077
jvanverth992ad362016-02-26 09:21:02 -080078 if (fPipelineLayout) {
Greg Daniel7d918fd2018-06-19 15:22:01 -040079 fPipelineLayout->unref(gpu);
80 fPipelineLayout = nullptr;
jvanverth992ad362016-02-26 09:21:02 -080081 }
82
Greg Daniel18f96022017-05-04 15:09:03 -040083 if (fGeometryUniformBuffer) {
84 fGeometryUniformBuffer->release(gpu);
jvanverth992ad362016-02-26 09:21:02 -080085 }
86
87 if (fFragmentUniformBuffer) {
88 fFragmentUniformBuffer->release(gpu);
89 }
egdanielc2dc1b22016-03-18 13:18:23 -070090
egdaniela95220d2016-07-21 11:50:37 -070091 if (fUniformDescriptorSet) {
92 fUniformDescriptorSet->recycle(const_cast<GrVkGpu*>(gpu));
93 fUniformDescriptorSet = nullptr;
egdaniel778555c2016-05-02 06:50:36 -070094 }
egdanielc2dc1b22016-03-18 13:18:23 -070095
egdaniel707bbd62016-07-26 07:19:47 -070096 if (fSamplerDescriptorSet) {
97 fSamplerDescriptorSet->recycle(const_cast<GrVkGpu*>(gpu));
98 fSamplerDescriptorSet = nullptr;
99 }
jvanverth992ad362016-02-26 09:21:02 -0800100}
101
egdaniel22281c12016-03-23 13:49:40 -0700102void GrVkPipelineState::abandonGPUResources() {
Greg Daniel7d918fd2018-06-19 15:22:01 -0400103 if (fPipeline) {
104 fPipeline->unrefAndAbandon();
105 fPipeline = nullptr;
106 }
egdanielc2dc1b22016-03-18 13:18:23 -0700107
Greg Daniel7d918fd2018-06-19 15:22:01 -0400108 if (fPipelineLayout) {
109 fPipelineLayout->unrefAndAbandon();
110 fPipelineLayout = nullptr;
111 }
jvanverth992ad362016-02-26 09:21:02 -0800112
Greg Daniel18f96022017-05-04 15:09:03 -0400113 fGeometryUniformBuffer->abandon();
jvanverth992ad362016-02-26 09:21:02 -0800114 fFragmentUniformBuffer->abandon();
115
egdaniela95220d2016-07-21 11:50:37 -0700116 if (fUniformDescriptorSet) {
117 fUniformDescriptorSet->unrefAndAbandon();
118 fUniformDescriptorSet = nullptr;
egdaniel778555c2016-05-02 06:50:36 -0700119 }
egdaniel707bbd62016-07-26 07:19:47 -0700120
121 if (fSamplerDescriptorSet) {
122 fSamplerDescriptorSet->unrefAndAbandon();
123 fSamplerDescriptorSet = nullptr;
124 }
jvanverth992ad362016-02-26 09:21:02 -0800125}
126
Brian Salomon5e81a122018-08-23 16:46:07 -0400127void GrVkPipelineState::setAndBindUniforms(GrVkGpu* gpu,
128 const GrPrimitiveProcessor& primProc,
129 const GrPipeline& pipeline,
130 GrVkCommandBuffer* commandBuffer) {
Robert Phillips2890fbf2017-07-26 15:48:41 -0400131 this->setRenderTargetState(pipeline.proxy());
jvanverth992ad362016-02-26 09:21:02 -0800132
bsalomona624bf32016-09-20 09:12:47 -0700133 fGeometryProcessor->setData(fDataManager, primProc,
134 GrFragmentProcessor::CoordTransformIter(pipeline));
bsalomonb58a2b42016-09-26 06:55:02 -0700135 GrFragmentProcessor::Iter iter(pipeline);
Brian Salomon4d3f5172018-06-07 14:42:52 -0400136 GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
bsalomonb58a2b42016-09-26 06:55:02 -0700137 const GrFragmentProcessor* fp = iter.next();
138 GrGLSLFragmentProcessor* glslFP = glslIter.next();
139 while (fp && glslFP) {
140 glslFP->setData(fDataManager, *fp);
mtklein85552e42016-09-26 08:39:43 -0700141 fp = iter.next();
142 glslFP = glslIter.next();
jvanverth992ad362016-02-26 09:21:02 -0800143 }
bsalomonb58a2b42016-09-26 06:55:02 -0700144 SkASSERT(!fp && !glslFP);
jvanverth992ad362016-02-26 09:21:02 -0800145
Robert Phillipsbb581ce2017-05-29 15:05:15 -0400146 {
147 SkIPoint offset;
148 GrTexture* dstTexture = pipeline.peekDstTexture(&offset);
149
150 fXferProcessor->setData(fDataManager, pipeline.getXferProcessor(), dstTexture, offset);
151 }
152
Brian Salomon5e81a122018-08-23 16:46:07 -0400153 // Get new descriptor set
154 if (fGeometryUniformBuffer || fFragmentUniformBuffer) {
155 int uniformDSIdx = GrVkUniformHandler::kUniformBufferDescSet;
156 if (fDataManager.uploadUniformBuffers(
157 gpu, fGeometryUniformBuffer.get(), fFragmentUniformBuffer.get()) ||
158 !fUniformDescriptorSet) {
159 if (fUniformDescriptorSet) {
160 fUniformDescriptorSet->recycle(gpu);
161 }
162 fUniformDescriptorSet = gpu->resourceProvider().getUniformDescriptorSet();
163 fDescriptorSets[uniformDSIdx] = fUniformDescriptorSet->descriptorSet();
164 this->writeUniformBuffers(gpu);
165 }
166 commandBuffer->bindDescriptorSets(gpu, this, fPipelineLayout, uniformDSIdx, 1,
167 &fDescriptorSets[uniformDSIdx], 0, nullptr);
168 if (fUniformDescriptorSet) {
169 commandBuffer->addRecycledResource(fUniformDescriptorSet);
170 }
171 if (fGeometryUniformBuffer) {
172 commandBuffer->addRecycledResource(fGeometryUniformBuffer->resource());
173 }
174 if (fFragmentUniformBuffer) {
175 commandBuffer->addRecycledResource(fFragmentUniformBuffer->resource());
176 }
177 }
178}
179
180void GrVkPipelineState::setAndBindTextures(GrVkGpu* gpu,
181 const GrPrimitiveProcessor& primProc,
182 const GrPipeline& pipeline,
183 const GrTextureProxy* const primProcTextures[],
184 GrVkCommandBuffer* commandBuffer) {
185 SkASSERT(primProcTextures || !primProc.numTextureSamplers());
186
187 struct SamplerBindings {
188 GrSamplerState fState;
189 GrVkTexture* fTexture;
190 };
191 SkAutoSTMalloc<8, SamplerBindings> samplerBindings(fNumSamplers);
192 int currTextureBinding = 0;
193
194 fGeometryProcessor->setData(fDataManager, primProc,
195 GrFragmentProcessor::CoordTransformIter(pipeline));
196 for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
197 const auto& sampler = primProc.textureSampler(i);
198 auto texture = static_cast<GrVkTexture*>(primProcTextures[i]->peekTexture());
199 samplerBindings[currTextureBinding++] = {sampler.samplerState(), texture};
200 }
201
202 GrFragmentProcessor::Iter iter(pipeline);
203 GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
204 const GrFragmentProcessor* fp = iter.next();
205 GrGLSLFragmentProcessor* glslFP = glslIter.next();
206 while (fp && glslFP) {
207 for (int i = 0; i < fp->numTextureSamplers(); ++i) {
208 const auto& sampler = fp->textureSampler(i);
209 samplerBindings[currTextureBinding++] =
210 {sampler.samplerState(), static_cast<GrVkTexture*>(sampler.peekTexture())};
211 }
212 fp = iter.next();
213 glslFP = glslIter.next();
214 }
215 SkASSERT(!fp && !glslFP);
216
Robert Phillipsbb581ce2017-05-29 15:05:15 -0400217 if (GrTextureProxy* dstTextureProxy = pipeline.dstTextureProxy()) {
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400218 samplerBindings[currTextureBinding++] = {
219 GrSamplerState::ClampNearest(),
220 static_cast<GrVkTexture*>(dstTextureProxy->peekTexture())};
Brian Salomon18dfa982017-04-03 16:57:43 -0400221 }
jvanverth992ad362016-02-26 09:21:02 -0800222
Brian Salomon5e81a122018-08-23 16:46:07 -0400223 // Get new descriptor set
Brian Salomone782f842018-07-31 13:53:11 -0400224 SkASSERT(fNumSamplers == currTextureBinding);
egdanielc2dc1b22016-03-18 13:18:23 -0700225 if (fNumSamplers) {
egdaniel707bbd62016-07-26 07:19:47 -0700226 if (fSamplerDescriptorSet) {
227 fSamplerDescriptorSet->recycle(gpu);
228 }
229 fSamplerDescriptorSet = gpu->resourceProvider().getSamplerDescriptorSet(fSamplerDSHandle);
230 int samplerDSIdx = GrVkUniformHandler::kSamplerDescSet;
231 fDescriptorSets[samplerDSIdx] = fSamplerDescriptorSet->descriptorSet();
Brian Salomon5e81a122018-08-23 16:46:07 -0400232 for (int i = 0; i < fNumSamplers; ++i) {
233 const GrSamplerState& state = samplerBindings[i].fState;
234 GrVkTexture* texture = samplerBindings[i].fTexture;
egdanielb4aa3622016-04-06 13:47:08 -0700235
Brian Salomon5e81a122018-08-23 16:46:07 -0400236 const GrVkImageView* textureView = texture->textureView();
237 GrVkSampler* sampler = gpu->resourceProvider().findOrCreateCompatibleSampler(
238 state, texture->texturePriv().maxMipMapLevel());
239
240 VkDescriptorImageInfo imageInfo;
241 memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo));
242 imageInfo.sampler = sampler->sampler();
243 imageInfo.imageView = textureView->imageView();
244 imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
245
246 VkWriteDescriptorSet writeInfo;
247 memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet));
248 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
249 writeInfo.pNext = nullptr;
250 writeInfo.dstSet = fDescriptorSets[GrVkUniformHandler::kSamplerDescSet];
251 writeInfo.dstBinding = i;
252 writeInfo.dstArrayElement = 0;
253 writeInfo.descriptorCount = 1;
254 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
255 writeInfo.pImageInfo = &imageInfo;
256 writeInfo.pBufferInfo = nullptr;
257 writeInfo.pTexelBufferView = nullptr;
258
259 GR_VK_CALL(gpu->vkInterface(),
260 UpdateDescriptorSets(gpu->device(), 1, &writeInfo, 0, nullptr));
261 commandBuffer->addResource(sampler);
262 sampler->unref(gpu);
263 commandBuffer->addResource(samplerBindings[i].fTexture->textureView());
264 commandBuffer->addResource(samplerBindings[i].fTexture->resource());
egdaniel7cbffda2016-04-08 13:27:53 -0700265 }
Brian Salomon5e81a122018-08-23 16:46:07 -0400266
267 commandBuffer->bindDescriptorSets(gpu, this, fPipelineLayout, samplerDSIdx, 1,
268 &fDescriptorSets[samplerDSIdx], 0, nullptr);
269 commandBuffer->addRecycledResource(fSamplerDescriptorSet);
egdanielb4aa3622016-04-06 13:47:08 -0700270 }
jvanverth992ad362016-02-26 09:21:02 -0800271}
272
Greg Daniel18f96022017-05-04 15:09:03 -0400273void set_uniform_descriptor_writes(VkWriteDescriptorSet* descriptorWrite,
274 VkDescriptorBufferInfo* bufferInfo,
275 const GrVkUniformBuffer* buffer,
276 VkDescriptorSet descriptorSet,
277 uint32_t binding) {
278
279 memset(bufferInfo, 0, sizeof(VkDescriptorBufferInfo));
280 bufferInfo->buffer = buffer->buffer();
281 bufferInfo->offset = buffer->offset();
282 bufferInfo->range = buffer->size();
283
284 memset(descriptorWrite, 0, sizeof(VkWriteDescriptorSet));
285 descriptorWrite->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
286 descriptorWrite->pNext = nullptr;
Greg Daniel783c4362017-05-04 17:29:09 -0400287 descriptorWrite->dstSet = descriptorSet;
Greg Daniel18f96022017-05-04 15:09:03 -0400288 descriptorWrite->dstBinding = binding;
289 descriptorWrite->dstArrayElement = 0;
290 descriptorWrite->descriptorCount = 1;
291 descriptorWrite->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
292 descriptorWrite->pImageInfo = nullptr;
293 descriptorWrite->pBufferInfo = bufferInfo;
294 descriptorWrite->pTexelBufferView = nullptr;
295}
296
egdaniel22281c12016-03-23 13:49:40 -0700297void GrVkPipelineState::writeUniformBuffers(const GrVkGpu* gpu) {
Greg Daniel18f96022017-05-04 15:09:03 -0400298 VkWriteDescriptorSet descriptorWrites[3];
299 VkDescriptorBufferInfo bufferInfos[3];
jvanverth992ad362016-02-26 09:21:02 -0800300
Greg Daniel18f96022017-05-04 15:09:03 -0400301 uint32_t writeCount = 0;
jvanverth992ad362016-02-26 09:21:02 -0800302
Greg Daniel18f96022017-05-04 15:09:03 -0400303 // Geometry Uniform Buffer
304 if (fGeometryUniformBuffer.get()) {
305 set_uniform_descriptor_writes(&descriptorWrites[writeCount],
306 &bufferInfos[writeCount],
307 fGeometryUniformBuffer.get(),
308 fDescriptorSets[GrVkUniformHandler::kUniformBufferDescSet],
309 GrVkUniformHandler::kGeometryBinding);
310 ++writeCount;
jvanverth992ad362016-02-26 09:21:02 -0800311 }
312
313 // Fragment Uniform Buffer
314 if (fFragmentUniformBuffer.get()) {
Greg Daniel18f96022017-05-04 15:09:03 -0400315 set_uniform_descriptor_writes(&descriptorWrites[writeCount],
316 &bufferInfos[writeCount],
317 fFragmentUniformBuffer.get(),
318 fDescriptorSets[GrVkUniformHandler::kUniformBufferDescSet],
319 GrVkUniformHandler::kFragBinding);
320 ++writeCount;
jvanverth992ad362016-02-26 09:21:02 -0800321 }
322
Greg Daniel18f96022017-05-04 15:09:03 -0400323 if (writeCount) {
jvanverth992ad362016-02-26 09:21:02 -0800324 GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(),
Greg Daniel18f96022017-05-04 15:09:03 -0400325 writeCount,
326 descriptorWrites,
jvanverth992ad362016-02-26 09:21:02 -0800327 0, nullptr));
328 }
329}
330
Robert Phillips2890fbf2017-07-26 15:48:41 -0400331void GrVkPipelineState::setRenderTargetState(const GrRenderTargetProxy* proxy) {
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400332 GrRenderTarget* rt = proxy->peekRenderTarget();
Robert Phillips2890fbf2017-07-26 15:48:41 -0400333
jvanverth992ad362016-02-26 09:21:02 -0800334 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
Greg Daniele6ab9982018-08-22 13:56:32 +0000335 if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
336 fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
337 fDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height()));
jvanverth992ad362016-02-26 09:21:02 -0800338 }
339
340 // set RT adjustment
jvanverth992ad362016-02-26 09:21:02 -0800341 SkISize size;
342 size.set(rt->width(), rt->height());
343 SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
Robert Phillips2890fbf2017-07-26 15:48:41 -0400344 if (fRenderTargetState.fRenderTargetOrigin != proxy->origin() ||
jvanverth992ad362016-02-26 09:21:02 -0800345 fRenderTargetState.fRenderTargetSize != size) {
346 fRenderTargetState.fRenderTargetSize = size;
Robert Phillips2890fbf2017-07-26 15:48:41 -0400347 fRenderTargetState.fRenderTargetOrigin = proxy->origin();
jvanverth992ad362016-02-26 09:21:02 -0800348
349 float rtAdjustmentVec[4];
350 fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
egdaniel22281c12016-03-23 13:49:40 -0700351 fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
jvanverth992ad362016-02-26 09:21:02 -0800352 }
353}
354
Brian Salomon5e81a122018-08-23 16:46:07 -0400355void GrVkPipelineState::bindPipeline(const GrVkGpu* gpu, GrVkCommandBuffer* commandBuffer) {
jvanverth992ad362016-02-26 09:21:02 -0800356 commandBuffer->bindPipeline(gpu, fPipeline);
egdanielc2dc1b22016-03-18 13:18:23 -0700357}