• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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