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 931 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
942 width, | 942 width, |
943 height, | 943 height, |
944 samples, | 944 samples, |
945 sFmt)); | 945 sFmt)); |
946 fStats.incStencilAttachmentCreates(); | 946 fStats.incStencilAttachmentCreates(); |
947 return stencil; | 947 return stencil; |
948 } | 948 } |
949 | 949 |
950 //////////////////////////////////////////////////////////////////////////////// | 950 //////////////////////////////////////////////////////////////////////////////// |
951 | 951 |
| 952 bool copy_testing_data(GrVkGpu* gpu, void* srcData, GrVkAlloc* alloc, |
| 953 size_t srcRowBytes, size_t dstRowBytes, int h) { |
| 954 void* mapPtr; |
| 955 VkResult err = GR_VK_CALL(gpu->vkInterface(), MapMemory(gpu->device(), |
| 956 alloc->fMemory, |
| 957 alloc->fOffset, |
| 958 dstRowBytes * h, |
| 959 0, |
| 960 &mapPtr)); |
| 961 if (err) { |
| 962 return false; |
| 963 } |
| 964 |
| 965 // If there is no padding on dst we can do a single memcopy. |
| 966 // This assumes the srcData comes in with no padding. |
| 967 if (srcRowBytes == dstRowBytes) { |
| 968 memcpy(mapPtr, srcData, srcRowBytes * h); |
| 969 } else { |
| 970 SkRectMemcpy(mapPtr, static_cast<size_t>(dstRowBytes), srcData, srcRowBy
tes, |
| 971 srcRowBytes, h); |
| 972 } |
| 973 GR_VK_CALL(gpu->vkInterface(), UnmapMemory(gpu->device(), alloc->fMemory)); |
| 974 return true; |
| 975 } |
| 976 |
952 GrBackendObject GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, i
nt h, | 977 GrBackendObject GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, i
nt h, |
953 GrPixelConfig config, | 978 GrPixelConfig config, |
954 bool isRenderTarget) { | 979 bool isRenderTarget) { |
955 | 980 |
956 VkFormat pixelFormat; | 981 VkFormat pixelFormat; |
957 if (!GrPixelConfigToVkFormat(config, &pixelFormat)) { | 982 if (!GrPixelConfigToVkFormat(config, &pixelFormat)) { |
958 return 0; | 983 return 0; |
959 } | 984 } |
960 | 985 |
961 bool linearTiling = false; | 986 bool linearTiling = false; |
962 if (!fVkCaps->isConfigTexturable(config)) { | 987 if (!fVkCaps->isConfigTexturable(config)) { |
963 return 0; | 988 return 0; |
964 } | 989 } |
965 | 990 |
966 if (isRenderTarget && !fVkCaps->isConfigRenderable(config, false)) { | 991 if (isRenderTarget && !fVkCaps->isConfigRenderable(config, false)) { |
967 return 0; | 992 return 0; |
968 } | 993 } |
969 | 994 |
970 if (fVkCaps->isConfigTexurableLinearly(config) && | 995 if (fVkCaps->isConfigTexurableLinearly(config) && |
971 (!isRenderTarget || fVkCaps->isConfigRenderableLinearly(config, false)))
{ | 996 (!isRenderTarget || fVkCaps->isConfigRenderableLinearly(config, false)))
{ |
972 linearTiling = true; | 997 linearTiling = true; |
973 } | 998 } |
974 | 999 |
975 // Currently this is not supported since it requires a copy which has not ye
t been implemented. | |
976 if (srcData && !linearTiling) { | |
977 return 0; | |
978 } | |
979 | |
980 VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT; | 1000 VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT; |
981 usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; | 1001 usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
982 usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; | 1002 usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
983 if (isRenderTarget) { | 1003 if (isRenderTarget) { |
984 usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; | 1004 usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
985 } | 1005 } |
986 | 1006 |
987 VkImage image = VK_NULL_HANDLE; | 1007 VkImage image = VK_NULL_HANDLE; |
988 GrVkAlloc alloc = { VK_NULL_HANDLE, 0, 0 }; | 1008 GrVkAlloc alloc = { VK_NULL_HANDLE, 0, 0 }; |
989 | 1009 |
(...skipping 27 matching lines...) Expand all Loading... |
1017 }; | 1037 }; |
1018 | 1038 |
1019 GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateImage(this->device(), &imageC
reateInfo, nullptr, &image)); | 1039 GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateImage(this->device(), &imageC
reateInfo, nullptr, &image)); |
1020 | 1040 |
1021 if (!GrVkMemory::AllocAndBindImageMemory(this, image, linearTiling, &alloc))
{ | 1041 if (!GrVkMemory::AllocAndBindImageMemory(this, image, linearTiling, &alloc))
{ |
1022 VK_CALL(DestroyImage(this->device(), image, nullptr)); | 1042 VK_CALL(DestroyImage(this->device(), image, nullptr)); |
1023 return 0; | 1043 return 0; |
1024 } | 1044 } |
1025 | 1045 |
1026 if (srcData) { | 1046 if (srcData) { |
| 1047 size_t bpp = GrBytesPerPixel(config); |
| 1048 size_t rowCopyBytes = bpp * w; |
1027 if (linearTiling) { | 1049 if (linearTiling) { |
1028 const VkImageSubresource subres = { | 1050 const VkImageSubresource subres = { |
1029 VK_IMAGE_ASPECT_COLOR_BIT, | 1051 VK_IMAGE_ASPECT_COLOR_BIT, |
1030 0, // mipLevel | 1052 0, // mipLevel |
1031 0, // arraySlice | 1053 0, // arraySlice |
1032 }; | 1054 }; |
1033 VkSubresourceLayout layout; | 1055 VkSubresourceLayout layout; |
1034 VkResult err; | |
1035 | 1056 |
1036 VK_CALL(GetImageSubresourceLayout(fDevice, image, &subres, &layout))
; | 1057 VK_CALL(GetImageSubresourceLayout(fDevice, image, &subres, &layout))
; |
1037 | 1058 |
1038 void* mapPtr; | 1059 if (!copy_testing_data(this, srcData, &alloc, rowCopyBytes, layout.r
owPitch, h)) { |
1039 err = VK_CALL(MapMemory(fDevice, alloc.fMemory, alloc.fOffset, layou
t.rowPitch * h, | 1060 GrVkMemory::FreeImageMemory(this, linearTiling, alloc); |
1040 0, &mapPtr)); | 1061 VK_CALL(DestroyImage(fDevice, image, nullptr)); |
| 1062 return 0; |
| 1063 } |
| 1064 } else { |
| 1065 SkASSERT(w && h); |
| 1066 |
| 1067 VkBuffer buffer; |
| 1068 VkBufferCreateInfo bufInfo; |
| 1069 memset(&bufInfo, 0, sizeof(VkBufferCreateInfo)); |
| 1070 bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; |
| 1071 bufInfo.flags = 0; |
| 1072 bufInfo.size = rowCopyBytes * h; |
| 1073 bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; |
| 1074 bufInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; |
| 1075 bufInfo.queueFamilyIndexCount = 0; |
| 1076 bufInfo.pQueueFamilyIndices = nullptr; |
| 1077 VkResult err; |
| 1078 err = VK_CALL(CreateBuffer(fDevice, &bufInfo, nullptr, &buffer)); |
| 1079 |
1041 if (err) { | 1080 if (err) { |
1042 GrVkMemory::FreeImageMemory(this, linearTiling, alloc); | 1081 GrVkMemory::FreeImageMemory(this, linearTiling, alloc); |
1043 VK_CALL(DestroyImage(this->device(), image, nullptr)); | 1082 VK_CALL(DestroyImage(fDevice, image, nullptr)); |
1044 return 0; | 1083 return 0; |
1045 } | 1084 } |
1046 | 1085 |
1047 size_t bpp = GrBytesPerPixel(config); | 1086 GrVkAlloc bufferAlloc = { VK_NULL_HANDLE, 0, 0 }; |
1048 size_t rowCopyBytes = bpp * w; | 1087 if (!GrVkMemory::AllocAndBindBufferMemory(this, buffer, GrVkBuffer::
kCopyRead_Type, |
1049 // If there is no padding on dst (layout.rowPitch) we can do a singl
e memcopy. | 1088 true, &bufferAlloc)) { |
1050 // This assumes the srcData comes in with no padding. | 1089 GrVkMemory::FreeImageMemory(this, linearTiling, alloc); |
1051 if (rowCopyBytes == layout.rowPitch) { | 1090 VK_CALL(DestroyImage(fDevice, image, nullptr)); |
1052 memcpy(mapPtr, srcData, rowCopyBytes * h); | 1091 VK_CALL(DestroyBuffer(fDevice, buffer, nullptr)); |
1053 } else { | 1092 return 0; |
1054 SkRectMemcpy(mapPtr, static_cast<size_t>(layout.rowPitch), srcDa
ta, rowCopyBytes, | |
1055 rowCopyBytes, h); | |
1056 } | 1093 } |
1057 VK_CALL(UnmapMemory(fDevice, alloc.fMemory)); | 1094 |
1058 } else { | 1095 if (!copy_testing_data(this, srcData, &bufferAlloc, rowCopyBytes, ro
wCopyBytes, h)) { |
1059 // TODO: Add support for copying to optimal tiling | 1096 GrVkMemory::FreeImageMemory(this, linearTiling, alloc); |
1060 SkASSERT(false); | 1097 VK_CALL(DestroyImage(fDevice, image, nullptr)); |
| 1098 GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, b
ufferAlloc); |
| 1099 VK_CALL(DestroyBuffer(fDevice, buffer, nullptr)); |
| 1100 return 0; |
| 1101 } |
| 1102 |
| 1103 const VkCommandBufferAllocateInfo cmdInfo = { |
| 1104 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType |
| 1105 NULL, // pNext |
| 1106 fCmdPool, // commandPool |
| 1107 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level |
| 1108 1 // bufferCount |
| 1109 }; |
| 1110 |
| 1111 VkCommandBuffer cmdBuffer; |
| 1112 err = VK_CALL(AllocateCommandBuffers(fDevice, &cmdInfo, &cmdBuffer))
; |
| 1113 if (err) { |
| 1114 GrVkMemory::FreeImageMemory(this, linearTiling, alloc); |
| 1115 VK_CALL(DestroyImage(fDevice, image, nullptr)); |
| 1116 GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, b
ufferAlloc); |
| 1117 VK_CALL(DestroyBuffer(fDevice, buffer, nullptr)); |
| 1118 return 0; |
| 1119 } |
| 1120 |
| 1121 VkCommandBufferBeginInfo cmdBufferBeginInfo; |
| 1122 memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo)); |
| 1123 cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_IN
FO; |
| 1124 cmdBufferBeginInfo.pNext = nullptr; |
| 1125 cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_B
IT; |
| 1126 cmdBufferBeginInfo.pInheritanceInfo = nullptr; |
| 1127 |
| 1128 err = VK_CALL(BeginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo)); |
| 1129 SkASSERT(!err); |
| 1130 |
| 1131 // Set image layout and add barrier |
| 1132 VkImageMemoryBarrier barrier; |
| 1133 memset(&barrier, 0, sizeof(VkImageMemoryBarrier)); |
| 1134 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; |
| 1135 barrier.pNext = nullptr; |
| 1136 barrier.srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(initialLay
out); |
| 1137 barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; |
| 1138 barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| 1139 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 1140 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 1141 barrier.image = image; |
| 1142 barrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0 , 1}
; |
| 1143 |
| 1144 VK_CALL(CmdPipelineBarrier(cmdBuffer, |
| 1145 GrVkMemory::LayoutToPipelineStageFlags(in
itialLayout), |
| 1146 VK_PIPELINE_STAGE_TRANSFER_BIT, |
| 1147 0, |
| 1148 0, nullptr, |
| 1149 0, nullptr, |
| 1150 1, &barrier)); |
| 1151 initialLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; |
| 1152 |
| 1153 // Make sure buffer has finished the unmap |
| 1154 VkBufferMemoryBarrier bufBarrier; |
| 1155 memset(&barrier, 0, sizeof(VkImageMemoryBarrier)); |
| 1156 bufBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; |
| 1157 bufBarrier.pNext = nullptr; |
| 1158 bufBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; |
| 1159 bufBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; |
| 1160 bufBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 1161 bufBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 1162 bufBarrier.buffer = buffer; |
| 1163 bufBarrier.offset = 0; |
| 1164 bufBarrier.size = bufInfo.size; |
| 1165 |
| 1166 VK_CALL(CmdPipelineBarrier(cmdBuffer, |
| 1167 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, |
| 1168 VK_PIPELINE_STAGE_TRANSFER_BIT, |
| 1169 0, |
| 1170 0, nullptr, |
| 1171 1, &bufBarrier, |
| 1172 0, nullptr)); |
| 1173 |
| 1174 // Submit copy command |
| 1175 VkBufferImageCopy region; |
| 1176 memset(®ion, 0, sizeof(VkBufferImageCopy)); |
| 1177 region.bufferOffset = 0; |
| 1178 region.bufferRowLength = (uint32_t)rowCopyBytes; |
| 1179 region.bufferImageHeight = h; |
| 1180 region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; |
| 1181 region.imageOffset = { 0, 0, 0 }; |
| 1182 region.imageExtent = { (uint32_t)w, (uint32_t)h, 1 }; |
| 1183 |
| 1184 VK_CALL(CmdCopyBufferToImage(cmdBuffer, buffer, image, initialLayout
, 1, ®ion)); |
| 1185 |
| 1186 // End CommandBuffer |
| 1187 err = VK_CALL(EndCommandBuffer(cmdBuffer)); |
| 1188 SkASSERT(!err); |
| 1189 |
| 1190 // Create Fence for queue |
| 1191 VkFence fence; |
| 1192 VkFenceCreateInfo fenceInfo; |
| 1193 memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo)); |
| 1194 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; |
| 1195 |
| 1196 err = VK_CALL(CreateFence(fDevice, &fenceInfo, nullptr, &fence)); |
| 1197 SkASSERT(!err); |
| 1198 |
| 1199 VkSubmitInfo submitInfo; |
| 1200 memset(&submitInfo, 0, sizeof(VkSubmitInfo)); |
| 1201 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; |
| 1202 submitInfo.pNext = nullptr; |
| 1203 submitInfo.waitSemaphoreCount = 0; |
| 1204 submitInfo.pWaitSemaphores = nullptr; |
| 1205 submitInfo.pWaitDstStageMask = 0; |
| 1206 submitInfo.commandBufferCount = 1; |
| 1207 submitInfo.pCommandBuffers = &cmdBuffer; |
| 1208 submitInfo.signalSemaphoreCount = 0; |
| 1209 submitInfo.pSignalSemaphores = nullptr; |
| 1210 err = VK_CALL(QueueSubmit(this->queue(), 1, &submitInfo, fence)); |
| 1211 SkASSERT(!err); |
| 1212 |
| 1213 err = VK_CALL(WaitForFences(fDevice, 1, &fence, true, UINT64_MAX)); |
| 1214 if (VK_TIMEOUT == err) { |
| 1215 GrVkMemory::FreeImageMemory(this, linearTiling, alloc); |
| 1216 VK_CALL(DestroyImage(fDevice, image, nullptr)); |
| 1217 GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, b
ufferAlloc); |
| 1218 VK_CALL(DestroyBuffer(fDevice, buffer, nullptr)); |
| 1219 VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer)); |
| 1220 VK_CALL(DestroyFence(fDevice, fence, nullptr)); |
| 1221 SkDebugf("Fence failed to signal: %d\n", err); |
| 1222 SkFAIL("failing"); |
| 1223 } |
| 1224 SkASSERT(!err); |
| 1225 |
| 1226 // Clean up transfer resources |
| 1227 GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, buffe
rAlloc); |
| 1228 VK_CALL(DestroyBuffer(fDevice, buffer, nullptr)); |
| 1229 VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer)); |
| 1230 VK_CALL(DestroyFence(fDevice, fence, nullptr)); |
1061 } | 1231 } |
1062 } | 1232 } |
1063 | 1233 |
1064 GrVkImageInfo* info = new GrVkImageInfo; | 1234 GrVkImageInfo* info = new GrVkImageInfo; |
1065 info->fImage = image; | 1235 info->fImage = image; |
1066 info->fAlloc = alloc; | 1236 info->fAlloc = alloc; |
1067 info->fImageTiling = imageTiling; | 1237 info->fImageTiling = imageTiling; |
1068 info->fImageLayout = initialLayout; | 1238 info->fImageLayout = initialLayout; |
1069 info->fFormat = pixelFormat; | 1239 info->fFormat = pixelFormat; |
1070 info->fLevelCount = 1; | 1240 info->fLevelCount = 1; |
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1602 } | 1772 } |
1603 | 1773 |
1604 // Currently it is fine for us to always pass in 1 for the clear count even
if no attachment | 1774 // 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 | 1775 // 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. | 1776 // which is always at the first attachment. |
1607 fCurrentCmdBuffer->beginRenderPass(this, renderPass, 1, colorClear, *target,
*pBounds, true); | 1777 fCurrentCmdBuffer->beginRenderPass(this, renderPass, 1, colorClear, *target,
*pBounds, true); |
1608 fCurrentCmdBuffer->executeCommands(this, buffer); | 1778 fCurrentCmdBuffer->executeCommands(this, buffer); |
1609 fCurrentCmdBuffer->endRenderPass(this); | 1779 fCurrentCmdBuffer->endRenderPass(this); |
1610 } | 1780 } |
1611 | 1781 |
OLD | NEW |