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