1 /* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 #define LOG_TAG "VulkanTestHelpers" 19 20 #include "VulkanTestHelpers.h" 21 22 #include <android/asset_manager.h> 23 #include <android/asset_manager_jni.h> 24 #include <android/hardware_buffer.h> 25 #include <android/log.h> 26 27 #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 28 29 #define ASSERT(a) \ 30 if (!(a)) { \ 31 ALOGE("Failure: " #a " at " __FILE__ ":%d", __LINE__); \ 32 return false; \ 33 } 34 35 #define VK_CALL(a) ASSERT(VK_SUCCESS == (a)) 36 37 namespace { 38 39 void addImageTransitionBarrier(VkCommandBuffer commandBuffer, VkImage image, 40 VkPipelineStageFlags srcStageMask, 41 VkPipelineStageFlags dstStageMask, 42 VkAccessFlags srcAccessMask, 43 VkAccessFlags dstAccessMask, 44 VkImageLayout oldLayout, VkImageLayout newLayout, 45 uint32_t srcQueue = VK_QUEUE_FAMILY_IGNORED, 46 uint32_t dstQueue = VK_QUEUE_FAMILY_IGNORED) { 47 const VkImageSubresourceRange subResourcerange{ 48 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 49 .baseMipLevel = 0, 50 .levelCount = 1, 51 .baseArrayLayer = 0, 52 .layerCount = 1, 53 }; 54 const VkImageMemoryBarrier imageBarrier{ 55 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 56 .pNext = nullptr, 57 .srcAccessMask = srcAccessMask, 58 .dstAccessMask = dstAccessMask, 59 .oldLayout = oldLayout, 60 .newLayout = newLayout, 61 .srcQueueFamilyIndex = srcQueue, 62 .dstQueueFamilyIndex = dstQueue, 63 .image = image, 64 .subresourceRange = subResourcerange, 65 }; 66 vkCmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, 0, 0, nullptr, 67 0, nullptr, 1, &imageBarrier); 68 } 69 70 } // namespace 71 72 bool VkInit::init() { 73 VkApplicationInfo appInfo = { 74 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, 75 .pNext = nullptr, 76 .apiVersion = VK_MAKE_VERSION(1, 1, 0), 77 .applicationVersion = VK_MAKE_VERSION(1, 0, 0), 78 .engineVersion = VK_MAKE_VERSION(1, 0, 0), 79 .pApplicationName = "VulkanGpuTest", 80 .pEngineName = "VulkanGpuTestEngine", 81 }; 82 std::vector<const char *> instanceExt, deviceExt; 83 instanceExt.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); 84 instanceExt.push_back(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME); 85 instanceExt.push_back(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME); 86 instanceExt.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); 87 deviceExt.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); 88 deviceExt.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME); 89 deviceExt.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME); 90 deviceExt.push_back(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME); 91 deviceExt.push_back(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME); 92 deviceExt.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); 93 deviceExt.push_back(VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME); 94 VkInstanceCreateInfo createInfo = { 95 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 96 .pNext = nullptr, 97 .pApplicationInfo = &appInfo, 98 .enabledExtensionCount = static_cast<uint32_t>(instanceExt.size()), 99 .ppEnabledExtensionNames = instanceExt.data(), 100 .enabledLayerCount = 0, 101 .ppEnabledLayerNames = nullptr, 102 }; 103 VK_CALL(vkCreateInstance(&createInfo, nullptr, &mInstance)); 104 105 // Find a GPU to use. 106 uint32_t gpuCount = 1; 107 int status = vkEnumeratePhysicalDevices(mInstance, &gpuCount, &mGpu); 108 ASSERT(status == VK_SUCCESS || status == VK_INCOMPLETE); 109 ASSERT(gpuCount > 0); 110 111 uint32_t queueFamilyCount = 0; 112 vkGetPhysicalDeviceQueueFamilyProperties(mGpu, &queueFamilyCount, nullptr); 113 ASSERT(queueFamilyCount != 0); 114 std::vector<VkQueueFamilyProperties> queueFamilyProperties(queueFamilyCount); 115 vkGetPhysicalDeviceQueueFamilyProperties(mGpu, &queueFamilyCount, 116 queueFamilyProperties.data()); 117 118 uint32_t queueFamilyIndex; 119 for (queueFamilyIndex = 0; queueFamilyIndex < queueFamilyCount; 120 ++queueFamilyIndex) { 121 if (queueFamilyProperties[queueFamilyIndex].queueFlags & 122 VK_QUEUE_GRAPHICS_BIT) 123 break; 124 } 125 ASSERT(queueFamilyIndex < queueFamilyCount); 126 mQueueFamilyIndex = queueFamilyIndex; 127 128 float priorities[] = {1.0f}; 129 VkDeviceQueueCreateInfo queueCreateInfo{ 130 .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 131 .pNext = nullptr, 132 .flags = 0, 133 .queueCount = 1, 134 .queueFamilyIndex = queueFamilyIndex, 135 .pQueuePriorities = priorities, 136 }; 137 138 VkDeviceCreateInfo deviceCreateInfo{ 139 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 140 .pNext = nullptr, 141 .queueCreateInfoCount = 1, 142 .pQueueCreateInfos = &queueCreateInfo, 143 .enabledLayerCount = 0, 144 .ppEnabledLayerNames = nullptr, 145 .enabledExtensionCount = static_cast<uint32_t>(deviceExt.size()), 146 .ppEnabledExtensionNames = deviceExt.data(), 147 .pEnabledFeatures = nullptr, 148 }; 149 150 VK_CALL(vkCreateDevice(mGpu, &deviceCreateInfo, nullptr, &mDevice)); 151 152 mPfnGetAndroidHardwareBufferPropertiesANDROID = 153 (PFN_vkGetAndroidHardwareBufferPropertiesANDROID)vkGetDeviceProcAddr( 154 mDevice, "vkGetAndroidHardwareBufferPropertiesANDROID"); 155 ASSERT(mPfnGetAndroidHardwareBufferPropertiesANDROID); 156 157 VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR ycbcrFeatures{ 158 .sType = 159 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR, 160 .pNext = nullptr, 161 }; 162 VkPhysicalDeviceFeatures2KHR physicalDeviceFeatures{ 163 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR, 164 .pNext = &ycbcrFeatures, 165 }; 166 PFN_vkGetPhysicalDeviceFeatures2KHR getFeatures = 167 (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr( 168 mInstance, "vkGetPhysicalDeviceFeatures2KHR"); 169 ASSERT(getFeatures); 170 getFeatures(mGpu, &physicalDeviceFeatures); 171 ASSERT(ycbcrFeatures.samplerYcbcrConversion == VK_TRUE); 172 173 vkGetDeviceQueue(mDevice, 0, 0, &mQueue); 174 vkGetPhysicalDeviceMemoryProperties(mGpu, &mMemoryProperties); 175 176 return true; 177 } 178 179 VkInit::~VkInit() { 180 if (mQueue != VK_NULL_HANDLE) { 181 // Queues are implicitly destroyed with the device. 182 mQueue = VK_NULL_HANDLE; 183 } 184 if (mDevice != VK_NULL_HANDLE) { 185 vkDestroyDevice(mDevice, nullptr); 186 mDevice = VK_NULL_HANDLE; 187 } 188 if (mInstance != VK_NULL_HANDLE) { 189 vkDestroyInstance(mInstance, nullptr); 190 mInstance = VK_NULL_HANDLE; 191 } 192 } 193 194 uint32_t VkInit::findMemoryType(uint32_t memoryTypeBitsRequirement, 195 VkFlags requirementsMask) { 196 for (uint32_t memoryIndex = 0; memoryIndex < VK_MAX_MEMORY_TYPES; 197 ++memoryIndex) { 198 const uint32_t memoryTypeBits = (1 << memoryIndex); 199 const bool isRequiredMemoryType = 200 memoryTypeBitsRequirement & memoryTypeBits; 201 const bool satisfiesFlags = 202 (mMemoryProperties.memoryTypes[memoryIndex].propertyFlags & 203 requirementsMask) == requirementsMask; 204 if (isRequiredMemoryType && satisfiesFlags) 205 return memoryIndex; 206 } 207 208 // failed to find memory type. 209 ALOGE("Couldn't find required memory type."); 210 return 0; 211 } 212 213 VkAHardwareBufferImage::VkAHardwareBufferImage(VkInit *init) : mInit(init) {} 214 215 bool VkAHardwareBufferImage::init(AHardwareBuffer *buffer, bool useExternalFormat, int syncFd) { 216 AHardwareBuffer_Desc bufferDesc; 217 AHardwareBuffer_describe(buffer, &bufferDesc); 218 ASSERT(bufferDesc.layers == 1); 219 220 VkAndroidHardwareBufferFormatPropertiesANDROID formatInfo = { 221 .sType = 222 VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID, 223 .pNext = nullptr, 224 }; 225 VkAndroidHardwareBufferPropertiesANDROID properties = { 226 .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, 227 .pNext = &formatInfo, 228 }; 229 VK_CALL(mInit->getHardwareBufferPropertiesFn()(mInit->device(), buffer, 230 &properties)); 231 ASSERT(useExternalFormat || formatInfo.format != VK_FORMAT_UNDEFINED); 232 // Create an image to bind to our AHardwareBuffer. 233 VkExternalFormatANDROID externalFormat{ 234 .sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID, 235 .pNext = nullptr, 236 .externalFormat = formatInfo.externalFormat, 237 }; 238 VkExternalMemoryImageCreateInfo externalCreateInfo{ 239 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, 240 .pNext = useExternalFormat ? &externalFormat : nullptr, 241 .handleTypes = 242 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, 243 }; 244 VkImageCreateInfo createInfo{ 245 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 246 .pNext = &externalCreateInfo, 247 .flags = 0u, 248 .imageType = VK_IMAGE_TYPE_2D, 249 .format = useExternalFormat ? VK_FORMAT_UNDEFINED : formatInfo.format, 250 .extent = 251 { 252 bufferDesc.width, bufferDesc.height, 1u, 253 }, 254 .mipLevels = 1u, 255 .arrayLayers = 1u, 256 .samples = VK_SAMPLE_COUNT_1_BIT, 257 .tiling = VK_IMAGE_TILING_OPTIMAL, 258 .usage = VK_IMAGE_USAGE_SAMPLED_BIT, 259 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 260 .queueFamilyIndexCount = 0, 261 .pQueueFamilyIndices = nullptr, 262 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, 263 }; 264 VK_CALL(vkCreateImage(mInit->device(), &createInfo, nullptr, &mImage)); 265 266 VkImageMemoryRequirementsInfo2 memReqsInfo; 267 memReqsInfo.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2; 268 memReqsInfo.pNext = nullptr; 269 memReqsInfo.image = mImage; 270 271 VkMemoryDedicatedRequirements dedicatedMemReqs; 272 dedicatedMemReqs.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS; 273 dedicatedMemReqs.pNext = nullptr; 274 275 VkMemoryRequirements2 memReqs; 276 memReqs.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; 277 memReqs.pNext = &dedicatedMemReqs; 278 279 PFN_vkGetImageMemoryRequirements2KHR getImageMemoryRequirements = 280 (PFN_vkGetImageMemoryRequirements2KHR)vkGetDeviceProcAddr( 281 mInit->device(), "vkGetImageMemoryRequirements2KHR"); 282 ASSERT(getImageMemoryRequirements); 283 getImageMemoryRequirements(mInit->device(), &memReqsInfo, &memReqs); 284 ASSERT(VK_TRUE == dedicatedMemReqs.prefersDedicatedAllocation); 285 ASSERT(VK_TRUE == dedicatedMemReqs.requiresDedicatedAllocation); 286 287 VkImportAndroidHardwareBufferInfoANDROID androidHardwareBufferInfo{ 288 .sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID, 289 .pNext = nullptr, 290 .buffer = buffer, 291 }; 292 VkMemoryDedicatedAllocateInfo memoryAllocateInfo{ 293 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, 294 .pNext = &androidHardwareBufferInfo, 295 .image = mImage, 296 .buffer = VK_NULL_HANDLE, 297 }; 298 VkMemoryAllocateInfo allocateInfo{ 299 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 300 .pNext = &memoryAllocateInfo, 301 .allocationSize = properties.allocationSize, 302 .memoryTypeIndex = mInit->findMemoryType( 303 properties.memoryTypeBits, 0u /* requirementsMask */), 304 }; 305 306 VK_CALL(vkAllocateMemory(mInit->device(), &allocateInfo, nullptr, &mMemory)); 307 VkBindImageMemoryInfo bindImageInfo; 308 bindImageInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; 309 bindImageInfo.pNext = nullptr; 310 bindImageInfo.image = mImage; 311 bindImageInfo.memory = mMemory; 312 bindImageInfo.memoryOffset = 0; 313 314 PFN_vkBindImageMemory2KHR bindImageMemory = 315 (PFN_vkBindImageMemory2KHR)vkGetDeviceProcAddr(mInit->device(), 316 "vkBindImageMemory2KHR"); 317 ASSERT(bindImageMemory); 318 VK_CALL(bindImageMemory(mInit->device(), 1, &bindImageInfo)); 319 320 if (useExternalFormat /* TODO: || explicit format requires conversion */) { 321 VkSamplerYcbcrConversionCreateInfo conversionCreateInfo{ 322 .sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO, 323 .pNext = &externalFormat, 324 .format = useExternalFormat ? VK_FORMAT_UNDEFINED : formatInfo.format, 325 .ycbcrModel = formatInfo.suggestedYcbcrModel, 326 .ycbcrRange = formatInfo.suggestedYcbcrRange, 327 .components = formatInfo.samplerYcbcrConversionComponents, 328 .xChromaOffset = formatInfo.suggestedXChromaOffset, 329 .yChromaOffset = formatInfo.suggestedYChromaOffset, 330 .chromaFilter = VK_FILTER_NEAREST, 331 .forceExplicitReconstruction = VK_FALSE, 332 }; 333 PFN_vkCreateSamplerYcbcrConversionKHR createSamplerYcbcrConversion = 334 (PFN_vkCreateSamplerYcbcrConversionKHR)vkGetDeviceProcAddr( 335 mInit->device(), "vkCreateSamplerYcbcrConversionKHR"); 336 ASSERT(createSamplerYcbcrConversion); 337 VK_CALL(createSamplerYcbcrConversion(mInit->device(), &conversionCreateInfo, 338 nullptr, &mConversion)); 339 } 340 VkSamplerYcbcrConversionInfo samplerConversionInfo{ 341 .sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, 342 .pNext = &externalFormat, 343 .conversion = mConversion, 344 }; 345 346 VkSamplerCreateInfo samplerCreateInfo{ 347 .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, 348 .pNext = 349 (mConversion == VK_NULL_HANDLE) ? nullptr : &samplerConversionInfo, 350 .magFilter = VK_FILTER_NEAREST, 351 .minFilter = VK_FILTER_NEAREST, 352 .mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST, 353 .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, 354 .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, 355 .addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, 356 .mipLodBias = 0.0f, 357 .anisotropyEnable = VK_FALSE, 358 .maxAnisotropy = 1, 359 .compareEnable = VK_FALSE, 360 .compareOp = VK_COMPARE_OP_NEVER, 361 .minLod = 0.0f, 362 .maxLod = 0.0f, 363 .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE, 364 .unnormalizedCoordinates = VK_FALSE, 365 }; 366 VK_CALL( 367 vkCreateSampler(mInit->device(), &samplerCreateInfo, nullptr, &mSampler)); 368 369 VkImageViewCreateInfo viewCreateInfo{ 370 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 371 .pNext = 372 (mConversion == VK_NULL_HANDLE) ? nullptr : &samplerConversionInfo, 373 .image = mImage, 374 .viewType = VK_IMAGE_VIEW_TYPE_2D, 375 .format = useExternalFormat ? VK_FORMAT_UNDEFINED : formatInfo.format, 376 .components = 377 { 378 VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, 379 VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, 380 }, 381 .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}, 382 .flags = 0, 383 }; 384 VK_CALL(vkCreateImageView(mInit->device(), &viewCreateInfo, nullptr, &mView)); 385 386 // Create semaphore if necessary. 387 if (syncFd != -1) { 388 VkSemaphoreCreateInfo semaphoreCreateInfo{ 389 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, 390 .pNext = nullptr, 391 .flags = 0, 392 }; 393 VK_CALL(vkCreateSemaphore(mInit->device(), &semaphoreCreateInfo, nullptr, 394 &mSemaphore)); 395 396 // Import the fd into a semaphore. 397 VkImportSemaphoreFdInfoKHR importSemaphoreInfo{ 398 .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, 399 .pNext = nullptr, 400 .semaphore = mSemaphore, 401 .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT, 402 .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, 403 .fd = syncFd, 404 }; 405 406 PFN_vkImportSemaphoreFdKHR importSemaphoreFd = 407 (PFN_vkImportSemaphoreFdKHR)vkGetDeviceProcAddr( 408 mInit->device(), "vkImportSemaphoreFdKHR"); 409 ASSERT(importSemaphoreFd); 410 VK_CALL(importSemaphoreFd(mInit->device(), &importSemaphoreInfo)); 411 } 412 413 return true; 414 } 415 416 VkAHardwareBufferImage::~VkAHardwareBufferImage() { 417 if (mView != VK_NULL_HANDLE) { 418 vkDestroyImageView(mInit->device(), mView, nullptr); 419 mView = VK_NULL_HANDLE; 420 } 421 if (mSampler != VK_NULL_HANDLE) { 422 vkDestroySampler(mInit->device(), mSampler, nullptr); 423 mSampler = VK_NULL_HANDLE; 424 } 425 if (mConversion != VK_NULL_HANDLE) { 426 PFN_vkDestroySamplerYcbcrConversionKHR destroySamplerYcbcrConversion = 427 (PFN_vkDestroySamplerYcbcrConversionKHR)vkGetDeviceProcAddr( 428 mInit->device(), "vkDestroySamplerYcbcrConversionKHR"); 429 destroySamplerYcbcrConversion(mInit->device(), mConversion, nullptr); 430 } 431 if (mMemory != VK_NULL_HANDLE) { 432 vkFreeMemory(mInit->device(), mMemory, nullptr); 433 mMemory = VK_NULL_HANDLE; 434 } 435 if (mImage != VK_NULL_HANDLE) { 436 vkDestroyImage(mInit->device(), mImage, nullptr); 437 mImage = VK_NULL_HANDLE; 438 } 439 if (mSemaphore != VK_NULL_HANDLE) { 440 vkDestroySemaphore(mInit->device(), mSemaphore, nullptr); 441 mSemaphore = VK_NULL_HANDLE; 442 } 443 } 444 445 VkImageRenderer::VkImageRenderer(VkInit *init, uint32_t width, uint32_t height, 446 VkFormat format, uint32_t bytesPerPixel) 447 : mInit(init), mWidth(width), mHeight(height), mFormat(format), 448 mResultBufferSize(width * height * bytesPerPixel) {} 449 450 bool VkImageRenderer::init(JNIEnv *env, jobject assetMgr) { 451 // Create an image to back our framebuffer. 452 { 453 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | 454 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | 455 VK_IMAGE_USAGE_TRANSFER_DST_BIT; 456 const VkImageCreateInfo imageCreateInfo{ 457 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 458 .pNext = nullptr, 459 .flags = 0u, 460 .imageType = VK_IMAGE_TYPE_2D, 461 .format = mFormat, 462 .extent = {mWidth, mHeight, 1u}, 463 .mipLevels = 1u, 464 .arrayLayers = 1u, 465 .samples = VK_SAMPLE_COUNT_1_BIT, 466 .tiling = VK_IMAGE_TILING_OPTIMAL, 467 .usage = imageUsage, 468 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 469 .queueFamilyIndexCount = 0u, 470 .pQueueFamilyIndices = nullptr, 471 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, 472 }; 473 VK_CALL( 474 vkCreateImage(mInit->device(), &imageCreateInfo, nullptr, &mDestImage)); 475 476 // Get memory requirements for image and allocate memory backing. 477 VkMemoryRequirements memoryRequirements; 478 vkGetImageMemoryRequirements(mInit->device(), mDestImage, 479 &memoryRequirements); 480 481 VkMemoryAllocateInfo memoryAllocateInfo{ 482 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 483 .pNext = nullptr, 484 .allocationSize = memoryRequirements.size, 485 .memoryTypeIndex = 486 mInit->findMemoryType(memoryRequirements.memoryTypeBits, 0u), 487 }; 488 VK_CALL(vkAllocateMemory(mInit->device(), &memoryAllocateInfo, nullptr, 489 &mDestImageMemory)); 490 VK_CALL( 491 vkBindImageMemory(mInit->device(), mDestImage, mDestImageMemory, 0)); 492 } 493 494 // Create image view. 495 { 496 VkImageViewCreateInfo imageViewCreateInfo{ 497 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 498 .pNext = nullptr, 499 .flags = 0u, 500 .image = mDestImage, 501 .viewType = VK_IMAGE_VIEW_TYPE_2D, 502 .format = mFormat, 503 .components = {VK_COMPONENT_SWIZZLE_IDENTITY, 504 VK_COMPONENT_SWIZZLE_IDENTITY, 505 VK_COMPONENT_SWIZZLE_IDENTITY, 506 VK_COMPONENT_SWIZZLE_IDENTITY}, 507 .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}, 508 }; 509 VK_CALL(vkCreateImageView(mInit->device(), &imageViewCreateInfo, nullptr, 510 &mDestImageView)); 511 } 512 513 // Create render pass 514 { 515 VkAttachmentDescription attachmentDesc{ 516 .flags = 0u, 517 .format = mFormat, 518 .samples = VK_SAMPLE_COUNT_1_BIT, 519 .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, 520 .storeOp = VK_ATTACHMENT_STORE_OP_STORE, 521 .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, 522 .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, 523 .initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 524 .finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; 525 VkAttachmentReference attachmentRef{ 526 .attachment = 0u, .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 527 }; 528 VkSubpassDescription subpassDesc{ 529 .flags = 0u, 530 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, 531 .inputAttachmentCount = 0u, 532 .pInputAttachments = nullptr, 533 .colorAttachmentCount = 1u, 534 .pColorAttachments = &attachmentRef, 535 .pResolveAttachments = nullptr, 536 .pDepthStencilAttachment = nullptr, 537 .preserveAttachmentCount = 0u, 538 .pPreserveAttachments = nullptr, 539 }; 540 VkRenderPassCreateInfo renderPassCreateInfo{ 541 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 542 .pNext = nullptr, 543 .flags = 0u, 544 .attachmentCount = 1u, 545 .pAttachments = &attachmentDesc, 546 .subpassCount = 1u, 547 .pSubpasses = &subpassDesc, 548 .dependencyCount = 0u, 549 .pDependencies = nullptr, 550 }; 551 VK_CALL(vkCreateRenderPass(mInit->device(), &renderPassCreateInfo, nullptr, 552 &mRenderPass)); 553 } 554 555 // Create vertex buffer. 556 { 557 const float vertexData[] = { 558 -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 559 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 560 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 561 }; 562 VkBufferCreateInfo createBufferInfo{ 563 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 564 .pNext = nullptr, 565 .size = sizeof(vertexData), 566 .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 567 .flags = 0, 568 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 569 .queueFamilyIndexCount = 0, 570 .pQueueFamilyIndices = nullptr, 571 }; 572 VK_CALL(vkCreateBuffer(mInit->device(), &createBufferInfo, nullptr, 573 &mVertexBuffer)); 574 575 VkMemoryRequirements memReq; 576 vkGetBufferMemoryRequirements(mInit->device(), mVertexBuffer, &memReq); 577 VkMemoryAllocateInfo allocInfo{ 578 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 579 .pNext = nullptr, 580 .allocationSize = memReq.size, 581 .memoryTypeIndex = mInit->findMemoryType( 582 memReq.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | 583 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT), 584 }; 585 VK_CALL(vkAllocateMemory(mInit->device(), &allocInfo, nullptr, 586 &mVertexBufferMemory)); 587 588 void *mappedData; 589 VK_CALL(vkMapMemory(mInit->device(), mVertexBufferMemory, 0, 590 sizeof(vertexData), 0, &mappedData)); 591 memcpy(mappedData, vertexData, sizeof(vertexData)); 592 vkUnmapMemory(mInit->device(), mVertexBufferMemory); 593 594 VK_CALL(vkBindBufferMemory(mInit->device(), mVertexBuffer, 595 mVertexBufferMemory, 0)); 596 } 597 598 // Create framebuffer. 599 { 600 VkFramebufferCreateInfo framebufferCreateInfo{ 601 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 602 .pNext = nullptr, 603 .flags = 0u, 604 .renderPass = mRenderPass, 605 .attachmentCount = 1u, 606 .pAttachments = &mDestImageView, 607 .width = mWidth, 608 .height = mHeight, 609 .layers = 1u, 610 }; 611 VK_CALL(vkCreateFramebuffer(mInit->device(), &framebufferCreateInfo, 612 nullptr, &mFramebuffer)); 613 } 614 615 // Create the host-side buffer which will be used to read back the results. 616 { 617 VkBufferCreateInfo bufferCreateInfo{ 618 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 619 .pNext = nullptr, 620 .flags = 0u, 621 .size = mResultBufferSize, 622 .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT, 623 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 624 .queueFamilyIndexCount = 0u, 625 .pQueueFamilyIndices = nullptr, 626 }; 627 VK_CALL(vkCreateBuffer(mInit->device(), &bufferCreateInfo, nullptr, 628 &mResultBuffer)); 629 630 VkMemoryRequirements memReq; 631 vkGetBufferMemoryRequirements(mInit->device(), mResultBuffer, &memReq); 632 VkMemoryAllocateInfo allocInfo{ 633 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 634 .pNext = nullptr, 635 .allocationSize = memReq.size, 636 .memoryTypeIndex = mInit->findMemoryType( 637 memReq.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | 638 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT), 639 }; 640 VK_CALL(vkAllocateMemory(mInit->device(), &allocInfo, nullptr, 641 &mResultBufferMemory)); 642 VK_CALL(vkBindBufferMemory(mInit->device(), mResultBuffer, 643 mResultBufferMemory, 0)); 644 } 645 646 // Create shaders. 647 { 648 AAsset *vertFile = 649 AAssetManager_open(AAssetManager_fromJava(env, assetMgr), 650 "passthrough_vsh.spv", AASSET_MODE_BUFFER); 651 ASSERT(vertFile); 652 size_t vertShaderLength = AAsset_getLength(vertFile); 653 std::vector<uint8_t> vertShader; 654 vertShader.resize(vertShaderLength); 655 AAsset_read(vertFile, static_cast<void *>(vertShader.data()), 656 vertShaderLength); 657 AAsset_close(vertFile); 658 659 AAsset *pixelFile = 660 AAssetManager_open(AAssetManager_fromJava(env, assetMgr), 661 "passthrough_fsh.spv", AASSET_MODE_BUFFER); 662 ASSERT(pixelFile); 663 size_t pixelShaderLength = AAsset_getLength(pixelFile); 664 std::vector<uint8_t> pixelShader; 665 pixelShader.resize(pixelShaderLength); 666 AAsset_read(pixelFile, static_cast<void *>(pixelShader.data()), 667 pixelShaderLength); 668 AAsset_close(pixelFile); 669 670 VkShaderModuleCreateInfo vertexShaderInfo{ 671 .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, 672 .pNext = nullptr, 673 .flags = 0u, 674 .codeSize = vertShaderLength, 675 .pCode = reinterpret_cast<const uint32_t *>(vertShader.data()), 676 }; 677 VK_CALL(vkCreateShaderModule(mInit->device(), &vertexShaderInfo, nullptr, 678 &mVertModule)); 679 680 VkShaderModuleCreateInfo pixelShaderInfo{ 681 .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, 682 .pNext = nullptr, 683 .flags = 0u, 684 .codeSize = pixelShaderLength, 685 .pCode = reinterpret_cast<const uint32_t *>(pixelShader.data()), 686 }; 687 VK_CALL(vkCreateShaderModule(mInit->device(), &pixelShaderInfo, nullptr, 688 &mPixelModule)); 689 } 690 691 VkPipelineCacheCreateInfo pipelineCacheInfo{ 692 .sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, 693 .pNext = nullptr, 694 .initialDataSize = 0, 695 .pInitialData = nullptr, 696 .flags = 0, // reserved, must be 0 697 }; 698 VK_CALL(vkCreatePipelineCache(mInit->device(), &pipelineCacheInfo, nullptr, 699 &mCache)); 700 701 // Create Descriptor Pool 702 { 703 const VkDescriptorPoolSize typeCount = { 704 .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = 1, 705 }; 706 const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo{ 707 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, 708 .pNext = nullptr, 709 .maxSets = 1, 710 .poolSizeCount = 1, 711 .pPoolSizes = &typeCount, 712 }; 713 714 VK_CALL(vkCreateDescriptorPool(mInit->device(), &descriptorPoolCreateInfo, 715 nullptr, &mDescriptorPool)); 716 } 717 718 // Create command pool. 719 { 720 VkCommandPoolCreateInfo cmdPoolCreateInfo{ 721 .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 722 .pNext = nullptr, 723 .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, 724 .queueFamilyIndex = 0, 725 }; 726 VK_CALL(vkCreateCommandPool(mInit->device(), &cmdPoolCreateInfo, nullptr, 727 &mCmdPool)); 728 } 729 730 // Create a fence 731 { 732 VkFenceCreateInfo fenceInfo = { 733 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 734 .pNext = nullptr, 735 .flags = 0, 736 }; 737 VK_CALL(vkCreateFence(mInit->device(), &fenceInfo, nullptr, &mFence)); 738 } 739 740 return true; 741 } 742 743 VkImageRenderer::~VkImageRenderer() { 744 cleanUpTemporaries(); 745 746 if (mCmdPool != VK_NULL_HANDLE) { 747 vkDestroyCommandPool(mInit->device(), mCmdPool, nullptr); 748 mCmdPool = VK_NULL_HANDLE; 749 } 750 if (mDescriptorPool != VK_NULL_HANDLE) { 751 vkDestroyDescriptorPool(mInit->device(), mDescriptorPool, nullptr); 752 mDescriptorPool = VK_NULL_HANDLE; 753 } 754 if (mDestImageView != VK_NULL_HANDLE) { 755 vkDestroyImageView(mInit->device(), mDestImageView, nullptr); 756 mDestImageView = VK_NULL_HANDLE; 757 } 758 if (mDestImage != VK_NULL_HANDLE) { 759 vkDestroyImage(mInit->device(), mDestImage, nullptr); 760 mDestImage = VK_NULL_HANDLE; 761 } 762 if (mDestImageMemory != VK_NULL_HANDLE) { 763 vkFreeMemory(mInit->device(), mDestImageMemory, nullptr); 764 mDestImageMemory = VK_NULL_HANDLE; 765 } 766 if (mResultBuffer != VK_NULL_HANDLE) { 767 vkDestroyBuffer(mInit->device(), mResultBuffer, nullptr); 768 mResultBuffer = VK_NULL_HANDLE; 769 } 770 if (mResultBufferMemory != VK_NULL_HANDLE) { 771 vkFreeMemory(mInit->device(), mResultBufferMemory, nullptr); 772 mResultBufferMemory = VK_NULL_HANDLE; 773 } 774 if (mRenderPass != VK_NULL_HANDLE) { 775 vkDestroyRenderPass(mInit->device(), mRenderPass, nullptr); 776 mRenderPass = VK_NULL_HANDLE; 777 } 778 if (mVertexBuffer != VK_NULL_HANDLE) { 779 vkDestroyBuffer(mInit->device(), mVertexBuffer, nullptr); 780 mVertexBuffer = VK_NULL_HANDLE; 781 } 782 if (mVertexBufferMemory != VK_NULL_HANDLE) { 783 vkFreeMemory(mInit->device(), mVertexBufferMemory, nullptr); 784 mVertexBufferMemory = VK_NULL_HANDLE; 785 } 786 if (mFramebuffer != VK_NULL_HANDLE) { 787 vkDestroyFramebuffer(mInit->device(), mFramebuffer, nullptr); 788 mFramebuffer = VK_NULL_HANDLE; 789 } 790 if (mCache != VK_NULL_HANDLE) { 791 vkDestroyPipelineCache(mInit->device(), mCache, nullptr); 792 mCache = VK_NULL_HANDLE; 793 } 794 if (mVertModule != VK_NULL_HANDLE) { 795 vkDestroyShaderModule(mInit->device(), mVertModule, nullptr); 796 mVertModule = VK_NULL_HANDLE; 797 } 798 if (mPixelModule != VK_NULL_HANDLE) { 799 vkDestroyShaderModule(mInit->device(), mPixelModule, nullptr); 800 mPixelModule = VK_NULL_HANDLE; 801 } 802 if (mFence != VK_NULL_HANDLE) { 803 vkDestroyFence(mInit->device(), mFence, nullptr); 804 mFence = VK_NULL_HANDLE; 805 } 806 } 807 808 bool VkImageRenderer::renderImageAndReadback(VkImage image, VkSampler sampler, 809 VkImageView view, 810 VkSemaphore semaphore, 811 bool useExternalFormat, 812 std::vector<uint32_t> *data) { 813 std::vector<uint8_t> unconvertedData; 814 ASSERT(renderImageAndReadback(image, sampler, view, semaphore, 815 useExternalFormat, &unconvertedData)); 816 if ((unconvertedData.size() % sizeof(uint32_t)) != 0) 817 return false; 818 819 const uint32_t *dataPtr = 820 reinterpret_cast<const uint32_t *>(unconvertedData.data()); 821 *data = std::vector<uint32_t>(dataPtr, dataPtr + unconvertedData.size() / 822 sizeof(uint32_t)); 823 return true; 824 } 825 826 bool VkImageRenderer::renderImageAndReadback(VkImage image, VkSampler sampler, 827 VkImageView view, 828 VkSemaphore semaphore, 829 bool useImmutableSampler, 830 std::vector<uint8_t> *data) { 831 cleanUpTemporaries(); 832 833 // Create graphics pipeline. 834 { 835 VkDescriptorSetLayoutBinding descriptorSetLayoutBinding{ 836 .binding = 0, 837 .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 838 .descriptorCount = 1u, 839 .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, 840 .pImmutableSamplers = useImmutableSampler ? &sampler : nullptr, 841 }; 842 const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = { 843 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, 844 .pNext = nullptr, 845 .bindingCount = 1, 846 .pBindings = &descriptorSetLayoutBinding, 847 }; 848 VK_CALL(vkCreateDescriptorSetLayout(mInit->device(), 849 &descriptorSetLayoutCreateInfo, nullptr, 850 &mDescriptorLayout)); 851 852 VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{ 853 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 854 .pNext = nullptr, 855 .setLayoutCount = 1, 856 .pSetLayouts = &mDescriptorLayout, 857 .pushConstantRangeCount = 0, 858 .pPushConstantRanges = nullptr, 859 }; 860 861 VK_CALL(vkCreatePipelineLayout(mInit->device(), &pipelineLayoutCreateInfo, 862 nullptr, &mLayout)); 863 864 VkPipelineShaderStageCreateInfo shaderStageParams[2] = { 865 { 866 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 867 .pNext = nullptr, 868 .flags = 0, 869 .stage = VK_SHADER_STAGE_VERTEX_BIT, 870 .module = mVertModule, 871 .pName = "main", 872 .pSpecializationInfo = nullptr, 873 }, 874 { 875 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 876 .pNext = nullptr, 877 .flags = 0, 878 .stage = VK_SHADER_STAGE_FRAGMENT_BIT, 879 .module = mPixelModule, 880 .pName = "main", 881 .pSpecializationInfo = nullptr, 882 }}; 883 884 VkViewport viewports{ 885 .minDepth = 0.0f, 886 .maxDepth = 1.0f, 887 .x = 0, 888 .y = 0, 889 .width = static_cast<float>(mWidth), 890 .height = static_cast<float>(mHeight), 891 }; 892 893 VkRect2D scissor = {.extent = {mWidth, mHeight}, .offset = {0, 0}}; 894 VkPipelineViewportStateCreateInfo viewportInfo{ 895 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 896 .pNext = nullptr, 897 .viewportCount = 1, 898 .pViewports = &viewports, 899 .scissorCount = 1, 900 .pScissors = &scissor, 901 }; 902 903 VkSampleMask sampleMask = ~0u; 904 VkPipelineMultisampleStateCreateInfo multisampleInfo{ 905 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 906 .pNext = nullptr, 907 .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, 908 .sampleShadingEnable = VK_FALSE, 909 .minSampleShading = 0, 910 .pSampleMask = &sampleMask, 911 .alphaToCoverageEnable = VK_FALSE, 912 .alphaToOneEnable = VK_FALSE, 913 }; 914 VkPipelineColorBlendAttachmentState attachmentStates{ 915 .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | 916 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, 917 .blendEnable = VK_FALSE, 918 }; 919 VkPipelineColorBlendStateCreateInfo colorBlendInfo{ 920 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 921 .pNext = nullptr, 922 .logicOpEnable = VK_FALSE, 923 .logicOp = VK_LOGIC_OP_COPY, 924 .attachmentCount = 1, 925 .pAttachments = &attachmentStates, 926 .flags = 0, 927 }; 928 VkPipelineRasterizationStateCreateInfo rasterInfo{ 929 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 930 .pNext = nullptr, 931 .depthClampEnable = VK_FALSE, 932 .rasterizerDiscardEnable = VK_FALSE, 933 .polygonMode = VK_POLYGON_MODE_FILL, 934 .cullMode = VK_CULL_MODE_NONE, 935 .frontFace = VK_FRONT_FACE_CLOCKWISE, 936 .depthBiasEnable = VK_FALSE, 937 .lineWidth = 1, 938 }; 939 VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo{ 940 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 941 .pNext = nullptr, 942 .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 943 .primitiveRestartEnable = VK_FALSE, 944 }; 945 946 // Specify vertex input state 947 VkVertexInputBindingDescription vertexInputBindingDescription{ 948 .binding = 0u, 949 .stride = 4 * sizeof(float), 950 .inputRate = VK_VERTEX_INPUT_RATE_VERTEX}; 951 VkVertexInputAttributeDescription vertex_input_attributes[2]{ 952 { 953 .binding = 0, 954 .location = 0, 955 .format = VK_FORMAT_R32G32_SFLOAT, 956 .offset = 0, 957 }, 958 { 959 .binding = 0, 960 .location = 1, 961 .format = VK_FORMAT_R32G32_SFLOAT, 962 .offset = sizeof(float) * 2, 963 }}; 964 VkPipelineVertexInputStateCreateInfo vertexInputInfo{ 965 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 966 .pNext = nullptr, 967 .vertexBindingDescriptionCount = 1, 968 .pVertexBindingDescriptions = &vertexInputBindingDescription, 969 .vertexAttributeDescriptionCount = 2, 970 .pVertexAttributeDescriptions = vertex_input_attributes, 971 }; 972 973 // Create the pipeline 974 VkGraphicsPipelineCreateInfo pipelineCreateInfo{ 975 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 976 .pNext = nullptr, 977 .flags = 0, 978 .stageCount = 2, 979 .pStages = shaderStageParams, 980 .pVertexInputState = &vertexInputInfo, 981 .pInputAssemblyState = &inputAssemblyInfo, 982 .pTessellationState = nullptr, 983 .pViewportState = &viewportInfo, 984 .pRasterizationState = &rasterInfo, 985 .pMultisampleState = &multisampleInfo, 986 .pDepthStencilState = nullptr, 987 .pColorBlendState = &colorBlendInfo, 988 .pDynamicState = 0u, 989 .layout = mLayout, 990 .renderPass = mRenderPass, 991 .subpass = 0, 992 .basePipelineHandle = VK_NULL_HANDLE, 993 .basePipelineIndex = 0, 994 }; 995 996 VK_CALL(vkCreateGraphicsPipelines( 997 mInit->device(), mCache, 1, &pipelineCreateInfo, nullptr, &mPipeline)); 998 } 999 1000 // Create a command buffer. 1001 { 1002 VkCommandBufferAllocateInfo cmdBufferCreateInfo{ 1003 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 1004 .pNext = nullptr, 1005 .commandPool = mCmdPool, 1006 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1007 .commandBufferCount = 1, 1008 }; 1009 VK_CALL(vkAllocateCommandBuffers(mInit->device(), &cmdBufferCreateInfo, 1010 &mCmdBuffer)); 1011 } 1012 1013 // Create the descriptor sets. 1014 { 1015 VkDescriptorSetAllocateInfo allocInfo{ 1016 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 1017 .pNext = nullptr, 1018 .descriptorPool = mDescriptorPool, 1019 .descriptorSetCount = 1, 1020 .pSetLayouts = &mDescriptorLayout}; 1021 VK_CALL( 1022 vkAllocateDescriptorSets(mInit->device(), &allocInfo, &mDescriptorSet)); 1023 1024 VkDescriptorImageInfo texDesc{ 1025 .sampler = sampler, 1026 .imageView = view, 1027 .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1028 }; 1029 1030 VkWriteDescriptorSet writeDst{ 1031 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 1032 .pNext = nullptr, 1033 .dstSet = mDescriptorSet, 1034 .dstBinding = 0, 1035 .dstArrayElement = 0, 1036 .descriptorCount = 1, 1037 .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1038 .pImageInfo = &texDesc, 1039 .pBufferInfo = nullptr, 1040 .pTexelBufferView = nullptr}; 1041 vkUpdateDescriptorSets(mInit->device(), 1, &writeDst, 0, nullptr); 1042 } 1043 1044 // Begin Command Buffer 1045 { 1046 VkCommandBufferBeginInfo cmdBufferBeginInfo{ 1047 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 1048 .pNext = nullptr, 1049 .flags = 0u, 1050 .pInheritanceInfo = nullptr, 1051 }; 1052 1053 VK_CALL(vkBeginCommandBuffer(mCmdBuffer, &cmdBufferBeginInfo)); 1054 } 1055 1056 // Transition the provided resource so we can sample from it. 1057 addImageTransitionBarrier( 1058 mCmdBuffer, image, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 1059 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, VK_ACCESS_SHADER_READ_BIT, 1060 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1061 VK_QUEUE_FAMILY_EXTERNAL_KHR, mInit->queueFamilyIndex()); 1062 1063 // Transition the destination texture for use as a framebuffer. 1064 addImageTransitionBarrier( 1065 mCmdBuffer, mDestImage, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 1066 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1067 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, 1068 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); 1069 1070 // Begin Render Pass to draw the source resource to the framebuffer. 1071 { 1072 const VkClearValue clearValue{ 1073 .color = 1074 { 1075 .float32 = {0.0f, 0.0f, 0.0f, 0.0f}, 1076 }, 1077 }; 1078 VkRenderPassBeginInfo renderPassBeginInfo{ 1079 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 1080 .pNext = nullptr, 1081 .renderPass = mRenderPass, 1082 .framebuffer = mFramebuffer, 1083 .renderArea = {{0, 0}, {mWidth, mHeight}}, 1084 .clearValueCount = 1u, 1085 .pClearValues = &clearValue, 1086 }; 1087 vkCmdBeginRenderPass(mCmdBuffer, &renderPassBeginInfo, 1088 VK_SUBPASS_CONTENTS_INLINE); 1089 } 1090 1091 /// Draw texture to renderpass. 1092 vkCmdBindPipeline(mCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, mPipeline); 1093 vkCmdBindDescriptorSets(mCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, mLayout, 1094 0u, 1, &mDescriptorSet, 0u, nullptr); 1095 VkDeviceSize offset = 0; 1096 vkCmdBindVertexBuffers(mCmdBuffer, 0, 1, &mVertexBuffer, &offset); 1097 vkCmdDraw(mCmdBuffer, 6u, 1u, 0u, 0u); 1098 vkCmdEndRenderPass(mCmdBuffer); 1099 1100 // Copy to our staging buffer. 1101 { 1102 VkBufferMemoryBarrier bufferBarrier{ 1103 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 1104 .pNext = nullptr, 1105 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, 1106 .dstAccessMask = VK_ACCESS_HOST_READ_BIT, 1107 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 1108 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 1109 .buffer = mResultBuffer, 1110 .offset = 0u, 1111 .size = mResultBufferSize, 1112 }; 1113 1114 VkBufferImageCopy copyRegion{ 1115 .bufferOffset = 0u, 1116 .bufferRowLength = mWidth, 1117 .bufferImageHeight = mHeight, 1118 .imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u}, 1119 .imageOffset = {0, 0, 0}, 1120 .imageExtent = {mWidth, mHeight, 1u}}; 1121 1122 addImageTransitionBarrier( 1123 mCmdBuffer, mDestImage, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 1124 VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 1125 VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1126 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); 1127 1128 vkCmdCopyImageToBuffer(mCmdBuffer, mDestImage, 1129 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, mResultBuffer, 1130 1, ©Region); 1131 1132 vkCmdPipelineBarrier(mCmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, 1133 VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, 1134 (const VkMemoryBarrier *)nullptr, 1, &bufferBarrier, 0, 1135 (const VkImageMemoryBarrier *)nullptr); 1136 } 1137 1138 VK_CALL(vkEndCommandBuffer(mCmdBuffer)); 1139 1140 VkPipelineStageFlags semaphoreWaitFlags = 1141 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; 1142 VkSubmitInfo submitInfo{ 1143 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, 1144 .pNext = nullptr, 1145 .waitSemaphoreCount = semaphore != VK_NULL_HANDLE ? 1u : 0u, 1146 .pWaitSemaphores = semaphore != VK_NULL_HANDLE ? &semaphore : nullptr, 1147 .pWaitDstStageMask = 1148 semaphore != VK_NULL_HANDLE ? &semaphoreWaitFlags : nullptr, 1149 .commandBufferCount = 1u, 1150 .pCommandBuffers = &mCmdBuffer, 1151 .signalSemaphoreCount = 0u, 1152 .pSignalSemaphores = nullptr, 1153 }; 1154 VK_CALL(vkResetFences(mInit->device(), 1, &mFence)) 1155 VK_CALL(vkQueueSubmit(mInit->queue(), 1, &submitInfo, mFence)); 1156 VK_CALL(vkWaitForFences(mInit->device(), 1, &mFence, VK_TRUE, 1157 ~(0ull) /* infinity */)); 1158 1159 void *outData; 1160 VK_CALL(vkMapMemory(mInit->device(), mResultBufferMemory, 0u, 1161 mResultBufferSize, 0u, &outData)); 1162 uint8_t *uData = reinterpret_cast<uint8_t *>(outData); 1163 *data = std::vector<uint8_t>(uData, uData + mResultBufferSize); 1164 vkUnmapMemory(mInit->device(), mResultBufferMemory); 1165 1166 return true; 1167 } 1168 1169 void VkImageRenderer::cleanUpTemporaries() { 1170 if (mCmdBuffer != VK_NULL_HANDLE) { 1171 vkFreeCommandBuffers(mInit->device(), mCmdPool, 1, &mCmdBuffer); 1172 mCmdBuffer = VK_NULL_HANDLE; 1173 } 1174 if (mDescriptorSet != VK_NULL_HANDLE) { 1175 vkResetDescriptorPool(mInit->device(), mDescriptorPool, 0 /*flags*/); 1176 mDescriptorSet = VK_NULL_HANDLE; 1177 } 1178 if (mPipeline != VK_NULL_HANDLE) { 1179 vkDestroyPipeline(mInit->device(), mPipeline, nullptr); 1180 mPipeline = VK_NULL_HANDLE; 1181 } 1182 if (mDescriptorLayout != VK_NULL_HANDLE) { 1183 vkDestroyDescriptorSetLayout(mInit->device(), mDescriptorLayout, nullptr); 1184 mDescriptorLayout = VK_NULL_HANDLE; 1185 } 1186 if (mLayout != VK_NULL_HANDLE) { 1187 vkDestroyPipelineLayout(mInit->device(), mLayout, nullptr); 1188 mLayout = VK_NULL_HANDLE; 1189 } 1190 } 1191