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 "GrVkProgram.h"
9 
10 #include "GrPipeline.h"
11 #include "GrVkCommandBuffer.h"
12 #include "GrVkDescriptorPool.h"
13 #include "GrVkGpu.h"
14 #include "GrVkImageView.h"
15 #include "GrVkMemory.h"
16 #include "GrVkPipeline.h"
17 #include "GrVkSampler.h"
18 #include "GrVkTexture.h"
19 #include "GrVkUniformBuffer.h"
20 #include "glsl/GrGLSLFragmentProcessor.h"
21 #include "glsl/GrGLSLGeometryProcessor.h"
22 #include "glsl/GrGLSLXferProcessor.h"
23 
GrVkProgram(GrVkGpu * gpu,GrVkPipeline * pipeline,VkPipelineLayout layout,VkDescriptorSetLayout dsLayout[2],GrVkDescriptorPool * descriptorPool,VkDescriptorSet descriptorSets[2],const BuiltinUniformHandles & builtinUniformHandles,const UniformInfoArray & uniforms,uint32_t vertexUniformSize,uint32_t fragmentUniformSize,uint32_t numSamplers,GrGLSLPrimitiveProcessor * geometryProcessor,GrGLSLXferProcessor * xferProcessor,const GrGLSLFragProcs & fragmentProcessors)24 GrVkProgram::GrVkProgram(GrVkGpu* gpu,
25                          GrVkPipeline* pipeline,
26                          VkPipelineLayout layout,
27                          VkDescriptorSetLayout dsLayout[2],
28                          GrVkDescriptorPool* descriptorPool,
29                          VkDescriptorSet descriptorSets[2],
30                          const BuiltinUniformHandles& builtinUniformHandles,
31                          const UniformInfoArray& uniforms,
32                          uint32_t vertexUniformSize,
33                          uint32_t fragmentUniformSize,
34                          uint32_t numSamplers,
35                          GrGLSLPrimitiveProcessor* geometryProcessor,
36                          GrGLSLXferProcessor* xferProcessor,
37                          const GrGLSLFragProcs& fragmentProcessors)
38     : fDescriptorPool(descriptorPool)
39     , fPipeline(pipeline)
40     , fPipelineLayout(layout)
41     , fBuiltinUniformHandles(builtinUniformHandles)
42     , fGeometryProcessor(geometryProcessor)
43     , fXferProcessor(xferProcessor)
44     , fFragmentProcessors(fragmentProcessors)
45     , fProgramDataManager(uniforms, vertexUniformSize, fragmentUniformSize) {
46     fSamplers.setReserve(numSamplers);
47     fTextureViews.setReserve(numSamplers);
48     fTextures.setReserve(numSamplers);
49 
50     memcpy(fDSLayout, dsLayout, 2 * sizeof(VkDescriptorSetLayout));
51     memcpy(fDescriptorSets, descriptorSets, 2 * sizeof(VkDescriptorSetLayout));
52 
53     fVertexUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, vertexUniformSize, true));
54     fFragmentUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, fragmentUniformSize, true));
55 
56 #ifdef SK_DEBUG
57     fNumSamplers = numSamplers;
58 #endif
59 }
60 
~GrVkProgram()61 GrVkProgram::~GrVkProgram() {
62     // Must of freed all GPU resources before this is destroyed
63     SkASSERT(!fPipeline);
64     SkASSERT(!fDescriptorPool);
65     SkASSERT(!fPipelineLayout);
66     SkASSERT(!fDSLayout[0]);
67     SkASSERT(!fDSLayout[1]);
68     SkASSERT(!fSamplers.count());
69     SkASSERT(!fTextureViews.count());
70     SkASSERT(!fTextures.count());
71 }
72 
freeTempResources(const GrVkGpu * gpu)73 void GrVkProgram::freeTempResources(const GrVkGpu* gpu) {
74     for (int i = 0; i < fSamplers.count(); ++i) {
75         fSamplers[i]->unref(gpu);
76     }
77     fSamplers.rewind();
78 
79     for (int i = 0; i < fTextureViews.count(); ++i) {
80             fTextureViews[i]->unref(gpu);
81     }
82     fTextureViews.rewind();
83 
84     for (int i = 0; i < fTextures.count(); ++i) {
85             fTextures[i]->unref(gpu);
86     }
87     fTextures.rewind();
88 }
89 
freeGPUResources(const GrVkGpu * gpu)90 void GrVkProgram::freeGPUResources(const GrVkGpu* gpu) {
91     if (fPipeline) {
92         fPipeline->unref(gpu);
93         fPipeline = nullptr;
94     }
95     if (fDescriptorPool) {
96         fDescriptorPool->unref(gpu);
97         fDescriptorPool = nullptr;
98     }
99     if (fPipelineLayout) {
100         GR_VK_CALL(gpu->vkInterface(), DestroyPipelineLayout(gpu->device(),
101                                                              fPipelineLayout,
102                                                              nullptr));
103         fPipelineLayout = nullptr;
104     }
105 
106     if (fDSLayout[0]) {
107         GR_VK_CALL(gpu->vkInterface(), DestroyDescriptorSetLayout(gpu->device(), fDSLayout[0],
108                                                                   nullptr));
109         fDSLayout[0] = nullptr;
110     }
111     if (fDSLayout[1]) {
112         GR_VK_CALL(gpu->vkInterface(), DestroyDescriptorSetLayout(gpu->device(), fDSLayout[1],
113                                                                   nullptr));
114         fDSLayout[1] = nullptr;
115     }
116 
117     if (fVertexUniformBuffer) {
118         fVertexUniformBuffer->release(gpu);
119     }
120 
121     if (fFragmentUniformBuffer) {
122         fFragmentUniformBuffer->release(gpu);
123     }
124     this->freeTempResources(gpu);
125 }
126 
abandonGPUResources()127 void GrVkProgram::abandonGPUResources() {
128     fPipeline->unrefAndAbandon();
129     fPipeline = nullptr;
130     fDescriptorPool->unrefAndAbandon();
131     fDescriptorPool = nullptr;
132     fPipelineLayout = nullptr;
133     fDSLayout[0] = nullptr;
134     fDSLayout[1] = nullptr;
135 
136     fVertexUniformBuffer->abandon();
137     fFragmentUniformBuffer->abandon();
138 
139     for (int i = 0; i < fSamplers.count(); ++i) {
140         fSamplers[i]->unrefAndAbandon();
141     }
142     fSamplers.rewind();
143 
144     for (int i = 0; i < fTextureViews.count(); ++i) {
145         fTextureViews[i]->unrefAndAbandon();
146     }
147     fTextureViews.rewind();
148 
149     for (int i = 0; i < fTextures.count(); ++i) {
150         fTextures[i]->unrefAndAbandon();
151     }
152     fTextures.rewind();
153 }
154 
append_texture_bindings(const GrProcessor & processor,SkTArray<const GrTextureAccess * > * textureBindings)155 static void append_texture_bindings(const GrProcessor& processor,
156                                     SkTArray<const GrTextureAccess*>* textureBindings) {
157     if (int numTextures = processor.numTextures()) {
158         const GrTextureAccess** bindings = textureBindings->push_back_n(numTextures);
159         int i = 0;
160         do {
161             bindings[i] = &processor.textureAccess(i);
162         } while (++i < numTextures);
163     }
164 }
165 
setData(const GrVkGpu * gpu,const GrPrimitiveProcessor & primProc,const GrPipeline & pipeline)166 void GrVkProgram::setData(const GrVkGpu* gpu,
167                           const GrPrimitiveProcessor& primProc,
168                           const GrPipeline& pipeline) {
169     // This is here to protect against someone calling setData multiple times in a row without
170     // freeing the tempData between calls.
171     this->freeTempResources(gpu);
172 
173     this->setRenderTargetState(pipeline);
174 
175     SkSTArray<8, const GrTextureAccess*> textureBindings;
176 
177     fGeometryProcessor->setData(fProgramDataManager, primProc);
178     append_texture_bindings(primProc, &textureBindings);
179 
180     for (int i = 0; i < fFragmentProcessors.count(); ++i) {
181         const GrFragmentProcessor& processor = pipeline.getFragmentProcessor(i);
182         fFragmentProcessors[i]->setData(fProgramDataManager, processor);
183         fGeometryProcessor->setTransformData(primProc, fProgramDataManager, i,
184                                              processor.coordTransforms());
185         append_texture_bindings(processor, &textureBindings);
186     }
187 
188     fXferProcessor->setData(fProgramDataManager, pipeline.getXferProcessor());
189     append_texture_bindings(pipeline.getXferProcessor(), &textureBindings);
190 
191     this->writeUniformBuffers(gpu);
192 
193     this->writeSamplers(gpu, textureBindings);
194 }
195 
writeUniformBuffers(const GrVkGpu * gpu)196 void GrVkProgram::writeUniformBuffers(const GrVkGpu* gpu) {
197     fProgramDataManager.uploadUniformBuffers(gpu, fVertexUniformBuffer, fFragmentUniformBuffer);
198 
199     VkWriteDescriptorSet descriptorWrites[2];
200     memset(descriptorWrites, 0, 2 * sizeof(VkWriteDescriptorSet));
201 
202     uint32_t firstUniformWrite = 0;
203     uint32_t uniformBindingUpdateCount = 0;
204 
205     // Vertex Uniform Buffer
206     if (fVertexUniformBuffer.get()) {
207         ++uniformBindingUpdateCount;
208         VkDescriptorBufferInfo vertBufferInfo;
209         memset(&vertBufferInfo, 0, sizeof(VkDescriptorBufferInfo));
210         vertBufferInfo.buffer = fVertexUniformBuffer->buffer();
211         vertBufferInfo.offset = 0;
212         vertBufferInfo.range = fVertexUniformBuffer->size();
213 
214         descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
215         descriptorWrites[0].pNext = nullptr;
216         descriptorWrites[0].dstSet = fDescriptorSets[1];
217         descriptorWrites[0].dstBinding = GrVkUniformHandler::kVertexBinding;
218         descriptorWrites[0].dstArrayElement = 0;
219         descriptorWrites[0].descriptorCount = 1;
220         descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
221         descriptorWrites[0].pImageInfo = nullptr;
222         descriptorWrites[0].pBufferInfo = &vertBufferInfo;
223         descriptorWrites[0].pTexelBufferView = nullptr;
224     }
225 
226     // Fragment Uniform Buffer
227     if (fFragmentUniformBuffer.get()) {
228         if (0 == uniformBindingUpdateCount) {
229             firstUniformWrite = 1;
230         }
231         ++uniformBindingUpdateCount;
232         VkDescriptorBufferInfo fragBufferInfo;
233         memset(&fragBufferInfo, 0, sizeof(VkDescriptorBufferInfo));
234         fragBufferInfo.buffer = fFragmentUniformBuffer->buffer();
235         fragBufferInfo.offset = 0;
236         fragBufferInfo.range = fFragmentUniformBuffer->size();
237 
238         descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
239         descriptorWrites[1].pNext = nullptr;
240         descriptorWrites[1].dstSet = fDescriptorSets[1];
241         descriptorWrites[1].dstBinding = GrVkUniformHandler::kFragBinding;;
242         descriptorWrites[1].dstArrayElement = 0;
243         descriptorWrites[1].descriptorCount = 1;
244         descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
245         descriptorWrites[1].pImageInfo = nullptr;
246         descriptorWrites[1].pBufferInfo = &fragBufferInfo;
247         descriptorWrites[1].pTexelBufferView = nullptr;
248     }
249 
250     if (uniformBindingUpdateCount) {
251         GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(),
252                                                             uniformBindingUpdateCount,
253                                                             &descriptorWrites[firstUniformWrite],
254                                                             0, nullptr));
255     }
256 }
257 
writeSamplers(const GrVkGpu * gpu,const SkTArray<const GrTextureAccess * > & textureBindings)258 void GrVkProgram::writeSamplers(const GrVkGpu* gpu,
259                                 const SkTArray<const GrTextureAccess*>& textureBindings) {
260     SkASSERT(fNumSamplers == textureBindings.count());
261 
262     for (int i = 0; i < textureBindings.count(); ++i) {
263         fSamplers.push(GrVkSampler::Create(gpu, *textureBindings[i]));
264 
265         GrVkTexture* texture = static_cast<GrVkTexture*>(textureBindings[i]->getTexture());
266 
267         const GrVkImage::Resource* textureResource = texture->resource();
268         textureResource->ref();
269         fTextures.push(textureResource);
270 
271         const GrVkImageView* textureView = texture->textureView();
272         textureView->ref();
273         fTextureViews.push(textureView);
274 
275         // Change texture layout so it can be read in shader
276         VkImageLayout layout = texture->currentLayout();
277         VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFlags(layout);
278         VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
279         VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
280         VkAccessFlags dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
281         texture->setImageLayout(gpu,
282                                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
283                                 srcAccessMask,
284                                 dstAccessMask,
285                                 srcStageMask,
286                                 dstStageMask,
287                                 false);
288 
289         VkDescriptorImageInfo imageInfo;
290         memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo));
291         imageInfo.sampler = fSamplers[i]->sampler();
292         imageInfo.imageView = texture->textureView()->imageView();
293         imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
294 
295         VkWriteDescriptorSet writeInfo;
296         memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet));
297         writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
298         writeInfo.pNext = nullptr;
299         writeInfo.dstSet = fDescriptorSets[GrVkUniformHandler::kSamplerDescSet];
300         writeInfo.dstBinding = i;
301         writeInfo.dstArrayElement = 0;
302         writeInfo.descriptorCount = 1;
303         writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
304         writeInfo.pImageInfo = &imageInfo;
305         writeInfo.pBufferInfo = nullptr;
306         writeInfo.pTexelBufferView = nullptr;
307 
308         GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(),
309                                                             1,
310                                                             &writeInfo,
311                                                             0,
312                                                             nullptr));
313     }
314 }
315 
setRenderTargetState(const GrPipeline & pipeline)316 void GrVkProgram::setRenderTargetState(const GrPipeline& pipeline) {
317     // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
318     if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
319         fRenderTargetState.fRenderTargetSize.fHeight != pipeline.getRenderTarget()->height()) {
320         fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni,
321                                   SkIntToScalar(pipeline.getRenderTarget()->height()));
322     }
323 
324     // set RT adjustment
325     const GrRenderTarget* rt = pipeline.getRenderTarget();
326     SkISize size;
327     size.set(rt->width(), rt->height());
328     SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
329     if (fRenderTargetState.fRenderTargetOrigin != rt->origin() ||
330         fRenderTargetState.fRenderTargetSize != size) {
331         fRenderTargetState.fRenderTargetSize = size;
332         fRenderTargetState.fRenderTargetOrigin = rt->origin();
333 
334         float rtAdjustmentVec[4];
335         fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
336         fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
337     }
338 }
339 
bind(const GrVkGpu * gpu,GrVkCommandBuffer * commandBuffer)340 void GrVkProgram::bind(const GrVkGpu* gpu, GrVkCommandBuffer* commandBuffer) {
341     commandBuffer->bindPipeline(gpu, fPipeline);
342     commandBuffer->bindDescriptorSets(gpu, this, fPipelineLayout, 0, 2, fDescriptorSets, 0,
343                                       nullptr);
344 }
345 
addUniformResources(GrVkCommandBuffer & commandBuffer)346 void GrVkProgram::addUniformResources(GrVkCommandBuffer& commandBuffer) {
347 #if 1
348     commandBuffer.addResource(fDescriptorPool);
349     if (fVertexUniformBuffer.get()) {
350         commandBuffer.addResource(fVertexUniformBuffer->resource());
351     }
352     if (fFragmentUniformBuffer.get()) {
353         commandBuffer.addResource(fFragmentUniformBuffer->resource());
354     }
355     for (int i = 0; i < fSamplers.count(); ++i) {
356         commandBuffer.addResource(fSamplers[i]);
357     }
358 
359     for (int i = 0; i < fTextureViews.count(); ++i) {
360         commandBuffer.addResource(fTextureViews[i]);
361     }
362 
363     for (int i = 0; i < fTextures.count(); ++i) {
364         commandBuffer.addResource(fTextures[i]);
365     }
366 #endif
367 }
368