 Chromium Code Reviews
 Chromium Code Reviews Issue 2215363003:
  Add addtional resolve calls to vulkan backend  (Closed) 
  Base URL: https://skia.googlesource.com/skia.git@fixResolve
    
  
    Issue 2215363003:
  Add addtional resolve calls to vulkan backend  (Closed) 
  Base URL: https://skia.googlesource.com/skia.git@fixResolve| OLD | NEW | 
|---|---|
| 1 /* | 1 /* | 
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. | 
| 3 * | 3 * | 
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be | 
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. | 
| 6 */ | 6 */ | 
| 7 | 7 | 
| 8 #include "GrVkGpu.h" | 8 #include "GrVkGpu.h" | 
| 9 | 9 | 
| 10 #include "GrContextOptions.h" | 10 #include "GrContextOptions.h" | 
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 277 tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig; | 277 tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig; | 
| 278 tempDrawInfo->fTempSurfaceDesc.fWidth = width; | 278 tempDrawInfo->fTempSurfaceDesc.fWidth = width; | 
| 279 tempDrawInfo->fTempSurfaceDesc.fHeight = height; | 279 tempDrawInfo->fTempSurfaceDesc.fHeight = height; | 
| 280 tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0; | 280 tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 0; | 
| 281 tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; | 281 tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; | 
| 282 | 282 | 
| 283 if (dstSurface->config() == srcConfig) { | 283 if (dstSurface->config() == srcConfig) { | 
| 284 return true; | 284 return true; | 
| 285 } | 285 } | 
| 286 | 286 | 
| 287 if (renderTarget && this->vkCaps().isConfigRenderable(renderTarget->config() , false)) { | 287 if (renderTarget && this->vkCaps().isConfigRenderable(renderTarget->config() , | 
| 288 renderTarget->numColor Samples() > 1)) { | |
| 288 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); | 289 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); | 
| 289 | 290 | 
| 290 bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcConfig) == dstSurface ->config(); | 291 bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcConfig) == dstSurface ->config(); | 
| 291 | 292 | 
| 292 if (!this->vkCaps().isConfigTexturable(srcConfig) && configsAreRBSwaps) { | 293 if (!this->vkCaps().isConfigTexturable(srcConfig) && configsAreRBSwaps) { | 
| 293 if (!this->vkCaps().isConfigTexturable(dstSurface->config())) { | 294 if (!this->vkCaps().isConfigTexturable(dstSurface->config())) { | 
| 294 return false; | 295 return false; | 
| 295 } | 296 } | 
| 296 tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config(); | 297 tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config(); | 
| 297 tempDrawInfo->fSwizzle = GrSwizzle::BGRA(); | 298 tempDrawInfo->fSwizzle = GrSwizzle::BGRA(); | 
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 359 } | 360 } | 
| 360 } | 361 } | 
| 361 success = this->uploadTexDataOptimal(vkTex, left, top, width, height , config, texels); | 362 success = this->uploadTexDataOptimal(vkTex, left, top, width, height , config, texels); | 
| 362 } | 363 } | 
| 363 } | 364 } | 
| 364 | 365 | 
| 365 return success; | 366 return success; | 
| 366 } | 367 } | 
| 367 | 368 | 
| 368 void GrVkGpu::onResolveRenderTarget(GrRenderTarget* target) { | 369 void GrVkGpu::onResolveRenderTarget(GrRenderTarget* target) { | 
| 369 if (target->needsResolve() && target->numColorSamples() > 1) { | 370 if (target->needsResolve()) { | 
| 371 SkASSERT(target->numColorSamples() > 1); | |
| 
egdaniel
2016/08/05 19:07:15
going back to this. Returning getResolveType as au
 | |
| 370 GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(target); | 372 GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(target); | 
| 371 SkASSERT(rt->msaaImage()); | 373 SkASSERT(rt->msaaImage()); | 
| 372 | 374 | 
| 373 // Flip rect if necessary | 375 // Flip rect if necessary | 
| 374 SkIRect srcVkRect = rt->getResolveRect(); | 376 SkIRect srcVkRect = rt->getResolveRect(); | 
| 375 | 377 | 
| 376 if (kBottomLeft_GrSurfaceOrigin == rt->origin()) { | 378 if (kBottomLeft_GrSurfaceOrigin == rt->origin()) { | 
| 377 srcVkRect.fTop = rt->height() - rt->getResolveRect().fBottom; | 379 srcVkRect.fTop = rt->height() - rt->getResolveRect().fBottom; | 
| 378 srcVkRect.fBottom = rt->height() - rt->getResolveRect().fTop; | 380 srcVkRect.fBottom = rt->height() - rt->getResolveRect().fTop; | 
| 379 } | 381 } | 
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 810 return tgt; | 812 return tgt; | 
| 811 } | 813 } | 
| 812 | 814 | 
| 813 void GrVkGpu::generateMipmap(GrVkTexture* tex) { | 815 void GrVkGpu::generateMipmap(GrVkTexture* tex) { | 
| 814 // don't do anything for linearly tiled textures (can't have mipmaps) | 816 // don't do anything for linearly tiled textures (can't have mipmaps) | 
| 815 if (tex->isLinearTiled()) { | 817 if (tex->isLinearTiled()) { | 
| 816 SkDebugf("Trying to create mipmap for linear tiled texture"); | 818 SkDebugf("Trying to create mipmap for linear tiled texture"); | 
| 817 return; | 819 return; | 
| 818 } | 820 } | 
| 819 | 821 | 
| 820 // We currently don't support generating mipmaps for images that are multisa mpled. | |
| 821 // TODO: Add support for mipmapping the resolve target of a multisampled ima ge | |
| 822 if (tex->asRenderTarget() && tex->asRenderTarget()->numColorSamples() > 1) { | |
| 823 return; | |
| 824 } | |
| 825 | |
| 826 // determine if we can blit to and from this format | 822 // determine if we can blit to and from this format | 
| 827 const GrVkCaps& caps = this->vkCaps(); | 823 const GrVkCaps& caps = this->vkCaps(); | 
| 828 if (!caps.configCanBeDstofBlit(tex->config(), false) || | 824 if (!caps.configCanBeDstofBlit(tex->config(), false) || | 
| 829 !caps.configCanBeSrcofBlit(tex->config(), false) || | 825 !caps.configCanBeSrcofBlit(tex->config(), false) || | 
| 830 !caps.mipMapSupport()) { | 826 !caps.mipMapSupport()) { | 
| 831 return; | 827 return; | 
| 832 } | 828 } | 
| 833 | 829 | 
| 830 // We may need to resolve the texture first if it is also a render target | |
| 831 GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(tex->asRenderTarget ()); | |
| 832 if (texRT) { | |
| 833 this->onResolveRenderTarget(texRT); | |
| 834 } | |
| 835 | |
| 834 int width = tex->width(); | 836 int width = tex->width(); | 
| 835 int height = tex->height(); | 837 int height = tex->height(); | 
| 836 VkImageBlit blitRegion; | 838 VkImageBlit blitRegion; | 
| 837 memset(&blitRegion, 0, sizeof(VkImageBlit)); | 839 memset(&blitRegion, 0, sizeof(VkImageBlit)); | 
| 838 | 840 | 
| 839 // SkMipMap doesn't include the base level in the level count so we have to add 1 | 841 // SkMipMap doesn't include the base level in the level count so we have to add 1 | 
| 840 uint32_t levelCount = SkMipMap::ComputeLevelCount(tex->width(), tex->height( )) + 1; | 842 uint32_t levelCount = SkMipMap::ComputeLevelCount(tex->width(), tex->height( )) + 1; | 
| 841 if (levelCount != tex->mipLevels()) { | 843 if (levelCount != tex->mipLevels()) { | 
| 842 const GrVkResource* oldResource = tex->resource(); | 844 const GrVkResource* oldResource = tex->resource(); | 
| 843 oldResource->ref(); | 845 oldResource->ref(); | 
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1255 SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, | 1257 SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, | 
| 1256 srcRect.width(), srcRect.height()); | 1258 srcRect.width(), srcRect.height()); | 
| 1257 this->didWriteToSurface(dst, &dstRect); | 1259 this->didWriteToSurface(dst, &dstRect); | 
| 1258 } | 1260 } | 
| 1259 | 1261 | 
| 1260 inline bool can_copy_as_blit(const GrSurface* dst, | 1262 inline bool can_copy_as_blit(const GrSurface* dst, | 
| 1261 const GrSurface* src, | 1263 const GrSurface* src, | 
| 1262 const GrVkImage* dstImage, | 1264 const GrVkImage* dstImage, | 
| 1263 const GrVkImage* srcImage, | 1265 const GrVkImage* srcImage, | 
| 1264 const GrVkGpu* gpu) { | 1266 const GrVkGpu* gpu) { | 
| 1265 // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src | 1267 // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src | 
| 1266 // as image usage flags. | 1268 // as image usage flags. | 
| 1267 const GrVkCaps& caps = gpu->vkCaps(); | 1269 const GrVkCaps& caps = gpu->vkCaps(); | 
| 1268 if (!caps.configCanBeDstofBlit(dst->config(), dstImage->isLinearTiled()) || | 1270 if (!caps.configCanBeDstofBlit(dst->config(), dstImage->isLinearTiled()) || | 
| 1269 !caps.configCanBeSrcofBlit(src->config(), srcImage->isLinearTiled())) { | 1271 !caps.configCanBeSrcofBlit(src->config(), srcImage->isLinearTiled())) { | 
| 1270 return false; | 1272 return false; | 
| 1271 } | 1273 } | 
| 1272 | 1274 | 
| 1273 // We cannot blit images that are multisampled. Will need to figure out if w e can blit the | 1275 // We cannot blit images that are multisampled. Will need to figure out if w e can blit the | 
| 1274 // resolved msaa though. | 1276 // resolved msaa though. | 
| 1275 if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1) || | 1277 if ((dst->asRenderTarget() && dst->asRenderTarget()->numColorSamples() > 1) || | 
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1437 // from will be srcConfig and we will read readConfig pixels from it. | 1439 // from will be srcConfig and we will read readConfig pixels from it. | 
| 1438 // Not that if we require a draw and return a non-renderable format for the temp surface the | 1440 // Not that if we require a draw and return a non-renderable format for the temp surface the | 
| 1439 // base class will fail for us. | 1441 // base class will fail for us. | 
| 1440 tempDrawInfo->fTempSurfaceDesc.fConfig = srcSurface->config(); | 1442 tempDrawInfo->fTempSurfaceDesc.fConfig = srcSurface->config(); | 
| 1441 tempDrawInfo->fReadConfig = readConfig; | 1443 tempDrawInfo->fReadConfig = readConfig; | 
| 1442 | 1444 | 
| 1443 if (srcSurface->config() == readConfig) { | 1445 if (srcSurface->config() == readConfig) { | 
| 1444 return true; | 1446 return true; | 
| 1445 } | 1447 } | 
| 1446 | 1448 | 
| 1447 if (this->vkCaps().isConfigRenderable(readConfig, false)) { | 1449 if (this->vkCaps().isConfigRenderable(readConfig, srcSurface->desc().fSample Cnt > 1)) { | 
| 1448 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); | 1450 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); | 
| 1449 tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig; | 1451 tempDrawInfo->fTempSurfaceDesc.fConfig = readConfig; | 
| 1450 tempDrawInfo->fReadConfig = readConfig; | 1452 tempDrawInfo->fReadConfig = readConfig; | 
| 1451 return true; | 1453 return true; | 
| 1452 } | 1454 } | 
| 1453 | 1455 | 
| 1454 return false; | 1456 return false; | 
| 1455 } | 1457 } | 
| 1456 | 1458 | 
| 1457 bool GrVkGpu::onReadPixels(GrSurface* surface, | 1459 bool GrVkGpu::onReadPixels(GrSurface* surface, | 
| 1458 int left, int top, int width, int height, | 1460 int left, int top, int width, int height, | 
| 1459 GrPixelConfig config, | 1461 GrPixelConfig config, | 
| 1460 void* buffer, | 1462 void* buffer, | 
| 1461 size_t rowBytes) { | 1463 size_t rowBytes) { | 
| 1462 VkFormat pixelFormat; | 1464 VkFormat pixelFormat; | 
| 1463 if (!GrPixelConfigToVkFormat(config, &pixelFormat)) { | 1465 if (!GrPixelConfigToVkFormat(config, &pixelFormat)) { | 
| 1464 return false; | 1466 return false; | 
| 1465 } | 1467 } | 
| 1466 | 1468 | 
| 1467 GrVkTexture* tgt = static_cast<GrVkTexture*>(surface->asTexture()); | 1469 GrVkImage* image = nullptr; | 
| 1468 if (!tgt) { | 1470 GrVkRenderTarget* rt = static_cast<GrVkRenderTarget*>(surface->asRenderTarge t()); | 
| 
Brian Osman
2016/08/18 13:28:22
This is the only place where you're doing the extr
 
egdaniel
2016/08/18 13:31:39
Yeah I can move it up there. I was actually just c
 
egdaniel
2016/08/18 13:36:23
Actually I see the reasoning now. onResolveRenderT
 | |
| 1471 if (rt) { | |
| 1472 // resolve the render target if necessary | |
| 1473 switch (rt->getResolveType()) { | |
| 1474 case GrVkRenderTarget::kCantResolve_ResolveType: | |
| 1475 return false; | |
| 1476 case GrVkRenderTarget::kAutoResolves_ResolveType: | |
| 1477 break; | |
| 1478 case GrVkRenderTarget::kCanResolve_ResolveType: | |
| 1479 this->onResolveRenderTarget(rt); | |
| 1480 break; | |
| 1481 default: | |
| 1482 SkFAIL("Unknown resolve type"); | |
| 1483 } | |
| 1484 image = rt; | |
| 1485 } else { | |
| 1486 image = static_cast<GrVkTexture*>(surface->asTexture()); | |
| 1487 } | |
| 1488 | |
| 1489 if (!image) { | |
| 1469 return false; | 1490 return false; | 
| 1470 } | 1491 } | 
| 1471 | 1492 | 
| 1472 // Change layout of our target so it can be used as copy | 1493 // Change layout of our target so it can be used as copy | 
| 1473 tgt->setImageLayout(this, | 1494 image->setImageLayout(this, | 
| 1474 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, | 1495 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, | 
| 1475 VK_ACCESS_TRANSFER_READ_BIT, | 1496 VK_ACCESS_TRANSFER_READ_BIT, | 
| 1476 VK_PIPELINE_STAGE_TRANSFER_BIT, | 1497 VK_PIPELINE_STAGE_TRANSFER_BIT, | 
| 1477 false); | 1498 false); | 
| 1478 | 1499 | 
| 1479 GrVkTransferBuffer* transferBuffer = | 1500 GrVkTransferBuffer* transferBuffer = | 
| 1480 static_cast<GrVkTransferBuffer*>(this->createBuffer(rowBytes * height, | 1501 static_cast<GrVkTransferBuffer*>(this->createBuffer(rowBytes * height, | 
| 1481 kXferGpuToCpu_GrBuff erType, | 1502 kXferGpuToCpu_GrBuff erType, | 
| 1482 kStream_GrAccessPatt ern)); | 1503 kStream_GrAccessPatt ern)); | 
| 1483 | 1504 | 
| 1484 bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin(); | 1505 bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin(); | 
| 1485 VkOffset3D offset = { | 1506 VkOffset3D offset = { | 
| 1486 left, | 1507 left, | 
| 1487 flipY ? surface->height() - top - height : top, | 1508 flipY ? surface->height() - top - height : top, | 
| 1488 0 | 1509 0 | 
| 1489 }; | 1510 }; | 
| 1490 | 1511 | 
| 1491 // Copy the image to a buffer so we can map it to cpu memory | 1512 // Copy the image to a buffer so we can map it to cpu memory | 
| 1492 VkBufferImageCopy region; | 1513 VkBufferImageCopy region; | 
| 1493 memset(®ion, 0, sizeof(VkBufferImageCopy)); | 1514 memset(®ion, 0, sizeof(VkBufferImageCopy)); | 
| 1494 region.bufferOffset = transferBuffer->offset(); | 1515 region.bufferOffset = transferBuffer->offset(); | 
| 1495 region.bufferRowLength = 0; // Forces RowLength to be width. We handle the r owBytes below. | 1516 region.bufferRowLength = 0; // Forces RowLength to be width. We handle the r owBytes below. | 
| 1496 region.bufferImageHeight = 0; // Forces height to be tightly packed. Only us eful for 3d images. | 1517 region.bufferImageHeight = 0; // Forces height to be tightly packed. Only us eful for 3d images. | 
| 1497 region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; | 1518 region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; | 
| 1498 region.imageOffset = offset; | 1519 region.imageOffset = offset; | 
| 1499 region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 }; | 1520 region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 }; | 
| 1500 | 1521 | 
| 1501 fCurrentCmdBuffer->copyImageToBuffer(this, | 1522 fCurrentCmdBuffer->copyImageToBuffer(this, | 
| 1502 tgt, | 1523 image, | 
| 1503 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, | 1524 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, | 
| 1504 transferBuffer, | 1525 transferBuffer, | 
| 1505 1, | 1526 1, | 
| 1506 ®ion); | 1527 ®ion); | 
| 1507 | 1528 | 
| 1508 // make sure the copy to buffer has finished | 1529 // make sure the copy to buffer has finished | 
| 1509 transferBuffer->addMemoryBarrier(this, | 1530 transferBuffer->addMemoryBarrier(this, | 
| 1510 VK_ACCESS_TRANSFER_WRITE_BIT, | 1531 VK_ACCESS_TRANSFER_WRITE_BIT, | 
| 1511 VK_ACCESS_HOST_READ_BIT, | 1532 VK_ACCESS_HOST_READ_BIT, | 
| 1512 VK_PIPELINE_STAGE_TRANSFER_BIT, | 1533 VK_PIPELINE_STAGE_TRANSFER_BIT, | 
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1600 target->width(), target->height()); | 1621 target->width(), target->height()); | 
| 1601 pBounds = &adjustedBounds; | 1622 pBounds = &adjustedBounds; | 
| 1602 } | 1623 } | 
| 1603 | 1624 | 
| 1604 // Currently it is fine for us to always pass in 1 for the clear count even if no attachment | 1625 // Currently it is fine for us to always pass in 1 for the clear count even if no attachment | 
| 1605 // uses it. In the current state, we also only use the LOAD_OP_CLEAR for the color attachment | 1626 // uses it. In the current state, we also only use the LOAD_OP_CLEAR for the color attachment | 
| 1606 // which is always at the first attachment. | 1627 // which is always at the first attachment. | 
| 1607 fCurrentCmdBuffer->beginRenderPass(this, renderPass, 1, colorClear, *target, *pBounds, true); | 1628 fCurrentCmdBuffer->beginRenderPass(this, renderPass, 1, colorClear, *target, *pBounds, true); | 
| 1608 fCurrentCmdBuffer->executeCommands(this, buffer); | 1629 fCurrentCmdBuffer->executeCommands(this, buffer); | 
| 1609 fCurrentCmdBuffer->endRenderPass(this); | 1630 fCurrentCmdBuffer->endRenderPass(this); | 
| 1631 | |
| 1632 this->didWriteToSurface(target, pBounds); | |
| 1610 } | 1633 } | 
| 1611 | 1634 | 
| OLD | NEW |