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 1684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1695 return false; | 1695 return false; |
1696 } | 1696 } |
1697 | 1697 |
1698 // Change layout of our target so it can be used as copy | 1698 // Change layout of our target so it can be used as copy |
1699 image->setImageLayout(this, | 1699 image->setImageLayout(this, |
1700 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, | 1700 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
1701 VK_ACCESS_TRANSFER_READ_BIT, | 1701 VK_ACCESS_TRANSFER_READ_BIT, |
1702 VK_PIPELINE_STAGE_TRANSFER_BIT, | 1702 VK_PIPELINE_STAGE_TRANSFER_BIT, |
1703 false); | 1703 false); |
1704 | 1704 |
| 1705 size_t bpp = GrBytesPerPixel(config); |
| 1706 size_t tightRowBytes = bpp * width; |
| 1707 bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin(); |
| 1708 |
| 1709 VkBufferImageCopy region; |
| 1710 memset(®ion, 0, sizeof(VkBufferImageCopy)); |
| 1711 |
| 1712 bool copyFromOrigin = this->vkCaps().mustDoCopiesFromOrigin(); |
| 1713 if (copyFromOrigin) { |
| 1714 region.imageOffset = { 0, 0, 0 }; |
| 1715 region.imageExtent = { (uint32_t)(left + width), |
| 1716 (uint32_t)(flipY ? surface->height() - top : top
+ height), |
| 1717 1 |
| 1718 }; |
| 1719 } else { |
| 1720 VkOffset3D offset = { |
| 1721 left, |
| 1722 flipY ? surface->height() - top - height : top, |
| 1723 0 |
| 1724 }; |
| 1725 region.imageOffset = offset; |
| 1726 region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 }; |
| 1727 } |
| 1728 |
| 1729 size_t transBufferRowBytes = bpp * region.imageExtent.width; |
1705 GrVkTransferBuffer* transferBuffer = | 1730 GrVkTransferBuffer* transferBuffer = |
1706 static_cast<GrVkTransferBuffer*>(this->createBuffer(rowBytes * height, | 1731 static_cast<GrVkTransferBuffer*>(this->createBuffer(transBufferRowBy
tes * height, |
1707 kXferGpuToCpu_GrBuff
erType, | 1732 kXferGpuToCpu_Gr
BufferType, |
1708 kStream_GrAccessPatt
ern)); | 1733 kStream_GrAccess
Pattern)); |
1709 | |
1710 bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin(); | |
1711 VkOffset3D offset = { | |
1712 left, | |
1713 flipY ? surface->height() - top - height : top, | |
1714 0 | |
1715 }; | |
1716 | 1734 |
1717 // Copy the image to a buffer so we can map it to cpu memory | 1735 // Copy the image to a buffer so we can map it to cpu memory |
1718 VkBufferImageCopy region; | |
1719 memset(®ion, 0, sizeof(VkBufferImageCopy)); | |
1720 region.bufferOffset = transferBuffer->offset(); | 1736 region.bufferOffset = transferBuffer->offset(); |
1721 region.bufferRowLength = 0; // Forces RowLength to be width. We handle the r
owBytes below. | 1737 region.bufferRowLength = 0; // Forces RowLength to be width. We handle the r
owBytes below. |
1722 region.bufferImageHeight = 0; // Forces height to be tightly packed. Only us
eful for 3d images. | 1738 region.bufferImageHeight = 0; // Forces height to be tightly packed. Only us
eful for 3d images. |
1723 region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; | 1739 region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; |
1724 region.imageOffset = offset; | |
1725 region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 }; | |
1726 | 1740 |
1727 fCurrentCmdBuffer->copyImageToBuffer(this, | 1741 fCurrentCmdBuffer->copyImageToBuffer(this, |
1728 image, | 1742 image, |
1729 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, | 1743 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
1730 transferBuffer, | 1744 transferBuffer, |
1731 1, | 1745 1, |
1732 ®ion); | 1746 ®ion); |
1733 | 1747 |
1734 // make sure the copy to buffer has finished | 1748 // make sure the copy to buffer has finished |
1735 transferBuffer->addMemoryBarrier(this, | 1749 transferBuffer->addMemoryBarrier(this, |
1736 VK_ACCESS_TRANSFER_WRITE_BIT, | 1750 VK_ACCESS_TRANSFER_WRITE_BIT, |
1737 VK_ACCESS_HOST_READ_BIT, | 1751 VK_ACCESS_HOST_READ_BIT, |
1738 VK_PIPELINE_STAGE_TRANSFER_BIT, | 1752 VK_PIPELINE_STAGE_TRANSFER_BIT, |
1739 VK_PIPELINE_STAGE_HOST_BIT, | 1753 VK_PIPELINE_STAGE_HOST_BIT, |
1740 false); | 1754 false); |
1741 | 1755 |
1742 // We need to submit the current command buffer to the Queue and make sure i
t finishes before | 1756 // We need to submit the current command buffer to the Queue and make sure i
t finishes before |
1743 // we can copy the data out of the buffer. | 1757 // we can copy the data out of the buffer. |
1744 this->submitCommandBuffer(kForce_SyncQueue); | 1758 this->submitCommandBuffer(kForce_SyncQueue); |
1745 | 1759 |
1746 void* mappedMemory = transferBuffer->map(); | 1760 void* mappedMemory = transferBuffer->map(); |
1747 | 1761 |
1748 size_t tightRowBytes = GrBytesPerPixel(config) * width; | 1762 if (copyFromOrigin) { |
| 1763 uint32_t skipRows = region.imageExtent.height - height; |
| 1764 mappedMemory = (char*)mappedMemory + transBufferRowBytes * skipRows + bp
p * left; |
| 1765 } |
| 1766 |
1749 if (flipY) { | 1767 if (flipY) { |
1750 const char* srcRow = reinterpret_cast<const char*>(mappedMemory); | 1768 const char* srcRow = reinterpret_cast<const char*>(mappedMemory); |
1751 char* dstRow = reinterpret_cast<char*>(buffer)+(height - 1) * rowBytes; | 1769 char* dstRow = reinterpret_cast<char*>(buffer)+(height - 1) * rowBytes; |
1752 for (int y = 0; y < height; y++) { | 1770 for (int y = 0; y < height; y++) { |
1753 memcpy(dstRow, srcRow, tightRowBytes); | 1771 memcpy(dstRow, srcRow, tightRowBytes); |
1754 srcRow += tightRowBytes; | 1772 srcRow += transBufferRowBytes; |
1755 dstRow -= rowBytes; | 1773 dstRow -= rowBytes; |
1756 } | 1774 } |
1757 } else { | 1775 } else { |
1758 if (tightRowBytes == rowBytes) { | 1776 if (transBufferRowBytes == rowBytes) { |
1759 memcpy(buffer, mappedMemory, rowBytes*height); | 1777 memcpy(buffer, mappedMemory, rowBytes*height); |
1760 } else { | 1778 } else { |
1761 SkRectMemcpy(buffer, rowBytes, mappedMemory, tightRowBytes, tightRow
Bytes, height); | 1779 SkRectMemcpy(buffer, rowBytes, mappedMemory, transBufferRowBytes, ti
ghtRowBytes, |
| 1780 height); |
1762 } | 1781 } |
1763 } | 1782 } |
1764 | 1783 |
1765 transferBuffer->unmap(); | 1784 transferBuffer->unmap(); |
1766 transferBuffer->unref(); | 1785 transferBuffer->unref(); |
1767 | |
1768 return true; | 1786 return true; |
1769 } | 1787 } |
1770 | 1788 |
1771 // The RenderArea bounds we pass into BeginRenderPass must have a start x value
that is a multiple | 1789 // The RenderArea bounds we pass into BeginRenderPass must have a start x value
that is a multiple |
1772 // of the granularity. The width must also be a multiple of the granularity or e
aqual to the width | 1790 // of the granularity. The width must also be a multiple of the granularity or e
aqual to the width |
1773 // the the entire attachment. Similar requirements for the y and height componen
ts. | 1791 // the the entire attachment. Similar requirements for the y and height componen
ts. |
1774 void adjust_bounds_to_granularity(SkIRect* dstBounds, const SkIRect& srcBounds, | 1792 void adjust_bounds_to_granularity(SkIRect* dstBounds, const SkIRect& srcBounds, |
1775 const VkExtent2D& granularity, int maxWidth, i
nt maxHeight) { | 1793 const VkExtent2D& granularity, int maxWidth, i
nt maxHeight) { |
1776 // Adjust Width | 1794 // Adjust Width |
1777 // Start with the right side of rect so we know if we end up going pass the
maxWidth. | 1795 // Start with the right side of rect so we know if we end up going pass the
maxWidth. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1830 // Currently it is fine for us to always pass in 1 for the clear count even
if no attachment | 1848 // Currently it is fine for us to always pass in 1 for the clear count even
if no attachment |
1831 // uses it. In the current state, we also only use the LOAD_OP_CLEAR for the
color attachment | 1849 // uses it. In the current state, we also only use the LOAD_OP_CLEAR for the
color attachment |
1832 // which is always at the first attachment. | 1850 // which is always at the first attachment. |
1833 fCurrentCmdBuffer->beginRenderPass(this, renderPass, 1, colorClear, *target,
*pBounds, true); | 1851 fCurrentCmdBuffer->beginRenderPass(this, renderPass, 1, colorClear, *target,
*pBounds, true); |
1834 fCurrentCmdBuffer->executeCommands(this, buffer); | 1852 fCurrentCmdBuffer->executeCommands(this, buffer); |
1835 fCurrentCmdBuffer->endRenderPass(this); | 1853 fCurrentCmdBuffer->endRenderPass(this); |
1836 | 1854 |
1837 this->didWriteToSurface(target, &bounds); | 1855 this->didWriteToSurface(target, &bounds); |
1838 } | 1856 } |
1839 | 1857 |
OLD | NEW |