• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expresso or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 #include "VkAndroidNativeBuffer.h"
14 
15 #include "cereal/common/goldfish_vk_private_defs.h"
16 #include "cereal/common/goldfish_vk_extension_structs.h"
17 
18 #include "stream-servers/FrameBuffer.h"
19 #include "GrallocDefs.h"
20 #include "VkCommonOperations.h"
21 #include "VulkanDispatch.h"
22 
23 #include <string.h>
24 
25 #define VK_ANB_ERR(fmt,...) fprintf(stderr, "%s:%d " fmt "\n", __func__, __LINE__, ##__VA_ARGS__);
26 
27 namespace goldfish_vk {
28 
parseAndroidNativeBufferInfo(const VkImageCreateInfo * pCreateInfo,AndroidNativeBufferInfo * info_out)29 bool parseAndroidNativeBufferInfo(
30     const VkImageCreateInfo* pCreateInfo,
31     AndroidNativeBufferInfo* info_out) {
32 
33     // Look through the extension chain.
34     const void* curr_pNext = pCreateInfo->pNext;
35     if (!curr_pNext) return false;
36 
37     uint32_t structType = goldfish_vk_struct_type(curr_pNext);
38 
39     return structType == VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID;
40 }
41 
prepareAndroidNativeBufferImage(VulkanDispatch * vk,VkDevice device,const VkImageCreateInfo * pCreateInfo,const VkNativeBufferANDROID * nativeBufferANDROID,const VkAllocationCallbacks * pAllocator,const VkPhysicalDeviceMemoryProperties * memProps,AndroidNativeBufferInfo * out)42 VkResult prepareAndroidNativeBufferImage(
43     VulkanDispatch* vk,
44     VkDevice device,
45     const VkImageCreateInfo* pCreateInfo,
46     const VkNativeBufferANDROID* nativeBufferANDROID,
47     const VkAllocationCallbacks* pAllocator,
48     const VkPhysicalDeviceMemoryProperties* memProps,
49     AndroidNativeBufferInfo* out) {
50 
51     *out = {};
52 
53     out->device = device;
54     out->vkFormat = pCreateInfo->format;
55     out->extent = pCreateInfo->extent;
56     out->usage = pCreateInfo->usage;
57 
58     for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; ++i) {
59         out->queueFamilyIndices.push_back(
60                 pCreateInfo->pQueueFamilyIndices[i]);
61     }
62 
63     out->format = nativeBufferANDROID->format;
64     out->stride = nativeBufferANDROID->stride;
65     out->colorBufferHandle = *(nativeBufferANDROID->handle);
66 
67     bool colorBufferVulkanCompatible =
68         isColorBufferVulkanCompatible(out->colorBufferHandle);
69     bool externalMemoryCompatible = false;
70 
71     auto emu = getGlobalVkEmulation();
72 
73     if (emu && emu->live) {
74         externalMemoryCompatible =
75             emu->deviceInfo.supportsExternalMemory;
76     }
77 
78     if (colorBufferVulkanCompatible && externalMemoryCompatible &&
79         setupVkColorBuffer(out->colorBufferHandle, false /* not Vulkan only */,
80                            0u /* memoryProperty */, &out->isGlTexture)) {
81         out->externallyBacked = true;
82     }
83 
84     // delete the info struct and pass to vkCreateImage, and also add
85     // transfer src capability to allow us to copy to CPU.
86     VkImageCreateInfo infoNoNative = *pCreateInfo;
87     infoNoNative.pNext = nullptr;
88     infoNoNative.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
89 
90     if (out->externallyBacked) {
91         // Create the image with extension structure about external backing.
92         VkExternalMemoryImageCreateInfo extImageCi = {
93             VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, 0,
94             VK_EXT_MEMORY_HANDLE_TYPE_BIT,
95         };
96 
97         infoNoNative.pNext = &extImageCi;
98 
99         VkResult createResult =
100             vk->vkCreateImage(
101                 device, &infoNoNative, pAllocator, &out->image);
102 
103         if (createResult != VK_SUCCESS) return createResult;
104 
105         // Now import the backing memory.
106         const auto& cbInfo = getColorBufferInfo(out->colorBufferHandle);
107         const auto& memInfo = cbInfo.memory;
108 
109         vk->vkGetImageMemoryRequirements(
110             device, out->image, &out->memReqs);
111 
112         if (out->memReqs.size < memInfo.size) {
113             out->memReqs.size = memInfo.size;
114         }
115 
116         if (!importExternalMemory(vk, device, &memInfo, &out->imageMemory)) {
117             fprintf(stderr, "%s: Failed to import external memory\n", __func__);
118             return VK_ERROR_INITIALIZATION_FAILED;
119         }
120 
121     } else {
122         VkResult createResult =
123             vk->vkCreateImage(
124                 device, &infoNoNative, pAllocator, &out->image);
125 
126         if (createResult != VK_SUCCESS) return createResult;
127 
128         vk->vkGetImageMemoryRequirements(
129             device, out->image, &out->memReqs);
130 
131         uint32_t imageMemoryTypeIndex = 0;
132         bool imageMemoryTypeIndexFound = false;
133 
134         for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i) {
135             bool supported =
136                 out->memReqs.memoryTypeBits & (1 << i);
137             if (supported) {
138                 imageMemoryTypeIndex = i;
139                 imageMemoryTypeIndexFound = true;
140                 break;
141             }
142         }
143 
144         if (!imageMemoryTypeIndexFound) {
145             VK_ANB_ERR("VK_ANDROID_native_buffer: could not obtain "
146                        "image memory type index");
147             teardownAndroidNativeBufferImage(vk, out);
148             return VK_ERROR_OUT_OF_DEVICE_MEMORY;
149         }
150 
151         out->imageMemoryTypeIndex = imageMemoryTypeIndex;
152 
153         VkMemoryAllocateInfo allocInfo = {
154             VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 0,
155             out->memReqs.size,
156             out->imageMemoryTypeIndex,
157         };
158 
159         if (VK_SUCCESS !=
160             vk->vkAllocateMemory(
161                 device, &allocInfo, nullptr,
162                 &out->imageMemory)) {
163                 VK_ANB_ERR("VK_ANDROID_native_buffer: could not allocate "
164                            "image memory. requested size: %zu", (size_t)(out->memReqs.size));
165             teardownAndroidNativeBufferImage(vk, out);
166             return VK_ERROR_OUT_OF_DEVICE_MEMORY;
167         }
168     }
169 
170     if (VK_SUCCESS !=
171         vk->vkBindImageMemory(
172             device, out->image, out->imageMemory, 0)) {
173         VK_ANB_ERR("VK_ANDROID_native_buffer: could not bind "
174                 "image memory.");
175         teardownAndroidNativeBufferImage(vk, out);
176         return VK_ERROR_OUT_OF_DEVICE_MEMORY;
177     }
178 
179     // Allocate a staging memory and set up the staging buffer.
180     // TODO: Make this shared as well if we can get that to
181     // work on Windows with NVIDIA.
182     {
183         bool stagingIndexRes =
184             getStagingMemoryTypeIndex(
185                 vk, device, memProps, &out->stagingMemoryTypeIndex);
186 
187         if (!stagingIndexRes) {
188             VK_ANB_ERR(
189                 "VK_ANDROID_native_buffer: could not obtain "
190                 "staging memory type index");
191             teardownAndroidNativeBufferImage(vk, out);
192             return VK_ERROR_OUT_OF_HOST_MEMORY;
193         }
194 
195         VkMemoryAllocateInfo allocInfo = {
196             VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 0,
197             out->memReqs.size,
198             out->stagingMemoryTypeIndex,
199         };
200 
201         if (VK_SUCCESS !=
202             vk->vkAllocateMemory(
203                 device, &allocInfo, nullptr,
204                 &out->stagingMemory)) {
205             VK_ANB_ERR(
206                 "VK_ANDROID_native_buffer: could not allocate "
207                 "staging memory. requested size: %zu", (size_t)(out->memReqs.size));
208             teardownAndroidNativeBufferImage(vk, out);
209             return VK_ERROR_OUT_OF_HOST_MEMORY;
210         }
211 
212         VkBufferCreateInfo stagingBufferCreateInfo = {
213             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 0, 0,
214             out->memReqs.size,
215             VK_BUFFER_USAGE_TRANSFER_DST_BIT |
216             VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
217             out->sharingMode,
218             (uint32_t)out->queueFamilyIndices.size(),
219             out->queueFamilyIndices.size() ? out->queueFamilyIndices.data() : nullptr,
220         };
221 
222         if (VK_SUCCESS !=
223             vk->vkCreateBuffer(
224                 device, &stagingBufferCreateInfo, nullptr,
225                 &out->stagingBuffer)) {
226             VK_ANB_ERR("VK_ANDROID_native_buffer: could not create "
227                        "staging buffer.");
228             teardownAndroidNativeBufferImage(vk, out);
229             return VK_ERROR_OUT_OF_HOST_MEMORY;
230         }
231 
232         if (VK_SUCCESS !=
233             vk->vkBindBufferMemory(
234                 device, out->stagingBuffer, out->stagingMemory, 0)) {
235             VK_ANB_ERR("VK_ANDROID_native_buffer: could not bind "
236                        "staging buffer to staging memory.");
237             teardownAndroidNativeBufferImage(vk, out);
238             return VK_ERROR_OUT_OF_HOST_MEMORY;
239         }
240 
241         if (VK_SUCCESS !=
242             vk->vkMapMemory(
243                 device, out->stagingMemory, 0,
244                 out->memReqs.size, 0,
245                 (void**)&out->mappedStagingPtr)) {
246             VK_ANB_ERR("VK_ANDROID_native_buffer: could not map "
247                        "staging buffer.");
248             teardownAndroidNativeBufferImage(vk, out);
249             return VK_ERROR_OUT_OF_HOST_MEMORY;
250         }
251     }
252 
253     return VK_SUCCESS;
254 }
255 
teardownAndroidNativeBufferImage(VulkanDispatch * vk,AndroidNativeBufferInfo * anbInfo)256 void teardownAndroidNativeBufferImage(
257     VulkanDispatch* vk, AndroidNativeBufferInfo* anbInfo) {
258     auto device = anbInfo->device;
259 
260     auto image = anbInfo->image;
261     auto imageMemory = anbInfo->imageMemory;
262 
263     auto stagingBuffer = anbInfo->stagingBuffer;
264     auto mappedPtr = anbInfo->mappedStagingPtr;
265     auto stagingMemory = anbInfo->stagingMemory;
266 
267     if (image) vk->vkDestroyImage(device, image, nullptr);
268     if (imageMemory) vk->vkFreeMemory(device, imageMemory, nullptr);
269     if (stagingBuffer) vk->vkDestroyBuffer(device, stagingBuffer, nullptr);
270     if (mappedPtr) vk->vkUnmapMemory(device, stagingMemory);
271     if (stagingMemory) vk->vkFreeMemory(device, stagingMemory, nullptr);
272 
273     for (auto queueState : anbInfo->queueStates) {
274         queueState.teardown(vk, device);
275     }
276     anbInfo->queueStates.clear();
277 
278     anbInfo->acquireQueueState.teardown(vk, device);
279 
280     *anbInfo = {};
281 }
282 
getGralloc0Usage(VkFormat format,VkImageUsageFlags imageUsage,int * usage_out)283 void getGralloc0Usage(VkFormat format, VkImageUsageFlags imageUsage,
284                       int* usage_out) {
285     // Pick some default flexible values for gralloc usage for now.
286     (void)format;
287     (void)imageUsage;
288     *usage_out =
289         GRALLOC_USAGE_SW_READ_OFTEN |
290         GRALLOC_USAGE_SW_WRITE_OFTEN |
291         GRALLOC_USAGE_HW_RENDER |
292         GRALLOC_USAGE_HW_TEXTURE;
293 }
294 
295 // Taken from Android GrallocUsageConversion.h
getGralloc1Usage(VkFormat format,VkImageUsageFlags imageUsage,VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,uint64_t * consumerUsage_out,uint64_t * producerUsage_out)296 void getGralloc1Usage(VkFormat format, VkImageUsageFlags imageUsage,
297                       VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
298                       uint64_t* consumerUsage_out,
299                       uint64_t* producerUsage_out) {
300     // Pick some default flexible values for gralloc usage for now.
301     (void)format;
302     (void)imageUsage;
303     (void)swapchainImageUsage;
304 
305     constexpr int usage =
306         GRALLOC_USAGE_SW_READ_OFTEN |
307         GRALLOC_USAGE_SW_WRITE_OFTEN |
308         GRALLOC_USAGE_HW_RENDER |
309         GRALLOC_USAGE_HW_TEXTURE;
310 
311     constexpr uint64_t PRODUCER_MASK =
312             GRALLOC1_PRODUCER_USAGE_CPU_READ |
313             /* GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN | */
314             GRALLOC1_PRODUCER_USAGE_CPU_WRITE |
315             /* GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN | */
316             GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET |
317             GRALLOC1_PRODUCER_USAGE_PROTECTED |
318             GRALLOC1_PRODUCER_USAGE_CAMERA |
319             GRALLOC1_PRODUCER_USAGE_VIDEO_DECODER |
320             GRALLOC1_PRODUCER_USAGE_SENSOR_DIRECT_DATA;
321     constexpr uint64_t CONSUMER_MASK =
322             GRALLOC1_CONSUMER_USAGE_CPU_READ |
323             /* GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN | */
324             GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE |
325             GRALLOC1_CONSUMER_USAGE_HWCOMPOSER |
326             GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET |
327             GRALLOC1_CONSUMER_USAGE_CURSOR |
328             GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER |
329             GRALLOC1_CONSUMER_USAGE_CAMERA |
330             GRALLOC1_CONSUMER_USAGE_RENDERSCRIPT |
331             GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
332 
333     *producerUsage_out = static_cast<uint64_t>(usage) & PRODUCER_MASK;
334     *consumerUsage_out = static_cast<uint64_t>(usage) & CONSUMER_MASK;
335 
336     if ((static_cast<uint32_t>(usage) & GRALLOC_USAGE_SW_READ_OFTEN) ==
337         GRALLOC_USAGE_SW_READ_OFTEN) {
338         *producerUsage_out |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
339         *consumerUsage_out |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
340     }
341 
342     if ((static_cast<uint32_t>(usage) & GRALLOC_USAGE_SW_WRITE_OFTEN) ==
343         GRALLOC_USAGE_SW_WRITE_OFTEN) {
344         *producerUsage_out |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
345     }
346 }
347 
setup(VulkanDispatch * vk,VkDevice device,VkQueue queueIn,uint32_t queueFamilyIndexIn)348 void AndroidNativeBufferInfo::QueueState::setup(
349     VulkanDispatch* vk,
350     VkDevice device,
351     VkQueue queueIn,
352     uint32_t queueFamilyIndexIn) {
353 
354     queue = queueIn;
355     queueFamilyIndex = queueFamilyIndexIn;
356 
357     VkCommandPoolCreateInfo poolCreateInfo = {
358         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 0,
359         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
360         queueFamilyIndex,
361     };
362 
363     vk->vkCreateCommandPool(
364         device,
365         &poolCreateInfo,
366         nullptr,
367         &pool);
368 
369     VkCommandBufferAllocateInfo cbAllocInfo = {
370         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 0,
371         pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1,
372     };
373 
374     vk->vkAllocateCommandBuffers(
375         device,
376         &cbAllocInfo,
377         &cb);
378 
379     vk->vkAllocateCommandBuffers(
380         device,
381         &cbAllocInfo,
382         &cb2);
383 
384     VkFenceCreateInfo fenceCreateInfo = {
385         VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 0, 0,
386     };
387 
388     vk->vkCreateFence(
389         device,
390         &fenceCreateInfo,
391         nullptr,
392         &fence);
393 }
394 
teardown(VulkanDispatch * vk,VkDevice device)395 void AndroidNativeBufferInfo::QueueState::teardown(
396     VulkanDispatch* vk, VkDevice device) {
397 
398     if (queue) vk->vkQueueWaitIdle(queue);
399     if (cb) vk->vkFreeCommandBuffers(device, pool, 1, &cb);
400     if (pool) vk->vkDestroyCommandPool(device, pool, nullptr);
401     if (fence) vk->vkDestroyFence(device, fence, nullptr);
402 
403     queue = VK_NULL_HANDLE;
404     pool = VK_NULL_HANDLE;
405     cb = VK_NULL_HANDLE;
406     fence = VK_NULL_HANDLE;
407     queueFamilyIndex = 0;
408 }
409 
setAndroidNativeImageSemaphoreSignaled(VulkanDispatch * vk,VkDevice device,VkQueue defaultQueue,uint32_t defaultQueueFamilyIndex,VkSemaphore semaphore,VkFence fence,AndroidNativeBufferInfo * anbInfo)410 VkResult setAndroidNativeImageSemaphoreSignaled(
411     VulkanDispatch* vk,
412     VkDevice device,
413     VkQueue defaultQueue,
414     uint32_t defaultQueueFamilyIndex,
415     VkSemaphore semaphore,
416     VkFence fence,
417     AndroidNativeBufferInfo* anbInfo) {
418 
419     auto fb = FrameBuffer::getFB();
420 
421     bool firstTimeSetup =
422         !anbInfo->everSynced &&
423         !anbInfo->everAcquired;
424 
425     anbInfo->everAcquired = true;
426         // fprintf(stderr, "%s: call\n", __func__);
427 
428     if (firstTimeSetup) {
429 
430         VkSubmitInfo submitInfo = {
431             VK_STRUCTURE_TYPE_SUBMIT_INFO, 0,
432             0, nullptr, nullptr,
433             0, nullptr,
434             1, &semaphore,
435         };
436 
437         vk->vkQueueSubmit(defaultQueue, 1, &submitInfo, fence);
438     } else {
439 
440         const AndroidNativeBufferInfo::QueueState& queueState =
441                 anbInfo->queueStates[anbInfo->lastUsedQueueFamilyIndex];
442 
443         // For GL interop, transfer back to present layout from general.
444         if (anbInfo->isGlTexture) {
445             fb->setColorBufferInUse(anbInfo->colorBufferHandle, true);
446 
447             VkCommandBufferBeginInfo beginInfo = {
448                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
449                 0,
450                 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
451                 nullptr /* no inheritance info */,
452             };
453 
454             vk->vkBeginCommandBuffer(queueState.cb2, &beginInfo);
455 
456             VkImageMemoryBarrier backToPresentSrc = {
457                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0,
458                 VK_ACCESS_HOST_READ_BIT, 0,
459                 fb->getVkImageLayoutForPresent(),
460                 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
461                 VK_QUEUE_FAMILY_EXTERNAL,
462                 anbInfo->lastUsedQueueFamilyIndex,
463                 anbInfo->image,
464                 {
465                     VK_IMAGE_ASPECT_COLOR_BIT,
466                     0, 1, 0, 1,
467                 },
468             };
469 
470             vk->vkCmdPipelineBarrier(queueState.cb2,
471                     VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
472                     VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0,
473                     nullptr, 0, nullptr, 1, &backToPresentSrc);
474 
475             vk->vkEndCommandBuffer(queueState.cb2);
476 
477             VkSubmitInfo submitInfo = {
478                 VK_STRUCTURE_TYPE_SUBMIT_INFO,
479                 0,
480                 0,
481                 nullptr,
482                 nullptr,
483                 1,
484                 &queueState.cb2,
485                 1,
486                 &semaphore,
487             };
488 
489             // TODO(kaiyili): initiate ownership transfer from DisplayVk here
490             vk->vkQueueSubmit(queueState.queue, 1, &submitInfo, fence);
491         } else {
492             const AndroidNativeBufferInfo::QueueState&
493                 queueState = anbInfo->queueStates[anbInfo->lastUsedQueueFamilyIndex];
494             VkSubmitInfo submitInfo = {
495                 VK_STRUCTURE_TYPE_SUBMIT_INFO, 0,
496                 0, nullptr, nullptr,
497                 0, nullptr,
498                 1, &semaphore,
499             };
500             vk->vkQueueSubmit(queueState.queue, 1, &submitInfo, fence);
501         }
502     }
503 
504     return VK_SUCCESS;
505 }
506 
syncImageToColorBuffer(VulkanDispatch * vk,uint32_t queueFamilyIndex,VkQueue queue,uint32_t waitSemaphoreCount,const VkSemaphore * pWaitSemaphores,int * pNativeFenceFd,AndroidNativeBufferInfo * anbInfo)507 VkResult syncImageToColorBuffer(
508     VulkanDispatch* vk,
509     uint32_t queueFamilyIndex,
510     VkQueue queue,
511     uint32_t waitSemaphoreCount,
512     const VkSemaphore* pWaitSemaphores,
513     int* pNativeFenceFd,
514     AndroidNativeBufferInfo* anbInfo) {
515 
516     auto fb = FrameBuffer::getFB();
517     fb->lock();
518 
519     // Implicitly synchronized
520     *pNativeFenceFd = -1;
521 
522     anbInfo->everSynced = true;
523     anbInfo->lastUsedQueueFamilyIndex = queueFamilyIndex;
524 
525     // Setup queue state for this queue family index.
526     if (queueFamilyIndex >= anbInfo->queueStates.size()) {
527         anbInfo->queueStates.resize(queueFamilyIndex + 1);
528     }
529 
530     auto& queueState = anbInfo->queueStates[queueFamilyIndex];
531 
532     if (!queueState.queue) {
533         queueState.setup(
534             vk, anbInfo->device, queue, queueFamilyIndex);
535     }
536 
537     // Record our synchronization commands.
538     VkCommandBufferBeginInfo beginInfo = {
539         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0,
540         VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
541         nullptr /* no inheritance info */,
542     };
543 
544     vk->vkBeginCommandBuffer(queueState.cb, &beginInfo);
545 
546     // If GL texture, transfer image layout to "general" for GL interop.
547     if (anbInfo->isGlTexture) {
548         VkImageMemoryBarrier present2GeneralBarrier = {
549             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0,
550             VK_ACCESS_HOST_READ_BIT, 0,
551             VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
552             fb->getVkImageLayoutForPresent(),
553             queueFamilyIndex,
554             VK_QUEUE_FAMILY_EXTERNAL,
555             anbInfo->image,
556             {
557                 VK_IMAGE_ASPECT_COLOR_BIT,
558                 0, 1, 0, 1,
559             },
560         };
561 
562         vk->vkCmdPipelineBarrier(
563             queueState.cb,
564             VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
565             VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
566             0,
567             0, nullptr,
568             0, nullptr,
569             1, &present2GeneralBarrier);
570 
571     } else {
572         // Not a GL texture. Read it back and put it back in present layout.
573 
574         // From the spec: If an application does not need the contents of a resource
575         // to remain valid when transferring from one queue family to another, then
576         // the ownership transfer should be skipped.
577         // We definitely need to transition the image to
578         // VK_TRANSFER_SRC_OPTIMAL and back.
579         VkImageMemoryBarrier presentToTransferSrc = {
580             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0,
581             0,
582             VK_ACCESS_HOST_READ_BIT,
583             VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
584             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
585             VK_QUEUE_FAMILY_IGNORED,
586             VK_QUEUE_FAMILY_IGNORED,
587             anbInfo->image,
588             {
589                 VK_IMAGE_ASPECT_COLOR_BIT,
590                 0, 1, 0, 1,
591             },
592         };
593 
594         vk->vkCmdPipelineBarrier(
595             queueState.cb,
596             VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
597             VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
598             0,
599             0, nullptr,
600             0, nullptr,
601             1, &presentToTransferSrc);
602 
603         VkBufferImageCopy region = {
604             0 /* buffer offset */,
605             anbInfo->extent.width,
606             anbInfo->extent.height,
607             {
608                 VK_IMAGE_ASPECT_COLOR_BIT,
609                 0, 0, 1,
610             },
611             { 0, 0, 0 },
612             anbInfo->extent,
613         };
614 
615         vk->vkCmdCopyImageToBuffer(
616             queueState.cb,
617             anbInfo->image,
618             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
619             anbInfo->stagingBuffer,
620             1, &region);
621 
622         // Transfer back to present src.
623         VkImageMemoryBarrier backToPresentSrc = {
624             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0,
625             VK_ACCESS_HOST_READ_BIT,
626             0,
627             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
628             VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
629             VK_QUEUE_FAMILY_IGNORED,
630             VK_QUEUE_FAMILY_IGNORED,
631             anbInfo->image,
632             {
633                 VK_IMAGE_ASPECT_COLOR_BIT,
634                 0, 1, 0, 1,
635             },
636         };
637 
638         vk->vkCmdPipelineBarrier(
639             queueState.cb,
640             VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
641             VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
642             0,
643             0, nullptr,
644             0, nullptr,
645             1, &backToPresentSrc);
646 
647     }
648 
649     vk->vkEndCommandBuffer(queueState.cb);
650 
651     std::vector<VkPipelineStageFlags> pipelineStageFlags;
652     pipelineStageFlags.resize(waitSemaphoreCount, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
653 
654     VkSubmitInfo submitInfo = {
655         VK_STRUCTURE_TYPE_SUBMIT_INFO, 0,
656         waitSemaphoreCount, pWaitSemaphores,
657         pipelineStageFlags.data(),
658         1, &queueState.cb,
659         0, nullptr,
660     };
661 
662     // TODO(kaiyili): initiate ownership transfer to DisplayVk here.
663     vk->vkQueueSubmit(queueState.queue, 1, &submitInfo, VK_NULL_HANDLE);
664 
665     fb->unlock();
666 
667     if (anbInfo->isGlTexture) {
668         fb->setColorBufferInUse(anbInfo->colorBufferHandle, false);
669     } else {
670 
671         VkMappedMemoryRange toInvalidate = {
672             VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
673             anbInfo->stagingMemory,
674             0, VK_WHOLE_SIZE,
675         };
676 
677         vk->vkInvalidateMappedMemoryRanges(
678             anbInfo->device, 1, &toInvalidate);
679 
680         uint32_t colorBufferHandle = anbInfo->colorBufferHandle;
681 
682         // Copy to from staging buffer to color buffer
683         uint32_t bpp = 4; /* format always rgba8...not */
684         switch (anbInfo->vkFormat) {
685             case VK_FORMAT_R5G6B5_UNORM_PACK16:
686                 bpp = 2;
687                 break;
688             case VK_FORMAT_R8G8B8_UNORM:
689                 bpp = 3;
690                 break;
691             default:
692             case VK_FORMAT_R8G8B8A8_UNORM:
693             case VK_FORMAT_B8G8R8A8_UNORM:
694                 bpp = 4;
695                 break;
696         }
697 
698         FrameBuffer::getFB()->
699             replaceColorBufferContents(
700                 colorBufferHandle,
701                 anbInfo->mappedStagingPtr,
702                 bpp * anbInfo->extent.width * anbInfo->extent.height);
703     }
704 
705     return VK_SUCCESS;
706 }
707 
708 } // namespace goldfish_vk
709