Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(558)

Side by Side Diff: src/gpu/vk/GrVkProgram.cpp

Issue 1816153002: Set up cache in vulkan to reuse GrVkPrograms (aka VkPipelines) (Closed) Base URL: https://skia.googlesource.com/skia.git@progSamplers
Patch Set: rebase Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/vk/GrVkProgram.h ('k') | src/gpu/vk/GrVkProgramBuilder.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
24 GrVkProgram::GrVkProgram(GrVkGpu* gpu,
25 GrVkPipeline* pipeline,
26 VkPipelineLayout layout,
27 VkDescriptorSetLayout dsLayout[2],
28 const BuiltinUniformHandles& builtinUniformHandles,
29 const UniformInfoArray& uniforms,
30 uint32_t vertexUniformSize,
31 uint32_t fragmentUniformSize,
32 uint32_t numSamplers,
33 GrGLSLPrimitiveProcessor* geometryProcessor,
34 GrGLSLXferProcessor* xferProcessor,
35 const GrGLSLFragProcs& fragmentProcessors)
36 : fPipeline(pipeline)
37 , fPipelineLayout(layout)
38 , fBuiltinUniformHandles(builtinUniformHandles)
39 , fGeometryProcessor(geometryProcessor)
40 , fXferProcessor(xferProcessor)
41 , fFragmentProcessors(fragmentProcessors)
42 , fProgramDataManager(uniforms, vertexUniformSize, fragmentUniformSize)
43 , fSamplerPoolManager(dsLayout[GrVkUniformHandler::kSamplerDescSet],
44 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, numSamplers , gpu)
45 , fUniformPoolManager(dsLayout[GrVkUniformHandler::kUniformBufferDescSet],
46 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, gpu) {
47 fSamplers.setReserve(numSamplers);
48 fTextureViews.setReserve(numSamplers);
49 fTextures.setReserve(numSamplers);
50
51 fDescriptorSets[0] = VK_NULL_HANDLE;
52 fDescriptorSets[1] = VK_NULL_HANDLE;
53
54 // Currently we are always binding a descriptor set for uniform buffers.
55 fStartDS = GrVkUniformHandler::kUniformBufferDescSet;
56 fDSCount = 1;
57 if (numSamplers) {
58 fDSCount++;
59 fStartDS = SkTMin(fStartDS, (int)GrVkUniformHandler::kSamplerDescSet);
60 }
61
62 fVertexUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, vertexUniformSize, true));
63 fFragmentUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, fragmentUniformS ize, true));
64
65 fNumSamplers = numSamplers;
66 }
67
68 GrVkProgram::~GrVkProgram() {
69 // Must of freed all GPU resources before this is destroyed
70 SkASSERT(!fPipeline);
71 SkASSERT(!fPipelineLayout);
72 SkASSERT(!fSamplers.count());
73 SkASSERT(!fTextureViews.count());
74 SkASSERT(!fTextures.count());
75 }
76
77 void GrVkProgram::freeTempResources(const GrVkGpu* gpu) {
78 for (int i = 0; i < fSamplers.count(); ++i) {
79 fSamplers[i]->unref(gpu);
80 }
81 fSamplers.rewind();
82
83 for (int i = 0; i < fTextureViews.count(); ++i) {
84 fTextureViews[i]->unref(gpu);
85 }
86 fTextureViews.rewind();
87
88 for (int i = 0; i < fTextures.count(); ++i) {
89 fTextures[i]->unref(gpu);
90 }
91 fTextures.rewind();
92 }
93
94 void GrVkProgram::freeGPUResources(const GrVkGpu* gpu) {
95 if (fPipeline) {
96 fPipeline->unref(gpu);
97 fPipeline = nullptr;
98 }
99
100 if (fPipelineLayout) {
101 GR_VK_CALL(gpu->vkInterface(), DestroyPipelineLayout(gpu->device(),
102 fPipelineLayout,
103 nullptr));
104 fPipelineLayout = VK_NULL_HANDLE;
105 }
106
107 if (fVertexUniformBuffer) {
108 fVertexUniformBuffer->release(gpu);
109 }
110
111 if (fFragmentUniformBuffer) {
112 fFragmentUniformBuffer->release(gpu);
113 }
114
115 fSamplerPoolManager.freeGPUResources(gpu);
116 fUniformPoolManager.freeGPUResources(gpu);
117
118 this->freeTempResources(gpu);
119 }
120
121 void GrVkProgram::abandonGPUResources() {
122 fPipeline->unrefAndAbandon();
123 fPipeline = nullptr;
124
125 fPipelineLayout = VK_NULL_HANDLE;
126
127 fVertexUniformBuffer->abandon();
128 fFragmentUniformBuffer->abandon();
129
130 for (int i = 0; i < fSamplers.count(); ++i) {
131 fSamplers[i]->unrefAndAbandon();
132 }
133 fSamplers.rewind();
134
135 for (int i = 0; i < fTextureViews.count(); ++i) {
136 fTextureViews[i]->unrefAndAbandon();
137 }
138 fTextureViews.rewind();
139
140 for (int i = 0; i < fTextures.count(); ++i) {
141 fTextures[i]->unrefAndAbandon();
142 }
143 fTextures.rewind();
144
145 fSamplerPoolManager.abandonGPUResources();
146 fUniformPoolManager.abandonGPUResources();
147 }
148
149 static void append_texture_bindings(const GrProcessor& processor,
150 SkTArray<const GrTextureAccess*>* textureBin dings) {
151 if (int numTextures = processor.numTextures()) {
152 const GrTextureAccess** bindings = textureBindings->push_back_n(numTextu res);
153 int i = 0;
154 do {
155 bindings[i] = &processor.textureAccess(i);
156 } while (++i < numTextures);
157 }
158 }
159
160 void GrVkProgram::setData(GrVkGpu* gpu,
161 const GrPrimitiveProcessor& primProc,
162 const GrPipeline& pipeline) {
163 // This is here to protect against someone calling setData multiple times in a row without
164 // freeing the tempData between calls.
165 this->freeTempResources(gpu);
166
167 this->setRenderTargetState(pipeline);
168
169 SkSTArray<8, const GrTextureAccess*> textureBindings;
170
171 fGeometryProcessor->setData(fProgramDataManager, primProc);
172 append_texture_bindings(primProc, &textureBindings);
173
174 for (int i = 0; i < fFragmentProcessors.count(); ++i) {
175 const GrFragmentProcessor& processor = pipeline.getFragmentProcessor(i);
176 fFragmentProcessors[i]->setData(fProgramDataManager, processor);
177 fGeometryProcessor->setTransformData(primProc, fProgramDataManager, i,
178 processor.coordTransforms());
179 append_texture_bindings(processor, &textureBindings);
180 }
181
182 fXferProcessor->setData(fProgramDataManager, pipeline.getXferProcessor());
183 append_texture_bindings(pipeline.getXferProcessor(), &textureBindings);
184
185 // Get new descriptor sets
186 if (fNumSamplers) {
187 fSamplerPoolManager.getNewDescriptorSet(gpu,
188 &fDescriptorSets[GrVkUniformHandler ::kSamplerDescSet]);
189 }
190 fUniformPoolManager.getNewDescriptorSet(gpu,
191 &fDescriptorSets[GrVkUniformHandler::kUni formBufferDescSet]);
192
193 this->writeUniformBuffers(gpu);
194
195 this->writeSamplers(gpu, textureBindings);
196 }
197
198 void GrVkProgram::writeUniformBuffers(const GrVkGpu* gpu) {
199 fProgramDataManager.uploadUniformBuffers(gpu, fVertexUniformBuffer, fFragmen tUniformBuffer);
200
201 VkWriteDescriptorSet descriptorWrites[2];
202 memset(descriptorWrites, 0, 2 * sizeof(VkWriteDescriptorSet));
203
204 uint32_t firstUniformWrite = 0;
205 uint32_t uniformBindingUpdateCount = 0;
206
207 VkDescriptorBufferInfo vertBufferInfo;
208 // Vertex Uniform Buffer
209 if (fVertexUniformBuffer.get()) {
210 ++uniformBindingUpdateCount;
211 memset(&vertBufferInfo, 0, sizeof(VkDescriptorBufferInfo));
212 vertBufferInfo.buffer = fVertexUniformBuffer->buffer();
213 vertBufferInfo.offset = 0;
214 vertBufferInfo.range = fVertexUniformBuffer->size();
215
216 descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
217 descriptorWrites[0].pNext = nullptr;
218 descriptorWrites[0].dstSet = fDescriptorSets[1];
219 descriptorWrites[0].dstBinding = GrVkUniformHandler::kVertexBinding;
220 descriptorWrites[0].dstArrayElement = 0;
221 descriptorWrites[0].descriptorCount = 1;
222 descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
223 descriptorWrites[0].pImageInfo = nullptr;
224 descriptorWrites[0].pBufferInfo = &vertBufferInfo;
225 descriptorWrites[0].pTexelBufferView = nullptr;
226 }
227
228 VkDescriptorBufferInfo fragBufferInfo;
229 // Fragment Uniform Buffer
230 if (fFragmentUniformBuffer.get()) {
231 if (0 == uniformBindingUpdateCount) {
232 firstUniformWrite = 1;
233 }
234 ++uniformBindingUpdateCount;
235 memset(&fragBufferInfo, 0, sizeof(VkDescriptorBufferInfo));
236 fragBufferInfo.buffer = fFragmentUniformBuffer->buffer();
237 fragBufferInfo.offset = 0;
238 fragBufferInfo.range = fFragmentUniformBuffer->size();
239
240 descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
241 descriptorWrites[1].pNext = nullptr;
242 descriptorWrites[1].dstSet = fDescriptorSets[1];
243 descriptorWrites[1].dstBinding = GrVkUniformHandler::kFragBinding;;
244 descriptorWrites[1].dstArrayElement = 0;
245 descriptorWrites[1].descriptorCount = 1;
246 descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
247 descriptorWrites[1].pImageInfo = nullptr;
248 descriptorWrites[1].pBufferInfo = &fragBufferInfo;
249 descriptorWrites[1].pTexelBufferView = nullptr;
250 }
251
252 if (uniformBindingUpdateCount) {
253 GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(),
254 uniformBindingUpdate Count,
255 &descriptorWrites[fi rstUniformWrite],
256 0, nullptr));
257 }
258 }
259
260 void GrVkProgram::writeSamplers(GrVkGpu* gpu,
261 const SkTArray<const GrTextureAccess*>& textureB indings) {
262 SkASSERT(fNumSamplers == textureBindings.count());
263
264 for (int i = 0; i < textureBindings.count(); ++i) {
265 const GrTextureParams& params = textureBindings[i]->getParams();
266 fSamplers.push(gpu->resourceProvider().findOrCreateCompatibleSampler(par ams));
267
268 GrVkTexture* texture = static_cast<GrVkTexture*>(textureBindings[i]->get Texture());
269
270 const GrVkImage::Resource* textureResource = texture->resource();
271 textureResource->ref();
272 fTextures.push(textureResource);
273
274 const GrVkImageView* textureView = texture->textureView();
275 textureView->ref();
276 fTextureViews.push(textureView);
277
278 // Change texture layout so it can be read in shader
279 VkImageLayout layout = texture->currentLayout();
280 VkPipelineStageFlags srcStageMask = GrVkMemory::LayoutToPipelineStageFla gs(layout);
281 VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
282 VkAccessFlags srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(layout);
283 VkAccessFlags dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
284 texture->setImageLayout(gpu,
285 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
286 srcAccessMask,
287 dstAccessMask,
288 srcStageMask,
289 dstStageMask,
290 false);
291
292 VkDescriptorImageInfo imageInfo;
293 memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo));
294 imageInfo.sampler = fSamplers[i]->sampler();
295 imageInfo.imageView = texture->textureView()->imageView();
296 imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
297
298 VkWriteDescriptorSet writeInfo;
299 memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet));
300 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
301 writeInfo.pNext = nullptr;
302 writeInfo.dstSet = fDescriptorSets[GrVkUniformHandler::kSamplerDescSet];
303 writeInfo.dstBinding = i;
304 writeInfo.dstArrayElement = 0;
305 writeInfo.descriptorCount = 1;
306 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
307 writeInfo.pImageInfo = &imageInfo;
308 writeInfo.pBufferInfo = nullptr;
309 writeInfo.pTexelBufferView = nullptr;
310
311 GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(),
312 1,
313 &writeInfo,
314 0,
315 nullptr));
316 }
317 }
318
319 void GrVkProgram::setRenderTargetState(const GrPipeline& pipeline) {
320 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
321 if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
322 fRenderTargetState.fRenderTargetSize.fHeight != pipeline.getRenderTarget ()->height()) {
323 fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni,
324 SkIntToScalar(pipeline.getRenderTarget()->heig ht()));
325 }
326
327 // set RT adjustment
328 const GrRenderTarget* rt = pipeline.getRenderTarget();
329 SkISize size;
330 size.set(rt->width(), rt->height());
331 SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
332 if (fRenderTargetState.fRenderTargetOrigin != rt->origin() ||
333 fRenderTargetState.fRenderTargetSize != size) {
334 fRenderTargetState.fRenderTargetSize = size;
335 fRenderTargetState.fRenderTargetOrigin = rt->origin();
336
337 float rtAdjustmentVec[4];
338 fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
339 fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, r tAdjustmentVec);
340 }
341 }
342
343 void GrVkProgram::bind(const GrVkGpu* gpu, GrVkCommandBuffer* commandBuffer) {
344 commandBuffer->bindPipeline(gpu, fPipeline);
345
346 if (fDSCount) {
347 commandBuffer->bindDescriptorSets(gpu, this, fPipelineLayout, fStartDS, fDSCount,
348 &fDescriptorSets[fStartDS], 0, nullptr );
349 }
350 }
351
352 void GrVkProgram::addUniformResources(GrVkCommandBuffer& commandBuffer) {
353 if (fSamplerPoolManager.fPool) {
354 commandBuffer.addResource(fSamplerPoolManager.fPool);
355 }
356 if (fUniformPoolManager.fPool) {
357 commandBuffer.addResource(fUniformPoolManager.fPool);
358 }
359
360 if (fVertexUniformBuffer.get()) {
361 commandBuffer.addResource(fVertexUniformBuffer->resource());
362 }
363 if (fFragmentUniformBuffer.get()) {
364 commandBuffer.addResource(fFragmentUniformBuffer->resource());
365 }
366 for (int i = 0; i < fSamplers.count(); ++i) {
367 commandBuffer.addResource(fSamplers[i]);
368 }
369
370 for (int i = 0; i < fTextureViews.count(); ++i) {
371 commandBuffer.addResource(fTextureViews[i]);
372 }
373
374 for (int i = 0; i < fTextures.count(); ++i) {
375 commandBuffer.addResource(fTextures[i]);
376 }
377 }
378
379 ////////////////////////////////////////////////////////////////////////////////
380
381 void GrVkProgram::DescriptorPoolManager::getNewPool(GrVkGpu* gpu) {
382 if (fPool) {
383 fPool->unref(gpu);
384 SkASSERT(fMaxDescriptorSets < (SK_MaxU32 >> 1));
385 fMaxDescriptorSets = fMaxDescriptorSets << 1;
386
387 }
388 if (fMaxDescriptorSets) {
389 fPool = gpu->resourceProvider().findOrCreateCompatibleDescriptorPool(fDe scType,
390 fMa xDescriptorSets);
391 }
392 SkASSERT(fPool || !fMaxDescriptorSets);
393 }
394
395 void GrVkProgram::DescriptorPoolManager::getNewDescriptorSet(GrVkGpu* gpu, VkDes criptorSet* ds) {
396 if (!fMaxDescriptorSets) {
397 return;
398 }
399 if (fCurrentDescriptorSet == fMaxDescriptorSets) {
400 this->getNewPool(gpu);
401 fCurrentDescriptorSet = 0;
402 }
403 fCurrentDescriptorSet++;
404
405 VkDescriptorSetAllocateInfo dsAllocateInfo;
406 memset(&dsAllocateInfo, 0, sizeof(VkDescriptorSetAllocateInfo));
407 dsAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
408 dsAllocateInfo.pNext = nullptr;
409 dsAllocateInfo.descriptorPool = fPool->descPool();
410 dsAllocateInfo.descriptorSetCount = 1;
411 dsAllocateInfo.pSetLayouts = &fDescLayout;
412
413 GR_VK_CALL_ERRCHECK(gpu->vkInterface(), AllocateDescriptorSets(gpu->device() ,
414 &dsAllocateIn fo,
415 ds));
416 }
417
418 void GrVkProgram::DescriptorPoolManager::freeGPUResources(const GrVkGpu* gpu) {
419 if (fDescLayout) {
420 GR_VK_CALL(gpu->vkInterface(), DestroyDescriptorSetLayout(gpu->device(), fDescLayout,
421 nullptr));
422 fDescLayout = VK_NULL_HANDLE;
423 }
424
425 if (fPool) {
426 fPool->unref(gpu);
427 fPool = nullptr;
428 }
429 }
430
431 void GrVkProgram::DescriptorPoolManager::abandonGPUResources() {
432 fDescLayout = VK_NULL_HANDLE;
433 if (fPool) {
434 fPool->unrefAndAbandon();
435 fPool = nullptr;
436 }
437 }
OLDNEW
« no previous file with comments | « src/gpu/vk/GrVkProgram.h ('k') | src/gpu/vk/GrVkProgramBuilder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698