• 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 "GrVkCopyManager.h"
9 
10 #include "GrSamplerParams.h"
11 #include "GrShaderCaps.h"
12 #include "GrSurface.h"
13 #include "GrTexturePriv.h"
14 #include "GrVkCommandBuffer.h"
15 #include "GrVkCopyPipeline.h"
16 #include "GrVkDescriptorSet.h"
17 #include "GrVkGpu.h"
18 #include "GrVkImageView.h"
19 #include "GrVkRenderTarget.h"
20 #include "GrVkResourceProvider.h"
21 #include "GrVkSampler.h"
22 #include "GrVkTexture.h"
23 #include "GrVkUniformBuffer.h"
24 #include "GrVkVertexBuffer.h"
25 #include "SkPoint.h"
26 #include "SkRect.h"
27 
GrVkCopyManager()28 GrVkCopyManager::GrVkCopyManager()
29     : fVertShaderModule(VK_NULL_HANDLE)
30     , fFragShaderModule(VK_NULL_HANDLE)
31     , fPipelineLayout(VK_NULL_HANDLE) {}
32 
~GrVkCopyManager()33 GrVkCopyManager::~GrVkCopyManager() {}
34 
createCopyProgram(GrVkGpu * gpu)35 bool GrVkCopyManager::createCopyProgram(GrVkGpu* gpu) {
36     const GrShaderCaps* shaderCaps = gpu->caps()->shaderCaps();
37     const char* version = shaderCaps->versionDeclString();
38     SkString vertShaderText(version);
39     vertShaderText.append(
40         "#extension GL_ARB_separate_shader_objects : enable\n"
41         "#extension GL_ARB_shading_language_420pack : enable\n"
42 
43         "layout(set = 0, binding = 0) uniform vertexUniformBuffer {"
44             "mediump vec4 uPosXform;"
45             "mediump vec4 uTexCoordXform;"
46         "};"
47         "layout(location = 0) in highp vec2 inPosition;"
48         "layout(location = 1) out mediump vec2 vTexCoord;"
49 
50         "// Copy Program VS\n"
51         "void main() {"
52             "vTexCoord = inPosition * uTexCoordXform.xy + uTexCoordXform.zw;"
53             "gl_Position.xy = inPosition * uPosXform.xy + uPosXform.zw;"
54             "gl_Position.zw = vec2(0, 1);"
55         "}"
56     );
57 
58     SkString fragShaderText(version);
59     fragShaderText.append(
60         "#extension GL_ARB_separate_shader_objects : enable\n"
61         "#extension GL_ARB_shading_language_420pack : enable\n"
62 
63         "precision mediump float;"
64 
65         "layout(set = 1, binding = 0) uniform mediump sampler2D uTextureSampler;"
66         "layout(location = 1) in mediump vec2 vTexCoord;"
67         "layout(location = 0, index = 0) out mediump vec4 fsColorOut;"
68 
69         "// Copy Program FS\n"
70         "void main() {"
71             "fsColorOut = texture(uTextureSampler, vTexCoord);"
72         "}"
73     );
74 
75     SkSL::Program::Settings settings;
76     SkSL::Program::Inputs inputs;
77     if (!GrCompileVkShaderModule(gpu, vertShaderText.c_str(), VK_SHADER_STAGE_VERTEX_BIT,
78                                  &fVertShaderModule, &fShaderStageInfo[0], settings, &inputs)) {
79         this->destroyResources(gpu);
80         return false;
81     }
82     SkASSERT(inputs.isEmpty());
83 
84     if (!GrCompileVkShaderModule(gpu, fragShaderText.c_str(), VK_SHADER_STAGE_FRAGMENT_BIT,
85                                  &fFragShaderModule, &fShaderStageInfo[1], settings, &inputs)) {
86         this->destroyResources(gpu);
87         return false;
88     }
89     SkASSERT(inputs.isEmpty());
90 
91     VkDescriptorSetLayout dsLayout[2];
92 
93     GrVkResourceProvider& resourceProvider = gpu->resourceProvider();
94 
95     dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout();
96 
97     uint32_t samplerVisibility = kFragment_GrShaderFlag;
98     SkTArray<uint32_t> visibilityArray(&samplerVisibility, 1);
99 
100     resourceProvider.getSamplerDescriptorSetHandle(visibilityArray, &fSamplerDSHandle);
101     dsLayout[GrVkUniformHandler::kSamplerDescSet] =
102         resourceProvider.getSamplerDSLayout(fSamplerDSHandle);
103 
104     // Create the VkPipelineLayout
105     VkPipelineLayoutCreateInfo layoutCreateInfo;
106     memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags));
107     layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
108     layoutCreateInfo.pNext = 0;
109     layoutCreateInfo.flags = 0;
110     layoutCreateInfo.setLayoutCount = 2;
111     layoutCreateInfo.pSetLayouts = dsLayout;
112     layoutCreateInfo.pushConstantRangeCount = 0;
113     layoutCreateInfo.pPushConstantRanges = nullptr;
114 
115     VkResult err = GR_VK_CALL(gpu->vkInterface(), CreatePipelineLayout(gpu->device(),
116                                                                        &layoutCreateInfo,
117                                                                        nullptr,
118                                                                        &fPipelineLayout));
119     if (err) {
120         this->destroyResources(gpu);
121         return false;
122     }
123 
124     static const float vdata[] = {
125         0, 0,
126         0, 1,
127         1, 0,
128         1, 1
129     };
130     fVertexBuffer.reset(GrVkVertexBuffer::Create(gpu, sizeof(vdata), false));
131     SkASSERT(fVertexBuffer.get());
132     fVertexBuffer->updateData(vdata, sizeof(vdata));
133 
134     // We use 2 vec4's for uniforms
135     fUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, 8 * sizeof(float)));
136     SkASSERT(fUniformBuffer.get());
137 
138     return true;
139 }
140 
copySurfaceAsDraw(GrVkGpu * gpu,GrSurface * dst,GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint)141 bool GrVkCopyManager::copySurfaceAsDraw(GrVkGpu* gpu,
142                                         GrSurface* dst,
143                                         GrSurface* src,
144                                         const SkIRect& srcRect,
145                                         const SkIPoint& dstPoint) {
146     if (!gpu->vkCaps().supportsCopiesAsDraws()) {
147         return false;
148     }
149 
150     GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(dst->asRenderTarget());
151     if (!rt) {
152         return false;
153     }
154 
155     GrVkTexture* srcTex = static_cast<GrVkTexture*>(src->asTexture());
156     if (!srcTex) {
157         return false;
158     }
159 
160     if (VK_NULL_HANDLE == fVertShaderModule) {
161         SkASSERT(VK_NULL_HANDLE == fFragShaderModule &&
162                  VK_NULL_HANDLE == fPipelineLayout &&
163                  nullptr == fVertexBuffer.get() &&
164                  nullptr == fUniformBuffer.get());
165         if (!this->createCopyProgram(gpu)) {
166             SkDebugf("Failed to create copy program.\n");
167             return false;
168         }
169     }
170 
171     GrVkResourceProvider& resourceProv = gpu->resourceProvider();
172 
173     GrVkCopyPipeline* pipeline = resourceProv.findOrCreateCopyPipeline(rt,
174                                                                        fShaderStageInfo,
175                                                                        fPipelineLayout);
176     if (!pipeline) {
177         return false;
178     }
179 
180     // UPDATE UNIFORM DESCRIPTOR SET
181     int w = srcRect.width();
182     int h = srcRect.height();
183 
184     // dst rect edges in NDC (-1 to 1)
185     int dw = dst->width();
186     int dh = dst->height();
187     float dx0 = 2.f * dstPoint.fX / dw - 1.f;
188     float dx1 = 2.f * (dstPoint.fX + w) / dw - 1.f;
189     float dy0 = 2.f * dstPoint.fY / dh - 1.f;
190     float dy1 = 2.f * (dstPoint.fY + h) / dh - 1.f;
191     if (kBottomLeft_GrSurfaceOrigin == dst->origin()) {
192         dy0 = -dy0;
193         dy1 = -dy1;
194     }
195 
196 
197     float sx0 = (float)srcRect.fLeft;
198     float sx1 = (float)(srcRect.fLeft + w);
199     float sy0 = (float)srcRect.fTop;
200     float sy1 = (float)(srcRect.fTop + h);
201     int sh = src->height();
202     if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
203         sy0 = sh - sy0;
204         sy1 = sh - sy1;
205     }
206     // src rect edges in normalized texture space (0 to 1).
207     int sw = src->width();
208     sx0 /= sw;
209     sx1 /= sw;
210     sy0 /= sh;
211     sy1 /= sh;
212 
213     float uniData[] = { dx1 - dx0, dy1 - dy0, dx0, dy0,    // posXform
214                         sx1 - sx0, sy1 - sy0, sx0, sy0 };  // texCoordXform
215 
216     fUniformBuffer->updateData(gpu, uniData, sizeof(uniData), nullptr);
217 
218     const GrVkDescriptorSet* uniformDS = resourceProv.getUniformDescriptorSet();
219     SkASSERT(uniformDS);
220 
221     VkDescriptorBufferInfo uniBufferInfo;
222     uniBufferInfo.buffer = fUniformBuffer->buffer();
223     uniBufferInfo.offset = fUniformBuffer->offset();
224     uniBufferInfo.range = fUniformBuffer->size();
225 
226     VkWriteDescriptorSet descriptorWrites;
227     descriptorWrites.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
228     descriptorWrites.pNext = nullptr;
229     descriptorWrites.dstSet = uniformDS->descriptorSet();
230     descriptorWrites.dstBinding = GrVkUniformHandler::kVertexBinding;
231     descriptorWrites.dstArrayElement = 0;
232     descriptorWrites.descriptorCount = 1;
233     descriptorWrites.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
234     descriptorWrites.pImageInfo = nullptr;
235     descriptorWrites.pBufferInfo = &uniBufferInfo;
236     descriptorWrites.pTexelBufferView = nullptr;
237 
238     GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(),
239                                                         1,
240                                                         &descriptorWrites,
241                                                         0, nullptr));
242 
243     // UPDATE SAMPLER DESCRIPTOR SET
244     const GrVkDescriptorSet* samplerDS =
245         gpu->resourceProvider().getSamplerDescriptorSet(fSamplerDSHandle);
246 
247     GrSamplerParams params(SkShader::kClamp_TileMode, GrSamplerParams::kNone_FilterMode);
248 
249     GrVkSampler* sampler =
250         resourceProv.findOrCreateCompatibleSampler(params, srcTex->texturePriv().maxMipMapLevel());
251 
252     VkDescriptorImageInfo imageInfo;
253     memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo));
254     imageInfo.sampler = sampler->sampler();
255     imageInfo.imageView = srcTex->textureView(true)->imageView();
256     imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
257 
258     VkWriteDescriptorSet writeInfo;
259     memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet));
260     writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
261     writeInfo.pNext = nullptr;
262     writeInfo.dstSet = samplerDS->descriptorSet();
263     writeInfo.dstBinding = 0;
264     writeInfo.dstArrayElement = 0;
265     writeInfo.descriptorCount = 1;
266     writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
267     writeInfo.pImageInfo = &imageInfo;
268     writeInfo.pBufferInfo = nullptr;
269     writeInfo.pTexelBufferView = nullptr;
270 
271     GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(),
272                                                         1,
273                                                         &writeInfo,
274                                                         0, nullptr));
275 
276     VkDescriptorSet vkDescSets[] = { uniformDS->descriptorSet(), samplerDS->descriptorSet() };
277 
278     GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(srcTex->asRenderTarget());
279     if (texRT) {
280         gpu->onResolveRenderTarget(texRT);
281     }
282 
283     GrVkPrimaryCommandBuffer* cmdBuffer = gpu->currentCommandBuffer();
284 
285     // TODO: Make tighter bounds and then adjust bounds for origin and granularity if we see
286     //       any perf issues with using the whole bounds
287     SkIRect bounds = SkIRect::MakeWH(rt->width(), rt->height());
288 
289     // Change layouts of rt and texture
290     GrVkImage* targetImage = rt->msaaImage() ? rt->msaaImage() : rt;
291     targetImage->setImageLayout(gpu,
292                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
293                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
294                                 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
295                                 false);
296 
297     srcTex->setImageLayout(gpu,
298                            VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
299                            VK_ACCESS_SHADER_READ_BIT,
300                            VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
301                            false);
302 
303     GrVkRenderPass::LoadStoreOps vkColorOps(VK_ATTACHMENT_LOAD_OP_DONT_CARE,
304                                             VK_ATTACHMENT_STORE_OP_STORE);
305     GrVkRenderPass::LoadStoreOps vkStencilOps(VK_ATTACHMENT_LOAD_OP_LOAD,
306                                               VK_ATTACHMENT_STORE_OP_STORE);
307     const GrVkRenderPass* renderPass;
308     const GrVkResourceProvider::CompatibleRPHandle& rpHandle =
309         rt->compatibleRenderPassHandle();
310     if (rpHandle.isValid()) {
311         renderPass = gpu->resourceProvider().findRenderPass(rpHandle,
312                                                             vkColorOps,
313                                                             vkStencilOps);
314     } else {
315         renderPass = gpu->resourceProvider().findRenderPass(*rt,
316                                                             vkColorOps,
317                                                             vkStencilOps);
318     }
319 
320     SkASSERT(renderPass->isCompatible(*rt->simpleRenderPass()));
321 
322 
323     cmdBuffer->beginRenderPass(gpu, renderPass, nullptr, *rt, bounds, false);
324     cmdBuffer->bindPipeline(gpu, pipeline);
325 
326     // Uniform DescriptorSet, Sampler DescriptorSet, and vertex shader uniformBuffer
327     SkSTArray<3, const GrVkRecycledResource*> descriptorRecycledResources;
328     descriptorRecycledResources.push_back(uniformDS);
329     descriptorRecycledResources.push_back(samplerDS);
330     descriptorRecycledResources.push_back(fUniformBuffer->resource());
331 
332     // One sampler, texture view, and texture
333     SkSTArray<3, const GrVkResource*> descriptorResources;
334     descriptorResources.push_back(sampler);
335     descriptorResources.push_back(srcTex->textureView(true));
336     descriptorResources.push_back(srcTex->resource());
337 
338     cmdBuffer->bindDescriptorSets(gpu,
339                                   descriptorRecycledResources,
340                                   descriptorResources,
341                                   fPipelineLayout,
342                                   0,
343                                   2,
344                                   vkDescSets,
345                                   0,
346                                   nullptr);
347 
348     // Set Dynamic viewport and stencil
349     // We always use one viewport the size of the RT
350     VkViewport viewport;
351     viewport.x = 0.0f;
352     viewport.y = 0.0f;
353     viewport.width = SkIntToScalar(rt->width());
354     viewport.height = SkIntToScalar(rt->height());
355     viewport.minDepth = 0.0f;
356     viewport.maxDepth = 1.0f;
357     cmdBuffer->setViewport(gpu, 0, 1, &viewport);
358 
359     // We assume the scissor is not enabled so just set it to the whole RT
360     VkRect2D scissor;
361     scissor.extent.width = rt->width();
362     scissor.extent.height = rt->height();
363     scissor.offset.x = 0;
364     scissor.offset.y = 0;
365     cmdBuffer->setScissor(gpu, 0, 1, &scissor);
366 
367     cmdBuffer->bindVertexBuffer(gpu, fVertexBuffer.get());
368     cmdBuffer->draw(gpu, 4, 1, 0, 0);
369     cmdBuffer->endRenderPass(gpu);
370 
371     // Release all temp resources which should now be reffed by the cmd buffer
372     pipeline->unref(gpu);
373     uniformDS->unref(gpu);
374     samplerDS->unref(gpu);
375     sampler->unref(gpu);
376     renderPass->unref(gpu);
377 
378     return true;
379 }
380 
destroyResources(GrVkGpu * gpu)381 void GrVkCopyManager::destroyResources(GrVkGpu* gpu) {
382     if (VK_NULL_HANDLE != fVertShaderModule) {
383         GR_VK_CALL(gpu->vkInterface(), DestroyShaderModule(gpu->device(), fVertShaderModule,
384                                                            nullptr));
385         fVertShaderModule = VK_NULL_HANDLE;
386     }
387 
388     if (VK_NULL_HANDLE != fFragShaderModule) {
389         GR_VK_CALL(gpu->vkInterface(), DestroyShaderModule(gpu->device(), fFragShaderModule,
390                                                            nullptr));
391         fFragShaderModule = VK_NULL_HANDLE;
392     }
393 
394     if (VK_NULL_HANDLE != fPipelineLayout) {
395         GR_VK_CALL(gpu->vkInterface(), DestroyPipelineLayout(gpu->device(), fPipelineLayout,
396                                                              nullptr));
397         fPipelineLayout = VK_NULL_HANDLE;
398     }
399 
400     if (fUniformBuffer) {
401         fUniformBuffer->release(gpu);
402         fUniformBuffer.reset();
403     }
404 }
405 
abandonResources()406 void GrVkCopyManager::abandonResources() {
407     fVertShaderModule = VK_NULL_HANDLE;
408     fFragShaderModule = VK_NULL_HANDLE;
409     fPipelineLayout = VK_NULL_HANDLE;
410 
411     if (fUniformBuffer) {
412         fUniformBuffer->abandon();
413         fUniformBuffer.reset();
414     }
415 }
416