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