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, ®ion);
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