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