blob: 73d00437ca2caf5b87987bd6b03a4d1b71d291b1 [file] [log] [blame]
jvanverth992ad362016-02-26 09:21:02 -08001/*
Greg Danielc10bb6a2019-10-29 09:50:32 -04002 * 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 */
jvanverth992ad362016-02-26 09:21:02 -08007
Greg Daniel9d02a4c2020-07-15 14:26:08 -04008#include "src/gpu/vk/GrVkPipelineState.h"
9
Mike Reed13711eb2020-07-14 17:16:32 -040010#include "src/core/SkMipmap.h"
Brian Salomon48959462021-08-11 13:01:06 -040011#include "src/gpu/GrFragmentProcessor.h"
12#include "src/gpu/GrGeometryProcessor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "src/gpu/GrPipeline.h"
Brian Salomon201cdbb2019-08-14 17:00:30 -040014#include "src/gpu/GrRenderTarget.h"
Brian Salomon4cfae3b2020-07-23 10:33:24 -040015#include "src/gpu/GrTexture.h"
Brian Salomon48959462021-08-11 13:01:06 -040016#include "src/gpu/GrXferProcessor.h"
Robert Phillips550de7f2021-07-06 16:28:52 -040017#include "src/gpu/effects/GrTextureEffect.h"
Greg Danielaf1d1932021-02-08 13:55:26 -050018#include "src/gpu/vk/GrVkBuffer.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "src/gpu/vk/GrVkCommandBuffer.h"
20#include "src/gpu/vk/GrVkDescriptorPool.h"
21#include "src/gpu/vk/GrVkDescriptorSet.h"
22#include "src/gpu/vk/GrVkGpu.h"
23#include "src/gpu/vk/GrVkImageView.h"
24#include "src/gpu/vk/GrVkMemory.h"
25#include "src/gpu/vk/GrVkPipeline.h"
Greg Daniel37fd6582020-09-14 12:36:09 -040026#include "src/gpu/vk/GrVkRenderTarget.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050027#include "src/gpu/vk/GrVkSampler.h"
28#include "src/gpu/vk/GrVkTexture.h"
jvanverth992ad362016-02-26 09:21:02 -080029
Brian Salomon1471df92018-06-08 10:49:00 -040030GrVkPipelineState::GrVkPipelineState(
Brian Salomonf95940b2021-08-09 15:56:24 -040031 GrVkGpu* gpu,
32 sk_sp<const GrVkPipeline> pipeline,
33 const GrVkDescriptorSetManager::Handle& samplerDSHandle,
34 const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
35 const UniformInfoArray& uniforms,
36 uint32_t uniformSize,
37 bool usePushConstants,
38 const UniformInfoArray& samplers,
39 std::unique_ptr<GrGeometryProcessor::ProgramImpl> gpImpl,
Brian Salomond89d4452021-08-09 16:42:36 -040040 std::unique_ptr<GrXferProcessor::ProgramImpl> xpImpl,
Brian Salomonf95940b2021-08-09 15:56:24 -040041 std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fpImpls)
Greg Daniel3ef052c2021-01-05 12:20:27 -050042 : fPipeline(std::move(pipeline))
Brian Salomon4d3f5172018-06-07 14:42:52 -040043 , fSamplerDSHandle(samplerDSHandle)
Brian Salomon4d3f5172018-06-07 14:42:52 -040044 , fBuiltinUniformHandles(builtinUniformHandles)
Brian Salomonf95940b2021-08-09 15:56:24 -040045 , fGPImpl(std::move(gpImpl))
Brian Salomond89d4452021-08-09 16:42:36 -040046 , fXPImpl(std::move(xpImpl))
Brian Salomon17f95b12021-02-23 09:35:08 -050047 , fFPImpls(std::move(fpImpls))
Brian Salomonae594262021-09-13 21:21:13 +000048 , fDataManager(uniforms, uniformSize, usePushConstants) {
Greg Daniel7a82edf2018-12-04 10:54:34 -050049 fNumSamplers = samplers.count();
Michael Ludwig45191342020-03-24 12:29:39 -040050 for (const auto& sampler : samplers.items()) {
Greg Daniel20bb83f2021-03-18 13:06:00 -040051 // We store the immutable samplers here and take a ref on the sampler. Once we switch to
52 // using sk_sps here we should just move the immutable samplers to save the extra ref/unref.
53 if (sampler.fImmutableSampler) {
54 sampler.fImmutableSampler->ref();
55 }
Michael Ludwig45191342020-03-24 12:29:39 -040056 fImmutableSamplers.push_back(sampler.fImmutableSampler);
Greg Daniel7a82edf2018-12-04 10:54:34 -050057 }
jvanverth992ad362016-02-26 09:21:02 -080058}
59
egdaniel22281c12016-03-23 13:49:40 -070060GrVkPipelineState::~GrVkPipelineState() {
Ethan Nicholas87f340e2017-01-03 14:32:01 -050061 // Must have freed all GPU resources before this is destroyed
jvanverth992ad362016-02-26 09:21:02 -080062 SkASSERT(!fPipeline);
jvanverth992ad362016-02-26 09:21:02 -080063}
64
Greg Daniel9d02a4c2020-07-15 14:26:08 -040065void GrVkPipelineState::freeGPUResources(GrVkGpu* gpu) {
Greg Daniel3ef052c2021-01-05 12:20:27 -050066 fPipeline.reset();
Greg Daniel8eb119a2021-02-04 09:41:19 -050067 fDataManager.releaseData();
Greg Daniel20bb83f2021-03-18 13:06:00 -040068 for (int i = 0; i < fImmutableSamplers.count(); ++i) {
69 if (fImmutableSamplers[i]) {
70 fImmutableSamplers[i]->unref();
71 fImmutableSamplers[i] = nullptr;
72 }
73 }
jvanverth992ad362016-02-26 09:21:02 -080074}
75
Greg Daniel95f0b162019-11-11 13:42:30 -050076bool GrVkPipelineState::setAndBindUniforms(GrVkGpu* gpu,
Greg Daniela36cb402021-04-20 12:42:11 -040077 SkISize colorAttachmentDimensions,
Robert Phillips835cbda2019-10-09 15:41:50 -040078 const GrProgramInfo& programInfo,
Brian Salomonf7232642018-09-19 08:58:08 -040079 GrVkCommandBuffer* commandBuffer) {
Greg Daniela36cb402021-04-20 12:42:11 -040080 this->setRenderTargetState(colorAttachmentDimensions, programInfo.origin());
jvanverth992ad362016-02-26 09:21:02 -080081
Brian Salomonf95940b2021-08-09 15:56:24 -040082 fGPImpl->setData(fDataManager, *gpu->caps()->shaderCaps(), programInfo.geomProc());
Brian Salomon91398032021-08-05 10:02:08 -040083
Brian Salomon61a70fb2020-07-08 19:02:54 -040084 for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) {
Brian Salomon91398032021-08-05 10:02:08 -040085 const auto& fp = programInfo.pipeline().getFragmentProcessor(i);
Brian Salomon3176e862021-08-09 11:23:04 -040086 fp.visitWithImpls([&](const GrFragmentProcessor& fp,
87 GrFragmentProcessor::ProgramImpl& impl) {
Brian Salomon17f95b12021-02-23 09:35:08 -050088 impl.setData(fDataManager, fp);
Brian Salomon91398032021-08-05 10:02:08 -040089 }, *fFPImpls[i]);
Brian Salomonf7232642018-09-19 08:58:08 -040090 }
Brian Salomonf7232642018-09-19 08:58:08 -040091
John Stiles010d0882021-06-03 20:28:41 -040092 programInfo.pipeline().setDstTextureUniforms(fDataManager, &fBuiltinUniformHandles);
Brian Salomond89d4452021-08-09 16:42:36 -040093 fXPImpl->setData(fDataManager, programInfo.pipeline().getXferProcessor());
Brian Salomonf7232642018-09-19 08:58:08 -040094
Jim Van Verth205e99a2021-02-08 18:02:41 -050095 // Upload uniform data and bind descriptor set.
96 auto [uniformBuffer, success] = fDataManager.uploadUniforms(gpu, fPipeline->layout(),
97 commandBuffer);
Greg Daniel8eb119a2021-02-04 09:41:19 -050098 if (!success) {
99 return false;
100 }
101 if (uniformBuffer) {
Greg Danielaf1d1932021-02-08 13:55:26 -0500102 const GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(uniformBuffer.get());
Greg Danielc10bb6a2019-10-29 09:50:32 -0400103 static const int kUniformDSIdx = GrVkUniformHandler::kUniformBufferDescSet;
Greg Daniel1cf4bc72020-11-24 10:41:04 -0500104 commandBuffer->bindDescriptorSets(gpu, fPipeline->layout(), kUniformDSIdx, /*setCount=*/1,
Greg Daniel8eb119a2021-02-04 09:41:19 -0500105 vkBuffer->uniformDescriptorSet(),
106 /*dynamicOffsetCount=*/0, /*dynamicOffsets=*/nullptr);
107 commandBuffer->addGrBuffer(std::move(uniformBuffer));
Brian Salomonf7232642018-09-19 08:58:08 -0400108 }
Greg Daniel95f0b162019-11-11 13:42:30 -0500109 return true;
Brian Salomonf7232642018-09-19 08:58:08 -0400110}
111
Greg Daniel95f0b162019-11-11 13:42:30 -0500112bool GrVkPipelineState::setAndBindTextures(GrVkGpu* gpu,
Robert Phillips787fd9d2021-03-22 14:48:09 -0400113 const GrGeometryProcessor& geomProc,
Brian Salomonf7232642018-09-19 08:58:08 -0400114 const GrPipeline& pipeline,
Robert Phillips787fd9d2021-03-22 14:48:09 -0400115 const GrSurfaceProxy* const geomProcTextures[],
Brian Salomonf7232642018-09-19 08:58:08 -0400116 GrVkCommandBuffer* commandBuffer) {
Robert Phillips787fd9d2021-03-22 14:48:09 -0400117 SkASSERT(geomProcTextures || !geomProc.numTextureSamplers());
Greg Daniel4a58bde2021-05-06 11:49:13 -0400118 if (!fNumSamplers) {
119 return true;
egdanielb4aa3622016-04-06 13:47:08 -0700120 }
Greg Daniel4a58bde2021-05-06 11:49:13 -0400121 struct SamplerBindings {
122 GrSamplerState fState;
123 GrVkTexture* fTexture;
124 };
125 SkAutoSTArray<8, SamplerBindings> samplerBindings(fNumSamplers);
126 int currTextureBinding = 0;
127
128 for (int i = 0; i < geomProc.numTextureSamplers(); ++i) {
129 SkASSERT(geomProcTextures[i]->asTextureProxy());
130 const auto& sampler = geomProc.textureSampler(i);
131 auto texture = static_cast<GrVkTexture*>(geomProcTextures[i]->peekTexture());
132 samplerBindings[currTextureBinding++] = {sampler.samplerState(), texture};
133 }
134
Greg Daniel4a58bde2021-05-06 11:49:13 -0400135
136 if (GrTexture* dstTexture = pipeline.peekDstTexture()) {
137 samplerBindings[currTextureBinding++] = {GrSamplerState::Filter::kNearest,
138 static_cast<GrVkTexture*>(dstTexture)};
139 }
140
John Stiles03e78302021-06-02 17:34:21 -0400141 pipeline.visitTextureEffects([&](const GrTextureEffect& te) {
142 GrSamplerState samplerState = te.samplerState();
143 auto* texture = static_cast<GrVkTexture*>(te.texture());
144 samplerBindings[currTextureBinding++] = {samplerState, texture};
145 });
146
Greg Daniel4a58bde2021-05-06 11:49:13 -0400147 // Get new descriptor set
148 SkASSERT(fNumSamplers == currTextureBinding);
149 static const int kSamplerDSIdx = GrVkUniformHandler::kSamplerDescSet;
150
151 if (fNumSamplers == 1) {
152 auto texture = samplerBindings[0].fTexture;
Greg Daniel2bc96d62021-09-13 13:08:02 -0400153 auto texAttachment = texture->textureImage();
Greg Daniel4a58bde2021-05-06 11:49:13 -0400154 const auto& samplerState = samplerBindings[0].fState;
155 const GrVkDescriptorSet* descriptorSet = texture->cachedSingleDescSet(samplerState);
156 if (descriptorSet) {
157 commandBuffer->addGrSurface(sk_ref_sp<const GrSurface>(texture));
158 commandBuffer->addResource(texAttachment->textureView());
159 commandBuffer->addResource(texAttachment->resource());
160 commandBuffer->addRecycledResource(descriptorSet);
161 commandBuffer->bindDescriptorSets(gpu, fPipeline->layout(), kSamplerDSIdx,
162 /*setCount=*/1, descriptorSet->descriptorSet(),
163 /*dynamicOffsetCount=*/0,
164 /*dynamicOffsets=*/nullptr);
165 return true;
166 }
167 }
168
169 const GrVkDescriptorSet* descriptorSet =
170 gpu->resourceProvider().getSamplerDescriptorSet(fSamplerDSHandle);
171 if (!descriptorSet) {
172 return false;
173 }
174
175 for (int i = 0; i < fNumSamplers; ++i) {
176 GrSamplerState state = samplerBindings[i].fState;
177 GrVkTexture* texture = samplerBindings[i].fTexture;
Greg Daniel2bc96d62021-09-13 13:08:02 -0400178 auto texAttachment = texture->textureImage();
Greg Daniel4a58bde2021-05-06 11:49:13 -0400179
180 const GrVkImageView* textureView = texAttachment->textureView();
181 const GrVkSampler* sampler = nullptr;
182 if (fImmutableSamplers[i]) {
183 sampler = fImmutableSamplers[i];
184 } else {
185 sampler = gpu->resourceProvider().findOrCreateCompatibleSampler(
186 state, texAttachment->ycbcrConversionInfo());
187 if (!sampler) {
188 descriptorSet->recycle();
189 return false;
190 }
191 }
192 SkASSERT(sampler);
193
194 VkDescriptorImageInfo imageInfo;
195 memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo));
196 imageInfo.sampler = fImmutableSamplers[i] ? VK_NULL_HANDLE : sampler->sampler();
197 imageInfo.imageView = textureView->imageView();
198 imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
199
200 VkWriteDescriptorSet writeInfo;
201 memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet));
202 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
203 writeInfo.pNext = nullptr;
204 writeInfo.dstSet = *descriptorSet->descriptorSet();
205 writeInfo.dstBinding = i;
206 writeInfo.dstArrayElement = 0;
207 writeInfo.descriptorCount = 1;
208 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
209 writeInfo.pImageInfo = &imageInfo;
210 writeInfo.pBufferInfo = nullptr;
211 writeInfo.pTexelBufferView = nullptr;
212
213 GR_VK_CALL(gpu->vkInterface(),
214 UpdateDescriptorSets(gpu->device(), 1, &writeInfo, 0, nullptr));
215 commandBuffer->addResource(sampler);
216 if (!fImmutableSamplers[i]) {
217 sampler->unref();
218 }
219 commandBuffer->addResource(textureView);
220 commandBuffer->addResource(texAttachment->resource());
221 }
222 if (fNumSamplers == 1) {
223 GrSamplerState state = samplerBindings[0].fState;
224 GrVkTexture* texture = samplerBindings[0].fTexture;
225 texture->addDescriptorSetToCache(descriptorSet, state);
226 }
227
228 commandBuffer->bindDescriptorSets(gpu, fPipeline->layout(), kSamplerDSIdx, /*setCount=*/1,
229 descriptorSet->descriptorSet(),
230 /*dynamicOffsetCount=*/0, /*dynamicOffsets=*/nullptr);
231 commandBuffer->addRecycledResource(descriptorSet);
232 descriptorSet->recycle();
Greg Daniel95f0b162019-11-11 13:42:30 -0500233 return true;
jvanverth992ad362016-02-26 09:21:02 -0800234}
235
Greg Daniel37fd6582020-09-14 12:36:09 -0400236bool GrVkPipelineState::setAndBindInputAttachment(GrVkGpu* gpu,
Greg Daniel10344252021-04-22 09:52:25 -0400237 gr_rp<const GrVkDescriptorSet> inputDescSet,
Greg Daniel37fd6582020-09-14 12:36:09 -0400238 GrVkCommandBuffer* commandBuffer) {
Greg Daniel10344252021-04-22 09:52:25 -0400239 SkASSERT(inputDescSet);
Greg Daniel1cf4bc72020-11-24 10:41:04 -0500240 commandBuffer->bindDescriptorSets(gpu, fPipeline->layout(), GrVkUniformHandler::kInputDescSet,
Greg Daniel10344252021-04-22 09:52:25 -0400241 /*setCount=*/1, inputDescSet->descriptorSet(),
Greg Daniel8cc5f192020-10-02 10:45:43 -0400242 /*dynamicOffsetCount=*/0, /*dynamicOffsets=*/nullptr);
243 // We don't add the input resource to the command buffer to track since the input will be
244 // the same as the color attachment which is already tracked on the command buffer.
Greg Daniel10344252021-04-22 09:52:25 -0400245 commandBuffer->addRecycledResource(std::move(inputDescSet));
Greg Daniel37fd6582020-09-14 12:36:09 -0400246 return true;
247}
248
Greg Daniela36cb402021-04-20 12:42:11 -0400249void GrVkPipelineState::setRenderTargetState(SkISize colorAttachmentDimensions,
250 GrSurfaceOrigin origin) {
Brian Salomond8d85b92021-07-07 09:41:17 -0400251 // Set RT adjustment and RT flip
jvanverth992ad362016-02-26 09:21:02 -0800252 SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500253 if (fRenderTargetState.fRenderTargetOrigin != origin ||
Greg Daniela36cb402021-04-20 12:42:11 -0400254 fRenderTargetState.fRenderTargetSize != colorAttachmentDimensions) {
255 fRenderTargetState.fRenderTargetSize = colorAttachmentDimensions;
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500256 fRenderTargetState.fRenderTargetOrigin = origin;
jvanverth992ad362016-02-26 09:21:02 -0800257
Brian Salomon3e2fe2b2021-06-02 09:16:30 -0400258 // The client will mark a swap buffer as kTopLeft when making a SkSurface because
259 // Vulkan's framebuffer space has (0, 0) at the top left. This agrees with Skia's device
260 // coords and with Vulkan's NDC that has (-1, -1) in the top left. So a flip is needed when
261 // surface origin is kBottomLeft rather than kTopLeft.
262 bool flip = (origin == kBottomLeft_GrSurfaceOrigin);
263 std::array<float, 4> v = SkSL::Compiler::GetRTAdjustVector(colorAttachmentDimensions, flip);
264 fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, v.data());
Brian Salomond8d85b92021-07-07 09:41:17 -0400265 if (fBuiltinUniformHandles.fRTFlipUni.isValid()) {
266 std::array<float, 2> d =
267 SkSL::Compiler::GetRTFlipVector(colorAttachmentDimensions.height(), flip);
268 fDataManager.set2fv(fBuiltinUniformHandles.fRTFlipUni, 1, d.data());
269 }
jvanverth992ad362016-02-26 09:21:02 -0800270 }
271}
272
Brian Salomonf7232642018-09-19 08:58:08 -0400273void GrVkPipelineState::bindPipeline(const GrVkGpu* gpu, GrVkCommandBuffer* commandBuffer) {
jvanverth992ad362016-02-26 09:21:02 -0800274 commandBuffer->bindPipeline(gpu, fPipeline);
egdanielc2dc1b22016-03-18 13:18:23 -0700275}