1 /*
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
8 #include "include/gpu/GrContext.h"
9 #include "src/core/SkMipMap.h"
10 #include "src/gpu/GrContextPriv.h"
11 #include "src/gpu/GrPipeline.h"
12 #include "src/gpu/GrRenderTarget.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/GrVkCommandBuffer.h"
18 #include "src/gpu/vk/GrVkDescriptorPool.h"
19 #include "src/gpu/vk/GrVkDescriptorSet.h"
20 #include "src/gpu/vk/GrVkGpu.h"
21 #include "src/gpu/vk/GrVkImageView.h"
22 #include "src/gpu/vk/GrVkMemory.h"
23 #include "src/gpu/vk/GrVkPipeline.h"
24 #include "src/gpu/vk/GrVkPipelineState.h"
25 #include "src/gpu/vk/GrVkSampler.h"
26 #include "src/gpu/vk/GrVkTexture.h"
27 #include "src/gpu/vk/GrVkUniformBuffer.h"
28
GrVkPipelineState(GrVkGpu * gpu,GrVkPipeline * pipeline,const GrVkDescriptorSetManager::Handle & samplerDSHandle,const GrGLSLBuiltinUniformHandles & builtinUniformHandles,const UniformInfoArray & uniforms,uint32_t uniformSize,const UniformInfoArray & samplers,std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,std::unique_ptr<GrGLSLXferProcessor> xferProcessor,std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,int fragmentProcessorCnt)29 GrVkPipelineState::GrVkPipelineState(
30 GrVkGpu* gpu,
31 GrVkPipeline* pipeline,
32 const GrVkDescriptorSetManager::Handle& samplerDSHandle,
33 const GrGLSLBuiltinUniformHandles& builtinUniformHandles,
34 const UniformInfoArray& uniforms,
35 uint32_t uniformSize,
36 const UniformInfoArray& samplers,
37 std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
38 std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
39 std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,
40 int fragmentProcessorCnt)
41 : fPipeline(pipeline)
42 , fUniformDescriptorSet(nullptr)
43 , fSamplerDSHandle(samplerDSHandle)
44 , fBuiltinUniformHandles(builtinUniformHandles)
45 , fGeometryProcessor(std::move(geometryProcessor))
46 , fXferProcessor(std::move(xferProcessor))
47 , fFragmentProcessors(std::move(fragmentProcessors))
48 , fFragmentProcessorCnt(fragmentProcessorCnt)
49 , fDataManager(uniforms, uniformSize) {
50 fUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, uniformSize));
51
52 fNumSamplers = samplers.count();
53
54 for (int i = 0; i < fNumSamplers; ++i) {
55 // We store the immutable samplers here and take ownership of the ref from the
56 // GrVkUnformHandler.
57 fImmutableSamplers.push_back(samplers[i].fImmutableSampler);
58 }
59 }
60
~GrVkPipelineState()61 GrVkPipelineState::~GrVkPipelineState() {
62 // Must have freed all GPU resources before this is destroyed
63 SkASSERT(!fPipeline);
64 }
65
freeGPUResources(GrVkGpu * gpu)66 void GrVkPipelineState::freeGPUResources(GrVkGpu* gpu) {
67 if (fPipeline) {
68 fPipeline->unref(gpu);
69 fPipeline = nullptr;
70 }
71
72 if (fUniformBuffer) {
73 fUniformBuffer->release(gpu);
74 fUniformBuffer.reset();
75 }
76
77 if (fUniformDescriptorSet) {
78 fUniformDescriptorSet->recycle(const_cast<GrVkGpu*>(gpu));
79 fUniformDescriptorSet = nullptr;
80 }
81 }
82
setAndBindUniforms(GrVkGpu * gpu,const GrRenderTarget * renderTarget,const GrProgramInfo & programInfo,GrVkCommandBuffer * commandBuffer)83 bool GrVkPipelineState::setAndBindUniforms(GrVkGpu* gpu,
84 const GrRenderTarget* renderTarget,
85 const GrProgramInfo& programInfo,
86 GrVkCommandBuffer* commandBuffer) {
87 this->setRenderTargetState(renderTarget, programInfo.origin());
88
89 GrFragmentProcessor::PipelineCoordTransformRange transformRange(programInfo.pipeline());
90 fGeometryProcessor->setData(fDataManager, programInfo.primProc(), transformRange);
91 GrFragmentProcessor::CIter fpIter(programInfo.pipeline());
92 GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
93 for (; fpIter && glslIter; ++fpIter, ++glslIter) {
94 glslIter->setData(fDataManager, *fpIter);
95 }
96 SkASSERT(!fpIter && !glslIter);
97
98 {
99 SkIPoint offset;
100 GrTexture* dstTexture = programInfo.pipeline().peekDstTexture(&offset);
101
102 fXferProcessor->setData(fDataManager, programInfo.pipeline().getXferProcessor(),
103 dstTexture, offset);
104 }
105
106 // Get new descriptor set
107 if (fUniformBuffer) {
108 if (fDataManager.uploadUniformBuffers(gpu, fUniformBuffer.get()) ||
109 !fUniformDescriptorSet) {
110 if (fUniformDescriptorSet) {
111 fUniformDescriptorSet->recycle(gpu);
112 }
113 fUniformDescriptorSet = gpu->resourceProvider().getUniformDescriptorSet();
114 if (!fUniformDescriptorSet) {
115 return false;
116 }
117 this->writeUniformBuffers(gpu);
118 }
119 static const int kUniformDSIdx = GrVkUniformHandler::kUniformBufferDescSet;
120 commandBuffer->bindDescriptorSets(gpu, this, fPipeline->layout(), kUniformDSIdx, 1,
121 fUniformDescriptorSet->descriptorSet(), 0, nullptr);
122 SkASSERT(fUniformDescriptorSet);
123 commandBuffer->addRecycledResource(fUniformDescriptorSet);
124 commandBuffer->addRecycledResource(fUniformBuffer->resource());
125 }
126 return true;
127 }
128
setAndBindTextures(GrVkGpu * gpu,const GrPrimitiveProcessor & primProc,const GrPipeline & pipeline,const GrSurfaceProxy * const primProcTextures[],GrVkCommandBuffer * commandBuffer)129 bool GrVkPipelineState::setAndBindTextures(GrVkGpu* gpu,
130 const GrPrimitiveProcessor& primProc,
131 const GrPipeline& pipeline,
132 const GrSurfaceProxy* const primProcTextures[],
133 GrVkCommandBuffer* commandBuffer) {
134 SkASSERT(primProcTextures || !primProc.numTextureSamplers());
135
136 struct SamplerBindings {
137 GrSamplerState fState;
138 GrVkTexture* fTexture;
139 };
140 SkAutoSTMalloc<8, SamplerBindings> samplerBindings(fNumSamplers);
141 int currTextureBinding = 0;
142
143 for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
144 SkASSERT(primProcTextures[i]->asTextureProxy());
145 const auto& sampler = primProc.textureSampler(i);
146 auto texture = static_cast<GrVkTexture*>(primProcTextures[i]->peekTexture());
147 samplerBindings[currTextureBinding++] = {sampler.samplerState(), texture};
148 }
149
150 GrFragmentProcessor::CIter fpIter(pipeline);
151 GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
152 for (; fpIter && glslIter; ++fpIter, ++glslIter) {
153 for (int i = 0; i < fpIter->numTextureSamplers(); ++i) {
154 const auto& sampler = fpIter->textureSampler(i);
155 samplerBindings[currTextureBinding++] =
156 {sampler.samplerState(), static_cast<GrVkTexture*>(sampler.peekTexture())};
157 }
158 }
159 SkASSERT(!fpIter && !glslIter);
160
161 if (GrTexture* dstTexture = pipeline.peekDstTexture()) {
162 samplerBindings[currTextureBinding++] = {
163 GrSamplerState::Filter::kNearest, static_cast<GrVkTexture*>(dstTexture)};
164 }
165
166 // Get new descriptor set
167 SkASSERT(fNumSamplers == currTextureBinding);
168 if (fNumSamplers) {
169 static const int kSamplerDSIdx = GrVkUniformHandler::kSamplerDescSet;
170
171 if (fNumSamplers == 1) {
172 auto texture = samplerBindings[0].fTexture;
173 const auto& samplerState = samplerBindings[0].fState;
174 const GrVkDescriptorSet* descriptorSet = texture->cachedSingleDescSet(samplerState);
175 if (descriptorSet) {
176 commandBuffer->addResource(texture->textureView());
177 commandBuffer->addResource(texture->resource());
178 commandBuffer->addRecycledResource(descriptorSet);
179 commandBuffer->bindDescriptorSets(gpu, this, fPipeline->layout(), kSamplerDSIdx, 1,
180 descriptorSet->descriptorSet(), 0, nullptr);
181 return true;
182 }
183 }
184
185 const GrVkDescriptorSet* descriptorSet =
186 gpu->resourceProvider().getSamplerDescriptorSet(fSamplerDSHandle);
187 if (!descriptorSet) {
188 return false;
189 }
190
191 for (int i = 0; i < fNumSamplers; ++i) {
192 GrSamplerState state = samplerBindings[i].fState;
193 GrVkTexture* texture = samplerBindings[i].fTexture;
194
195 const GrVkImageView* textureView = texture->textureView();
196 const GrVkSampler* sampler = nullptr;
197 if (fImmutableSamplers[i]) {
198 sampler = fImmutableSamplers[i];
199 } else {
200 sampler = gpu->resourceProvider().findOrCreateCompatibleSampler(
201 state, texture->ycbcrConversionInfo());
202 }
203 SkASSERT(sampler);
204
205 VkDescriptorImageInfo imageInfo;
206 memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo));
207 imageInfo.sampler = sampler->sampler();
208 imageInfo.imageView = textureView->imageView();
209 imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
210
211 VkWriteDescriptorSet writeInfo;
212 memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet));
213 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
214 writeInfo.pNext = nullptr;
215 writeInfo.dstSet = *descriptorSet->descriptorSet();
216 writeInfo.dstBinding = i;
217 writeInfo.dstArrayElement = 0;
218 writeInfo.descriptorCount = 1;
219 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
220 writeInfo.pImageInfo = &imageInfo;
221 writeInfo.pBufferInfo = nullptr;
222 writeInfo.pTexelBufferView = nullptr;
223
224 GR_VK_CALL(gpu->vkInterface(),
225 UpdateDescriptorSets(gpu->device(), 1, &writeInfo, 0, nullptr));
226 commandBuffer->addResource(sampler);
227 if (!fImmutableSamplers[i]) {
228 sampler->unref(gpu);
229 }
230 commandBuffer->addResource(samplerBindings[i].fTexture->textureView());
231 commandBuffer->addResource(samplerBindings[i].fTexture->resource());
232 }
233 if (fNumSamplers == 1) {
234 GrSamplerState state = samplerBindings[0].fState;
235 GrVkTexture* texture = samplerBindings[0].fTexture;
236 texture->addDescriptorSetToCache(descriptorSet, state);
237 }
238
239 commandBuffer->bindDescriptorSets(gpu, this, fPipeline->layout(), kSamplerDSIdx, 1,
240 descriptorSet->descriptorSet(), 0, nullptr);
241 commandBuffer->addRecycledResource(descriptorSet);
242 descriptorSet->recycle(gpu);
243 }
244 return true;
245 }
246
set_uniform_descriptor_writes(VkWriteDescriptorSet * descriptorWrite,VkDescriptorBufferInfo * bufferInfo,const GrVkUniformBuffer * buffer,VkDescriptorSet descriptorSet)247 void set_uniform_descriptor_writes(VkWriteDescriptorSet* descriptorWrite,
248 VkDescriptorBufferInfo* bufferInfo,
249 const GrVkUniformBuffer* buffer,
250 VkDescriptorSet descriptorSet) {
251
252 memset(bufferInfo, 0, sizeof(VkDescriptorBufferInfo));
253 bufferInfo->buffer = buffer->buffer();
254 bufferInfo->offset = buffer->offset();
255 bufferInfo->range = buffer->size();
256
257 memset(descriptorWrite, 0, sizeof(VkWriteDescriptorSet));
258 descriptorWrite->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
259 descriptorWrite->pNext = nullptr;
260 descriptorWrite->dstSet = descriptorSet;
261 descriptorWrite->dstBinding = GrVkUniformHandler::kUniformBinding;
262 descriptorWrite->dstArrayElement = 0;
263 descriptorWrite->descriptorCount = 1;
264 descriptorWrite->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
265 descriptorWrite->pImageInfo = nullptr;
266 descriptorWrite->pBufferInfo = bufferInfo;
267 descriptorWrite->pTexelBufferView = nullptr;
268 }
269
writeUniformBuffers(const GrVkGpu * gpu)270 void GrVkPipelineState::writeUniformBuffers(const GrVkGpu* gpu) {
271 VkWriteDescriptorSet descriptorWrites[3];
272 VkDescriptorBufferInfo bufferInfos[3];
273
274 uint32_t writeCount = 0;
275
276 if (fUniformBuffer.get()) {
277 SkASSERT(fUniformDescriptorSet);
278 set_uniform_descriptor_writes(&descriptorWrites[writeCount],
279 &bufferInfos[writeCount],
280 fUniformBuffer.get(),
281 *fUniformDescriptorSet->descriptorSet());
282 ++writeCount;
283 }
284
285 if (writeCount) {
286 GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(),
287 writeCount,
288 descriptorWrites,
289 0, nullptr));
290 }
291 }
292
setRenderTargetState(const GrRenderTarget * rt,GrSurfaceOrigin origin)293 void GrVkPipelineState::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin) {
294
295 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
296 if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
297 fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
298 fDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height()));
299 }
300
301 // set RT adjustment
302 SkISize dimensions = rt->dimensions();
303 SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
304 if (fRenderTargetState.fRenderTargetOrigin != origin ||
305 fRenderTargetState.fRenderTargetSize != dimensions) {
306 fRenderTargetState.fRenderTargetSize = dimensions;
307 fRenderTargetState.fRenderTargetOrigin = origin;
308
309 float rtAdjustmentVec[4];
310 fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
311 fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
312 }
313 }
314
bindPipeline(const GrVkGpu * gpu,GrVkCommandBuffer * commandBuffer)315 void GrVkPipelineState::bindPipeline(const GrVkGpu* gpu, GrVkCommandBuffer* commandBuffer) {
316 commandBuffer->bindPipeline(gpu, fPipeline);
317 }
318